T-Hex, a Mech inspired 6x4 DOF hexapod

It sure get messed up for some reason, another analyzer screendump when doing PL0SQ2ONCE:


The “O” and the “N” from ONCE got through this time :unamused: :laughing:
I’ve done several samples and they seem a bit random.

:smiley:

Problem solved!
I got a feeling that the disable or enable TIMERINT had something to do with it. So I added a little 10mS pause before and after. And that did the magic!

;Start sequence IF (GPStart=1) THEN gosub ControlAllowInput[0] disable TIMERINT pause 10 serout cSSC_OUT, cSSC_BAUD, "PL0SQ", dec GPSeq, "ONCE", 13] ;Start sequence pause 10' for testing enable TIMERINT

Proof:

10mS? That’s years!

Glad you got it working.
Alan KM6VV

WoW!! this is awesome…I just placed together the ed209 with a humanoid torso…but I don’t know anything about programming it or where to even start so I guess that’s as far as i can get… can’t wait to see the video of this T-hex…love your other work.

Glad you got it working. I am glad it showed up on the analyzer and you have a fix. I was going to suggest a pause if something showed up. As I have mentioned before, when we tell the XBee not to send, it may send up to 2 more characters and you are probably being hit by the interrupt that the HSERIAL had to process these characters… My guess a pause of 1 may be sufficient. That is if the XBee is running at 62500, the time it would take for us to receive 2 characters in ms would be approx: ((2*10)/62500) * 1000) or .32ms…

Kurt

Hi Kurt and Alan,

The 10 mS was just a test to see if it made it work. I’ll set it to 1 mS. In this part of the code 10mS isn’t a “year” because we are about to command a GP sequence that take several seconds. A pause of 10mS after entering the command isn’t noticeable at all. :wink:

Can’t say I remember this part :blush: but thanks for your explanation!

Thanks, and welcome to this forum!
Well… T-hex is kinda old news.
Here is an old (low quality) video:

It can also be seen in this video:

Hi Zenta,

Good to hear you had some fun with your course. I bet your audience had a good time as well! :slight_smile:

I’m sorry to hear about the GP-player. I have to say that I had the same problems some time ago. Sorry I didn’t mention it but I thought I messed something up while working on the TA stuff. Good to see you and Kurt already found the issue. I need to update my version as soon as possible before I don’t forget the solution.

BTW, do you have feedback if the GP player is enabled?? Dude, now I really want xbee :stuck_out_tongue:

Xan

Hi Xan,

I think the audience had a good time too. Its the first time someone has asked me for an autograph… :unamused: :laughing:
Yes, its a good thing to have the GP working again. It was a bit embarrassing under demonstration to see that it didn’t play.

Talking about XBee and GP feedback. At this moment I only get feedback when the sequence is started and ended. But it would be cool to get continuous feedback of what the current step is, similar to the GP player in Visual Sequences. I’ve also thought of using the right up/down joystick to directly control the speed and direction of the current sequence. That would be fun!

Xan: yes bidirectional communications like XBee open up lots of interesting capabilities.

I added the feedback code when I converted to the XBees. It has code that if you try to enter GP mode and the SSC-32 does not support that, it will tell you. Then when you try to run a sequence I check to see if the sequence it will first verify that sequence is defined (Checks the SSC-32 EEPROM to see if the pointer to sequence is valid… If it is I output sequence is stared, else I output sequence not defined. Then after GPPlayer completes, it outputs that the sequence was completed.

Zenta: Could easily be added. We could add code in the GPPlayer function: Maybe something like:

[code];--------------------------------------------------------------------
;[GP PLAYER]
GPStatSeq var byte
GPStatFromStep var byte
GPStatToStep var byte
GPStatTime var byte
GPStatFromStepPrev var byte
GPPlayer:

;Start sequence
IF (GPStart=1) THEN
gosub ControlAllowInput[0]
disable TIMERINT

serout cSSC_OUT, cSSC_BAUD, "PL0SQ", dec GPSeq, "ONCE", 13] ;Start sequence
enable TIMERINT

GPStatFromStepPrev = 0xff
;Wait for GPPlayer to complete sequence    
do
	pause 100
	disable TIMERINT
	serout cSSC_OUT, cSSC_BAUD, "QPL0", 13] 
	serin cSSC_IN, cSSC_BAUD, 200000, TO_GPWAIT, [GPStatSeq, GPStatFromStep, GPStatToStep, GPStatTime]
	enable TIMERINT	    ' make sure we are enabled if we timed out as well...
	
	if GPStatFromStepPrev <> GPStatFromStep then
		gosub ControlGPStatus[GPStatFromStep]
		GPStatFromStepPrev = GPStatFromStep
	endif
    	
while (GPStatSeq<>255) or (GPStatFromStep<>0) or (GPStatToStep<>0) or (GPStatTime<>0)

TO_GPWAIT:
enable TIMERINT ’ make sure we are enabled if we timed out as well…

GPStart=0
gosub ControlAllowInput[1]

ENDIF

return[/code]

Pardon my unnecessary changes of using the do/while instead of ifs and goto…

Then we would have to define dummy functions for the other control inputs like:

CGPSStep var byte ControlGPStatus [CGPSStep] : ; output to display... return

But in the XBee version you could easily build a string that said something like: Step XX

Kurt

Hi Kurt,

Thanks a lot for your help!

But I’ve a little problem, I’m not able to send the string to the DIY. There must be something I’m doing wrong here. The byte to string converting part work ok. Are you able to see what I’m doing wrong?

[code];[GP PLAYER]
GPStatSeq var byte
GPStatFromStep var byte
GPStatToStep var byte
GPStatTime var byte
GPStatFromStepPrev var byte
GPPlayer:

;Start sequence
IF (GPStart=1) THEN
gosub ControlAllowInput[0]
disable TIMERINT
pause 10
serout cSSC_OUT, cSSC_BAUD, “PL0SQ”, dec GPSeq, “ONCE”, 13] ;Start sequence
pause 10
enable TIMERINT

GPStatFromStepPrev = 0xff

;Wait for GPPlayer to complete sequence
do
pause 100
disable TIMERINT
serout cSSC_OUT, cSSC_BAUD, “QPL0”, 13]
serin cSSC_IN, cSSC_BAUD, 200000, TO_GPWAIT, [GPStatSeq, GPStatFromStep, GPStatToStep, GPStatTime]
enable TIMERINT ’ make sure we are enabled if we timed out as well…

  if GPStatFromStepPrev <> GPStatFromStep then
     gosub ControlGPStatus[GPStatFromStep]

     GPStatFromStepPrev = GPStatFromStep
  endif

while (GPStatSeq<>255) or (GPStatFromStep<>0) or (GPStatToStep<>0) or (GPStatTime<>0)

TO_GPWAIT:
enable TIMERINT ’ make sure we are enabled if we timed out as well…

GPStart=0

gosub ControlAllowInput[1]
ENDIF

return

bCGPSStep var byte
bCGPSStepLast var byte
sGPStepTxt var byte(9)
ControlGPStatus [bCGPSStep] :
sGPStepTxt = "Step: "
Index = 0
do ;Convert byte value to string:
bCGPSStepLast = bCGPSStep
sGPStepTxt(7-Index) = “0” + bCGPSStep // 10
bCGPSStep = bCGPSStep / 10
Index = Index + 1
while (bCGPSStepLast >= 10)
#IFDEF ZentaDebug
disable TIMERINT
pause 10
serout s_out, i57600, str sGPStepTxt\8, 13]
pause 10
enable TIMERINT
#ENDIF
; output to display…
gosub XBeeOutputString@sGPStepTxt]
return[/code]

I have a feeling it has something with the first byte that should be a count. I did try to add 8 in the start of the string but that didn’t work either. Any hint would be appreciated.

Yep using that function, assumes that the first byte is the count of bytes… But if you look at the actual function, it simply ends up doing:

gosub SendXBeePacket[_wTransmitterDL, XBEE_RECV_DISP_STR, cnt, string…]

so you might try replacing:
gosub XBeeOutputString@sGPStepTxt]

with
gosub SendXBeePacket[_wTransmitterDL, XBEE_RECV_DISP_STR, 8,@sGPStepTxt]

Could generate another wrapper for this…

Kurt

Hi Kurt,

Thanks, I did a short test, but it didn’t compile:

Ok I will play around on my Arc32 phoenix and see if I can get it up and running…

Kurt

Zenta, a slight variation of your code worked on my machine. I did put the count at the start of the string and then had to offset where the number started, and it sent the messages showing that the different steps was happening. This was on my Arc32 Phoenix with my SSC-32 sequence emulation… 1 sequence appears to be hanging now, so I need to debug that, but I doubt it has anything to do with the new code…

But then I started to think. When we are running the sequence, we have disabled receiving data from the XBEE (ControlAllowInput[0]). Not sure what the XBee does when you try to send data out and RTS is off… (Could not easily test that here as, my CHR-3 has Arduino on it now and the phoenix with no SSC-32 does not use the RTS. So I hacked up the code some to add a check to see if the line is defined and input is disabled, to temporarily turn it on before you send the data out and then turn it back off on the way out.

The function now looks like:

[code];==============================================================================
; [ControlGPStatus] - Allows us to pass back status about the GP sequence
;==============================================================================
bCGPSStep var byte
bCGPSStepLast var byte
sGPStepTxt var byte(9)
fInputAllowedSaved var byte

ControlGPStatus [bCGPSStep] :
#ifdef cXBEE_RTS
fInputAllowedSaved = g_fAllowInput
if !fInputAllowedSaved then
ControlAllowInput[1] ; we may need to allow input for the message to output properly…
endif
#endif
sGPStepTxt = 8,"Step: "
Index = 0
do ;Convert byte value to string:
bCGPSStepLast = bCGPSStep
sGPStepTxt(8-Index) = “0” + bCGPSStep // 10
bCGPSStep = bCGPSStep / 10
Index = Index + 1
while (bCGPSStepLast >= 10)
; output to display…
gosub XBeeOutputString@sGPStepTxt]

#ifdef cXBEE_RTS
fInputAllowedSaved = g_fAllowInput
if !fInputAllowedSaved then
ControlAllowInput[0] ; we needed to turn off input again.
pause 1 ; give the system some time to flush any pending chars
endif
#endif

return
[/code]
Note: before now the function ControlAllowInput did not save away the state, it simply set the IO line high or low. I could test that, but instead changed the function to save away the state.

;============================================================================== ; [ControlAllowInput] - Are we allowing input? ;============================================================================== _fCAI var byte ControlAllowInput[_fCAI]: #ifdef cXBEE_RTS gosub XbeeRTSAllowInput[_fCAI] #endif g_fAllowInput = _fCAI return

The variable g_fAllowInput was defined as a byte up in the declarations in the file and I init it to 1 in the input function… Let me know if it works for you…

Kurt

Side Note: With the current Arc 32 phoenix code that I was testing this with, I have in it code that outputs the voltages to the remote control. I think I will be making some minor changes to the transmitter code, that if an output string has happened since the last output value, the whole line should be cleared. Right now the values are showing up in the middle of strings…

Awesome Kurt, it works fine now! :smiley:

Just some minor changes, you forgot the gosub in the call of the ControlAllowInput’s.
The g_fAllowInput needed to be declared in the main file (I first tried declaring it in the DIY control file without success).

My next step is to add speed control (both reverse and forward) using the right joystick up/down.

Thank you so much for your help! Highly appreciated.

You are welcome, glad it is working. Sorry about missing the gosub :laughing: Must have had C on the brain!

Hi Kurt and others,

This might not be the correct thread to post about the GP since I keep running out of memory space for T-Hex and so far I’ve only made sequences on PEP for my Phoenix.

Anyway…
I’ve done some more work on the GP player part. Added speed control using the right Up/Down joystick as an input for the speed multiplier. This makes it possible to have some sort of control of the sequence by adjusting direction (play same part back and forward) while adjusting the speed. Pretty cool if you ask me! :smiley: I’ll demonstrate this in my next workshop video one day. When one sequence is activated nothing happens before you start moving the joystick upward and the result is a much more smooth transition between the current pose and the actual sequence.

The ONCE command does not work as expected if you send a new SM (speed multiplier) command so I had to find a way to stop the sequence when it reached the last step again. The best way was to read the header to get the amount of steps in the current sequences: This is part of the DIY control file:

[code]GPi var nib
IF (bXBeeControlMode = GPPlayerMode & iNumButton>=1 & iNumButton<=9 ) THEN ;1-9 Button Play GP Seq
IF (GPStart = 0) THEN
GPSEQ = iNumButton-1
ENDIF

			  serout cSSC_OUT, cSSC_BAUD, "EER -", dec GPSEQ*2, ";2",13];Read adr to current seq
			  serin cSSC_IN, cSSC_BAUD, 20000, _TO_GPSP, [str wNewDL\2] ;read in 2 byte header - bugbug reuse a local variable

_TO_GPSP:

			IF (wNewDL = 0)  or (wNewDL = 0xffff)	THEN
				gosub XBeeOutputString@_GPSEQNOTDEF]  ; that sequence was not defined...
				gosub XBeePlaySounds@_GPSNDERR, 4];	// BUGBUG: maybe should pass number of notes instead?
			ELSE
				;@0:1 = pointer to sequence 0 (high byte in address 0, low byte in address 1)
				;Read the sequence header:
				serout cSSC_OUT, cSSC_BAUD, "EER -", dec (wNewDL.highbyte*256+wNewDL.lowbyte), ";3",13] 
				For GPi = 0 to 2
					serin cSSC_IN, cSSC_BAUD, 20000,_TO_GPH, [GPVerData(GPi)];NB! reuse of the GPVerData
				next

_TO_GPH: ;serout s_out, i57600, “#steps:”, dec GPVerData(2),13]
; let user know that sequence was started
gosub XBeeOutputString@_GPSEQSTART] ; Tell user sequence started.

				fGPSequenceRun = 1 ; remember that ran one...
				GPStart = 1
			ENDIF
			iNumButton = 0 ; reset
		ENDIF
		
		IF ((bXBeeControlMode = GPPlayerMode) & (fGPSequenceRun = 1)) THEN
			bGPSM = (bPacket(PKT_RJOYUD)-128);Set GP Speed
			
		ENDIF[/code]

