Serial command set for controlling BB2 with powerpod program

Hi Apostolos,

I’d just bump the ± 1 in the “GaitSpeedTmp + 1” statements to +20 and -20. This should max them out immediately to their 3 and 20 values.

There are cleaner ways to implement this, but this is the simplest way, and will allow you to easily convert back, if desired.

Alan KM6VV

Hi Alan

It’s agood idea to use ±20 for the min,max values but what about intemediate values? How can I go about seting them also with one serial stream?

Hi Apostolos,

With just an up and a down key, you are limited. You could use an increment/decrement number like +5 and -5, this will give you a few intermediate steps.

Not much else without a better input device, like a joystick.

Alan KM6VV

There will not be any input devices (no joysticks or keys), I want to send these values depending on the state of the external sensors that will be connected on my mega128 board.

Hi Apostolos ,

Looks like I lost the edit I did to my last post. Since you are sending a packet that you make up, you can add an additional byte like a ‘Z’ axis. Then this byte can be read into the GaitSpeedTmp variable directly.

Actually, you could add any number of extra variables this way.

Alan KM6VV

Hi Alan, can you please give me a tip on how I would go about adding this extra byte to the serial string. remember that I’m a newbie at this :smiley:

Hi Apostolos,

It starts in your ATmega128 control board. Somewhere you have a routine to send the 7 or so bytes to the COM port. You add an additional byte or two after say, the joystick values. In a similar fashion, you modify the “receive” function on the BB2 to collect the additional byte(s). Also apply and check the string of bytes sent for checksum over the additional byte(s).

what’s your ATmega128 control board code in?

Alan KM6VV
(two more days to my new BB2 & SCC32!)

OK I think I get what you are saying

The code in my mega128 board is in Bascom AVR Basic

I’ll try it out and report back

Hi guys
I’m back again with yet another serial communication problem.

As you are aware of, I’m trying to make and autonomous hexapod using the BBII,SSC32 and an atmega128 control board.

What I’m trying to do is send a serial commands from the mega128 board to the BBII to make the bot go different directions. The serial commands that I’m sending are the same as the demo control program that comes with power pod (like this 00 FF FF 80 80 80 80).
I have managed to establish such a connection so when I for example send a repeating serial steam that corresponds to a certain direction, the bot goes toward that direction and when the serial stream stops so does the bot.
So far so good.
Now I’m trying to send the serial direction data only once and have the bot go to that direction until it receives another direction data that cancels the first. I have partially succeeded in doing this. I say partially because when I send the data the first time, the bot goes to that direction and when the stream stops the bot continues in that direction but with a different kind of speed. It’s like some parameter is affecting the speed. I have been trying to debug this the past couple of days but I’m stuck.

The code below is the modified power pod code that is in the the BBII.
I know it is a burden to look over the code but maybe someone can help this newbie with his robot quest
:smiley:

please forgive me if I have tired you

[code];
; Use Basic Micro ATOM PRO IDE 08.0.1.7
; *** not suitable for IDE 02.2.1.1 (there’s a specific version for this IDE)
; *** not suitable for IDE 05.3.0.0 (there’s a specific version for this IDE)
; Use Basic Atom PRO 28

;My version 1.10 “Hector 1”

;************************************************
;****** Basic Atom with SSC-32, PC control ******
;----------------- 3.43 3DOF-A ------------------
;---- Serial Port Control (Bot Board / PC) ------
;-------------- Round Body (H3-R) ---------------
;********** Bot Board Buzzer support ************
;***** Little Gripper / Pan & Tilt support ******
;**************** Deck support ******************
;************************************************
;** Programmer: Laurent Gay, [email protected] **
;************************************************
;
; let’s say that the 2 switches holes of the H3/H3R is the ‘rear’ of the robot
;
; *** using 3 ‘right’ legs and 3 ‘left’ legs ***
; put the SSC-32 card with the PC serial port looking to ‘Front’ (opposite to H3R switches)
;
; 3 right legs connections :
; Rear Right leg : Hip Horizontal : pin 17, Hip Vertical : pin 16, Knee : pin 15
; Middle Right leg : Hip Horizontal : pin 20, Hip Vertical : pin 19, Knee : pin 18
; Front Right leg : Hip Horizontal : pin 23, Hip Vertical : pin 22, Knee : pin 21
;
; 3 left legs connections :
; Rear Left leg : Hip Horizontal : pin 2, Hip Vertical : pin 1, Knee : pin 0
; Middle Left leg : Hip Horizontal : pin 5, Hip Vertical : pin 4, Knee : pin 3
; Front Left leg : Hip Horizontal : pin 8, Hip Vertical : pin 7, Knee : pin 6
;
; Default mode :
; Move the robot (2 axis translation) with the right joystick
; Turn with the left joystick X axis
; move Up/Down body with the left joystick Y axis
; lock/unlock the height with the left joystick push button (L3)
;
; Body move mode :
; Push ‘select’ button to activate this mode (push ‘select’ again to return to default mode)
; move the body horizontally (2 axis translation) with the right joystick
; the left joystick push button (L3) has a new function now, it selects between 4 control modes for the left joystick:
; 1)- (by default) move the body vertically + rotate around the vertical axis
; 2)- (push L3 to activate) move the body vertically + roll
; 3)- (push L3 again to activate) pitch + rotate around the vertical axis
; 4)- (push L3 again to activate) pitch + roll the body
; pushing L3 again will return to mode 1 (cycling)
;
; go to standby position with the ‘Triangle’ button, press again to go to walk position
; Attack posture with the ‘Cross’ button (*** only possible if legs are not moving )
; All = 1500 posture with the ‘Circle’ button (
only possible if legs are not moving )
; Learning to fly posture with the ‘Square’ button (uh ? nutty ?..it CAN fly…) (
only possible if legs are not moving )
; Change the legs ‘up’ position with the digital Up/Down buttons
;
; Change the gait speed with digital right/left buttons
;
; Presets buttons (only with ‘Default’ mode):
; - R1 => Tall grass
; - L1 => Tile floor
; - R2 => Body low
; - L2 => Default preset
;
; Little Gripper support on Pin 29 (Left/Right) and 30 (Open/Close) (only in ‘Body move’ mode)
; - R1 => Open
; - L1 => Close
; - R2 => Rotate Right
; - L2 => Rotate Left
;
; Deck support on Pin 31 (panning servo)
; allow to handle a deck (for camera, sensors, lights)
; the panning servo will follow the direction it walk
; Additional tilt servo support for 180° Deck on pin 28 (Round body only)
; When using a 180° deck + 2 GP2D12 back to back on a tilt servo
; the tilt servo will incline the ‘usable’ GP2D12 (looking the walking direction) to floor
; when walking at low speed, the angle increase (looking near)
; when walking at full speed, the angle is close to horizontal (looking far)
; when going opposite direction, the angle is mirrored to vertical,
; making the opposite GP2D12 looking near or far
;
; Start button toggles between the ‘knee angle shift’ and ‘normal’ mode
;
; R3 button : Horn
;
;
*********************************************
;
;
;--------------------------------------------------------------------
;-------------Constants
;
DeadZone con 8

;*** SSC-32 card communication on pin 15 ***
SSC32 con p15

;Deck
Deck_PulseMin con 600
Deck_PulseMax con 2400

;Little Gripper
LGripLR_PulseMin con 750
LGripLR_PulseMax con 2250
LGripOC_PulseMin con 750
LGripOC_PulseMax con 2250

;Legs
HipH_AngleMin con 21 ;30°
HipH_AngleMax con 107 ;150°
HipH_PulseMin con 910
HipH_PulseMax con 2090

HipV_AngleMin con 25 ;35°
HipV_AngleMax con 103 ;145°
HipV_PulseMin con 960
HipV_PulseMax con 2040

Knee_AngleMin con 36 ;50°
Knee_AngleMax con 107 ;150°
Knee_PulseMin con 1107
Knee_PulseMax con 2090

;****************************************************
; 3DOF-A Leg Dimensions (TibiaAngle constant = 0)
;HipV_HipH con 38 ;1.50" = 38mm (1.50 * 25.4)
;Femur_Length con 57 ;2.25" = 57mm (2.25 * 25.4)
;Tibia_Length con 124 ;4.875" = 124mm (4.875 * 25.4)

; 3DOF-B Leg Dimensions (TibiaAngle constant = 0)
;HipV_HipH con 29 ;1.14" = 29mm (1.14 * 25.4)
;Femur_Length con 57 ;2.25" = 57mm (2.25 * 25.4)
;Tibia_Length con 108 ;4.25" = 108mm (4.25 * 25.4)

; 3DOF-C Leg Dimensions (TibiaAngle constant = 20)
;HipV_HipH con 29 ;1.14" = 29mm (1.14 * 25.4)
;Femur_Length con 57 ;2.25" = 57mm (2.25 * 25.4)
;Tibia_Length con 141 ;5.55" = 141mm (5.55 * 25.4)

; 3DOF-(Old) Leg Dimensions (TibiaAngle constant = 0)
;HipV_HipH con 32 ;1.25" = 32mm (1.25 * 25.4)
;Femur_Length con 70 ;2.75" = 70mm (2.75 * 25.4)
;Tibia_Length con 108 ;4.25" = 108mm (4.25 * 25.4)
;****************************************************

; 3DOF-A Leg Dimensions (TibiaAngle constant = 0)
HipV_HipH con 38 ;1.50" = 38mm (1.50 * 25.4)
Femur_Length con 57 ;2.25" = 57mm (2.25 * 25.4)
Tibia_Length con 124 ;4.875" = 124mm (4.875 * 25.4)

LegUpShiftMin con 30
LegUpShiftMax con 70
KneeShiftPulse con 200 ;range is 0 to 255 (activated by pushing start button, affect the legs when up)
TibiaAngle con 0 ;range is -20 (interior) to 20 (exterior), 0 is vertical, this is ‘all time’ tibia angle

;ACos
ArcCos Bytetable 64,64,63,63,63,62,62,62,61,61,61,60,60,60,59,59,|
59,59,58,58,58,57,57,57,56,56,56,55,55,55,54,54,|
54,53,53,53,52,52,52,51,51,51,50,50,50,49,49,49,|
48,48,48,47,47,46,46,46,45,45,45,44,44,44,43,43,|
42,42,42,41,41,41,40,40,39,39,39,38,38,37,37,37,|
36,36,35,35,35,34,34,33,33,32,32,31,31,31,30,30,|
29,29,28,28,27,27,26,25,25,24,24,23,23,22,21,21,|
20,19,19,18,17,16,15,15,14,13,11,10,09,07,05,00

; Don’t use ByteTable instead, it takes too much memory
RRHH con “1” ;Rear Right leg : Hip Horizontal : pin 17
RRHH2 con “7”
RRHV con “1” ;Rear Right leg : Hip Vertical : pin 16
RRHV2 con “6”
RRK con “1” ;Rear Right leg : Knee : pin 15
RRK2 con “5”

MRHH con “2” ;Middle Right leg : Hip Horizontal : pin 20
MRHH2 con “0”
MRHV con “1” ;Middle Right leg : Hip Vertical : pin 19
MRHV2 con “9”
MRK con “1” ;Middle Right leg : Knee : pin 18
MRK2 con “8”

FRHH con “2” ;Front Right leg : Hip Horizontal : pin 23
FRHH2 con “3”
FRHV con “2” ;Front Right leg : Hip Vertical : pin 22
FRHV2 con “2”
FRK con “2” ;Front Right leg : Knee : pin 21
FRK2 con “1”

RLHH con “0” ;Rear Left leg : Hip Horizontal : pin 2
RLHH2 con “2”
RLHV con “0” ;Rear Left leg : Hip Vertical : pin 1
RLHV2 con “1”
RLK con “0” ;Rear Left leg : Knee : pin 0
RLK2 con “0”

MLHH con “0” ;Middle Left leg : Hip Horizontal : pin 5
MLHH2 con “5”
MLHV con “0” ;Middle Left leg : Hip Vertical : pin 4
MLHV2 con “4”
MLK con “0” ;Middle Left leg : Knee : pin 3
MLK2 con “3”

FLHH con “0” ;Front Left leg : Hip Horizontal : pin 8
FLHH2 con “8”
FLHV con “0” ;Front Left leg : Hip Vertical : pin 7
FLHV2 con “7”
FLK con “0” ;Front Left leg : Knee : pin 6
FLK2 con “6”

;Little Gripper Pin
LGripLR Con “2” ;Little Gripper Left/Right : pin 29
LGripLR2 Con “9”
LGripOC Con “3” ;Little Gripper Open/close : pin 30
LGripOC2 Con “0”

; Deck Pin
DeckP Con “3” ;Deck Panning servo : pin 31
DeckP2 Con “1”

; Additional Tilt servo for 180° Deck
DeckTilt Con “2”
DeckTilt2 Con “8”

;--------------------------------------------------------------------
;-------------Variables
Index var Byte
DualShock var Byte(7)
Dualshock_last var byte(7)
LastButton var Byte(2)
Steps var Byte
FlipFlap var Bit
FlagOff var Bit
MovesDelay var Sbyte
HeightAdjust var Bit

HeightShift var Sbyte(6)
KneeShift var Byte(7)

Steering var Sbyte
Height var Sbyte
LastHeight var Sbyte
HeightLimit var Byte
XSpeed var Sbyte
YSpeed var Sbyte
Roll var Sbyte
Pitch var Sbyte
Rotate var Sbyte(6)
DCoord var Byte
DAngle var Byte
NbSteps var Byte
GaitSpeed var Byte
GaitSpeedTmp var Byte
StepFlag var Byte

TmpXPos var Long
TmpYPos var Long
TmpZPos var Long
TmpDistance var Long
TmpSEW var Word
TmpSEWSEW var Long
TmpCos var Long
TmpAngle var Sbyte

XPos var Sword(6)
YPos var Sword(6)
ZPos var Sword(6)
XPos2 var Sword(6)
YPos2 var Sword(6)
ZPos2 var Sword(6)
Distance var Sword

HipH_Angle var Sbyte
HipV_Angle var Sword
Knee_Angle var Sword

HipH_Pulse var Word(6)
HipV_Pulse var Word(6)
Knee_Pulse var Word(6)

LittleGripOCPulse var Word
LittleGripLRPulse var Word
Deck_Pulse var Word
DeckTilt_Pulse var Word

LegUpShift var Byte
GaitKind var Bit
Freeze var Bit
Tripod var Bit
LockLegs var Bit
LeftStickMode var Byte

CheckSum var Byte
DualShock3_last var byte
DualShock4_last var byte

;--------------------------------------------------------------------
;***************
;*** Program ***
;***************

;-------------Init
clear

LastButton(0) = 255
LastButton(1) = 255

LittleGripOCPulse = 1500
LittleGripLRPulse = 1500

HeightLimit = 25 - ABS(TibiaAngle / 2)

pause 500

;-------------Init SSC-32 with pulse offsets
serout SSC32,i38400,"#", |
RRHH,RRHH2,“po0 #”,RRHV,RRHV2,“po-52 #”,RRK,RRK2,“po8 #”, |
MRHH,MRHH2,“po0 #”,MRHV,MRHV2,“po-48 #”,MRK,MRK2,“po-23 #”, |
FRHH,FRHH2,“po0 #”,FRHV,FRHV2,“po58 #”,FRK,FRK2,“po2 #”, |
RLHH,RLHH2,“po-35 #”,RLHV,RLHV2,“po61 #”,RLK,RLK2,“po0 #”, |
MLHH,MLHH2,“po-40 #”,MLHV,MLHV2,“po-3 #”,MLK,MLK2,“po-26 #”, |
FLHH,FLHH2,“po-26 #”,FLHV,FLHV2,“po12 #”,FLK,FLK2,“po-22”,13]

;SSC-32 -> H3 engine
gosub H3Init
Sound 9,[100\4235, 200\4435]
;neutral positions for movements
DualShock_last(3) = $80 ;by me
DualShock_last(4) = $80 ;by me
DualShock_last(5) = $80 ;by me
DualShock_last(6) = $80 ;by me
;--------------------------------------------------------------------
;-------------Main loop
main

;SerialQuery
serout S_OUT,i9600,“RD”] ; ‘Ready’ to recieve data now
toggle p7
serin S_OUT,i9600,200000,NoData,[str DualShock(0)\7]

CheckSum = DualShock(1) ^ DualShock(2) ^ DualShock(3) ^ |
	DualShock(4) ^ DualShock(5) ^ DualShock(6)

;serout S_OUT,i9600,[CheckSum]

if CheckSum <> DualShock(0) then
Sound 9,[50\2000]
NoData
;if dualshock(3)=128 then
;dualshock_last(3)=$80
;endif
;if dualshock(4)=128 then
;dualshock_last(4)=$80
;endif

DualShock(1) = $FF ;button value
DualShock(2) = $FF ;button value
for index = 3 to 6
DualShock(index) = DualShock_last(index) ;x direction ;by me
;DualShock(4) = DualShock_last(4) ;y direction ;by me
;DualShock(5) = $80 ;rotation
;DualShock(6) = $80 ;height
next

endif

;**********************************************************************
; R1-L1-R2-L2 presets code
;
; to change Body Height (range is -25 (body up) to 25 (body down)) :
;Height = 10 ; for example
;
; to change Leg Up Shift (range is 20 (close to floor) to 70 (about 2.5 inches from floor))
;LegUpShift = 30 ; for example
;
; to change Gait Speed (range is 3 (fast) to 20 (very slow))
;GaitSpeed = 4 ; for example

if (DualShock(2).bit3 = 0) and LastButton(1).bit3 then	;R1 Button test
	Height = -25		; tall grass
	LegUpShift = 70
	GaitSpeed = 10
elseif (DualShock(2).bit2 = 0) and LastButton(1).bit2	;L1 Button test
	Height = 5			; tile floor
	LegUpShift = 30
	GaitSpeed = 3
elseif (DualShock(2).bit1 = 0) and LastButton(1).bit1	;R2 Button test
	Height = 25			; Body low
	LegUpShift = 35
	GaitSpeed = 4
elseif (DualShock(2).bit0 = 0) and LastButton(1).bit0	;L2 Button test
	Height = 0			; Default preset
	LegUpShift = 35
	GaitSpeed = 4
else
	goto NoPresets
endif

HeightAdjust = 0
LegUpShift = (LegUpShift max LegUpShiftMax) min LegUpShiftMin 
GaitKind = LegUpShift > 45
GaitSpeedTmp = GaitSpeed max 20
MovesDelay = 8	

NoPresets
;**********************************************************************

if (DualShock(2).bit4 = 0) and LastButton(1).bit4 then	;Triangle Button test
	FlagOff = FlagOff ^ 1
	if FlagOff then
		gosub All1500
		Gosub InitPos
		pause 144
		for Index = 0 to 31
			serout SSC32,i38400,"#",DEC Index,"P0"]
		next
		serout SSC32,i38400,[13]
	else
		gosub H3Init
	endif
endif

if FlagOff then
	pause 144
	goto OffEnd
endif

if (MovesDelay <= 0) or LockLegs then
	if (DualShock(2).bit5 = 0) and LastButton(1).bit5 then	;Circle Button test
		gosub All1500
	endif

	if (DualShock(2).bit6 = 0) and LastButton(1).bit6 then	;Cross Button test
	Sound 9,[100\2235, 100\2435]
	    serout S_OUT,i9600,"AT"]  ;send "AT" to serial port to indicate that routine is active (by me)
		high p3;led on (by me)
		gosub All1500
		;Attack posture
		serout SSC32,i38400,"#",MRHH,MRHH2,"P1800#",MRHV,MRHV2,"P1700#",MRK,MRK2,"P1700#", |
			MLHH,MLHH2,"P1200#",MLHV,MLHV2,"P1300#",MLK,MLK2,"P1300T288",13]
		pause 288
		serout SSC32,i38400,"#",MRHV,MRHV2,"P1500#",MRK,MRK2,"P1500#",MLHV,MLHV2,"P1500#", |
			MLK,MLK2,"P1500T288",13]
		pause 288
		serout SSC32,i38400,"#",RRHV,RRHV2,"P1800#",RRK,RRK2,"P1800#",MRHV,MRHV2,"P1400#", |
			MRK,MRK2,"P1400#",FRHH,FRHH2,"P1800#",FRHV,FRHV2,"P2100#",RLHV,RLHV2,"P1200#", |
			RLK,RLK2,"P1200#",MLHV,MLHV2,"P1600#",MLK,MLK2,"P1600#",FLHH,FLHH2,"P1200#", |
			FLHV,FLHV2,"P900T288",13]
		pause 288
		for Index = 1 to 10
			serout SSC32,i38400,"#",FRHV,FRHV2,"P2000#",FRK,FRK2,"P1600#",FLHV,FLHV2,"P900#", |
				FLK,FLK2,"P1600T144",13]
			pause 144
			serout SSC32,i38400,"#",FRHV,FRHV2,"P2100#",FRK,FRK2,"P1400#",FLHV,FLHV2,"P1000#", |
				FLK,FLK2,"P1400T144",13]
			pause 144
		next
		serout SSC32,i38400,"#",FRHH,FRHH2,"P1500#",FRK,FRK2,"P1500#",FLHH,FLHH2,"P1500#", |
			FLHV,FLHV2,"P900#",FLK,FLK2,"P1500T288",13]
		pause 288
		serout SSC32,i38400,"#",RRHV,RRHV2,"P1500#",RRK,RRK2,"P1500#",MRHV,MRHV2,"P1500#", |
			MRK,MRK2,"P1500#",FRHV,FRHV2,"P1500#",MLHV,MLHV2,"P1500#",MLK,MLK2,"P1500#", |
			FLHV,FLHV2,"P1500#",RLHV,RLHV2,"P1500#",RLK,RLK2,"P1500T576",13]
		pause 576
		serout SSC32,i38400,"#",MRHH,MRHH2,"P1500#",MRHV,MRHV2,"P1700#",MRK,MRK2,"P1700#", |
			MLHH,MLHH2,"P1500#",MLHV,MLHV2,"P1300#",MLK,MLK2,"P1300T288",13]
		pause 288
		serout SSC32,i38400,"#",MRHV,MRHV2,"P1500#",MRK,MRK2,"P1500#",MLHV,MLHV2,"P1500#", |
			MLK,MLK2,"P1500T288",13]
		pause 288
		low p3;led off  (by me)
	endif

	if (DualShock(2).bit7 = 0) and LastButton(1).bit7 then	;Square Button test

Sound 9,[100\3235, 100\3435]
serout S_OUT,i9600,“FL”] ;send “FL” to serial port to indicate that routine is active (by me)
high p4;led on (by me)
gosub All1500
;Learning to fly posture (uh ? nutty ?..it CAN fly…)
for Index = 1 to 4
serout SSC32,i38400,"#",MRHV,MRHV2,“P1900#”,MRK,MRK2,“P1800#”,MLHV,MLHV2,“P1100#”, |
MLK,MLK2,“P1200T288”,13]
serout SSC32,i38400,"#",RRHV,RRHV2,“P1600#”,RRK,RRK2,“P1600#”,FRHV,FRHV2,“P1600#”, |
FRK,FRK2,“P1600#”,RLHV,RLHV2,“P1400#”,RLK,RLK2,“P1400#”,FLHV,FLHV2,“P1400#”, |
FLK,FLK2,“P1400T576”,13]
pause 288
serout SSC32,i38400,"#",MRK,MRK2,“P1200#”,MLK,MLK2,“P1800T288”,13]
pause 288
serout SSC32,i38400,"#",RRHV,RRHV2,“P1400#”,RRK,RRK2,“P1400#”,MRHV,MRHV2,“P1500#”, |
FRHV,FRHV2,“P1400#”,FRK,FRK2,“P1400#”,RLHV,RLHV2,“P1600#”,RLK,RLK2,“P1600#”, |
MLHV,MLHV2,“P1500#”,FLHV,FLHV2,“P1600#”,FLK,FLK2,“P1600T576”,13]
pause 576
next
serout SSC32,i38400,"#",MRHV,MRHV2,“P1800#”,MRK,MRK2,“P1800#”,MLHV,MLHV2,“P1200#”, |
MLK,MLK2,“P1200T288”,13]
pause 288
gosub All1500
low p4; led off (by me)
endif
endif

if (DualShock(1).bit0 = 0) and LastButton(0).bit0 then	;Select Button test
	LockLegs = LockLegs ^ 1
	Sound 9,[100\(2000 + LockLegs * 1000)]
	gosub FlatBody
endif

if (DualShock(1).bit3 = 0) and LastButton(0).bit3 then	;Start Button test
	KneeShift(6) = KneeShift(6) ^ KneeShiftPulse
	Sound 9,[100\(800 + KneeShift(6))]
endif

if (DualShock(1).bit1 = 0) and LastButton(0).bit1 then	;L3 Button test
	if LockLegs then
		LeftStickMode = (LeftStickMode + 1) & 3
		gosub FlatBody
	else
		HeightAdjust = HeightAdjust ^ 1
	endif
	Sound 9,[100\3500]
endif

if (DualShock(1).bit2 = 0) and LastButton(0).bit2 then	;R3 Button test (Horn)
	Sound 9,[800\392, 600\370, 200\0, 800\330, 600\294, 200\0, 300\330, 100\0, 300\330]
endif

if DualShock(1).bit4 = 0 then 	;Up Button test
	LegUpShift = (LegUpShift + 1) max LegUpShiftMax	
elseif DualShock(1).bit6 = 0	;Down Button test
	LegUpShift = (LegUpShift - 1) min LegUpShiftMin	
else
	goto NoSound
endif

GaitKind = LegUpShift > 45
Sound 9,[20\(LegUpShift * 10 + 400 + GaitKind * 200)]
MovesDelay = 8

NoSound

if (DualShock(1).bit5 = 0) and LastButton(0).bit5 then 	;Right Button test
	GaitSpeedTmp = (GaitSpeedTmp + 5) max 20


elseif (DualShock(1).bit7 = 0) and LastButton(0).bit7	;Left Button test
	GaitSpeedTmp = (GaitSpeedTmp - 5) min 3

else
	goto NoSound1
endif
Sound 9,[20\(50-GaitSpeedTmp) * 35 + 400]
MovesDelay = 8

NoSound1
GaitSpeed = GaitSpeedTmp min (3 + GaitKind)

for Index = 3 to 6
	if DualShock(Index) > (128 + DeadZone) then
	dualshock_last(index)=dualshock(index)
		DualShock(Index) = DualShock(Index) - DeadZone/2

	elseif DualShock(Index) < (128 - DeadZone)
	dualshock_last(index)=dualshock(index)
		DualShock(Index) = DualShock(Index) + DeadZone/2
	else
		DualShock(Index) = 128

	endif
next

YSpeed = DualShock(3) - 128		; Right Stick Horizontal

XSpeed = DualShock(4) - 128		; Right Stick Vertical

Steering = DualShock(5) - 128		; Left Stick Horizontal

StepFlag = (GaitSpeedTmp - 2) max 3
if HeightAdjust or LockLegs then
	Height = LastHeight + (((DualShock(6) - 128) / 5) - LastHeight) / StepFlag; Left Stick Vertical
endif

Height = (Height Max HeightLimit) min - HeightLimit

;H3
if Steering or (Height <> LastHeight) or YSpeed or XSpeed or LockLegs then
MovesDelay = 8
endif

if MovesDelay > 0 then
	LastHeight = Height
	DCoord = SQR(XSpeed * XSpeed + YSpeed * YSpeed)
	TmpCos = XSpeed * 127 / DCoord
	gosub ACos
	DAngle = TmpAngle
	if YSpeed > 0 then
		DAngle = 256 - DAngle
	endif

	DCoord = DCoord max (128 - ABS(Height) - ABS(TibiaAngle * 2))

	; 180° Deck Code
	if (Dangle < 64 or Dangle > 191) and (DCoord > 0) then
		DeckTilt_Pulse = 1680 - Dcoord
	else
		DeckTilt_Pulse = 1380 + Dcoord
	endif
	Deck_Pulse =  ((Deck_PulseMax - Deck_PulseMin) * ((DAngle + 64 ) & $7F)) / 127 + Deck_PulseMin

	; 360° Deck Code
	;Deck_Pulse = ((Deck_PulseMax - Deck_PulseMin) * DAngle) / 255 + Deck_PulseMin

	Steps = Steps + 1
	if Steps > NbSteps then
		Steps = 1
		FlipFlap = FlipFlap ^ 1
		NbSteps = GaitSpeed
	endif

	if LockLegs then
		if LeftStickMode > 0 then ;Body roll and pitch
			if (leftStickMode & 1) then
				Roll = Roll + (Steering - Roll) / StepFlag
				Steering = 0
			else
				Roll = 0
			endif

			if (leftStickMode & 2) then
				Pitch = Pitch + (Height - Pitch) / StepFlag
				Height = 0
			else
				Pitch = 0
			endif

			HeightShift(0) = Roll/10
			HeightShift(2) = HeightShift(0)
			HeightShift(3) = -HeightShift(0)
			HeightShift(5) = HeightShift(3)

			HeightShift(0) = ((HeightShift(0) + Pitch) max HeightLimit) min -HeightLimit
			HeightShift(3) = -HeightShift(0)
			HeightShift(2) = ((HeightShift(2) - Pitch) max HeightLimit) min -HeightLimit
			HeightShift(5) = -HeightShift(2)

			HeightShift(1) = HeightShift(0) + HeightShift(2)
			HeightShift(4) = HeightShift(3) + HeightShift(5)
		endif
		LittleGripOCPulse = ((LittleGripOCPulse + (DualShock(2).bit3 * 50) - (DualShock(2).bit2 * 50)) |
			min LGripOC_PulseMin) max LGripOC_PulseMax
		LittleGripLRPulse = ((LittleGripLRPulse + (DualShock(2).bit1 * 50) - (DualShock(2).bit0 * 50)) |
			min LGripLR_PulseMin) max LGripLR_PulseMax
		GaitSpeedTmp = StepFlag + 2
	else
		StepFlag = NbSteps - Steps + 1
	endif

	for Index = 0 to 5
		XPos2(Index) = -(DCoord * SIN(DAngle + (Index * 43 + 21) + 64) / 300) ; 43 => 60 degrees
		ZPos2(Index) = -(DCoord * SIN(DAngle + (Index * 43 + 21)) / 300) ; 43 => 60 degrees
	next

	Tripod = FlipFlap
	gosub AorB_Down

	Freeze = Steps < (NbSteps - GaitKind)
	Tripod = FlipFlap ^ 1
	gosub AorB_Up	

	for Index = 0 to 5

		;Distance and HipH_Angle with XZ
		Distance = SQR((XPos(Index) * XPos(Index) + ZPos(Index) * ZPos(Index)) / 4) * 2
		TmpCos = ZPos(Index) * 127 / Distance

		Distance = Distance + TibiaAngle ; Tibia angle for special legs (3DOF-C)

		Gosub ACos
		HipH_Angle = (TmpAngle max HipH_AngleMax) min HipH_AngleMin
		;----------

		;Set Angle
		TmpXPos = XPos(Index) * 127
		TmpYPos = (YPos(Index) * 127) max 0
		TmpZPos = ZPos(Index) * 127
		TmpDistance = ((Distance - HipV_HipH) * 127) min 0
		
		TmpSEWSEW = (TmpYPos * TmpYPos + TmpDistance * TmpDistance) / 16129
		TmpSEW = SQR(TmpSEWSEW)

		TmpCos = (Femur_Length * Femur_Length + Tibia_Length * Tibia_Length - TmpSEWSEW)
		TmpCos = TmpCos * 127 / (2 * Femur_Length * Tibia_Length)
		gosub ACos
		Knee_Angle = (TmpAngle max Knee_AngleMax) min Knee_AngleMin

		TmpCos = -TmpYPos / TmpSew
		gosub ACos
		HipV_Angle = TmpAngle

		TmpCos = (Femur_Length * Femur_Length - Tibia_Length * Tibia_Length + TmpSEWSEW) 
		TmpCos = TmpCos * 127 / (2 * Femur_Length * TmpSEW) 
	    gosub ACos
	    HipV_Angle = ((TmpAngle + HipV_Angle) max HipV_AngleMax) min HipV_AngleMin
	    ;----------

		HipH_Angle = HipH_Angle + Rotate(Index)
		
		HipH_Pulse(Index) =  (((HipH_PulseMax - HipH_PulseMin) * (HipH_Angle - HipH_AngleMin) |
			/ (HipH_AngleMax - HipH_AngleMin) + HipH_PulseMin) max HipH_PulseMax) min HipH_PulseMin

		HipV_Pulse(Index) = (((HipV_PulseMax - HipV_PulseMin) * (HipV_Angle - HipV_AngleMin) |
			/ (HipV_AngleMax - HipV_AngleMin) + HipV_PulseMin) max HipV_PulseMax) min HipV_PulseMin

		Knee_Pulse(Index) = (((Knee_PulseMax - Knee_PulseMin) * (Knee_Angle - Knee_AngleMin) |
			/ (Knee_AngleMax - Knee_AngleMin) + Knee_PulseMin) max Knee_PulseMax) min Knee_PulseMin
		Knee_Pulse(Index) = 3000 - Knee_Pulse(Index) - KneeShift(Index) * 2
	next

	serout SSC32,i38400,"#",RRHH,RRHH2,"P",DEC HipH_Pulse(0),"#",RRHV,RRHV2,"P",DEC HipV_Pulse(0), |
		"#",RRK,RRK2,"P",DEC Knee_Pulse(0),"#",FRHH,FRHH2,"P",DEC HipH_Pulse(2), |
		"#",FRHV,FRHV2,"P",DEC HipV_Pulse(2),"#",FRK,FRK2,"P",DEC Knee_Pulse(2), |
		"#",MLHH,MLHH2,"P",DEC HipH_Pulse(4),"#",MLHV,MLHV2,"P",DEC 3000 - HipV_Pulse(4), |
		"#",MLK,MLK2,"P",DEC 3000 - Knee_Pulse(4),"#",MRHH,MRHH2,"P",DEC HipH_Pulse(1), |
		"#",MRHV,MRHV2,"P",DEC HipV_Pulse(1),"#",MRK,MRK2,"P",DEC Knee_Pulse(1), |	
		"#",RLHH,RLHH2,"P",DEC HipH_Pulse(5),"#",RLHV,RLHV2,"P",DEC 3000 - HipV_Pulse(5), |
		"#",RLK,RLK2,"P",DEC 3000 - Knee_Pulse(5),"#",FLHH,FLHH2,"P",DEC HipH_Pulse(3), |	
		"#",FLHV,FLHV2,"P",DEC 3000 - HipV_Pulse(3),"#",FLK,FLK2,"P",DEC 3000 - Knee_Pulse(3), |
		"#",DeckP,DeckP2,"P",DEC Deck_Pulse,"#",DeckTilt,DeckTilt2,"P",DEC DeckTilt_Pulse, |
		"#",LGripOC,LGripOC2,"P",DEC LittleGripOCPulse,"#",LGripLR,LGripLR2,"P",DEC LittleGripLRPulse,"T210",13]
else
	pause 144
	if MovesDelay < -5 then
		MovesDelay = (NbSteps - GaitKind) - Steps + 1
	EndIf	
endif
MovesDelay = MovesDelay - 1

OffEnd
LastButton(0) = DualShock(1)
LastButton(1) = DualShock(2)

goto main

;--------------------------------------------------------------------
;-------------Sub H3 Init
H3Init
LockLegs = 0
NbSteps = 4
GaitSpeedTmp = NbSteps
LegUpShift = 35

for Index = 0 to 5
	XPos(Index) = HipV_HipH + Femur_Length
	YPos(Index) = - Tibia_Length
	ZPos(Index) = 0
next

