{{ GaitHexHDATS.spin }} ' ============================================================================== ' ' File...... GaitHexHDATS.spin ' Purpose... Gait object for the CrustCrawler HexCrawler HDATS ' Author.... (C) 2007 Steven R. Norris -- All Rights Reserved ' E-mail.... steve@norrislabs.com ' Started... 02/20/2007 ' Updated... 03/02/2007 ' ' ============================================================================== ' Note: Switch editor to Documentation mode to read all the text. ' ------------------------------------------------------------------------------ ' Program Description ' ------------------------------------------------------------------------------ {{ Author: Steve Norris Email : steve@norrislabs.com This object is a reusable walking engine for the HexCrawler HDATS from CrustCrawler. You can use it for all your Propeller-based HexCrawler HDATS applications. This object uses the same configuration as the Nomad GaitPIC. Consult the wiring diagram for the Nomad GaitPIC for details. This object requires two Cogs. One is for the walking engine and the other is for the serial communications to the Parallax Servo Controller. The serial communications to the PSC runs at 38400 baud. The Start, Stop and IsActive methods are used for Cog maintenance. The Walk, Crab, Spin, Home, Wait, IsBusy, and Halt methods are used to control the walking engine. The Parallax Servo Controller (PSC) is connected to the pin specified in the call to the Start method. You can adjust the home positions of all the servos in the TuneData constant defined in the DAT section. To use this object simply include it in the OBJ section of your application code. Be sure to call the Start method first before you call any of the other methods. }} ' ------------------------------------------------------------------------------ ' Revision History ' ------------------------------------------------------------------------------ {{ 0709a - This is the first version 0709b - added flag to prevent PSC contention issues }} CON ' ------------------------------------------------------------------------------ ' Constants ' ------------------------------------------------------------------------------ _clkmode = xtal1 + pll16x _xinfreq = 5_000_000 ' Leg positions CenterPos = 750 ' Center for all servos ' Vertical positions LeftRaisePos = 650 ' Vertical - normal LeftHiStepPos = 850 ' Vertical - High step LeftLowerPos = 300 ' Vertical RightRaisePos = 850 ' Vertical - normal RightHiStepPos = 650 ' Vertical - High step RightLowerPos = 1200 ' Vertical ' Gait types Gait_None = 0 Gait_Home = 1 Gait_HomeAB = 2 Gait_Walk = 3 Gait_Spin = 4 Gait_Crab = 5 ' Directions Dir_Fwd = 0 Dir_Back = 1 Dir_CW = 0 Dir_CCW = 1 Dir_Right = 0 Dir_Left = 1 DAT LegSeqs byte 0,8,20,16,24,4 ' Forward byte 16,24,4,0,8,20 ' Reverse TuneData long 0,0,-40 ' Leg 1 - 0,1,2 (horz,vert,foot) long 0 long 0,0,-50 ' Leg 2 - 4,5,6 long 0 long 0,0,-35 ' Leg 3 - 8,9,10 long 0,0,0,0,0 long 0,0,30 ' Leg 4 - 16,17,18 long 0 long 15,0,20 ' Leg 5 - 20,21,22 long 0 long 0,0,25 ' Leg 6 - 24,25,26 VAR ' ------------------------------------------------------------------------------ ' Variables ' ------------------------------------------------------------------------------ ' Cog maintenance variables byte m_Cog long m_Stack[50] ' Object initialized flag byte m_Init ' Parallax Serial Controller (PSC) Pin byte m_PscTx ' PSC send busy flag byte m_PscBusy ' Gait parameters byte m_Gait byte m_Direction byte m_Speed long m_Turn byte m_HiStep long m_Counter byte m_LastGait byte m_LastDir ' Servo center tuning data long m_ServoTune[27] ' Leg sequence byte m_LegSeq[6] ' Servo ramp speeds byte m_VertRamp byte m_HorzRamp byte m_FootRamp ' Delays long m_SetupDelay long m_ResetDelay long m_StrokeDelay ' Stride starting and ending position offsets long m_StrideHorzStart long m_StrideFootStart OBJ PscComm : "FullDuplexSerial" PUB Start(PinPsc) : Success ' ------------------------------------------------------------------------------ ' Start this resource (cog) ' ------------------------------------------------------------------------------ {{ Starts the walking engine in a seperate cog. Pass the pin number that is connected to the Parallax Servo Controller (PSC). Returns a true if the startup was successful. }} m_PscTx := PinPsc m_PscBusy := FALSE Stop Success := (m_Cog := cognew(Main,@m_Stack) + 1) m_Init := Success PUB Stop ' ------------------------------------------------------------------------------ ' Stop this resource (cog) ' ------------------------------------------------------------------------------ {{ Stops the execution of the walking engine. }} if m_Cog cogstop(m_Cog~ - 1) PUB IsActive :YesNo ' ------------------------------------------------------------------------------ ' Is this resource (cog) running? ' ------------------------------------------------------------------------------ {{ Determines if the walking engine is running in a cog. }} YesNo := m_Cog > 0 PUB Home ' ------------------------------------------------------------------------------ ' Home All Legs ' ------------------------------------------------------------------------------ {{ Home all the legs at once. This method is non-blocking. }} if m_Init Halt m_Gait := Gait_Home PUB HomeAB ' ------------------------------------------------------------------------------ ' Home Legs by Group ' ------------------------------------------------------------------------------ {{ Home the A group legs and then the B group legs. This method is non-blocking. }} if m_Init Halt m_Gait := Gait_HomeAB PUB Walk(Direction, Speed, Turn, Count) ' ------------------------------------------------------------------------------ ' Start walking ' ------------------------------------------------------------------------------ {{ Normal walk. This method is non-blocking. Pass the direction, speed, turn offset and the number of steps to take. Passing -1 for Count results in continous walking. Directions: 0 ....... Forward 1 ....... Reverse Speeds: 0 - Fast 1 - Normal 2 - Slow 3 - Slow with high step Turn offset: 0 - None 1 - Right, small 2 - Right, medium 3 - Right, large -1 - Left, small -2 - Left, medium -3 - Left, large }} if m_Init Halt m_Direction := Direction m_Speed := Speed SetTurn(Turn) m_Counter := Count m_Gait := Gait_Walk PUB SetTurn(Turn) ' ------------------------------------------------------------------------------ ' Set the turn rate ' ------------------------------------------------------------------------------ {{ Set turn rate. This method is non-blocking. Only valid when using the Walk gait. Can be set while the engine is walking. Turn rate: 0 - None 1 - Right, small 2 - Right, medium 3 - Right, large -1 - Left, small -2 - Left, medium -3 - Left, large }} ' Set turn offset case Turn 0: m_Turn := 0 ' straight -1: m_Turn := -50 ' left -2: m_Turn := -75 -3: m_Turn := -100 1: m_Turn := 50 ' right 2: m_Turn := 75 3: m_Turn := 100 PUB Crab(Direction, Speed, Count) ' ------------------------------------------------------------------------------ ' Start crabbing ' ------------------------------------------------------------------------------ {{ Crab left or right. This method is non-blocking. Pass the direction, speed, and the number of steps to take. Passing -1 for Count results in continous crabbing (like some people I know). Directions: 0 ....... Right 1 ....... Left Speeds: 0 - Fast 1 - Normal 2 - Slow 3 - Slow with high step }} if m_Init Halt m_Direction := Direction m_Speed := Speed m_Counter := Count m_Gait := Gait_Crab PUB Spin(Direction, HiStep, Count) ' ------------------------------------------------------------------------------ ' Start spinning ' ------------------------------------------------------------------------------ {{ Spin to the left or right. This method is non-blocking. Pass the direction, high step flag, and the number of steps to take. Passing -1 for Count results in continous spinning. Directions: 0 ....... Clockwise 1 ....... Counter-clockwise HiStep: FALSE - Use normal step TRUE - Use high step }} if m_Init Halt m_Direction := Direction m_HiStep := HiStep m_Counter := Count m_Gait := Gait_Spin PUB Wait ' ------------------------------------------------------------------------------ ' Wait for the current command to complete ' ------------------------------------------------------------------------------ {{ Wait for the current gait command to complete. Will not wait if you pass -1 for continous. }} repeat while m_Gait <> Gait_None PUB IsBusy : YesNo ' ------------------------------------------------------------------------------ ' Are we busy? ' ------------------------------------------------------------------------------ {{ Determines if we are currently executing a gait. }} YesNo := m_Gait <> Gait_None PUB Halt ' ------------------------------------------------------------------------------ ' Stop walking ' ------------------------------------------------------------------------------ {{ Stops the current gait. }} m_Counter := 0 repeat while m_Gait <> Gait_None PUB MoveServo(Servo, Ramp, Position) ' ------------------------------------------------------------------------------ ' Move a servo directly ' ------------------------------------------------------------------------------ {{ Moves the specified servo directly. }} if m_Init Send2PSC(Servo, Ramp, Position) PRI Main | i,ptr ' ------------------------------------------------------------------------------ ' Main for the Walking Engine ' This code runs in its own cog ' ------------------------------------------------------------------------------ ' Initialize PSC serial communications ' Step it up to 38400 baud PscComm.Start(-1, m_PscTx, 0, 2400) SetPscBaudRate(1) ' Now restart the cog using the higher baud PscComm.Stop PscComm.Start(-1, m_PscTx, 0, 38400) ' Give time for the PSC's to startup Pause_ms(1000) ' Load servo tuning data ptr := 0 repeat i from 0 to 26 m_ServoTune[i] := TuneData[ptr + i] ' Set stride start and end values m_StrideHorzStart := 125 m_StrideFootStart := 40 m_LastGait := $FF m_LastDir := $FF ' Main loop ' Process gait commands repeat if m_Gait <> Gait_None ' Initialize case m_Gait Gait_Home: HomeSeq Gait_HomeAB: HomeABSeq Gait_Walk: WalkInit Gait_Crab: CrabInit Gait_Spin: SpinInit ' Loop for sequence commands repeat while m_Counter > 0 or m_Counter == -1 case m_Gait Gait_Walk: WalkSeq Gait_Crab: CrabSeq Gait_Spin: SpinSeq if m_Counter > 0 m_Counter -= 1 m_Gait := Gait_None PRI WalkInit | i,ptr ' Setup servo sequence for this direction ptr := m_Direction * 6 repeat i from 0 to 5 m_LegSeq[i] := LegSeqs[ptr + i] ' Setup ramp speeds and delays SetSpeed(m_Speed) ' Set initial leg positions if m_Gait <> m_LastGait or m_Direction <> m_LastDir AllLower WalkReset(0) m_LastGait := m_Gait m_LastDir := m_Direction PRI WalkSeq WalkSetup(0) WalkReset(1) WalkStroke(0) WalkSetup(1) WalkReset(0) WalkStroke(1) PRI WalkSetup(Group) | idx,servo idx := Group * 3 repeat 3 servo := m_LegSeq[idx] + 1 Send2PSC(servo, m_VertRamp, GetVertLowerPos(servo)) idx++ Pause_ms(m_SetupDelay) PRI WalkReset(Group) | idx,servo,hStart,fStart ' Raise all the legs in this group RaiseLegGroup(Group) ' Position the horizontal and foot idx := Group * 3 repeat 3 servo := m_LegSeq[idx] ' Compute position if IsRelBack(servo) hStart := 750 + m_ServoTune[servo] fStart := 750 + m_ServoTune[servo + 2] else if IsRelRight(servo) hStart := (750 + m_ServoTune[servo]) + m_StrideHorzStart if servo == 4 and m_Turn > 0 hStart -= m_Turn if m_Direction == 0 fStart := (750 + m_ServoTune[servo + 2]) - m_StrideFootStart else fStart := (750 + m_ServoTune[servo + 2]) + m_StrideFootStart else hStart := (750 + m_ServoTune[servo]) - m_StrideHorzStart if servo == 20 and m_Turn < 0 hStart += ||m_Turn if m_Direction == 0 fStart := (750 + m_ServoTune[servo + 2]) + m_StrideFootStart else fStart := (750 + m_ServoTune[servo + 2]) - m_StrideFootStart ' Move to computed position Send2PSC(servo, m_HorzRamp, hStart) Send2PSC(servo + 2, m_FootRamp, fStart) idx++ Pause_ms(m_ResetDelay) PRI WalkStroke(Group) | idx,servo,hStart,fStart ' Horizontal and foot idx := Group * 3 repeat 3 servo := m_LegSeq[idx] ' Compute position if IsRelBack(servo) if IsRelRight(servo) hStart := (750 + m_ServoTune[servo]) - m_StrideHorzStart if m_Direction == 0 fStart := (750 + m_ServoTune[servo + 2]) - m_StrideFootStart else fStart := (750 + m_ServoTune[servo + 2]) + m_StrideFootStart else hStart := (750 + m_ServoTune[servo]) + m_StrideHorzStart if m_Direction == 0 fStart := (750 + m_ServoTune[servo + 2]) + m_StrideFootStart else fStart := (750 + m_ServoTune[servo + 2]) - m_StrideFootStart else hStart := 750 + m_ServoTune[servo] fStart := 750 + m_ServoTune[servo + 2] ' Move to computed position Send2PSC(servo, m_HorzRamp, hStart) Send2PSC(servo + 2, m_FootRamp, fStart) idx++ Pause_ms(m_StrokeDelay) PRI CrabInit | i,ptr ' Setup servo sequence for this direction ptr := m_Direction * 6 repeat i from 0 to 5 m_LegSeq[i] := LegSeqs[ptr + i] ' Setup ramp speeds and delays SetSpeed(m_Speed) ' Set initial leg positions if m_Gait <> m_LastGait or m_Direction <> m_LastDir AllLower CrabReset(0) m_LastGait := m_Gait m_LastDir := m_Direction PRI CrabSeq WalkSetup(0) CrabReset(1) CrabStroke(0) WalkSetup(1) CrabReset(0) CrabStroke(1) PRI CrabReset(Group) | idx,servo,hStart,fStart ' Raise all the legs in this group RaiseLegGroup(Group) ' Position the horizontal and foot idx := Group * 3 repeat 3 servo := m_LegSeq[idx] ' Compute position hStart := (750 + m_ServoTune[servo]) if m_Direction == Dir_Right fStart := (750 + m_ServoTune[servo + 2]) - 65 else fStart := (750 + m_ServoTune[servo + 2]) + 65 ' Move to computed position Send2PSC(servo, m_HorzRamp, hStart) Send2PSC(servo + 2, m_FootRamp, fStart) idx++ Pause_ms(m_ResetDelay) PRI CrabStroke(Group) | idx,servo,hStart,fStart ' Horizontal and foot idx := Group * 3 repeat 3 servo := m_LegSeq[idx] ' Compute position hStart := (750 + m_ServoTune[servo]) if m_Direction == Dir_Right fStart := (750 + m_ServoTune[servo + 2]) + 65 else fStart := (750 + m_ServoTune[servo + 2]) - 65 ' Move to computed position Send2PSC(servo, m_HorzRamp, hStart) Send2PSC(servo + 2, m_FootRamp, fStart) idx++ Pause_ms(m_StrokeDelay) PRI SetSpeed(Speed) m_SetupDelay := 100 m_ResetDelay := 100 case m_Speed 0: m_VertRamp := 6 m_HorzRamp := 9 m_FootRamp := 9 m_StrokeDelay := 400 1: m_VertRamp := 7 m_HorzRamp := 11 m_FootRamp := 11 m_StrokeDelay := 525 2: m_VertRamp := 7 m_HorzRamp := 14 m_FootRamp := 14 m_StrokeDelay := 800 3: m_VertRamp := 7 m_HorzRamp := 11 m_FootRamp := 11 m_SetupDelay := 250 m_ResetDelay := 200 m_StrokeDelay := 525 m_HiStep := TRUE PRI RaiseLegGroup(Group) | idx,servo idx := Group * 3 repeat 3 ' Raise the vertical servo := m_LegSeq[idx] + 1 Send2PSC(servo, m_VertRamp, GetVertRaisePos(servo)) idx++ ' Allow the leg to pop up before we move the horizontal or foot Pause_ms(50) PRI SpinInit | i ' Setup ramp speeds and delays if m_HiStep m_VertRamp := 6 m_HorzRamp := 11 m_FootRamp := 11 m_SetupDelay := 250 m_ResetDelay := 500 m_StrokeDelay := 525 else m_VertRamp := 7 m_HorzRamp := 9 m_FootRamp := 9 m_SetupDelay := 100 m_ResetDelay := 300 m_StrokeDelay := 400 AllLower m_LastGait := m_Gait m_LastDir := m_Direction PRI SpinSeq if m_Direction == Dir_CW SpinCW else SpinCCW PRI SpinCW | servo,hStart,fStart ' Step 1 - Raise, position and lower legs 2,5 and then 4 hStart := (750 + m_ServoTune[4]) - m_StrideHorzStart fStart := (750 + m_ServoTune[6]) MoveLeg(4, TRUE, hStart, fStart) hStart := (750 + m_ServoTune[20]) - m_StrideHorzStart fStart := (750 + m_ServoTune[22]) MoveLeg(20, TRUE, hStart, fStart) Pause_ms(m_ResetDelay) Send2PSC(5, m_VertRamp, GetVertLowerPos(5)) Send2PSC(21, m_VertRamp, GetVertLowerPos(21)) Pause_ms(m_SetupDelay) hStart := (750 + m_ServoTune[16]) + 125 fStart := (750 + m_ServoTune[18]) MoveLeg(16, TRUE, hStart, fStart) Pause_ms(m_ResetDelay) Send2PSC(17, m_VertRamp, GetVertLowerPos(17)) Pause_ms(m_SetupDelay) ' Step 2 - Raise legs 1,3,6 hStart := (750 + m_ServoTune[0]) fStart := (750 + m_ServoTune[2]) MoveLeg(0, TRUE, hStart, fStart) hStart := (750 + m_ServoTune[8]) fStart := (750 + m_ServoTune[10]) MoveLeg(8, TRUE, hStart, fStart) hStart := (750 + m_ServoTune[24]) fStart := (750 + m_ServoTune[26]) MoveLeg(24, TRUE, hStart, fStart) Pause_ms(m_ResetDelay) ' Step 3 - Power stroke hStart := (750 + m_ServoTune[4]) Send2PSC(4, m_HorzRamp, hStart) hStart := (750 + m_ServoTune[16]) + 125 + m_StrideHorzStart Send2PSC(16, m_HorzRamp, hStart) hStart := (750 + m_ServoTune[20]) Send2PSC(20, m_HorzRamp, hStart) Pause_ms(m_StrokeDelay) ' Step 4 - Lower legs 1,3,6 Send2PSC(1, m_VertRamp, GetVertLowerPos(1)) Send2PSC(9, m_VertRamp, GetVertLowerPos(9)) Send2PSC(25, m_VertRamp, GetVertLowerPos(25)) Pause_ms(m_SetUpDelay) PRI SpinCCW | servo,hStart,fStart ' Step 1 - Raise, position and lower legs 2,5 and then 3 hStart := (750 + m_ServoTune[4]) + m_StrideHorzStart fStart := (750 + m_ServoTune[6]) MoveLeg(4, TRUE, hStart, fStart) hStart := (750 + m_ServoTune[20]) + m_StrideHorzStart fStart := (750 + m_ServoTune[22]) MoveLeg(20, TRUE, hStart, fStart) Pause_ms(m_ResetDelay) Send2PSC(5, m_VertRamp, GetVertLowerPos(5)) Send2PSC(21, m_VertRamp, GetVertLowerPos(21)) Pause_ms(m_SetupDelay) hStart := (750 + m_ServoTune[8]) - 125 fStart := (750 + m_ServoTune[10]) MoveLeg(8, TRUE, hStart, fStart) Pause_ms(m_ResetDelay) Send2PSC(9, m_VertRamp, GetVertLowerPos(9)) Pause_ms(m_SetupDelay) ' Step 2 - Raise legs 1,4,6 hStart := (750 + m_ServoTune[0]) fStart := (750 + m_ServoTune[2]) MoveLeg(0, TRUE, hStart, fStart) hStart := (750 + m_ServoTune[16]) fStart := (750 + m_ServoTune[17]) MoveLeg(16, TRUE, hStart, fStart) hStart := (750 + m_ServoTune[24]) fStart := (750 + m_ServoTune[26]) MoveLeg(24, TRUE, hStart, fStart) Pause_ms(m_ResetDelay) ' Step 3 - Power stroke hStart := (750 + m_ServoTune[4]) Send2PSC(4, m_HorzRamp, hStart) hStart := (750 + m_ServoTune[8]) - 125 - m_StrideHorzStart Send2PSC(8, m_HorzRamp, hStart) hStart := (750 + m_ServoTune[20]) Send2PSC(20, m_HorzRamp, hStart) Pause_ms(m_StrokeDelay) ' Step 4 - Lower legs 1,4,6 Send2PSC(1, m_VertRamp, GetVertLowerPos(1)) Send2PSC(17, m_VertRamp, GetVertLowerPos(17)) Send2PSC(25, m_VertRamp, GetVertLowerPos(25)) Pause_ms(m_SetUpDelay) PRI HomeSeq | servo repeat servo from 0 to 8 step 4 Send2PSC(servo + 1, 8, GetVertLowerPos(servo)) Send2PSC(servo, 8, 750 + m_ServoTune[servo]) Send2PSC(servo + 2, 8, 750 + m_ServoTune[servo + 2]) repeat servo from 16 to 24 step 4 Send2PSC(servo + 1, 8, GetVertLowerPos(servo)) Send2PSC(servo, 8, 750 + m_ServoTune[servo]) Send2PSC(servo + 2, 8, 750 + m_ServoTune[servo + 2]) Pause_ms(500) m_LastGait := m_Gait PRI HomeEachSeq | servo,fStart,hStart AllLower repeat servo from 0 to 8 step 4 Send2PSC(servo + 1, 6, GetVertRaisePos(servo)) Send2PSC(servo, 8, 750 + m_ServoTune[servo]) Send2PSC(servo + 2, 8, 750 + m_ServoTune[servo + 2]) Pause_ms(350) Send2PSC(servo + 1, m_VertRamp, GetVertLowerPos(servo)) Pause_ms(350) repeat servo from 16 to 24 step 4 Send2PSC(servo + 1, 6, GetVertRaisePos(servo)) Send2PSC(servo, 8, 750 + m_ServoTune[servo]) Send2PSC(servo + 2, 8, 750 + m_ServoTune[servo + 2]) Pause_ms(350) Send2PSC(servo + 1, m_VertRamp, GetVertLowerPos(servo)) Pause_ms(350) m_LastGait := m_Gait PRI HomeABSeq | servo,fStart,hStart,idx,group ' Setup servo sequence repeat idx from 0 to 5 m_LegSeq[idx] := LegSeqs[idx] m_HiStep := FALSE m_VertRamp := 7 AllLower repeat group from 0 to 1 ' Raise all the legs in group A RaiseLegGroup(group) Pause_ms(200) ' Position the horizontal and foot idx := group * 3 repeat 3 servo := m_LegSeq[idx] hStart := (750 + m_ServoTune[servo]) fStart := (750 + m_ServoTune[servo + 2]) Send2PSC(servo, 7, hStart) Send2PSC(servo + 2, 7, fStart) idx++ Pause_ms(500) AllLower m_LastGait := m_Gait PRI AllLower | servo repeat servo from 1 to 9 step 4 Send2PSC(servo,8,GetVertLowerPos(servo)) repeat servo from 17 to 25 step 4 Send2PSC(servo,8,GetVertLowerPos(servo)) Pause_ms(350) PRI MoveLeg(Servo, Raise, HorzPos, FootPos) if Raise Send2PSC(Servo + 1, m_VertRamp, GetVertRaisePos(Servo)) else Send2PSC(Servo + 1, m_VertRamp, GetVertLowerPos(Servo)) Pause_ms(50) Send2PSC(Servo, m_HorzRamp, HorzPos) Send2PSC(Servo + 2, m_FootRamp, FootPos) PRI GetVertLowerPos(Servo) if Servo =< 10 return RightLowerPos else return LeftLowerPos PRI GetVertRaisePos(Servo) if Servo =< 10 if m_HiStep return RightHiStepPos else return RightRaisePos else if m_HiStep return LeftHiStepPos else return LeftRaisePos PRI IsRelRight(Servo) : yesno if m_Direction == Dir_Fwd if Servo =< 10 return TRUE else return FALSE else if Servo =< 10 return FALSE else return TRUE PRI IsRelBack(Servo) : yesno if m_Direction == Dir_Fwd if Servo == 8 or Servo == 16 return TRUE else return FALSE else if Servo == 0 or Servo == 24 return TRUE else return FALSE PRI Send2PSC(Servo, Ramp, Position) ' Wait for some other cog to send its PSC command repeat while m_PscBusy m_PscBusy := TRUE ' Busy sending command PscComm.str(string("!SC")) PscComm.tx(Servo) PscComm.tx(Ramp) PscComm.tx(Position.byte[0]) PscComm.tx(Position.byte[1]) PscComm.tx($0D) Pause_ms(10) m_PscBusy := FALSE ' All done, let some other cog in PRI SetPscBaudRate(Baud) ' Select the baud rate for the PSC ' 0 = 2400 ' 1 = 38400 PscComm.str(string("!SCSBR")) PscComm.tx(Baud) PscComm.tx($0D) Pause_ms(50) PRI Pause_ms(msDelay) waitcnt(cnt + ((clkfreq / 1000) * msDelay))