Code from the main file. I’m reusing the GPVerData to hold the # of steps in gait. Also send updates to the DIY remote of the current SM (speed multiplier).

[code];[GP PLAYER]
GPStatSeq var byte
GPStatFromStep var byte
GPStatToStep var byte
GPStatTime var byte

GPPlayer:

;Start sequence

IF (GPStart=1) THEN
bGPSM = 0
gosub ControlAllowInput[0]
disable TIMERINT
pause 10
serout cSSC_OUT, cSSC_BAUD, “PL0SQ”, dec GPSeq,“SM”, dec bGPSM, 13] ;Start sequence
pause 10
enable TIMERINT

;Wait for GPPlayer to complete sequence
do
pause 50
disable TIMERINT
serout cSSC_OUT, cSSC_BAUD, “QPL0”, 13]
serin cSSC_IN, cSSC_BAUD, 200000, TO_GPWAIT, [GPStatSeq, GPStatFromStep, GPStatToStep, GPStatTime]
serout cSSC_OUT, cSSC_BAUD, “PL0SM”, sdec bGPSM, 13] ; set speed
;The ONCE command does not work after PL0SM cmd, therefore our own function for stopping the player
;NB! Reuse of the GPVerData, now it contains total # of steps in current sequence
IF (GPStatFromStep = (GPVerData(2)-1))&(GPStatTime=0)THEN;Stop SQ at the last step in SQ,
serout cSSC_OUT, cSSC_BAUD, “PL0”, 13] ;Stop player
sound cSound, [50\1000]
ENDIF
enable TIMERINT ’ make sure we are enabled if we timed out as well…
gosub ControlGPStatus[GPStatFromStep]

while (GPStatSeq<>255) or (GPStatFromStep<>0) or (GPStatToStep<>0) or (GPStatTime<>0)

TO_GPWAIT:
enable TIMERINT ’ make sure we are enabled if we timed out as well…

GPStart=0

gosub ControlAllowInput[1]
ENDIF

return
;==============================================================================
; [ControlGPStatus] - Allows us to pass back status about the GP sequence
;==============================================================================
bCGPSStep var byte
bCGPLast var byte
sGPStepTxt var byte(15)
fInputAllowedSaved var byte

ControlGPStatus [bCGPSStep] :
#ifdef cXBEE_RTS
fInputAllowedSaved = g_fAllowInput
if !fInputAllowedSaved then
gosub ControlAllowInput[1] ; we may need to allow input for the message to output properly…
endif
#endif

sGPStepTxt = 14,"CS: SM: " ;Current Step and Speed Multiplier
Index = 0
do ;Convert byte value to string:
bCGPLast = bCGPSStep
sGPStepTxt(6-Index) = “0” + bCGPSStep // 10
bCGPSStep = bCGPSStep / 10
Index = Index + 1
while (bCGPLast >= 10)

  If bGPSM < 0 then
  	sGPStepTxt(10) = "-"
 	bGPSM = -bGPSM
  	Index = 1   
  endif

  do ;Convert byte value to string:
     bCGPLast = bGPSM
     sGPStepTxt(14-Index) = "0" + bGPSM // 10
     bGPSM = bGPSM / 10
     Index = Index + 1
  while (bCGPLast >= 10)
  GOSUB ControlInput	; Need to update the Speed Multiplier bGPSM 
; output to display...

gosub XBeeOutputString@sGPStepTxt]

#ifdef cXBEE_RTS
fInputAllowedSaved = g_fAllowInput
if !fInputAllowedSaved then
gosub ControlAllowInput[0] ; we needed to turn off input again.
pause 1 ; give the system some time to flush any pending chars
endif
#endif

return [/code]

There are also some other changes like an #IFDEF USEGP for excluding the GP part, or else T-Hex 4 DOF wont compile due to mem space.
This part won’t work with the PS2, I might try to make a PS2 version of the code later.
T_Hex_Phoenix_GP update.zip (55.8 KB)

Sounds like fun! Will be fun to try it out and. No video yet??? I may have to integrate this support into my Arc32 only version…

Kurt

Sounds very cool! 8)

You’ve to wait for the video since I thought I should tell a little about MorpHex too.
One thing I’m wondering about:

Does the internal reg offset in SSC-32 has any effect on GP sequences?

I’m asking because I observed that some servos was a little off in the sequences. Then I realized that these servos was the one I had replaced, meaning that the sequences stored in the EEPROM was calibrated values for the old servos. My solution to solve this is to reprogram the EEPROM after calibrating in the SSC-32 configuration in Visual SEQ.