Gosub InitPos
MovesDelay = 8
; then All1500

;-------------Sub All1500
All1500
HeightAdjust = 1
height = 0
LastHeight = 0

for Index = 0 to 27	;preserve servo 28 (Deck Tilt),29 and 30 (Little Gripper),31 (Deck)
	serout SSC32,i38400,"#",DEC Index,"P1500"]
next
serout SSC32,i38400,"T576",13]

pause 576

Steps = NbSteps
; then Flat Body

;-------------Sub Flat Body
FlatBody
Roll = 0
Pitch = 0
for Index = 0 to 5
HeightShift(Index) = 0
next

return	

;-------------Sub InitPos
InitPos
serout SSC32,i38400,"#",RRHV,RRHV2,“P2100#”,RRK,RRK2,“P1800#”,MRHV,MRHV2,“P2100#”,MRK,MRK2,“P1800#”, |
FRHV,FRHV2,“P2100#”,FRK,FRK2,“P1800#”,RLHV,RLHV2,“P900#”,RLK,RLK2,“P1200#”,MLHV,MLHV2,“P900#”, |
MLK,MLK2,“P1200#”,FLHV,FLHV2,“P900#”,FLK,FLK2,“P1200T1152”,13]
pause 576
serout SSC32,i38400,"#",RRHH,RRHH2,“P1500#”,MRHH,MRHH2,“P1500#”,FRHH,FRHH2,“P1500#”, |
RLHH,RLHH2,“P1500#”,MLHH,MLHH2,“P1500#”,FLHH,FLHH2,“P1500T576”,13]
pause 576

return

;-------------Sub Arc Cosinus
ACos
TmpCos = (TmpCos max 127) min -127
if TmpCos < 0 then
TmpAngle = 128 - ArcCos(-TmpCos)
else
TmpAngle = ArcCos(TmpCos)
endif

return

;-------------Tripod ‘A’ (tripod = 0) or ‘B’ (Tripod = 1) Down
AorB_Down
for Index = 0 + Tripod to 4 + Tripod Step 2
KneeShift(Index) = 0
Rotate(Index) = Rotate(Index) + (Steering/5 - Rotate(Index))/StepFlag
YPos(Index) = -Tibia_Length + Height + HeightShift(Index)
XPos(Index) = XPos(Index) + (XPos2(Index) - (XPos(Index) - (HipV_HipH + Femur_Length)))/StepFlag
ZPos(Index) = ZPos(Index) + (ZPos2(Index) - ZPos(Index))/StepFlag
next

return

;-------------Tripod ‘A’ (tripod = 0) or ‘B’ (Tripod = 1) Up
AorB_Up
if LockLegs then AorB_Down ;Goto sub AorB_Down and return directly from it to main loop

if (Steps = NbSteps) and GaitKind then
	StepFlag = NbSteps
	goto AorB_Down	;Goto sub AorB_Down and return directly from it to main loop
else
 	StepFlag = StepFlag - GaitKind - 1
endif	

for Index = 0 + Tripod to 4 + Tripod Step 2
	if (Steps > 1) and (Steps < (NbSteps - GaitKind - 1)) then 
		KneeShift(Index) = KneeShift(6)
	else
		KneeShift(Index) = 0
	endif
	Rotate(Index) = Rotate(Index) + (-Steering/5 - Rotate(Index))/StepFlag
	YPos(Index) = -Tibia_Length + Height + (LegUpShift * Freeze)
	XPos(Index) = XPos(Index) + (-XPos2(Index) - (XPos(Index) - (HipV_HipH + Femur_Length)))/StepFlag
	ZPos(Index) = ZPos(Index) + (-ZPos2(Index) - ZPos(Index))/StepFlag
next

return	

;--------------------------------------------------------------------
[/code]

When you mention that it goes at a different speed, what do you mean, faster or slower?

The one difference in this code is maybe the timings due to having to wait for the timeout from the serin. Have you tried experimenting with the timeout value on the serin? What happens if you decrease that number or increase it?

Not sure if it maters here but if you don’t get any input and before you had a button pressed, then it will act like the button was released…

That is all for now
Kurt

After the serial data is finished the speed decreases.
I have tried playing with the time out value but have not succeeded in doing anything.

Hi Apostolos,

I saw the “dualshock_last(index)=dualshock(index)” statements around line 556, but that was all, other then pin changes for the legs. Also “DualShock(index) = DualShock_last(index)” around 357. Also saw the gait speed ± 5 at 542, but these shouldn’t affect much.

A “search tag” like “by me” is useful to find one’s changes.

I’m wondering why you’d like the motion continuous after you start it up. At least in R/C, if you loose control, you’d like the model to stop, circle, or other wise “hang around”, rather then running off! I can see that it would be fewer messages to send to the BB2; but is it worth it? Just a comment.

I’d be inclined to simply send the command on a regular bases from your 168; say by an interrupt routine.

I’m looking forward to playing with the BB2 and Atom Basic. I notice you’re running the 'Pro. I almost bought that, but I kinda like the PICs. Now that I’ve learned where I saw the ‘C’ code option, I may wish I’d bought the 'Pro as well. I need to make another order anyway!

Alan KM6VV

Hi Alan

I think it would be easier to just send the command once and then only focus on the sensors until a next change of direction is needed. Since the bot will be autonomous and not R/C control, I’m not worried that it will go out of range of something and thus be uncontrollable.
Any ideas as to why the speed is decreasing every time the data stream stops. It keeps on going in the same direction but the speed goes down to the same value every time.
I have included a “by me” search string

Any ideas guys ?

That’s what I was concluding your reasoning was; it would be easier. But if the 'bot is to be autonomous, why send anything at all? Yeah, OK, you’re “sending” to the lower level modules. A “behavior” can cause it to roam; and if it sees something interesting (or dangerous!) it can alter course.

I don’t think you added anything to cause you to “loose speed”, rather, the code is designed to “execute” a move (joystick input) for a particular duration, and that move “decays” after a particular time. Hence it needs “refreshing” (by design). You might try getting a reply to your questions from the author.

I’ll probably be looking at the code again, if I get the time. I recall several pieces of code I wanted to examine further, and having running code to examine would have been much better!

