Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ;Project Lynxmotion Phoenix
- ;Description: Phoenix, controlled by a Futaba T7C remote
- ;Software version: V1.3
- ;Date: 20-10-2008
- ;Programmer: Jeroen Janssen (aka Xan)
- ;
- ;Hardware setup: ABB2 with ATOM 28 Pro, SSC32 V2, PS2 remote (See further for connections)
- ;
- ;NEW IN V1.3
- ; - Changed controls L1+ right stick
- ; - Balance calculations Thanks to Kåre Halvorsen (aka Zenta)
- ;
- ;RC control:
- ;Select between walking, movement and Individual leg control mode with the 3-state switch
- ;Use the two-state switch to toogle between the different gaits, movement or which leg to control
- ;
- ;KNOWN BUGS:
- ; - None at the moment ;)
- ;
- ;====================================================================
- ;[CONSTANDS]
- TRUE con 1
- FALSE con 0
- BUTTON_DOWN con 0
- BUTTON_UP con 1
- ;--------------------------------------------------------------------
- ;[SERIAL CONNECTIONS]
- SSC_LM_SETUP con 1 ;Changes the SSC pins corresponding to the setup
- ;1 = Setup with connector to the front
- ;0 = Setup with connector to the back
- SSC_OUT con P14 ;black wire ;Output pin for (SSC32 RX) on BotBoard (Yellow)
- SSC_IN con P15 ;white wire ;Input pin for (SSC32 TX) on BotBoard (Blue)
- SSC_BAUTE con i38400 ;SSC32 Baute rate
- ;--------------------------------------------------------------------
- ;[RC Controller] Futaba T7C Heli
- RCCh0 con P0 ;RC Remote Right Stick Left/Right (ch1 on T7C)
- RCCh1 con P1 ;RC Remote Right Stick Up/Down (ch2 on T7C)
- RCCh2 con P2 ;RC Remote Left Stick Up/Down (ch3 on T7C)
- RCCh3 con P3 ;RC Remote Left Stick Left/Right (ch4 on T7C)
- RCCh4 con P4 ;RC Remote E-switch (G switch on A model) 3-state (ch5 on T7C)
- RCCh5 con P5 ;RC Remote Vr-pot (ch6 on T7C)
- RCCh6 con P6 ;RC Remote H-switch (B switch on A model) 2-state (ch7 on T7C)
- awPulsesIn var word(7)
- bPulseTimeout var byte
- ;--------------------------------------------------------------------
- ;[PIN NUMBERS]
- #IF SSC_LM_SETUP ;Connector to the front
- RRCoxaPin con P0 ;Rear Right leg Hip Horizontal
- RRFemurPin con P1 ;Rear Right leg Hip Vertical
- RRTibiaPin con P2 ;Rear Right leg Knee
- RMCoxaPin con P4 ;Middle Right leg Hip Horizontal
- RMFemurPin con P5 ;Middle Right leg Hip Vertical
- RMTibiaPin con P6 ;Middle Right leg Knee
- RFCoxaPin con P8 ;Front Right leg Hip Horizontal
- RFFemurPin con P9 ;Front Right leg Hip Vertical
- RFTibiaPin con P10 ;Front Right leg Knee
- LRCoxaPin con P16 ;Rear Left leg Hip Horizontal
- LRFemurPin con P17 ;Rear Left leg Hip Vertical
- LRTibiaPin con P18 ;Rear Left leg Knee
- LMCoxaPin con P20 ;Middle Left leg Hip Horizontal
- LMFemurPin con P21 ;Middle Left leg Hip Vertical
- LMTibiaPin con P22 ;Middle Left leg Knee
- LFCoxaPin con P24 ;Front Left leg Hip Horizontal
- LFFemurPin con P25 ;Front Left leg Hip Vertical
- LFTibiaPin con P26 ;Front Left leg Knee
- ;--------------------------------------------------------------------
- ;[MIN/MAX ANGLES]
- RRCoxa_MIN con -26 ;Mechanical limits of the Right Rear Leg
- RRCoxa_MAX con 74
- RRFemur_MIN con -101
- RRFemur_MAX con 95
- RRTibia_MIN con -106
- RRTibia_MAX con 77
- RMCoxa_MIN con -53 ;Mechanical limits of the Right Middle Leg
- RMCoxa_MAX con 53
- RMFemur_MIN con -101
- RMFemur_MAX con 95
- RMTibia_MIN con -106
- RMTibia_MAX con 77
- RFCoxa_MIN con -58 ;Mechanical limits of the Right Front Leg
- RFCoxa_MAX con 74
- RFFemur_MIN con -101
- RFFemur_MAX con 95
- RFTibia_MIN con -106
- RFTibia_MAX con 77
- LRCoxa_MIN con -74 ;Mechanical limits of the Left Rear Leg
- LRCoxa_MAX con 26
- LRFemur_MIN con -95
- LRFemur_MAX con 101
- LRTibia_MIN con -77
- LRTibia_MAX con 106
- LMCoxa_MIN con -53 ;Mechanical limits of the Left Middle Leg
- LMCoxa_MAX con 53
- LMFemur_MIN con -95
- LMFemur_MAX con 101
- LMTibia_MIN con -77
- LMTibia_MAX con 106
- LFCoxa_MIN con -74 ;Mechanical limits of the Left Front Leg
- LFCoxa_MAX con 58
- LFFemur_MIN con -95
- LFFemur_MAX con 101
- LFTibia_MIN con -77
- LFTibia_MAX con 106
- ;--------------------------------------------------------------------
- ;[BODY DIMENSIONS]
- CoxaLength con 29 ;Length of the Coxa [mm]
- FemurLength con 76 ;Length of the Femur [mm]
- TibiaLength con 106 ;Lenght of the Tibia [mm]
- CoxaAngle con 60 ;Default Coxa setup angle
- RFOffsetX con -43 ;Distance X from center of the body to the Right Front coxa
- RFOffsetZ con -82 ;Distance Z from center of the body to the Right Front coxa
- RMOffsetX con -63 ;Distance X from center of the body to the Right Middle coxa
- RMOffsetZ con 0 ;Distance Z from center of the body to the Right Middle coxa
- RROffsetX con -43 ;Distance X from center of the body to the Right Rear coxa
- RROffsetZ con 82 ;Distance Z from center of the body to the Right Rear coxa
- LFOffsetX con 43 ;Distance X from center of the body to the Left Front coxa
- LFOffsetZ con -82 ;Distance Z from center of the body to the Left Front coxa
- LMOffsetX con 63 ;Distance X from center of the body to the Left Middle coxa
- LMOffsetZ con 0 ;Distance Z from center of the body to the Left Middle coxa
- LROffsetX con 43 ;Distance X from center of the body to the Left Rear coxa
- LROffsetZ con 82 ;Distance Z from center of the body to the Left Rear coxa
- ;--------------------------------------------------------------------
- ;[REMOTE]
- TravelDeadZone con 4 ;The deadzone for the analog input from the remote
- ;====================================================================
- ;[ANGLES]
- RFCoxaAngle var sword ;Actual Angle of the Right Front Leg
- RFFemurAngle var sword
- RFTibiaAngle var sword
- RMCoxaAngle var sword ;Actual Angle of the Right Middle Leg
- RMFemurAngle var sword
- RMTibiaAngle var sword
- RRCoxaAngle var sword ;Actual Angle of the Right Rear Leg
- RRFemurAngle var sword
- RRTibiaAngle var sword
- LFCoxaAngle var sword ;Actual Angle of the Left Front Leg
- LFFemurAngle var sword
- LFTibiaAngle var sword
- LMCoxaAngle var sword ;Actual Angle of the Left Middle Leg
- LMFemurAngle var sword
- LMTibiaAngle var sword
- LRCoxaAngle var sword ;Actual Angle of the Left Rear Leg
- LRFemurAngle var sword
- LRTibiaAngle var sword
- ;--------------------------------------------------------------------
- ;[POSITIONS]
- RFPosX var sword ;Actual Position of the Right Front Leg
- RFPosY var sword
- RFPosZ var sword
- RMPosX var sword ;Actual Position of the Right Middle Leg
- RMPosY var sword
- RMPosZ var sword
- RRPosX var sword ;Actual Position of the Right Rear Leg
- RRPosY var sword
- RRPosZ var sword
- LFPosX var sword ;Actual Position of the Left Front Leg
- LFPosY var sword
- LFPosZ var sword
- LMPosX var sword ;Actual Position of the Left Middle Leg
- LMPosY var sword
- LMPosZ var sword
- LRPosX var sword ;Actual Position of the Left Rear Leg
- LRPosY var sword
- LRPosZ var sword
- ;--------------------------------------------------------------------
- ;[INPUTS]
- butA var bit
- butB var bit
- butC var bit
- prev_butA var bit
- prev_butB var bit
- prev_butC var bit
- ;--------------------------------------------------------------------
- ;[OUTPUTS]
- LedA var bit ;Red
- LedB var bit ;Green
- LedC var bit ;Orange
- ;--------------------------------------------------------------------
- ;[VARIABLES]
- Index var byte ;Index used for freeing the servos
- SSCDone var byte ;Char to check if SSC is done
- ;GetSinCos
- AngleDeg var float ;Input Angle in degrees
- ABSAngleDeg var float ;Absolute value of the Angle in Degrees
- AngleRad var float ;Angle in Radian
- sinA var float ;Output Sinus of the given Angle
- cosA var float ;Output Cosinus of the given Angle
- ;GetBoogTan
- BoogTanX var sword ;Input X
- BoogTanY var sword ;Input Y
- BoogTan var float ;Output BOOGTAN2(X/Y)
- ;Body position
- BodyPosX var sbyte ;Global Input for the position of the body
- BodyPosY var sword
- BodyPosZ var sbyte
- ;Body Inverse Kinematics
- BodyRotX var sbyte ;Global Input pitch of the body
- BodyRotY var sbyte ;Global Input rotation of the body
- BodyRotZ var sbyte ;Global Input roll of the body
- PosX var sword ;Input position of the feet X
- PosZ var sword ;Input position of the feet Z
- PosY var sword ;Input position of the feet Y
- RotationY var sbyte ;Input for rotation of a single feet for the gait
- BodyOffsetX var sbyte ;Input Offset betweeen the body and Coxa X
- BodyOffsetZ var sbyte ;Input Offset betweeen the body and Coxa Z
- sinB var float ;Sin buffer for BodyRotX calculations
- cosB var float ;Cos buffer for BodyRotX calculations
- sinG var float ;Sin buffer for BodyRotZ calculations
- cosG var float ;Cos buffer for BodyRotZ calculations
- TotalX var sword ;Total X distance between the center of the body and the feet
- TotalZ var sword ;Total Z distance between the center of the body and the feet
- DistCenterBodyFeet var float ;Total distance between the center of the body and the feet
- AngleCenterBodyFeetX var float ;Angle between the center of the body and the feet
- BodyIKPosX var sword ;Output Position X of feet with Rotation
- BodyIKPosY var sword ;Output Position Y of feet with Rotation
- BodyIKPosZ var sword ;Output Position Z of feet with Rotation
- ;Leg Inverse Kinematics
- IKFeetPosX var sword ;Input position of the Feet X
- IKFeetPosY var sword ;Input position of the Feet Y
- IKFeetPosZ var sword ;Input Position of the Feet Z
- IKFeetPosXZ var sword ;Length between the coxa and feet
- IKSW var float ;Length between shoulder and wrist
- IKA1 var float ;Angle between SW line and the ground in rad
- IKA2 var float ;?
- IKSolution var bit ;Output true if the solution is possible
- IKSolutionWarning var bit ;Output true if the solution is NEARLY possible
- IKSolutionError var bit ;Output true if the solution is NOT possible
- IKFemurAngle var sword ;Output Angle of Femur in degrees
- IKTibiaAngle var sword ;Output Angle of Tibia in degrees
- IKCoxaAngle var sword ;Output Angle of Coxa in degrees
- ;--------------------------------------------------------------------
- ;[RC Remote]
- Buttons var byte
- LastButtons var byte
- Alive var byte
- Mode var Nib ;ch5 Mode switch + twostate switch H = 6 modes
- TwoStateSW var bit ;ch 7 ,2-state switch
- ToogleMovement var bit
- Testleg var nib
- Whatleg var nib
- ;--------------------------------------------------------------------
- ;[TIMING]
- lTimerWOverflowCnt var long ;used in WTimer overflow. Will keep a 16 bit overflow so we have a 32 bit timer
- lCurrentTime var long
- lTimerStart var long ;Start time of the calculation cycles
- lTimerEnd var long ;End time of the calculation cycles
- CycleTime var byte ;Total Cycle time
- SSCTime var word ;Time for servo updates
- PrevSSCTime var word ;Previous time for the servo updates
- InputTimeDelay var Byte ;Delay that depends on the input to get the "sneaking" effect
- ;--------------------------------------------------------------------
- ;[GLOABAL]
- HexOn var bit ;Switch to turn on Phoenix
- TurnOff var bit ;Mark to turn off Phoenix
- ;--------------------------------------------------------------------
- ;[Balance]
- BalanceMode var bit
- TravelHeightY var sword
- TotalTransX var sword
- TotalTransZ var sword
- TotalTransY var sword
- TotalYbal var sword
- TotalXBal var sword
- TotalZBal var sword
- TotalY var sword ;Total Y distance between the center of the body and the feet
- ;[gait]
- GaitType var byte ;Gait type
- NomGaitSpeed var byte ;Nominal speed of the gait
- LegLiftHeight var byte ;Current Travel height
- TravelLengthX var sword ;Current Travel length X
- TravelLengthZ var sword ;Current Travel length Z
- TravelRotationY var sword ;Current Travel Rotation Y
- TLDivFactor var byte ;Number of steps that a leg is on the floor while walking
- NrLiftedPos var nib ;Number of positions that a single leg is lifted (1-3)
- HalfLiftHeigth var bit ;If TRUE the outer positions of the ligted legs will be half height
- GaitInMotion var bit ;Temp to check if the gait is in motion
- StepsInGait var byte ;Number of steps in gait
- LastLeg var bit ;TRUE when the current leg is the last leg of the sequence
- GaitStep var byte ;Actual Gait step
- RFGaitLegNr var byte ;Init position of the leg
- RMGaitLegNr var byte ;Init position of the leg
- RRGaitLegNr var byte ;Init position of the leg
- LFGaitLegNr var byte ;Init position of the leg
- LMGaitLegNr var byte ;Init position of the leg
- LRGaitLegNr var byte ;Init position of the leg
- GaitLegNr var byte ;Input Number of the leg
- TravelMulti var sbyte ;Multiplier for the length of the step
- RFGaitPosX var sbyte ;Relative position corresponding to the Gait
- RFGaitPosY var sbyte
- RFGaitPosZ var sbyte
- RFGaitRotY var sbyte ;Relative rotation corresponding to the Gait
- RMGaitPosX var sbyte
- RMGaitPosY var sbyte
- RMGaitPosZ var sbyte
- RMGaitRotY var sbyte
- RRGaitPosX var sbyte
- RRGaitPosY var sbyte
- RRGaitPosZ var sbyte
- RRGaitRotY var sbyte
- LFGaitPosX var sbyte
- LFGaitPosY var sbyte
- LFGaitPosZ var sbyte
- LFGaitRotY var sbyte
- LMGaitPosX var sbyte
- LMGaitPosY var sbyte
- LMGaitPosZ var sbyte
- LMGaitRotY var sbyte
- LRGaitPosX var sbyte
- LRGaitPosY var sbyte
- LRGaitPosZ var sbyte
- LRGaitRotY var sbyte
- GaitPosX var sbyte ;In-/Output Pos X of feet
- GaitPosY var sword ;In-/Output Pos Y of feet
- GaitPosZ var sbyte ;In-/Output Pos Z of feet
- GaitRotY var sbyte ;In-/Output Rotation Y of feet
- ;====================================================================
- ;[TIMER INTERRUPT INIT]
- ONASMINTERRUPT TIMERWINT, Handle_TIMERW
- ;====================================================================
- ;[INIT]
- ;Turning off all the leds
- LedA = 0
- LedB = 0
- LedC = 0
- 'Feet Positions
- RFPosX = 53 ;Start positions of the Right Front leg
- RFPosY = 25
- RFPosZ = -91
- RMPosX = 105 ;Start positions of the Right Middle leg
- RMPosY = 25
- RMPosZ = 0 ;was 0
- RRPosX = 53 ;Start positions of the Right Rear leg
- RRPosY = 25
- RRPosZ = 91
- LFPosX = 53 ;Start positions of the Left Front leg
- LFPosY = 25
- LFPosZ = -91
- LMPosX = 105 ;Start positions of the Left Middle leg
- LMPosY = 25
- LMPosZ = 0 ;was 0
- LRPosX = 53 ;Start positions of the Left Rear leg
- LRPosY = 25
- LRPosZ = 91
- ;Body Positions
- BodyPosX = 0
- BodyPosY = 0
- BodyPosZ = 0
- ;Body Rotations
- BodyRotX = 0
- BodyRotY = 0
- BodyRotZ = 0
- ;Gait
- GaitType = 0
- BalanceMode = 0
- LegLiftHeight = 50
- GaitStep = 1
- ;What leg is active variable 1-6
- Whatleg = 0
- GOSUB GaitSelect
- ;Timer
- WTIMERTICSPERMS con 2000; we have 16 clocks per ms and we are incrementing every 8 so divide again by 2
- TCRW = 0x30 ;clears TCNT and sets the timer to inc clock cycle / 8
- TMRW = 0x80 ;starts the timer counting
- lTimerWOverflowCnt = 0
- enable TIMERWINT_OVF
- ;SSC
- SSCTime = 150
- InputTimeDelay = 0
- Pause 1000
- ;====================================================================
- ;[MAIN]
- main:
- 'Start time
- GOSUB GetCurrentTime[], lTimerStart
- ;Read input
- GOSUB RCInput1
- 'Reset IKsolution indicators
- IKSolution = False
- IKSolutionWarning = False
- IKSolutionError = False
- ;Gait
- GOSUB GaitSeq
- ;Balance calculations
- TotalTransX = 0 'reset values used for calculation of balance
- TotalTransZ = 0
- TotalTransY = 0
- TotalXBal = 0
- TotalYBal = 0
- TotalZBal = 0
- IF (BalanceMode>0) THEN
- gosub BalCalcOneLeg [-RFPosX+BodyPosX+RFGaitPosX, RFPosZ+BodyPosZ+RFGaitPosZ,RFGaitPosY, RFOffsetX, RFOffsetZ]
- gosub BalCalcOneLeg [-RMPosX+BodyPosX+RMGaitPosX, RMPosZ+BodyPosZ+RMGaitPosZ,RMGaitPosY, RMOffsetX, RMOffsetZ]
- gosub BalCalcOneLeg [-RRPosX+BodyPosX+RRGaitPosX, RRPosZ+BodyPosZ+RRGaitPosZ,RRGaitPosY, RROffsetX, RROffsetZ]
- gosub BalCalcOneLeg [LFPosX-BodyPosX+LFGaitPosX, LFPosZ+BodyPosZ+LFGaitPosZ,LFGaitPosY, LFOffsetX, LFOffsetZ]
- gosub BalCalcOneLeg [LMPosX-BodyPosX+LMGaitPosX, LMPosZ+BodyPosZ+LMGaitPosZ,LMGaitPosY, LMOffsetX, LMOffsetZ]
- gosub BalCalcOneLeg [LRPosX-BodyPosX+LRGaitPosX, LRPosZ+BodyPosZ+LRGaitPosZ,LRGaitPosY, LROffsetX, LROffsetZ]
- gosub BalanceBody
- ENDIF
- 'Reset IKsolution indicators
- IKSolution = False
- IKSolutionWarning = False
- IKSolutionError = False
- ;Right Front leg
- GOSUB BodyIK [-RFPosX+BodyPosX+RFGaitPosX, RFPosZ+BodyPosZ+RFGaitPosZ,RFPosY+BodyPosY+RFGaitPosY, RFOffsetX, RFOffsetZ, RFGaitRotY]
- GOSUB LegIK [RFPosX-BodyPosX+BodyIKPosX-RFGaitPosX, RFPosY+BodyPosY-BodyIKPosY+RFGaitPosY, RFPosZ+BodyPosZ-BodyIKPosZ+RFGaitPosZ]
- RFCoxaAngle = IKCoxaAngle + CoxaAngle ;Angle for the basic setup for the front leg
- RFFemurAngle = IKFemurAngle
- RFTibiaAngle = IKTibiaAngle
- ;Right Middle leg
- GOSUB BodyIK [-RMPosX+BodyPosX+RMGaitPosX, RMPosZ+BodyPosZ+RMGaitPosZ,RMPosY+BodyPosY+RMGaitPosY, RMOffsetX, RMOffsetZ, RMGaitRotY]
- GOSUB LegIK [RMPosX-BodyPosX+BodyIKPosX-RMGaitPosX, RMPosY+BodyPosY-BodyIKPosY+RMGaitPosY, RMPosZ+BodyPosZ-BodyIKPosZ+RMGaitPosZ]
- RMCoxaAngle = IKCoxaAngle
- RMFemurAngle = IKFemurAngle
- RMTibiaAngle = IKTibiaAngle
- ;Right Rear leg
- GOSUB BodyIK [-RRPosX+BodyPosX+RRGaitPosX, RRPosZ+BodyPosZ+RRGaitPosZ,RRPosY+BodyPosY+RRGaitPosY, RROffsetX, RROffsetZ, RRGaitRotY]
- GOSUB LegIK [RRPosX-BodyPosX+BodyIKPosX-RRGaitPosX, RRPosY+BodyPosY-BodyIKPosY+RRGaitPosY, RRPosZ+BodyPosZ-BodyIKPosZ+RRGaitPosZ]
- RRCoxaAngle = IKCoxaAngle - CoxaAngle ;Angle for the basic setup for the front leg
- RRFemurAngle = IKFemurAngle
- RRTibiaAngle = IKTibiaAngle
- ;Left Front leg
- GOSUB BodyIK [LFPosX-BodyPosX+LFGaitPosX, LFPosZ+BodyPosZ+LFGaitPosZ,LFPosY+BodyPosY+LFGaitPosY, LFOffsetX, LFOffsetZ, LFGaitRotY]
- GOSUB LegIK [LFPosX+BodyPosX-BodyIKPosX+LFGaitPosX, LFPosY+BodyPosY-BodyIKPosY+LFGaitPosY, LFPosZ+BodyPosZ-BodyIKPosZ+LFGaitPosZ]
- LFCoxaAngle = IKCoxaAngle + CoxaAngle ;Angle for the basic setup for the front leg
- LFFemurAngle = IKFemurAngle
- LFTibiaAngle = IKTibiaAngle
- ;Left Middle leg
- GOSUB BodyIK [LMPosX-BodyPosX+LMGaitPosX, LMPosZ+BodyPosZ+LMGaitPosZ,LMPosY+BodyPosY+LMGaitPosY, LMOffsetX, LMOffsetZ, LMGaitRotY]
- GOSUB LegIK [LMPosX+BodyPosX-BodyIKPosX+LMGaitPosX, LMPosY+BodyPosY-BodyIKPosY+LMGaitPosY, LMPosZ+BodyPosZ-BodyIKPosZ+LMGaitPosZ]
- LMCoxaAngle = IKCoxaAngle
- LMFemurAngle = IKFemurAngle
- LMTibiaAngle = IKTibiaAngle
- ;Left Rear leg
- GOSUB BodyIK [LRPosX-BodyPosX+LRGaitPosX, LRPosZ+BodyPosZ+LRGaitPosZ,LRPosY+BodyPosY+LRGaitPosY, LROffsetX, LROffsetZ, LRGaitRotY]
- GOSUB LegIK [LRPosX+BodyPosX-BodyIKPosX+LRGaitPosX, LRPosY+BodyPosY-BodyIKPosY+LRGaitPosY, LRPosZ+BodyPosZ-BodyIKPosZ+LRGaitPosZ]
- LRCoxaAngle = IKCoxaAngle - CoxaAngle ;Angle for the basic setup for the front leg
- LRFemurAngle = IKFemurAngle
- LRTibiaAngle = IKTibiaAngle
- GOSUB CheckAngles
- LedC = IKSolutionWarning
- LedA = IKSolutionError
- ;Get endtime and calculate wait time
- GOSUB GetCurrentTime[], lTimerEnd
- CycleTime = (lTimerEnd-lTimerStart)/WTIMERTICSPERMS
- ;Wait for previous commands to be completed while walking
- IF(ABS(TravelLengthX)>TravelDeadZone | ABS(TravelLengthZ)>TravelDeadZone | ABS(TravelRotationY*2)>TravelDeadZone) THEN
- pause (PrevSSCTime - CycleTime -50) MIN 1 ; Min 1 ensures that there alway is a value in the pause command
- Else
- SSCTime = NomGaitSpeed + InputTimeDelay
- ENDIF
- GOSUB ServoDriver
- goto main
- ;====================================================================
- ;[RCInput] reads the input data from the RC-Remote and processes the
- ;data to the parameters.
- RCInput1:
- ;Read input pulse lengths in the correct order that take shortest time
- ;-------------------------------------------------------------------
- ; Make sure all 7 IOs are set to input.
- PMR5 = 0 ; all IO lines are general IO
- PCR5 = 0 ; All are input (may want to leave bit 7 alone...
- ; Ok now lets transisiton to assembly language.
- ;
- ; bMask = 0x7f ; set a mask of which bits we are needing...
- ; ; Mask could be 0xFE for pins 1-7, need to make array 8 not 7
- mov.b #0x7f, r1l ; Ok R1l will be our mask for outstanding IO port bytes.
- ; wait until none of the IO lines are high...
- ; while PDR5 & bMask
- ; ;
- ; wend
- mov.l #250000,er2 ;(4) - setup timeout counter
- _PI7_WAIT_FOR_ALL_LOW:
- mov.b @PDR5:8, r0l
- and.b r1l, r0l ; see if any of the IO bits is still on...
- beq _PI7_WAIT_FOR_NEXT_IO_TO_GO_HIGH:8 ; all zero go to wait for one to go high...
- dec.l #1,er2 ;(2)
- bne _PI7_WAIT_FOR_ALL_LOW:8 ; an IO pin is high and we have not timed out, keep looping until none are high
- ; We timed out waiting for all inputs to be low, so error out...
- bra _P17_RETURN_STATUS:16 ; will return status that all timed out...
- ; while bMask
- _PI7_WAIT_FOR_NEXT_IO_TO_GO_HIGH:
- mov.l #250000,er2 ;(4) - setup timeout counter
- _PI7_WAIT_FOR_NEXT_IO_TO_GO_HIGH2:
- ; we still need some 1 or more of the pulses...
- ; while (PDR5 & bMask) = 0 ; waiting for a pulse to go high.
- mov.b @PDR5:8, r0l ;(4)
- and.b r1l, r0l ;(*2) see if any of the IO bits is still on...
- bne _P17_IO_WENT_HIGH:8 ;(*4) One went high so go process
- dec.l #1,er2 ;(2)
- bne _PI7_WAIT_FOR_NEXT_IO_TO_GO_HIGH2:8 ; (4) Not a timeout go try again.
- ; we timed out...
- bra _P17_RETURN_STATUS:16 ; will return status of what timed out...
- ; wend
- ; iPin = ???; TBD: convert which bit is high to IO line number 0-6
- ; see which bit is on in the mask
- _P17_IO_WENT_HIGH:
- xor.w r2,r2 ;(*2)
- xor.b r0h, r0h ;(*2)
- mov.l #AWPULSESIN,er3 ;(*6)
- _P17_WHICH_BIT_LOOP:
- shlr.b r0l ;(@2)
- bcs _P17_WHICH_BIT_LOOP_DONE:8 ;(@4)
- inc.b r0h ;(@2)
- inc.l #2, er3 ;(@2) - point to the next place in the array.
- add.w #18,r2 ;(@4) - we do 18 clocks for each pass through this loop
- bra _P17_WHICH_BIT_LOOP:8 ;(@4)
- _P17_WHICH_BIT_LOOP_DONE:
- ; bMaskBit = 1 << iPin ; get the mask for which pin...
- xor.b r1h,r1h ;(*2)
- bset.b r0h,r1h ;(*2) ok we have the mask
- bclr.b r0h,r1l ;(*2) and clear it from our global mask of ones we are waiting for
- ; = (22) - count so far of clocks after went high
- ; iPinLoopCnt = 0 ; This may be replaced with time calculations...
- ; while (PDR5 & bMaskBit)
- ; iPinLoopCnt = iPinLoopCnt + 1 ; how long until it goes low again
- ; wend
- _P17_WAIT_FOR_IO_GO_BACK_LOW:
- mov.b @PDR5:8, r0l ;(#4)
- and.b r1h, r0l ;(#2)
- beq _P17_IO_WENT_BACK_LOW:8 ;(#4)
- add.w #18,r2 ;(#4) - number of cyles per loop
- bcc _P17_WAIT_FOR_IO_GO_BACK_LOW:8 ;(#4)
- ; we had a timeout return the status.
- bset.b r0h, r1l ; turn back on the bit we were waiting for...
- bra _P17_RETURN_STATUS:8 ;
- _P17_IO_WENT_BACK_LOW:
- ; need to calculate the pulse width in ms... need to divide calculated clocks by 16
- add.w #22,r2 ; (4) ; need to add the rest of the overhead(*-1 loop above) in...
- shlr.w r2 ; (2)
- shlr.w r2 ; (2)
- shlr.w r2 ; (2)
- shlr.w r2 ; (2) / 16 (for clock speed)
- ; aPulses(iPin) = iPinLoopCnt ; convert loop count to pulse width...
- mov.w r2,@er3 ; Save away the value
- ; bMask = bMask & ~bMaskBit ; turn off waiting for this one...
- or r1l,r1l ; (2) see if we are done or not
- ; wend
- bne _PI7_WAIT_FOR_NEXT_IO_TO_GO_HIGH:16 ;(6)our mask has not gone to zero so wait for the next one.
- _P17_RETURN_STATUS:
- mov.b r1l,@BPULSETIMEOUT
- ; finally transisition back to basic and return.
- ;--------------------------------------------------------------------
- ;serout S_OUT, i9600, ["SSCTime=", sdec Ssctime, " ","InputTimeDelay=", sdec InputTimeDelay," ",sdec RcInput(0), 13]
- BalanceMode = False
- if awPulsesIn(4) < 1100 then
- Mode = 1
- elseif (awPulsesIn(4) > 1400) & (awPulsesIn(4) < 1600)
- Mode = 2
- else
- Mode = 3
- endif
- if awPulsesIn(6) < 1500 then
- TwoStateSW = False
- else
- TwoStateSW = True
- endif
- ;InputTimeDelay = (ABS((RCInput(0)-1500)/4) MIN ABS(((RCInput(1)-1500)/4)) MIN ABS(((RCInput(2)-1500)/4)) MIN ABS(((RCInput(3)-1500)/4)))
- ;***********************************************************************************
- ;*** Walking mode, toogle between the different walking gait with 2-state button ***
- ;***********************************************************************************
- if Mode = 1 then
- BalanceMode = True
- if TwoStateSW then 'Toggle gait method:
- if GaitType < 7 then 'so far we have 8 gait methods
- GaitType = GaitType +1
- sound P9,[150\(800+(GaitType*100))]
- else
- GaitType = 0
- sound P9,[100\1900,150\2100]
- endif
- gosub GaitSelect
- endif
- BodyPosY = (awPulsesIn(5)-1000)/8
- TravelLengthX = (awPulsesIn(0)-1500)/4
- TravelLengthZ = (awPulsesIn(1)-1500)/4
- TravelRotationY = (awPulsesIn(3)-1500)/12
- ;***********************************************************************************
- ;*** Move mode, toogle between translating and rotating body with 2-state button ***
- ;***********************************************************************************
- elseif Mode = 2
- if TwoStateSw then 'Toogle movement method
- if ToogleMovement then
- ToogleMovement = False
- sound P9,[100\800,150\1800]
- else
- ToogleMovement = True
- sound P9,[100\1800,150\800]
- endif
- endif
- if ToogleMovement then
- 'Body translate:
- BodyPosX = -(awPulsesIn(0)-1500)/10
- BodyPosZ = -(awPulsesIn(1)-1500)/8
- BodyRotY = -(awPulsesIn(3)-1500)/20
- BodyPosY = (awPulsesIn(5)-1000)/8
- else
- 'Body rotate:
- BodyRotX = -(awPulsesIn(1)-1500)/20
- BodyRotY = -(awPulsesIn(3)-1500)/20
- BodyRotZ = (awPulsesIn(0)-1500)/20
- BodyPosY = (awPulsesIn(5)-1000)/8
- endif
- ;*************************************************************************************
- ;*** Individual leg control mode choose between 6 legs with 2-state button ***
- ;*************************************************************************************
- elseif Mode = 3
- BalanceMode = True
- ;GaitType = 2
- If awPulsesIn(6) > 1600 then
- Whatleg = Whatleg + 1
- elseif Whatleg > 7
- Whatleg = 1
- endif
- if whatleg = 1 then
- TestLeg = RFGaitLegNr
- TravelLengthX = (awPulsesIn(1)-1500)/5
- TravelLengthZ = (awPulsesIn(3)-1500)/4
- TravelHeightY = (awPulsesIn(2)-1500)/4
- Elseif whatleg = 2
- TestLeg = RMGaitLegNr
- TravelLengthX = (awPulsesIn(1)-1500)/4
- TravelLengthZ = (awPulsesIn(3)-1500)/4
- TravelHeightY = (awPulsesIn(2)-1500)/4
- Elseif whatleg = 3
- TestLeg = RRGaitLegNr
- TravelLengthX = (awPulsesIn(1)-1500)/5
- TravelLengthZ = (awPulsesIn(3)-1500)/4
- TravelHeightY = (awPulsesIn(2)-1500)/4
- Elseif whatleg = 4
- TestLeg = LRGaitLegNr
- TravelLengthX = (awPulsesIn(1)-1500)/5
- TravelLengthZ = (awPulsesIn(3)-1500)/4
- TravelHeightY = (awPulsesIn(2)-1500)/4
- Elseif whatleg = 5
- TestLeg = LMGaitLegNr
- TravelLengthX = (awPulsesIn(1)-1500)/4
- TravelLengthZ = (awPulsesIn(3)-1500)/4
- TravelHeightY = (awPulsesIn(2)-1500)/4
- Elseif whatleg = 6
- TestLeg = LFGaitLegNr
- TravelLengthX = (awPulsesIn(1)-1500)/5
- TravelLengthZ = (awPulsesIn(3)-1500)/4
- TravelHeightY = (awPulsesIn(2)-1500)/4
- Endif
- ;serout S_OUT, i9600, ["GaitPosX=", sdec GaitPosX," GaitPosY=", sdec GaitPosY," GaitPosZ=", sdec GaitPosZ, 13]
- ;serout S_OUT, i9600, ["Whatleg=", sdec Whatleg, 13]
- ENDIF
- return
- ;--------------------------------------------------------------------
- ;[GAIT Select]
- GaitSelect
- ;Gait selector
- IF (GaitType = 0) THEN ;Ripple Gait 6 steps
- LRGaitLegNr = 1
- RFGaitLegNr = 2
- LMGaitLegNr = 3
- RRGaitLegNr = 4
- LFGaitLegNr = 5
- RMGaitLegNr = 6
- NrLiftedPos = 1
- TLDivFactor = 4
- StepsInGait = 6
- NomGaitSpeed = 150
- ENDIF
- IF (GaitType = 1) THEN ;Ripple Gait 12 steps
- LRGaitLegNr = 1
- RFGaitLegNr = 3
- LMGaitLegNr = 5
- RRGaitLegNr = 7
- LFGaitLegNr = 9
- RMGaitLegNr = 11
- NrLiftedPos = 3
- HalfLiftHeigth = TRUE
- TLDivFactor = 8
- StepsInGait = 12
- NomGaitSpeed = 100
- ENDIF
- IF (GaitType = 2) THEN ;Quadripple 9 steps
- LRGaitLegNr = 1
- RFGaitLegNr = 2
- LMGaitLegNr = 4
- RRGaitLegNr = 5
- LFGaitLegNr = 7
- RMGaitLegNr = 8
- NrLiftedPos = 2
- HalfLiftHeigth = FALSE
- TLDivFactor = 6
- StepsInGait = 9
- NomGaitSpeed = 150
- ENDIF
- IF (GaitType = 3) THEN ;Tripod 4 steps
- LRGaitLegNr = 3
- RFGaitLegNr = 1
- LMGaitLegNr = 1
- RRGaitLegNr = 1
- LFGaitLegNr = 3
- RMGaitLegNr = 3
- NrLiftedPos = 1
- TLDivFactor = 2
- StepsInGait = 4
- NomGaitSpeed = 150
- ENDIF
- IF (GaitType = 4) THEN ;Tripod 6 steps
- LRGaitLegNr = 4
- RFGaitLegNr = 1
- LMGaitLegNr = 1
- RRGaitLegNr = 1
- LFGaitLegNr = 4
- RMGaitLegNr = 4
- NrLiftedPos = 2
- HalfLiftHeigth = FALSE
- TLDivFactor = 4
- StepsInGait = 6
- NomGaitSpeed = 150
- ENDIF
- IF (GaitType = 5) THEN ;Tripod 8 steps
- LRGaitLegNr = 5
- RFGaitLegNr = 1
- LMGaitLegNr = 1
- RRGaitLegNr = 1
- LFGaitLegNr = 5
- RMGaitLegNr = 5
- NrLiftedPos = 3
- HalfLiftHeigth = TRUE
- TLDivFactor = 4
- StepsInGait = 8
- NomGaitSpeed = 110
- ENDIF
- IF (GaitType = 6) THEN ;Wave 12 steps
- LRGaitLegNr = 7
- RFGaitLegNr = 1
- LMGaitLegNr = 9
- RRGaitLegNr = 5
- LFGaitLegNr = 11
- RMGaitLegNr = 3
- NrLiftedPos = 1
- HalfLiftHeigth = FALSE
- TLDivFactor = 10
- StepsInGait = 12
- NomGaitSpeed = 120
- ENDIF
- IF (GaitType = 7) THEN ;Wave 18 steps
- LRGaitLegNr = 10
- RFGaitLegNr = 1
- LMGaitLegNr = 13
- RRGaitLegNr = 7
- LFGaitLegNr = 16
- RMGaitLegNr = 4
- NrLiftedPos = 2
- HalfLiftHeigth = FALSE
- TLDivFactor = 16
- StepsInGait = 18
- NomGaitSpeed = 100
- ENDIF
- return
- ;--------------------------------------------------------------------
- ;[GAIT Sequence]
- GaitSeq
- ;Calculate Gait sequence
- LastLeg = FALSE
- GOSUB Gait [LRGaitLegNr, LRGaitPosX, LRGaitPosY, LRGaitPosZ, LRGaitRotY]
- LRGaitPosX = GaitPosX
- LRGaitPosY = GaitPosY
- LRGaitPosZ = GaitPosZ
- LRGaitRotY = GaitRotY
- GOSUB Gait [RFGaitLegNr, RFGaitPosX, RFGaitPosY, RFGaitPosZ, RFGaitRotY]
- RFGaitPosX = GaitPosX
- RFGaitPosY = GaitPosY
- RFGaitPosZ = GaitPosZ
- RFGaitRotY = GaitRotY
- GOSUB Gait [LMGaitLegNr, LMGaitPosX, LMGaitPosY, LMGaitPosZ, LMGaitRotY]
- LMGaitPosX = GaitPosX
- LMGaitPosY = GaitPosY
- LMGaitPosZ = GaitPosZ
- LMGaitRotY = GaitRotY
- GOSUB Gait [RRGaitLegNr, RRGaitPosX, RRGaitPosY, RRGaitPosZ, RRGaitRotY]
- RRGaitPosX = GaitPosX
- RRGaitPosY = GaitPosY
- RRGaitPosZ = GaitPosZ
- RRGaitRotY = GaitRotY
- GOSUB Gait [LFGaitLegNr, LFGaitPosX, LFGaitPosY, LFGaitPosZ, LFGaitRotY]
- LFGaitPosX = GaitPosX
- LFGaitPosY = GaitPosY
- LFGaitPosZ = GaitPosZ
- LFGaitRotY = GaitRotY
- LastLeg = TRUE
- GOSUB Gait [RMGaitLegNr, RMGaitPosX, RMGaitPosY, RMGaitPosZ, RMGaitRotY]
- RMGaitPosX = GaitPosX
- RMGaitPosY = GaitPosY
- RMGaitPosZ = GaitPosZ
- RMGaitRotY = GaitRotY
- return
- ;--------------------------------------------------------------------
- ;[GAIT]
- Gait [GaitLegNr, GaitPosX, GaitPosY, GaitPosZ, GaitRotY]
- IF Mode = 3 then
- IF TestLeg = GaitLegNr then
- GaitPosX = TravelLengthX
- GaitPosY = -TravelHeightY
- GaitPosZ = TravelLengthZ
- GaitRotY = 0
- ENDIF
- ELSE
- ;Check IF the Gait is in motion
- GaitInMotion = ((ABS(TravelLengthX)>TravelDeadZone) | (ABS(TravelLengthZ)>TravelDeadZone) | (ABS(TravelRotationY)>TravelDeadZone) )
- ;Leg middle up position
- ;Gait in motion Gait NOT in motion, return to home position
- IF (GaitInMotion & (NrLiftedPos=1 | NrLiftedPos=3) & GaitStep=GaitLegNr) | (GaitInMotion=FALSE & GaitStep=GaitLegNr & ((ABS(GaitPosX)>2) | (ABS(GaitPosZ)>2) | (ABS(GaitRotY)>2))) THEN ;Up
- GaitPosX = 0
- GaitPosY = -LegLiftHeight
- GaitPosZ = 0
- GaitRotY = 0
- ELSE
- ;Optional Half heigth Rear
- IF ((NrLiftedPos=2 & GaitStep=GaitLegNr) | (NrLiftedPos=3 & (GaitStep=GaitLegNr-1 | GaitStep=GaitLegNr+(StepsInGait-1)))) & GaitInMotion THEN
- GaitPosX = -TravelLengthX/2
- GaitPosY = -LegLiftHeight/(HalfLiftHeigth+1)
- GaitPosZ = -TravelLengthZ/2
- GaitRotY = -TravelRotationY/2
- ELSE
- ;Optional half heigth front
- IF (NrLiftedPos>=2) & (GaitStep=GaitLegNr+1 | GaitStep=GaitLegNr-(StepsInGait-1)) & GaitInMotion THEN
- GaitPosX = TravelLengthX/2
- GaitPosY = -LegLiftHeight/(HalfLiftHeigth+1)
- GaitPosZ = TravelLengthZ/2
- GaitRotY = TravelRotationY/2
- ELSE
- ;Leg front down position
- IF (GaitStep=GaitLegNr+NrLiftedPos | GaitStep=GaitLegNr-(StepsInGait-NrLiftedPos)) & GaitPosY<0 THEN
- GaitPosX = TravelLengthX/2
- GaitPosY = 0
- GaitPosZ = TravelLengthZ/2
- GaitRotY = TravelRotationY/2
- ;Move body forward
- ELSE
- GaitPosX = GaitPosX - (TravelLengthX/TLDivFactor)
- GaitPosY = 0
- GaitPosZ = GaitPosZ - (TravelLengthZ/TLDivFactor)
- GaitRotY = GaitRotY - (TravelRotationY/TLDivFactor)
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- Endif
- ;Advance to the next step
- IF LastLeg THEN ;The last leg in this step
- GaitStep = GaitStep+1
- IF GaitStep>StepsInGait THEN
- GaitStep = 1
- ENDIF
- ENDIF
- return
- ;--------------------------------------------------------------------
- ;[BalCalcOneLeg]
- BalCalcOneLeg [PosX, PosZ, PosY, BodyOffsetX, BodyOffsetZ]
- ;Calculating totals from center of the body to the feet
- TotalZ = BodyOffsetZ+PosZ
- TotalX = BodyOffsetX+PosX
- TotalY = 150 + PosY' using the value 150 to lower the centerpoint of rotation 'BodyPosY +
- TotalTransY = TotalTransY + PosY
- TotalTransZ = TotalTransZ + TotalZ
- TotalTransX = TotalTransX + TotalX
- gosub GetBoogTan [TotalX, TotalZ]
- TotalYbal = TotalYbal + TOINT((BoogTan*180.0) / 3.141592)
- gosub GetBoogTan [TotalX, TotalY]
- TotalZbal = TotalZbal + TOINT((BoogTan*180.0) / 3.141592)
- gosub GetBoogTan [TotalZ, TotalY]
- TotalXbal = TotalXbal + TOINT((BoogTan*180.0) / 3.141592)
- ;serout S_OUT, i9600, ["BalOneLeg PosX=", sdec PosX," PosZ=", sdec PosZ," TotalXTransZ=", sdec TotalTransZ, 13]
- return
- ;--------------------------------------------------------------------
- ;[BalanceBody]
- BalanceBody:
- TotalTransZ = TotalTransZ/6
- TotalTransX = TotalTransX/6
- TotalTransY = TotalTransY/6
- if TotalYbal < -180 then 'Tangens fix caused by +/- 180 deg
- TotalYbal = TotalYbal + 360
- endif
- if TotalZbal < -180 then 'Tangens fix caused by +/- 180 deg
- TotalZbal = TotalZbal + 360
- endif
- if TotalXbal < -180 then 'Tangens fix caused by +/- 180 deg
- TotalXbal = TotalXbal + 360
- endif
- ;Balance rotation
- TotalYBal = TotalYbal/6
- TotalXBal = TotalXbal/6
- TotalZBal = -TotalZbal/6
- ;Balance translation
- LFGaitPosZ = LFGaitPosZ - TotalTransZ
- LMGaitPosZ = LMGaitPosZ - TotalTransZ
- LRGaitPosZ = LRGaitPosZ - TotalTransZ
- RFGaitPosZ = RFGaitPosZ - TotalTransZ
- RMGaitPosZ = RMGaitPosZ - TotalTransZ
- RRGaitPosZ = RRGaitPosZ - TotalTransZ
- LFGaitPosX = LFGaitPosX - TotalTransX
- LMGaitPosX = LMGaitPosX - TotalTransX
- LRGaitPosX = LRGaitPosX - TotalTransX
- RFGaitPosX = RFGaitPosX - TotalTransX
- RMGaitPosX = RMGaitPosX - TotalTransX
- RRGaitPosX = RRGaitPosX - TotalTransX
- LFGaitPosY = LFGaitPosY - TotalTransY
- LMGaitPosY = LMGaitPosY - TotalTransY
- LRGaitPosY = LRGaitPosY - TotalTransY
- RFGaitPosY = RFGaitPosY - TotalTransY
- RMGaitPosY = RMGaitPosY - TotalTransY
- RRGaitPosY = RRGaitPosY - TotalTransY
- return
- ;--------------------------------------------------------------------
- ;[GETSINCOS] Get the sinus and cosinus from the angle +/- multiple circles
- ;AngleDeg - Input Angle in degrees
- ;SinA - Output Sinus of AngleDeg
- ;CosA - Output Cosinus of AngleDeg
- GetSinCos [AngleDeg]
- ;Get the absolute value of AngleDeg
- IF AngleDeg < 0.0 THEN
- ABSAngleDeg = AngleDeg *-1.0
- ELSE
- ABSAngleDeg = AngleDeg
- ENDIF
- ;Shift rotation to a full circle of 360 deg -> AngleDeg // 360
- IF AngleDeg < 0.0 THEN ;Negative values
- AngleDeg = 360.0-(ABSAngleDeg-TOFLOAT(360*(TOINT(ABSAngleDeg/360.0))))
- ELSE ;Positive values
- AngleDeg = ABSAngleDeg-TOFLOAT(360*(TOINT(ABSAngleDeg/360.0)))
- ENDIF
- IF AngleDeg < 180.0 THEN ;Angle between 0 and 180
- ;Subtract 90 to shift range
- AngleDeg = AngleDeg -90.0
- ;Convert degree to radials
- AngleRad = (AngleDeg*3.141592)/180.0
- SinA = FCOS(AngleRad) ;Sin o to 180 deg = cos(Angle Rad - 90deg)
- CosA = -FSIN(AngleRad) ;Cos 0 to 180 deg = -sin(Angle Rad - 90deg)
- ELSE ;Angle between 180 and 360
- ;Subtract 270 to shift range
- AngleDeg = AngleDeg -270.0
- ;Convert degree to radials
- AngleRad = (AngleDeg*3.141592)/180.0
- SinA = -FCOS(AngleRad) ;Sin 180 to 360 deg = -cos(Angle Rad - 270deg)
- CosA = FSIN(AngleRad) ;Cos 180 to 360 deg = sin(Angle Rad - 270deg)
- ENDIF
- return
- ;--------------------------------------------------------------------
- ;[BOOGTAN2] Gets the Inverse Tangus from X/Y with the where Y can be zero or negative
- ;BoogTanX - Input X
- ;BoogTanY - Input Y
- ;BoogTan - Output BOOGTAN2(X/Y)
- GetBoogTan [BoogTanX, BoogTanY]
- IF(BoogTanX = 0) THEN ; X=0 -> 0 or PI
- IF(BoogTanY >= 0) THEN
- BoogTan = 0.0
- ELSE
- BoogTan = 3.141592
- ENDIF
- ELSE
- IF(BoogTanY = 0) THEN ; Y=0 -> +/- Pi/2
- IF(BoogTanX > 0) THEN
- BoogTan = 3.141592 / 2.0
- ELSE
- BoogTan = -3.141592 / 2.0
- ENDIF
- ELSE
- IF(BoogTanY > 0) THEN ;BOOGTAN(X/Y)
- BoogTan = FATAN(TOFLOAT(BoogTanX) / TOFLOAT(BoogTanY))
- ELSE
- IF(BoogTanX > 0) THEN ;BOOGTAN(X/Y) + PI
- BoogTan = FATAN(TOFLOAT(BoogTanX) / TOFLOAT(BoogTanY)) + 3.141592
- ELSE ;BOOGTAN(X/Y) - PI
- BoogTan = FATAN(TOFLOAT(BoogTanX) / TOFLOAT(BoogTanY)) - 3.141592
- ENDIF
- ENDIF
- ENDIF
- ENDIF
- return
- ;--------------------------------------------------------------------
- ;[BODY INVERSE KINEMATICS]
- ;BodyRotX - Global Input pitch of the body
- ;BodyRotY - Global Input rotation of the body
- ;BodyRotZ - Global Input roll of the body
- ;RotationY - Input Rotation for the gait
- ;PosX - Input position of the feet X
- ;PosZ - Input position of the feet Z
- ;BodyOffsetX - Input Offset betweeen the body and Coxa X
- ;BodyOffsetZ - Input Offset betweeen the body and Coxa Z
- ;SinB - Sin buffer for BodyRotX
- ;CosB - Cos buffer for BodyRotX
- ;SinG - Sin buffer for BodyRotZ
- ;CosG - Cos buffer for BodyRotZ
- ;BodyIKPosX - Output Position X of feet with Rotation
- ;BodyIKPosY - Output Position Y of feet with Rotation
- ;BodyIKPosZ - Output Position Z of feet with Rotation
- BodyIK [PosX, PosZ, PosY, BodyOffsetX, BodyOffsetZ, RotationY]
- ;Calculating totals from center of the body to the feet
- TotalZ = BodyOffsetZ+PosZ
- TotalX = BodyOffsetX+PosX
- ;PosY are equal to a "TotalY"
- ;Successive global rotation matrix:
- ;Math shorts for rotation: Alfa (A) = Xrotate, Beta (B) = Zrotate, Gamma (G) = Yrotate
- ;Sinus Alfa = sinA, cosinus Alfa = cosA. and so on...
- ;First calculate sinus and cosinus for each rotation:
- GOSUB GetSinCos [TOFLOAT(BodyRotX+TotalXBal)]
- SinG = SinA
- CosG = CosA
- GOSUB GetSinCos [TOFLOAT(BodyRotZ+TotalZBal)]
- SinB = SinA
- CosB = CosA
- GOSUB GetSinCos [TOFLOAT(BodyRotY+RotationY+TotalYBal)]
- ;Calcualtion of rotation matrix:
- BodyIKPosX = TotalX-TOINT(TOFLOAT(TotalX)*CosA*CosB - TOFLOAT(TotalZ)*CosB*SinA + TOFLOAT(PosY)*SinB)
- BodyIKPosZ = TotalZ-TOINT(TOFLOAT(TotalX)*CosG*SinA + TOFLOAT(TotalX)*CosA*SinB*SinG +TOFLOAT(TotalZ)*CosA*CosG-TOFLOAT(TotalZ)*SinA*SinB*SinG-TOFLOAT(PosY)*CosB*SinG)
- BodyIKPosY = PosY - TOINT(TOFLOAT(TotalX)*SinA*SinG - TOFLOAT(TotalX)*CosA*CosG*SinB + TOFLOAT(TotalZ)*CosA*SinG + TOFLOAT(TotalZ)*CosG*SinA*SinB + TOFLOAT(PosY)*CosB*CosG)
- return
- ;--------------------------------------------------------------------
- ;[LEG INVERSE KINEMATICS] Calculates the angles of the tibia and femur for the given position of the feet
- ;IKFeetPosX - Input position of the Feet X
- ;IKFeetPosY - Input position of the Feet Y
- ;IKFeetPosZ - Input Position of the Feet Z
- ;IKSolution - Output true IF the solution is possible
- ;IKSolutionWarning - Output true IF the solution is NEARLY possible
- ;IKSolutionError - Output true IF the solution is NOT possible
- ;IKFemurAngle - Output Angle of Femur in degrees
- ;IKTibiaAngle - Output Angle of Tibia in degrees
- ;IKCoxaAngle - Output Angle of Coxa in degrees
- LegIK [IKFeetPosX, IKFeetPosY, IKFeetPosZ]
- ;Length between the Coxa and Feet
- IKFeetPosXZ = TOINT(FSQRT(TOFLOAT((IKFeetPosX*IKFeetPosX)+(IKFeetPosZ*IKFeetPosZ))))
- ;IKSW - Length between shoulder and wrist
- IKSW = FSQRT(TOFLOAT(((IKFeetPosXZ-CoxaLength)*(IKFeetPosXZ-CoxaLength))+(IKFeetPosY*IKFeetPosY)))
- ;IKA1 - Angle between SW line and the ground in rad
- GOSUB GetBoogTan [IKFeetPosXZ-CoxaLength, IKFeetPosY]
- IKA1 = BoogTan
- ;IKA2 - ?
- IKA2 = FACOS((TOFLOAT((FemurLength*FemurLength) - (TibiaLength*TibiaLength)) + (IKSW*IKSW)) / (TOFLOAT(2*Femurlength) * IKSW))
- ;IKFemurAngle
- IKFemurAngle = (TOINT(((IKA1 + IKA2) * 180.0) / 3.141592)*-1)+90
- ;IKTibiaAngle
- IKTibiaAngle = (90-TOINT(((FACOS((TOFLOAT((FemurLength*FemurLength) + (TibiaLength*TibiaLength)) - (IKSW*IKSW)) / TOFLOAT(2*Femurlength*TibiaLength)))*180.0) / 3.141592)) * -1
- ;IKCoxaAngle
- GOSUB GetBoogTan [IKFeetPosZ, IKFeetPosX]
- IKCoxaAngle = TOINT((BoogTan*180.0) / 3.141592)
- ;Set the Solution quality
- IF(IKSW < TOFLOAT(FemurLength+TibiaLength-30)) THEN
- IKSolution = TRUE
- ELSE
- IF(IKSW < TOFLOAT(FemurLength+TibiaLength)) THEN
- IKSolutionWarning = TRUE
- ELSE
- IKSolutionError = TRUE
- ENDIF
- ENDIF
- return
- ;--------------------------------------------------------------------
- ;[CHECK ANGLES] Checks the mechanical limits of the servos
- CheckAngles:
- RFCoxaAngle = (RFCoxaAngle min RFCoxa_MIN) max RFCoxa_MAX
- RFFemurAngle = (RFFemurAngle min RFFemur_MIN) max RFFemur_MAX
- RFTibiaAngle = (RFTibiaAngle min RFTibia_MIN) max RFTibia_MAX
- RMCoxaAngle = (RMCoxaAngle min RMCoxa_MIN) max RMCoxa_MAX
- RMFemurAngle = (RMFemurAngle min RMFemur_MIN) max RMFemur_MAX
- RMTibiaAngle = (RMTibiaAngle min RMTibia_MIN) max RMTibia_MAX
- RRCoxaAngle = (RRCoxaAngle min RRCoxa_MIN) max RRCoxa_MAX
- RRFemurAngle = (RRFemurAngle min RRFemur_MIN) max RRFemur_MAX
- RRTibiaAngle = (RRTibiaAngle min RRTibia_MIN) max RRTibia_MAX
- LFCoxaAngle = (LFCoxaAngle min LFCoxa_MIN) max LFCoxa_MAX
- LFFemurAngle = (LFFemurAngle min LFFemur_MIN) max LFFemur_MAX
- LFTibiaAngle = (LFTibiaAngle min LFTibia_MIN) max LFTibia_MAX
- LMCoxaAngle = (LMCoxaAngle min LMCoxa_MIN) max LMCoxa_MAX
- LMFemurAngle = (LMFemurAngle min LMFemur_MIN) max LMFemur_MAX
- LMTibiaAngle = (LMTibiaAngle min LMTibia_MIN) max LMTibia_MAX
- LRCoxaAngle = (LRCoxaAngle min LRCoxa_MIN) max LRCoxa_MAX
- LRFemurAngle = (LRFemurAngle min LRFemur_MIN) max LRFemur_MAX
- LRTibiaAngle = (LRTibiaAngle min LRTibia_MIN) max LRTibia_MAX
- return
- ;--------------------------------------------------------------------
- ;[SERVO DRIVER] Updates the positions of the servos
- ServoDriver:
- ;Front Right leg
- serout SSC_OUT,SSC_BAUTE,["#",dec RFCoxaPin,"P",dec TOINT(TOFLOAT(-RFCoxaAngle +90)/0.10588238)+650]
- serout SSC_OUT,SSC_BAUTE,["#",dec RFFemurPin,"P",dec TOINT(TOFLOAT(-RFFemurAngle+90)/0.10588238)+650]
- serout SSC_OUT,SSC_BAUTE,["#",dec RFTibiaPin,"P",dec TOINT(TOFLOAT(-RFTibiaAngle+90)/0.10588238)+650]
- ;Middle Right leg
- serout SSC_OUT,SSC_BAUTE,["#",dec RMCoxaPin,"P",dec TOINT(TOFLOAT(-RMCoxaAngle +90)/0.10588238)+650]
- serout SSC_OUT,SSC_BAUTE,["#",dec RMFemurPin,"P",dec TOINT(TOFLOAT(-RMFemurAngle+90)/0.10588238)+650]
- serout SSC_OUT,SSC_BAUTE,["#",dec RMTibiaPin,"P",dec TOINT(TOFLOAT(-RMTibiaAngle+90)/0.10588238)+650]
- ;Rear Right leg
- serout SSC_OUT,SSC_BAUTE,["#",dec RRCoxaPin,"P",dec TOINT(TOFLOAT(-RRCoxaAngle +90)/0.10588238)+650]
- serout SSC_OUT,SSC_BAUTE,["#",dec RRFemurPin,"P",dec TOINT(TOFLOAT(-RRFemurAngle+90)/0.10588238)+650]
- serout SSC_OUT,SSC_BAUTE,["#",dec RRTibiaPin,"P",dec TOINT(TOFLOAT(-RRTibiaAngle+90)/0.10588238)+650]
- ;Front Left leg
- serout SSC_OUT,SSC_BAUTE,["#",dec LFCoxaPin,"P",dec TOINT(TOFLOAT(LFCoxaAngle +90)/0.10588238)+650]
- serout SSC_OUT,SSC_BAUTE,["#",dec LFFemurPin,"P",dec TOINT(TOFLOAT(LFFemurAngle+90)/0.10588238)+650]
- serout SSC_OUT,SSC_BAUTE,["#",dec LFTibiaPin ,"P",dec TOINT(TOFLOAT(LFTibiaAngle+90)/0.10588238)+650]
- ;Middle Left leg
- serout SSC_OUT,SSC_BAUTE,["#",dec LMCoxaPin,"P",dec TOINT(TOFLOAT(LMCoxaAngle +90)/0.10588238)+650]
- serout SSC_OUT,SSC_BAUTE,["#",dec LMFemurPin,"P",dec TOINT(TOFLOAT(LMFemurAngle+90)/0.10588238)+650]
- serout SSC_OUT,SSC_BAUTE,["#",dec LMTibiaPin,"P",dec TOINT(TOFLOAT(LMTibiaAngle+90)/0.10588238)+650]
- ;Rear Left leg
- serout SSC_OUT,SSC_BAUTE,["#",dec LRCoxaPin,"P",dec TOINT(TOFLOAT(LRCoxaAngle +90)/0.10588238)+650]
- serout SSC_OUT,SSC_BAUTE,["#",dec LRFemurPin,"P",dec TOINT(TOFLOAT(LRFemurAngle+90)/0.10588238)+650]
- serout SSC_OUT,SSC_BAUTE,["#",dec LRTibiaPin,"P",dec TOINT(TOFLOAT(LRTibiaAngle+90)/0.10588238)+650]
- ;Send <CR>
- serout SSC_OUT,SSC_BAUTE,["T",dec SSCTime,13]
- PrevSSCTime = SSCTime
- return
- ;--------------------------------------------------------------------
- ;[FREE SERVOS] Frees all the servos
- FreeServos
- for Index = 0 to 31
- serout SSC_OUT,SSC_BAUTE,["#",DEC Index,"P0"]
- next
- serout SSC_OUT,SSC_BAUTE,["T200",13]
- return
- ;-----------------------------------------------------------------------------------
- ;[Handle TimerW interrupt]
- BEGINASMSUB
- HANDLE_TIMERW
- push.w r1 ; save away register we will use
- bclr #7,@TSRW:8 ; clear the overflow bit in the Timer status word
- mov.w @LTIMERWOVERFLOWCNT+1:16,r1 ; We will increment the word that is the highword for a clock timer
- inc.w #1,r1
- mov.w r1, @LTIMERWOVERFLOWCNT+1:16
- pop.w r1 ; restore our registers
- rte ; and return
- return
- ;-------------------------------------------------------------------------------------
- ;[Simple function to get the current time and verify that no overflow happened]
- GetCurrentTime
- lCurrentTime = lTimerWoverflowCnt + TCNT ; calculate the timer
- IF lCurrentTime.highword <> lTimerWOverflowcnt.highword THEN
- lCurrentTime = lTimerWoverflowCnt + TCNT ; calculate the timer
- ENDIF
- return lCurrentTIme
- ;----------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment