Xan and Zenta's code for RC Pheonix and 7TC remote

Hey guys,

So Zenta had pretty much convinced me to buy the T7C heli transmitter and receiver, anyway very cool remote, it’s too bad that the remote cant use more switches at once as when used as 4 switches become dead when only configured for this type of usage…

I guess all the other channels are used for mixing… I do not own a heli or a plane so I don’t know… Anyway down to business.

Zenta has shared with me this code that was originally made by "Xan and numerous other people who chipped in "allows me to use the un modified T7C transmitter “7 Channel” for controlling the phoenix with bb2 and ssc32 basically the configuration is as follows

Left stick Horizontal = phoenix turns on its Z axis
Left stick Vertical = Raises and lowers Phoenix

Right stick Vertical = moves phoenix forward
Right stick Horizontal = Moves phoenix left and right

Channel 5:
3 state switch controls which mode the pheonix is in
mode 1: walk mode
mode 2: not walk mode but stands still and allows you to rotate and yaw and pitch while legs are locked to the ground
mode 3: GPmode plays sequences if you have the extra eeprom chip in the ssc32 for pre programmed moves and such.

channel 6:
VR pot that controls how fast the gait is executed
900-2100 output 900 being slow 2100 being max… "My opinion I don’t think this is really necessary as you should be able to simply use the right vertical stick to control the speed of the phoenix…but that’s just me…

Channel 7 is a momentary 2 state switch it is either at around 900 or 2100 decimal out via when read by the pulsin command “1500 is centered and this switch will never see 1500 value out on channel 7”

when in mode 1, pressing channel 7 will change gait type.
when in mode 2, pressing channel 7 will change something I forget but there are only 2 modes.

when in mode 3, this also does something “I do not have the eeprom chip in my ssc32 to be able to tell what it does although this is commented in the code quite a lot!”

So what I have done with this code is cannibalized mode 3 the original code has been commented out with ; the things I have commented out have two ;; so you can tell what I have done.

The goal of me hacking up his code is to want individual control of a leg for remote tentacle action per say… zenta had modified the ps2 remote code so RC could be used here is a video of him using his remote and showing it off
youtube.com/watch?v=72MY5GuHSpA

Anyway to activate this you would put the switch in state 3 and the robot would be stopped and moving the right analog stick one leg would be RC control and the code would just loop though controlling those 3 servos and the remaining 5 legs would be stuck to the ground.

In zenta’s video he is in mode 2 to make the phoenix lean backwards then went to mode 3 to get individual leg control propped up that leg onto the boxes and then switched back to mode 2 and wiggled a bit to let people know that that leg is locked in 3D space "as you can tell the plastic boxes don’t slide around when he tessellates the phoenix.

After that leg control is accomplished I would really like using that channel 7 momentary switch when in mode 3 “individual leg control” to change which of the 6 feet would be individually controlled.

the idea is to try and cram a lot of features use full or not into this robot without having to have the end user modify his transmitter.

I managed to find an 8 State rotary dial that stacking the correct resistors “zenta used 150 Ohm ones” you should be able to take the channel 6 VR pot and switch it on and off so that you have 8 roughly stable values when read with the pulsin command on channel 6. I still feel with the OEM setup a 3 state switch on channel 5 and a 2 state momentary on channel 7 you can program in an awfull lot of features without having to tear open your transmitter “No offense zenta” I love taking things apart like the rest of the gang :slight_smile:

with that part said above here is the problem I face.

Using the original code Zenta has provided me is special code he wrote for someone on the other tossin robotics forum to use the T7C but not modified like his controller preciously which code I would like to start with after playing with this code I realized that mode3 which was GP player completely crashed the BB2 and it had to be reset after some looking into it zenta had mentioned to me I needed to pick up an eeprom for that socket in the ssc32… well frankly this feature didn’t really fancy my taste buds and I wanted to do the individual leg control as I explained above so I decided to remove this code and use mode 3 for that.

When I had cannibalized his code I could no longer raise and lower the phoenix channel 3 was un responsive and I really had no idea why.

I have a feeling its something very very easy that I am missing, but it has to do with nested loops that I have a hard time keeping track of “I’m sure every programmer does” anyway enough of me babbling here is zenta’s orignal code untouched by me.