My current hexapod control code is in ‘C’ running on a '4620, doing much the same as Laurent’s code; although I do use what might be called a “baby RTOS”, and I LIKE state machines!

I can recommend the book “Mobile Robots” by Joseph Jones, et. al. He (they) explain Behaviors, Subsumption, an other of Brooks’ approaches to robotics. You should check it out!

Alan KM6VV

My two cents here,

I personally see nothing wrong here in the idea of only telling the BAP when there is new data to be processed. This is much in the same way as one of the benifits of the SSC-32 is I don’t have to tell it to go to the same place every n milliseconds. The fewer messages allows both processors to spend more of their time doing real work…

I have not seen anything in the current code that decays the input. That is if I move a PS2 joystick forward the robot starts that direction and continues at the same speed until I change the joystick position. The code he posted here once it handles the timeout is indistinguishable from normal input elsewhere in the code. I believe the ±5 won’t apply as this only happens if a button is pressed, which your code setting the two first values to $ff will not happen.

Ideas:

On my Rover, on the first implemention I controlled it with a HITEC rc receiver, which I had the BAP intercepting the RC signals and then have the BAP use HSERVO and the like to control the motors, I also had encoders trying to keep counts… I found I was maxing out the PRO. So I was considering using two BAPS or a BAP and a Propeller… My idea was to have one processor handle a lot of the IOS, in much the same way as you are wanting. So what I was planning to do is:

Have a three IO lines between the modules (could be done with 2). One of these IO lines would be used for serial input(ser) to the BAP, one would be an output from the BAP(rdy) and the third and input to the BAP(ndata).

so when your IO processor has new data for the BAP it would set a state on the NDATA line (assume pull it high). So when in the BAP code you get back up to main and want to know if you have input, you would simply check the state of the NDATA io line and if it is high, you would process it, if low you would simply continue.

To process the input on the BAP you would pull the IO line RDY high to signal the other processor you are ready for it and then go into the serin to get the new state. At which point both side would clear their state lines and this starts over again.

If you find that doing this type approach causes the robot to speed up when no new input is received then you could add in a real time clock and start each step after the input on a prescribed timing…

As I mentioned above you could do this with two io lines. The two signalers could be on one line that has a pull-up resistor. Each side could then pull it down when it wishes to signal the other side. Each side could also use interrupts to process the new states. While in the end this is probably the way I would go, I think it is a little harder to understand…

I hope this helps.

Kurt

Hi guys and thanks for the feedback.

I have though about adding control lines between the bap and my micro but why do it if the code is already there. The bap sends a “RD” signal every time that it is polling the serial port. This signal I use in my micro to send my serial command when needed.
I’m pretty sure that the BAP code needs only a small modification so it can operate as I wish but since I’m no programmer I’m having a hard time with this. :cry: I hope Laurent chimes in and sees this.

Thanks for taking the time to help me out, I really appreciate it.

Laurent is not on the forum on a regular basis. There isn’t anything in here asking anything from him. The one question I had on the first page was already answered. What specifically do you need from him?

Hi Kurte,

I certainly can see your approach. I like to “buffer upâ€

Hi Jim

It’s not a bug or something like this that Laurent can help me out. I’ts just that he is the developer of the program and might be able to easily point out some tips to help me get the program do what I want it.
Take a look at this post to see what I’m after
lynxmotion.net/phpbb/viewtop … 9099#49099

Thank you all for your time

Hi again,

Yep Laurent knows the code very well! I have a pretty good idea of how the code works as I was probably the first one to do the conversions to make it work on an atom pro.

As I said I am pretty sure it is the timing differences between receiving data and not receiving data. The code sort-of relies on reasonably consistent times of making it through the main loop. This works well on the PS2 code as it is pretty close to constant time to read the PS2.

However with the serial input code you with using the timeout to control thing changes the timing of the loop a reasonable amount. For example at 9600 baud sending 2 bytes and reading 7 with throwing in a little overhead for your other program waking up to respond to your request may take in the order of: (10 chars * 10 bits per char)/9600 ~ .01 seconds, where as your timeout is .2 seconds. Or in other words you are about 20 times faster when you receive input then when you don’t. Now this may be somewhat off as you might be using up more time in the normal case than I estimated…

As you mentioned the code already has a handshack between the two boards with the serout of “RD”. This is mainly there to tell the other side you are ready for input and sitting in a serin. This is necessary as this IO port has no serial hardware support, so if your code is not sitting in a serin when serial data arrives, the data will be lost. What I was suggesting was to have handshaking that tells your code that you have new Changed input to process. The code to do this would be very easy. Also the code on the main processor could do things like checking for slop or the like and only sending real changes.

There are other approaches that I have used or considered.

  1. change your interface from using S_OUT to using the IO ports that have hardware serial support (hserin/hserout) which are on P14 and P15. Note these two IO lines are TTL not rs232 so you would need to change something on the other board… This would allow your main board to send you data at any point and not have to have the BAP code sitting in an serin to process it. You could use interrupts to receive the new input and just have the main loop rely on the latest buffered values.

  2. *** Hack Alert *** - It turns out that S_IN and S_OUT are on the same IO line on the underlying H8 processor and that this IO line cooresponds to IRQ0. So in my TV Brat plus project, I had a VB sequencer program on the PC that if the user clicked a button like try one step of the sequence, I needed to communicate this with the brat. Putting a serin in the main loop and time out was too much overhead, so what I did was:

Setup IRQ0 on the BAP(falling edge…).

When the PC has new data available it sends out a one byte message, which I believe was 0x0, it might have been 0xff. With this one byte and the start and stop bit it has one simple little pulse that is great to trigger the interrupt on the BAP.

The Interrupt handler on the BAP simply sets a flag (variable) that says the interrupt happened.

In the main loop, it could simply test to see if the interrupt happened (flag set), if so it does the normal input (would not need to change the code here), except to clear the flag. Also the host after sending data to the BAP would clear its state, so it knows to signal the BAP again on the next change. If on the BAP the variable was not set, it could simply use the old values.

Just another 3 cents worth.

Kurt