;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 GP player mode with the 3-state switch
;Use the two-state switch to toogle between the different gaits, movement or GPsequences
;In GPMode start GP player by moving the right stick upwards
;
;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 P11      ;Output pin for (SSC32 RX) on BotBoard (Yellow)
SSC_IN       con P10      ;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)

;--------------------------------------------------------------------
;[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
 
#ELSE ;Connector to the back
  RFCoxaPin    con P2   ;Front Right leg Hip Horizontal
  RFFemurPin    con P1   ;Front Right leg Hip Vertical
  RFTibiaPin     con P0   ;Front Right leg Knee

  RMCoxaPin    con P6   ;Middle Right leg Hip Horizontal
  RMFemurPin    con P5   ;Middle Right leg Hip Vertical
  RMTibiaPin     con P4   ;Middle Right leg Knee

  RRCoxaPin    con P10   ;Rear Right leg Hip Horizontal
  RRFemurPin    con P9   ;Rear Right leg Hip Vertical
  RRTibiaPin     con P8   ;Rear Right leg Knee

  LFCoxaPin    con P18   ;Front Left leg Hip Horizontal
  LFFemurPin    con P17   ;Front Left leg Hip Vertical
  LFTibiaPin     con P16   ;Front Left leg Knee

  LMCoxaPin    con P22   ;Middle Left leg Hip Horizontal
  LMFemurPin    con P21   ;Middle Left leg Hip Vertical
  LMTibiaPin     con P20   ;Middle Left leg Knee

  LRCoxaPin    con P26   ;Rear Left leg Hip Horizontal
  LRFemurPin    con P25   ;Rear Left leg Hip Vertical
  LRTibiaPin     con P24   ;Rear Left leg Knee
#ENDIF
;--------------------------------------------------------------------
;[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 113;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
;--------------------------------------------------------------------
;[GP player]
GPByte0      var Byte
GPByte1      var Byte
GPByte2      var Byte
GPByte3      var Byte
GPIsPlaying var bit
GPSeqToBePlayed var Byte
GPoccupied   var bit
GPLastStep   var Byte
GPSpeed      var Byte
GPCounter   var byte
;--------------------------------------------------------------------
;[RC Remote]
RCInput    var word(7)
Buttons      var byte
LastButtons   var byte
StickMode   var nib
Alive      var byte
WalkMode         var bit   ;ch5 Mode switch (Switch E on Futaba T7C H)
MoveMode         var bit
GPModeON         var bit
TwoStateSW         var bit ;ch 7 ,2-state switch
ToogleMovement      var bit
;--------------------------------------------------------------------
;[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

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

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

;GP mode
GPIsPlaying = FALSE
GPoccupied = TRUE

;Gait
GaitType = 0
BalanceMode = 0
LegLiftHeight = 50
GaitStep = 1
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
HexOn = True 'KÃ¥re turned it on..
;====================================================================
;[MAIN]   
main:
  'Start time
  GOSUB GetCurrentTime], lTimerStart
  ;Read input
  GOSUB RCInput1
 
  'Check if we are in GPMode
  if (GPModeON OR GPIsPlaying) = FALSE then
 
  '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
 
  serout s_out, i38400, [dec HexOn, " ", sdec bodyposy, " "]
       
  IF(HexOn)THEN
   ;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
     
      IF(BalanceMode=0)THEN
        SSCTime = NomGaitSpeed + (InputTimeDelay*2)
     ELSE
        SSCTime = NomGaitSpeed + (InputTimeDelay*2) + 100
     ENDIF
    
   ELSE
     SSCTime = 200 ;NomGaitSpeed
     ENDIF
     
   GOSUB ServoDriver
 
    ;Turn the bot off
    IF TurnOff THEN
      ;pause 200
      ;GOSUB FreeServos 
     HexOn=FALSE
   ENDIF
  ENDIF   
 
  'We are in GPMode:
  else
     gosub GPPlayer
     pause 60
  endif
 
  'serout s_out, i38400, [sdec bodyposy, 13] 
     
goto main
;====================================================================
;[ReadButtons] Reading input buttons from the ABB
ReadButtons:
  input P4
  input P5
  input P6
   
  prev_butA = butA
  prev_butB = butB
  prev_butC = butC
   
  butA = IN4
  butB = IN5
  butC = IN6
return
;--------------------------------------------------------------------
;[WriteLEDs] Updates the state of the leds
WriteLEDs:
  if ledA = 1 THEN
   low p4
  ENDIF
  if ledB = 1 THEN
   low p5
  ENDIF
  if ledC = 1 THEN
   low p6
  ENDIF
return
;--------------------------------------------------------------------
;[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
  PULSIN RCCh0, 0, RCInput(0)
  PULSIN RCCh2, 0, RCInput(2)
  PULSIN RCCh4, 0, RCInput(4)
  PULSIN RCCh5, 0, RCInput(5)
 
  PULSIN RCCh1, 0, RCInput(1)
  PULSIN RCCh3, 0, RCInput(3)
  PULSIN RCCh6, 0, RCInput(6)
 
 
     WalkMode = False
   MoveMode = False
   GPModeON = False
   BalanceMode = False
   if RCInput(4) < 1100 then
      WalkMode = True
   elseif ((RCInput(4) > 1400) & (RCInput(4) < 1600))
      MoveMode = True
   else
      GPModeON = True
   endif
   
   if RCInput(6) < 1500 then
      TwoStateSW = False
   else
      TwoStateSW = True
   endif
   
   
   ;***********************************************************************************
   ;*** Walking mode, toogle between the different walking gait with 2-state button ***
   ;***********************************************************************************
   if WalkMode then
      if RCInput(5) < 1750 then 'Select BalanceMode with VR-pot at slower speed
         BalanceMode = TRUE
      else
         BalanceMode = FALSE
      endif
      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
      TravelLengthX = (RCInput(0)-1500)/4
        TravelLengthZ = (RCInput(1)-1500)/4
        TravelRotationY = (RCInput(3)-1500)/12
      
   ;***********************************************************************************
   ;*** Move mode, toogle between translating and rotating body with 2-state button ***
   ;***********************************************************************************
   elseif MoveMode
      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 = -(RCInput(0)-1500)/10
           BodyPosZ = -(RCInput(1)-1500)/8
           BodyRotY = -(RCInput(3)-1500)/20
        else
           'Body rotate:
           BodyRotX = -(RCInput(1)-1500)/20
           BodyRotY = -(RCInput(3)-1500)/20
           BodyRotZ = (RCInput(0)-1500)/20
        endif   
   
   
   ;*************************************************************************************
   ;*** GP sequencer player mode choose between two different seq with 2-state button ***
   ;*************************************************************************************
   elseif GPModeON
      'GPoccupied = TRUE    
      if TwoStateSW then   'Use 2-state switch to toogle between every sequence      
         if GPIsPlaying = FALSE then
               if GPSeqToBePlayed < 2 then
                  GPSeqToBePlayed = GPSeqToBePlayed +1
               else            
                  GPSeqToBePlayed = 0   'Selected GP sequence
               endif
               for GPCounter = 0 to GPSeqToBePlayed ' number of beeps = Sequence number to be played
                  pause 150
                  sound P9,[70\1200]
               next            
         endif               
      endif
      if RCInput(1) < 1400 then 'Start GP player by moving the right stick upwards
         GPoccupied = FALSE
         sound P9,[30\800,30\1000,30\1200,30\1400]
      endif
      GPSpeed = 100   
   
   endif
   
   BodyPosY = (RCInput(2)-1000)/8 'adjust body height

   ;Calculate walking time delay
   InputTimeDelay = 128 - (ABS((RCInput(1)-1500)/4) MIN ABS(((RCInput(0)-1500)/4))) MIN ABS(((RCInput(3)-1500)/6)) + (128 -(RCInput(5)-1010)/8)
   
  '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]

  ;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
   
  ;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
;--------------------------------------------------------------------
;GP player
GPPlayer

if (GPIsPlaying = FALSE) & (GPoccupied = FALSE) then
        serout SSC_OUT,SSC_BAUTE,"PL0 SQ", dec GPSeqToBePlayed, " SM" , dec GPSpeed, " IX0 PA0 ONCE",13]
        GPIsPlaying = TRUE
        GPoccupied = TRUE   'This inhibit the player to play the same sequence several times
else
  serout SSC_OUT,SSC_BAUTE,"QPL0",13]
  serin  SSC_IN, SSC_BAUTE,[GPByte0,GPByte1,GPByte2,GPByte3]
  ;debug:
  'serout S_OUT, i9600, "SQPlayed: ",dec GPByte0," IX: ", dec GPByte2," -> ",dec GPByte1," Remaining time: ",dec GPByte3, 13]
     
  IF GPByte0 = 255 THEN
      GPIsPlaying = FALSE
  endif
endif
return
;----------------------------------------------------------------------------------- 

This is the part I am concerned with and would like to replace GP player with my own code

 ;*************************************************************************************
   ;*** GP sequencer player mode choose between two different seq with 2-state button ***
   ;*************************************************************************************
   elseif GPModeON
      'GPoccupied = TRUE    
      if TwoStateSW then   'Use 2-state switch to toogle between every sequence      
         if GPIsPlaying = FALSE then
               if GPSeqToBePlayed < 2 then
                  GPSeqToBePlayed = GPSeqToBePlayed +1
               else            
                  GPSeqToBePlayed = 0   'Selected GP sequence
               endif
               for GPCounter = 0 to GPSeqToBePlayed ' number of beeps = Sequence number to be played
                  pause 150
                  sound P9,[70\1200]
               next            
         endif               
      endif
      if RCInput(1) < 1400 then 'Start GP player by moving the right stick upwards
         GPoccupied = FALSE
         sound P9,[30\800,30\1000,30\1200,30\1400]
      endif
      GPSpeed = 100   
   
   endif
   
   BodyPosY = (RCInput(2)-1000)/8 'adjust body height

   ;Calculate walking time delay
   InputTimeDelay = 128 - (ABS((RCInput(1)-1500)/4) MIN ABS(((RCInput(0)-1500)/4))) MIN ABS(((RCInput(3)-1500)/6)) + (128 -(RCInput(5)-1010)/8)
   
  'ENDIF 

And then this is what I did to it, notice I have commented things out with double ;; zenta’s work is only commented out with 1 ;

   ;*************************************************************************************
   ;*** GP sequencer player mode choose between two different seq with 2-state button ***
   ;*************************************************************************************
   elseif GPModeON
      'GPoccupied = TRUE    
      ;if TwoStateSW then   'Use 2-state switch to toogle between every sequence      
         ;;if GPIsPlaying = FALSE then
               ;;if GPSeqToBePlayed < 2 then
                  ;;GPSeqToBePlayed = GPSeqToBePlayed +1
               ;;else            
                  ;;GPSeqToBePlayed = 0   'Selected GP sequence
               ;;endif
              ;;for GPCounter = 0 to GPSeqToBePlayed ' number of beeps = Sequence number to be played
                  ;;pause 150
                  sound P9,[70\1200]
               ;;next            
         ;;endif               
      ;;endif
      ;;if RCInput(1) < 1400 then 'Start GP player by moving the right stick upwards
         ;;GPoccupied = FALSE
         ;;sound P9,[30\800,30\1000,30\1200,30\1400]
      ;;endif
      ;;GPSpeed = 100   
   
   ;;endif
   
   ;;BodyPosY = (RCInput(2)-1000)/8 'adjust body height

   ;Calculate walking time delay
   ;;InputTimeDelay = 128 - (ABS((RCInput(1)-1500)/4) MIN ABS(((RCInput(0)-1500)/4))) MIN ABS(((RCInput(3)-1500)/6)) + (128 -(RCInput(5)-910)/8)
   
  ENDIF
 
return  

so Zenta had sent me a PM to assist me in trying to figure out why this doesn’t work and told me that in the main loop of the code comment out these two pieces of code

'Check if we are in GPMode
  if (GPModeON OR GPIsPlaying) = FALSE then 

and

'We are in GPMode:
  else
     gosub GPPlayer
     pause 60
  endif

Ok so Ive done this and Still I can’t raise and lower my phoenix

How’s that for the longest post in thread history!

anyway let me know what you guys think.

–Aaron

Ok, before I continue to help you with the code I’ll again point out that this is Xan’s v1.3 code, not mine. I just modified the RC part and added a GP player mode for Harry Mueller for his article to the Robot Magazine.

I’ve tried to help you out with several PM’s but as for many of us I’ve limited time for everything…

my mistake.

I guess anytime someone modifies someones code I would always consult the person who modified it when there was an issue with it with at least the feature they have changed… I think that’s fair in saying that…

I guess since yourself and Xan have worked on this together I probably should have explained it as Xan and Zenta’s code rather then just yours. I know you two individuals are thought of as very smart people here when it comes to programming.

–Aaron

Hi everybody… I think the longer I stare at this code the more it’s all starting to come together in my head “sorta”

I think the thing that delays my learning ability is the nested If statements I don’t know when If statements end and get out of the if routine… I remember seeing in some other programming language they had some method of highlighting or coloring code blocks so you can quickly know what’s inside or outside a loop… does anyone know what I’m talking about? a side note anyway…

;[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
  PULSIN RCCh0, 0, RCInput(0)
  PULSIN RCCh2, 0, RCInput(2)
  PULSIN RCCh4, 0, RCInput(4)
  PULSIN RCCh5, 0, RCInput(5)
 
  PULSIN RCCh1, 0, RCInput(1)
  PULSIN RCCh3, 0, RCInput(3)
  PULSIN RCCh6, 0, RCInput(6)
 
 
     WalkMode = False
   MoveMode = False
   GPModeON = False
   BalanceMode = False
   if RCInput(4) < 1100 then
      WalkMode = True
   elseif ((RCInput(4) > 1400) & (RCInput(4) < 1600))
      MoveMode = True
   else
      GPModeON = True
   endif
   
   if RCInput(6) < 1500 then
      TwoStateSW = False
   else
      TwoStateSW = True
   endif
   
   
   ;***********************************************************************************
   ;*** Walking mode, toogle between the different walking gait with 2-state button ***
   ;***********************************************************************************
   if WalkMode then
      if RCInput(5) < 1750 then 'Select BalanceMode with VR-pot at slower speed
         BalanceMode = TRUE
      else
         BalanceMode = FALSE
      endif
      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
      TravelLengthX = (RCInput(0)-1500)/4
        TravelLengthZ = (RCInput(1)-1500)/4
        TravelRotationY = (RCInput(3)-1500)/12
      
   ;***********************************************************************************
   ;*** Move mode, toogle between translating and rotating body with 2-state button ***
   ;***********************************************************************************
   elseif MoveMode
      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 = -(RCInput(0)-1500)/10
           BodyPosZ = -(RCInput(1)-1500)/8
           BodyRotY = -(RCInput(3)-1500)/20
        else
           'Body rotate:
           BodyRotX = -(RCInput(1)-1500)/20
           BodyRotY = -(RCInput(3)-1500)/20
           BodyRotZ = (RCInput(0)-1500)/20
        endif   
   
   
   ;*************************************************************************************
   ;*** GP sequencer player mode choose between two different seq with 2-state button ***
   ;*************************************************************************************
   elseif GPModeON
      'GPoccupied = TRUE    
      ;if TwoStateSW then   'Use 2-state switch to toogle between every sequence      
         ;;if GPIsPlaying = FALSE then
               ;;if GPSeqToBePlayed < 2 then
                  ;;GPSeqToBePlayed = GPSeqToBePlayed +1
               ;;else            
                  ;;GPSeqToBePlayed = 0   'Selected GP sequence
               ;;endif
              ;;for GPCounter = 0 to GPSeqToBePlayed ' number of beeps = Sequence number to be played
                  ;;pause 150
                  sound P9,[70\1200]
               ;;next            
         ;;endif               
      ;;endif
      ;;if RCInput(1) < 1400 then 'Start GP player by moving the right stick upwards
         ;;GPoccupied = FALSE
         ;;sound P9,[30\800,30\1000,30\1200,30\1400]
      ;;endif
      ;;GPSpeed = 100   
   
   ;;endif
   
   BodyPosY = (RCInput(2)-1000)/8 'adjust body height

   ;Calculate walking time delay
   ;;InputTimeDelay = 128 - (ABS((RCInput(1)-1500)/4) MIN ABS(((RCInput(0)-1500)/4))) MIN ABS(((RCInput(3)-1500)/6)) + (128 -(RCInput(5)-910)/8)
   
  ENDIF
 
return   

Cool, so I figured out how to break the code “in a good way…at least with the idea I have” so that it works correctly…scratch that… works better then before I started this brainteaser.

so the code above I can’t seem to figure out why I can’t adjust body height while in walkmode now and Since I hadn’t removed any code from within the inside of the walkmode code block I wasnt sure how it worked originally ??? “scratches head”

so now the only place I can adjust phoenix Height is if I have the phoenix in mode 3 the mode I have intentionally broke to put a different phoenix feature inside “Individual leg control”

Since I am still heavily learning or at least attempting to I was curious if I would simply put this line of code

BodyPosY = (RCInput(2)-1000)/8 'adjust body height

into all 3 mode’s in which I would like to adjust Height of the robot? I’m going to be a nerd and answer my own question and say probably so… But the thing I would like to avoid is putting the same snippet of code in multiple spots if there is a better way of doing this? I’m not sure if I should jump out of the if block of code to a line that says “BodyPosY = (RCInput(2)-1000)/8” then jump back into the code, or simply just deal with it and put that code block inside all 3 modes?? Choices choices…

This line of code here

InputTimeDelay = 128 - (ABS((RCInput(1)-1500)/4) MIN ABS(((RCInput(0)-1500)/4))) MIN ABS(((RCInput(3)-1500)/6)) + (128 -(RCInput(5)-910)/8)

I have commented this out and was unsure of what it actually does?

I know its storing the Absolute values of the stick positions when they are either more or less then 1500 but as for what that variable actually does in the code is a bit beyond me…

I had a idea about the VR pot and I had noticed it in both this code and the ps2 remote code with the L2 button “for double gait speed”… I guess I’m not sure how to word this but I’ll do the best I can at describing what I’m thinking here…

When the Vr pot is at the value 2100 “or fully turned right” the phoenix walks fast and when the value is 900 or all the way turned left the phoenix walks slow… so I was kinda wondering what would happen if the VR pot channel was eliminated and the value of which ever direction the robot was going was stored in a variable to the value of the VR pot so you move the stick slightly forward and the gait would be moving slow at a slow speed, then you move the stick full forward and the gait would be fast at the maximum step “this would free up the usage of the VR pot dial for something else”

I’m guessing you would probably have to make a variable taking into account all 4 stick inputs and figuring out which one of those values has the highest absolute value after subtracting 1500 ?? that sound right?

to be honest I have no idea why I would eliminate the VR pot since when I’m harassing the pets with my spider its usually all the way full right? “for max speed” … Not sure what I would use the function of the VR pot for anyway although my banana robot…off topic…

I think possibly use the VR pot to adjust walking height so the controls are more like the ps2 controls and reverse the left and right sticks… come to think of it the right forward and reverse stick in the ps2 controller code wasn’t controlling anything…

I think I’ll use the VR pot channel to control walking height and use the left sticks for forward and reverse movement and also rotate and use the right left and right stick for move left and move right… although that still free’s up the forward and reverse right stick for something… OOH SCORPION TAIL…with a stinger …really no idea anyone have any ideas??

Either way that stuff is easy to figure out…

anyone have any ideas/comments/insults/jokes? care to chime in feel free, I have lot’s of free time without a job anymore, crappy economy.

Zenta do you have any photos of your phoenix up close with that black cover off it? I wanted to see how you wired up your 7 channel receiver or if its just taped inside the plastic dome or what

I wouldnt mind doing something with my 4 Futaba S3004 servo’s either, I know innerbreed suggested a pan and tilt camera I don’t have one though :stuck_out_tongue: wonder about a tail of sorts … any of you guys see those green laser pointers they modify for burning … bad idea I know but a walking spider with the ability to burn holes in things … REMOTELY… toss on a pan and tilt camera and you have a miniature WMD haha horrible.

anyway ideas ideas and more ideas.

–Aaron

Sorry to here you lost your job! :frowning: Crappy economy indeed.

The only comment I can provide is for you to start off with something a lot easier to understand. Work your way up, instead of the other way around.

A mushroom walked into a bar and said “Bartender I would like to enjoy a cold draft. Perhaps something in a lager…” The bar keep replied “We don’t serve your kind!” The mushroom replied “Why not! I’m a fungi…” 8)

Heh, Ive heard a different version of that joke.

This code really isn’t all that difficult to understand, "Frankly I was shocked when I first looked at the ps2 code version how small it was "

I couldn’t start this kinda code from scratch but what the programming masters of this forum have done really makes it easy to understand and how all the if statements are indented and just separated and all that jazz…

anyway…