BRAT based Mech is taking names and... You know the rest

The little guy can walk forward / backwards, turn left and right, rotate the turret, and shoot either of the two guns. All from the Atom Pro / PS2 game controller. There is a twitch in the guy that we are trying to nail down. We will have a nice video very soon. hehe 8)

Video here

Here’s the code I’m using. I started with the Autonomous BRAT code and spliced in bits of Xan’s code for PS2 control… It seemed like a good idea at the time… :laughing:
But it twitches a lot without touching any controls. I’m using 8.0.1.11 for this.

[code];Program written for Bot Board II, Basic Atom Pro 28, IDE Ver. 8.0.1.7
;Written by Nathan Scherdin, modified by Jim and James Frye
;System variables
righthip con p10
rightknee con p8
rightankle con p7
lefthip con p6
leftknee con p5
leftankle con p4

turret con p11
RGUNP con p0
RGswP con p1
LGUNP con p2
LGswP con p3

;[PS2 Controller]
PS2DAT con P12 ;PS2 Controller DAT (Brown)
PS2CMD con P13 ;PS2 controller CMD (Orange)
PS2SEL con P14 ;PS2 Controller SEL (Blue)
PS2CLK con P15 ;PS2 Controller CLK (White)
PadMode con $79

true con 1
false con 0

BUTTON_DOWN con 0
BUTTON_UP con 1

TravelDeadZone con 4 ;The deadzone for the analog input from the remote

;calibrate steps per degree.
stepsperdegree fcon 166.6

;You must calibrate the servos to “zero”. Each robot will be different!
;When homed in and servos are at 0 degrees the robot should be standing
;straight with the AtomPro chip pointing backward. If you know the number
;of degrees the servo is off, you can calculate the value. 166.6 steps
;per degree. The values for our test robot were found by running the
;program bratosf.bas written by James Frye.

righthip_start con 540
rightknee_start con -240
rightankle_start con 300

lefthip_start con -1140
leftknee_start con -120
leftankle_start con -660

turret_start con 0

;Interrupt init
ENABLEHSERVO

command var byte
xx var byte
RSwitch var bit
PrevRSW var bit
LSwitch var bit
PrevLSW var bit
TurretAngle var sword
IdleBot var word

BotActive var bit
BotActive = FALSE

;[Ps2 Controller]
DualShock var Byte(7)
LastButton var Byte(2)
DS2Mode var Byte
PS2Index var byte
BodyYShift var sbyte

;PS2 controller
high PS2CLK
LastButton(0) = 255
LastButton(1) = 255

;Init positions
;Note, movement subroutine arguments are Rightankle,Rightknee,Righthip,Leftankle,Leftknee,Lefthip,Turret,speed
gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

RGUNP con p0
RGswP con p1
LGUNP con p2
LGswP con p3

;Gun Initialization
hservo [RGUNP\0\0]
hservo [LGUNP\0\0]

;low 1
;low 2
pause 1000

;---------------------------------------;
;--------Command Quick Reference--------;
;---------------------------------------;
;- Command 1 = Walk Forward -;
;- Command 2 = Walk Backward -;
;- Command 3 = Long Stride Forward -;
;- Command 4 = Long Stride Backward -;
;- Command 5 = Kick -;
;- Command 6 = Headbutt -;
;- Command 7 = Get up from Front -;
;- Command 8 = Get up from Back -;
;- Command 9 = Rest Position -;
;- Command 0 = Home Position -;
;- Command 11= Turn Left -;
;---------------------------------------;

     sound 9,[50\4000,40\3500,40\3200,50\3900]

main

gosub PS2INPUT

if(IdleBot = 1000)then
command = 9
gosub move
else
IdleBot = IdleBot + 1
pause 15
endif

RSwitch = in1
LSwitch = in3

if PrevRSW = 0 AND RSwitch = 1 then
hservo [RGUNP-7000\0]
else
PrevRSW = RSwitch
endif

if PrevLSW = 0 AND LSwitch = 1 then
hservo [LGUNP-7000\0]
else
PrevLSW = LSwitch
endif

goto main

move:
if(command = 1) then ; Walk Forward
gosub movement 7.0,-20.0,-20.0, -7.0, 20.0, 20.0, 0.0,500.0]
gosub movement -7.0,-20.0,-20.0, 7.0, 20.0, 20.0, 0.0,500.0]
gosub movement -7.0, 20.0, 20.0, 7.0,-20.0,-20.0, 0.0,500.0]
gosub movement 7.0, 20.0, 20.0, -7.0,-20.0,-20.0, 0.0,500.0]
elseif(command = 2) ; Walk Backward
gosub movement -7.0,-20.0,-20.0, 7.0, 20.0, 20.0, 0.0,500.0]
gosub movement 7.0,-20.0,-20.0, -7.0, 20.0, 20.0, 0.0,500.0]
gosub movement 7.0, 20.0, 20.0, -7.0,-20.0,-20.0, 0.0,500.0]
gosub movement -7.0, 20.0, 20.0, 7.0,-20.0,-20.0, 0.0,500.0]
; elseif(command = 3) ; Long Stride Forward
; gosub movement -12.0, 45.0, 45.0, 12.0,-45.0,-45.0, 0.0,750.0]
; gosub movement 12.0, 45.0, 45.0,-12.0,-45.0,-45.0, 0.0,750.0]
; gosub movement 12.0,-45.0,-45.0,-12.0, 45.0, 45.0, 0.0,750.0]
; gosub movement -12.0,-45.0,-45.0, 12.0, 45.0, 45.0, 0.0,750.0]
; elseif(command = 4) ; Long Stride Backward
; gosub movement -12.0,-45.0,-45.0, 12.0, 45.0, 45.0, 0.0,750.0]
; gosub movement 12.0,-45.0,-45.0,-12.0, 45.0, 45.0, 0.0,750.0]
; gosub movement 12.0, 45.0, 45.0,-12.0,-45.0,-45.0, 0.0,750.0]
; gosub movement -12.0, 45.0, 45.0, 12.0,-45.0,-45.0, 0.0,750.0]
; elseif(command = 5) ; Kick
; gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 500.0]
; gosub movement 42.0, 0.0, 0.0,-14.0, 0.0, 0.0, 0.0, 500.0]
; gosub movement 0.0,-32.0, 41.0,-23.0, 0.0, 0.0, 0.0, 500.0]
; gosub movement 0.0, 24.0,-20.0,-23.0, 0.0, 0.0, 0.0, 250.0]
; gosub movement 0.0, 0.0, 0.0,-18.0, 0.0, 0.0, 0.0, 500.0]
; gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 500.0]
; elseif(command = 7) ; Get up from front
; gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,500.0]
; gosub movement 0.0, 90.0, 45.0, 0.0, 90.0, 45.0, 0.0,500.0]
; gosub movement 40.0, 90.0,-37.0, 0.0, 90.0, 45.0, 0.0,500.0]
; gosub movement 0.0, 90.0,-65.0, 0.0, 90.0,-65.0, 0.0,500.0]
; elseif(command = 8) ; Get up from back
; gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,1000.0]
; gosub movement 0.0,-90.0, 5.0, 0.0,-90.0, 5.0, 0.0,1000.0]
; gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,1000.0]
;pause 1000
;gosub movement 0.0, 22.0,-80.0, 0.0, 22.0,-80.0,1000.0]
;gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,1000.0]
elseif(command = 0) ; Home Position
gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 500.0]
; sound 9,[50\4400]
; pause 50
; sound 9,[50\4400]
; pause 50
; sound 9,[50\4400]
; elseif(command = 6) ; Headbutt
; gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,500.0]
; gosub movement 0.0,-50.0,-90.0, 0.0,-50.0,-90.0, 0.0,500.0]
; gosub movement 0.0, 32.0,-58.0, 0.0, 32.0,-58.0, 0.0,400.0]
; pause 200
;gosub movement 0.0,-11.0, 7.0, 0.0,-11.0, 7.0, 500.0]
; gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 500.0]
; sound 9,[50\4400]
; pause 50
; sound 9,[50\3960]
; pause 50
; sound 9,[50\3960]
; elseif(command = 11) ; Turn left
; gosub movement 0.0,-35.0,-40.0, 0.0, 35.0, 37.0, 0.0,500.0]
; gosub movement 0.0, 35.0, 37.0, 0.0,-35.0,-40.0, 0.0,500.0]
; gosub movement -14.0, 35.0, 37.0, 20.0,-35.0,-40.0, 0.0,500.0]
; gosub movement -14.0, 35.0, 37.0, 20.0, 35.0, 37.0, 0.0,500.0]
; gosub movement 20.0, 35.0, 37.0,-14.0, 35.0, 37.0, 0.0,500.0]
; gosub movement 20.0,-35.0,-40.0,-14.0, 35.0, 37.0, 0.0,500.0]

     ;gosub movement   0.0,-35.0,-70.0,  0.0, 35.0,  7.0,500.0] 
     ;gosub movement   0.0, 35.0,  7.0,  0.0,-35.0,-70.0,500.0] 
     ;gosub movement -14.0, 35.0,  7.0, 20.0,-35.0,-70.0,500.0] 
     ;gosub movement -14.0, 35.0,  7.0, 20.0, 35.0,  7.0,500.0] 
     ;gosub movement  20.0, 35.0,  7.0,-14.0, 35.0,  7.0,500.0] 
     ;gosub movement  20.0,-35.0,-70.0,-14.0, 35.0,  7.0,500.0] 



  elseif(command = 9)							; Rest Position 
     gosub movement   0.0, 45.0, 45.0,  0.0, 45.0, 45.0,  0.0,500.0] 
  endif 

IdleBot = 0
return

;--------------------------------------------------------------------
;[PS2Input] reads the input data from the PS2 controller and processes the
;data to the parameters.
Ps2Input:

low PS2SEL
shiftout PS2CMD,PS2CLK,FASTLSBPRE,$1\8]
shiftin PS2DAT,PS2CLK,FASTLSBPOST,[DS2Mode\8]
high PS2SEL
pause 1

low PS2SEL
shiftout PS2CMD,PS2CLK,FASTLSBPRE,$1\8,$42\8]
shiftin PS2DAT,PS2CLK,FASTLSBPOST,[DualShock(0)\8, DualShock(1)\8, DualShock(2)\8, DualShock(3)\8, |
DualShock(4)\8, DualShock(5)\8, DualShock(6)\8]
high PS2SEL
pause 1

if DS2Mode <> PadMode THEN
low PS2SEL
shiftout PS2CMD,PS2CLK,FASTLSBPRE,$1\8,$43\8,$0\8,$1\8,$0\8] ;CONFIG_MODE_ENTER
high PS2SEL
pause 1

low PS2SEL
shiftout PS2CMD,PS2CLK,FASTLSBPRE,$01\8,$44\8,$00\8,$01\8,$03\8,$00\8,$00\8,$00\8,$00\8] ;SET_MODE_AND_LOCK
high PS2SEL
pause 1

low PS2SEL
shiftout PS2CMD,PS2CLK,FASTLSBPRE,$01\8,$4F\8,$00\8,$FF\8,$FF\8,$03\8,$00\8,$00\8,$00\8] ;SET_DS2_NATIVE_MODE
high PS2SEL
pause 1

low PS2SEL
shiftout PS2CMD,PS2CLK,FASTLSBPRE,$01\8,$43\8,$00\8,$00\8,$5A\8,$5A\8,$5A\8,$5A\8,$5A\8] ;CONFIG_MODE_EXIT_DS2_NATIVE
high PS2SEL
pause 1

low PS2SEL
shiftout PS2CMD,PS2CLK,FASTLSBPRE,$01\8,$43\8,$00\8,$00\8,$00\8,$00\8,$00\8,$00\8,$00\8] ;CONFIG_MODE_EXIT
high PS2SEL
pause 100
	
sound P9,[100\3000, 100\3500, 100\4000]
return

ENDIF

IF (DualShock(1).bit3 = 0) and LastButton(0).bit3 THEN ;Start Button test
IF(BotActive) THEN
'Turn off
Sound P9,[100\4400,80\3800,60\3200]
command = 9
gosub move
BotActive = False
ELSE
'Turn on
Sound P9,[60\3200,80\3800,100\4400]
command = 0
gosub move
BotActive = True
ENDIF
ENDIF

IF BotActive THEN
; IF (DualShock(1).bit0 = 0) and LastButton(0).bit0 THEN ;Select Button test
; ENDIF

IF (DualShock(1).bit4 = 0) THEN;and LastButton(0).bit4 THEN	;Up Button test
  command = 1
  gosub move
ENDIF
	
IF (DualShock(1).bit6 = 0) THEN;and LastButton(0).bit6 THEN	;Down Button test
  command = 2
  gosub move	
ENDIF

; IF (DualShock(2).bit4 = 0) and LastButton(1).bit4 THEN ;Triangle Button test
; ENDIF

; IF (DualShock(2).bit5 = 0) and LastButton(1).bit5 THEN ;Circle Button test
; ENDIF

IF (DualShock(2).bit6 = 0) and LastButton(1).bit6 THEN	;Cross Button test
	command = 0
	gosub move
ENDIF	

; IF (DualShock(2).bit7 = 0) and LastButton(1).bit7 THEN ;Square Button test
; ENDIF

IF (DualShock(2).bit3 = 0) THEN	;R1 Button test
	;gosub Fire_R
	hservo [RGUNP\7000\0]
	PrevRSW = BUTTON_UP
ENDIF


IF (DualShock(2).bit2 = 0) THEN	;L1 Button test
	hservo [LGUNP\7000\0]
	PrevLSW = BUTTON_UP

ENDIF

; ELSEIF (DualShock(2).bit0 = 0) ;L2 Button test

; IF (DualShock(2).bit1 = 0) THEN ;R2 Button test
; ENDIF

; ENDIF

IF ((ABS DualShock(6)) > TravelDeadZone) THEN
	TurretAngle = TurretAngle + (Dualshock(5) - 128)/2 MAX 9000 MIN -9000
	;serout s_out,i38400,[sdec TurretAngle, 13]
	hservo [Turret\TurretAngle\200]
	IdleBot = 0	
ENDIF

; TravelLengthZ = (Dualshock(5) - 128)/2
; ENDIF
; TravelRotationY = -(Dualshock(3) - 128)/4

ENDIF

LastButton(0) = DualShock(1)
LastButton(1) = DualShock(2)
return
;--------------------------------------------------------------------

;Fire_R:

;pulsout RGUNP,2000

;return

;Should never need to edit anything below this line. Add user subroutines above this and below main.
lefthippos var float
leftkneepos var float
leftanklepos var float
righthippos var float
rightkneepos var float
rightanklepos var float
turretpos var float
last_lefthippos var float
last_leftkneepos var float
last_leftanklepos var float
last_righthippos var float
last_rightkneepos var float
last_rightanklepos var float
last_turretpos var float
lhspeed var float
lkspeed var float
laspeed var float
rhspeed var float
rkspeed var float
raspeed var float
tuspeed var float
speed var float
longestmove var float
;movement [lefthippos,leftkneepos,leftanklepos,righthippos,rightkneepos,rightanklepos,speed]
movement [rightanklepos,rightkneepos,righthippos,leftanklepos,leftkneepos,lefthippos,turretpos,speed]
if(speed<>0.0)then
gosub getlongest[lefthippos-last_lefthippos, |
leftkneepos-last_leftkneepos, |
leftanklepos-last_leftanklepos, |
righthippos-last_righthippos, |
rightkneepos-last_rightkneepos, |
rightanklepos-last_rightanklepos, |
turretpos-last_turretpos],longestmove
speed = ((longestmovestepsperdegree)/(speed/20.0))
gosub getspeed[lefthippos,last_lefthippos,longestmove,speed],lhspeed
gosub getspeed[leftkneepos,last_leftkneepos,longestmove,speed],lkspeed
gosub getspeed[leftanklepos,last_leftanklepos,longestmove,speed],laspeed
gosub getspeed[righthippos,last_righthippos,longestmove,speed],rhspeed
gosub getspeed[rightkneepos,last_rightkneepos,longestmove,speed],rkspeed
gosub getspeed[rightanklepos,last_rightanklepos,longestmove,speed],raspeed
gosub getspeed[turretpos,last_turretpos,longestmove,speed],tuspeed
else
lhspeed=0.0;
lkspeed=0.0;
laspeed=0.0;
rhspeed=0.0;
rkspeed=0.0;
raspeed=0.0;
tuspeed=0.0;
endif
hservo [lefthip\TOINT (-lefthippos
stepsperdegree) + lefthip_start\TOINT lhspeed, |
righthip\TOINT (righthipposstepsperdegree) + righthip_start\TOINT rhspeed, |
leftknee\TOINT (-leftkneepos
stepsperdegree) + leftknee_start\TOINT lkspeed, |
rightknee\TOINT (rightkneeposstepsperdegree) + rightknee_start\TOINT rkspeed, |
leftankle\TOINT (-leftanklepos
stepsperdegree) + leftankle_start\TOINT laspeed, |
rightankle\TOINT (rightankleposstepsperdegree) + rightankle_start\TOINT raspeed, |
turret\TOINT (turretpos
stepsperdegree) + turret_start\TOINT tuspeed]
hservowait [lefthip,righthip,leftknee,rightknee,leftankle,rightankle,turret]

idle var byte
finished var byte
junk var word
;sensorloop
; finished = true
; gethservo lefthip,junk,idle
; if(NOT idle)then
; finished=false
; endif
; gethservo righthip,junk,idle
; if(NOT idle)then
; finished=false
; endif
; gethservo leftknee,junk,idle
; if(NOT idle)then
; finished=false
; endif
; gethservo rightknee,junk,idle
; if(NOT idle)then
; finished=false
; endif
; gethservo leftankle,junk,idle
; if(NOT idle)then
; finished=false
; endif
; gethservo leftankle,junk,idle
; if(NOT idle)then
; finished=false
; endif
; gethservo turret,junk,idle
; if(NOT idle)then
; finished=false
; endif
;add sensor handling code here

;adin 0,ir
;if (ir > 210) then
; detect = true
;endif

; if(NOT finished)then sensorloop

last_lefthippos = lefthippos
last_leftkneepos = leftkneepos
last_leftanklepos = leftanklepos
last_righthippos = righthippos
last_rightkneepos = rightkneepos
last_rightanklepos = rightanklepos
last_turretpos = turretpos
return

one var float
two var float
three var float
four var float
five var float
six var float
seven var float
getlongest[one,two,three,four,five,six,seven]
if(one<0.0)then
one=-1.0one
endif
if(two<0.0)then
two=-1.0
two
endif
if(three<0.0)then
three=-1.0three
endif
if(four<0.0)then
four=-1.0
four
endif
if(five<0.0)then
five=-1.0five
endif
if(six<0.0)then
six=-1.0
six
endif
if(seven<0.0)then
seven=-1.0*seven
endif
if(one<two)then
one=two
endif
if(one<three)then
one=three
endif
if(one<four)then
one=four
endif
if(one<five)then
one=five
endif
if(one<six)then
one=six
endif
if(one<seven)then
one=seven
endif
return one

newpos var float
oldpos var float
longest var float
maxval var float
getspeed[newpos,oldpos,longest,maxval]
if(newpos>oldpos)then
return ((newpos-oldpos)/longest)*maxval
endif
return ((oldpos-newpos)/longest)*maxval [/code]

I am running this program on a test setup, with just the PS2 controller, 4 servos (RA, RN, RH, Turret). The servos are just sitting on the table so there is no load. Running with Wallwart. This has verified that I am getting servo jitters.

I have tested that Movement function is not getting repeatily run. Only once for (0,0,0…) at the start and then every 1000 times through the loop it calls it for idle. I have also commented out the HSERVO calls to init the guns. Still getting jitters, added an ENABLE to make sure interrupts are enabled. No help yet. Will try commenting out calls to get the PS2 input to see if that help…

Kurt

My guess is this is an issue for Nathan,

I hooked up the logic analyzer and here is a screenshot:
http://i416.photobucket.com/albums/pp245/Kurts_Robots/BratwithPS2HSERVOissue.png

If you look at line 6 you can see one of the places where a jitter happened and the signal is not correct. This cooresponds to IO pin 8 which is the right knee. I skipped useing line 1, but the 7 other lines are to pins (4, 5, 6, 7, 8, 10, 11). I believe looking at the code that P8 is only referenced in the HServo and the HservoWait commands.

It does not jitter if I don’t call the PS2 input code so my guess is it is either the ShiftOut or ShiftIn command that is interferring. Not sure if it is missing an interrupt, a system register being reused, an IO register GRA-GRD, being used… May look some more tomorrow.

Kurt

Good find Kurt!

This looks like the same problem that drove me crazy while programming the arm. What’s your YouTube channel Kurt? I want to show you a vid.

James,

Jim saw the vid I’m talking about. Is it about the same result? I’ve added a longer pause right after reading the PS2 input. I’ve looked at your code but it’s already in there :wink:

[code] low PS2SEL
shiftout PS2CMD,PS2CLK,FASTLSBPRE,$01\8,$43\8,$00\8,$00\8,$00\8,$00\8,$00\8,$00\8,$00\8] ;CONFIG_MODE_EXIT
high PS2SEL
pause 100

sound P9,[100\3000, 100\3500, 100\4000]
return
ENDIF
[/code]

You could try to change the pause back to 1 or another value.

Although the pause solved the problem, I’m not totally sure it’s gone for good.

BTW: Did I already mensioned that you’ve got a awesome mech! 8)

Xan

Hi Xan,

I don’t have a YouTube channel, as I have done everything on photobucket… But if this is the same issue you were chasing with the arm, then it probably implies it is more widespread then I originally thought. My first setup only appeared to catch the twitch on the group of servos on pins 8-11. If this was the only problem, I was going to modify James code to reassign all of the leg servos to lower servo numbers. Move the switches up to the high ones. It would leave one servo left in this group. But if the problem is the same as you had with the arm, then that implies the lower servo numbers have the problem as well.

It seams strange that that pause would help anything. That code should only be executed when the PS2 is not in the proper analog mode. But…

I will try a few more experiments, but to be fixed right will probably require some help from Nathan. My guessing is that, it will turn out something like an interrupt was missed, or maybe it is testing for equal to a value when it may need to be >= to a value… Somehow either pulsin or pulsout interfer.

Kurt

Just to confirm, If you remove the shiftin/shiftout commands it stops glitching? Can you confirm this by commenting out the shiftin/out commands and adding some hardwired movement routines? If we can be sure the problem is shiftin/out it will make it a LOT easier for me to track down. I’m looking at them now but confermation would be appriciated.

I just confirmed it. Taking out the shiftin/shiftout commands stops the twitching.

Thanks. I suspect it’s a read/modify/write problem in shiftin. What is probably happening is the hservo interrupt is triggering after shiftin/out reads the port it’s pin is on but before it writes the new value which would cause the old value on some of the other pins on the port to be rewritten back to the port. It could be the clock pin(which would cause both shiftin and shiftout to cause the problem) or it could be the data pin(in which case it can only be shiftout causing the problem).

A quick workaround for this problem shoudl be to put the servo pins on a different port than the shiftin/out pins. P0 to P7 are on Port5. P8 to P15 are on Port8. P16 to P19 are on Port1.

I’m working on fixing the shiftin/out commands but you won’t see a new release with the fix until sometime next week is my guess. We are in the process of consolidating the IDE into a new Studio with all modules/interpreter chips supported in one dev environment. It’s basically complete but won’t be released until we’ve had some heavy testing done on it.

That’ll be nice!

I’m switching between Basic Atom, Basic Atom Pro and MBasic, and it’s easy to get confused! Same base program.

Alan KM6VV

Just an update. Looks like there is definitely the possibility of a RMW(read modify write) race condition in SHIFTIN/OUT. Also I found one in SOUND. Basically in both these commands an I/O port is read with one command(mov @er#,r#) and then written with another command(mov r#,@er#). This leaves open the possibility the hservo interrupt will happen between these two commands causing the stored value from the read to no longer be valid for the whole port. I’ve updated the shiftin/out commands to use single instruction RMW commands so that should illiminate that problem with shiftin/out. Once I’ve got confirmation on that I’ll update sound to use the same single instruction RMW commands. I looked through the entire library and found no other cases like this so this hopefully will illiminate any more glitches in hservo caused by other commands.

Nice find! I’ll bet that wasn’t easy to discover!

I have have a question, is there an DTMF DECODE function? I’ve heard references to it (in a book review), but it’s not documented in any of the three (Basic Atom, Basic Atom Pro, or MBasic) manuals that I can see.

Thanks!

Alan KM6VV

No there isn’t. I think someone got that wrong in some article a while ago. However I think it could be done. Don’t ask me how though. Maybe check out this link: dattalo.com/technical/theory/dtmf.html

Thanks for the help everyone. :smiley:
So far I’ve switched the pins up, and made a few other changes.
Here’s what the pins look like now:[code]righthip con p5
rightknee con p4
rightankle con p3
lefthip con p2
leftknee con p1
leftankle con p0
turret con p6

RGUNP con p16
RGswP con p17
LGUNP con p18
LGswP con p19

PS2DAT con P12 ;PS2 Controller DAT (Brown)
PS2CMD con P13 ;PS2 controller CMD (Orange)
PS2SEL con P14 ;PS2 Controller SEL (Blue)
PS2CLK con P15 ;PS2 Controller CLK (White)[/code]That seems to have stopped the twitching, and makes a little more sense in my opinion. I’ll work on it a bit more and may shoot a short video later 8)

[size=150]I have my movie ticket! I’m going to camp out till the doors open![/size]

It’s not then. I wondered how it could have been done! Not that easy, as the URL you’ve kindly supplied explains. I might try the example, but probably with a little more processor!

I’ll stick to using a decoder in front of the module!

Thanks!

Alan

:open_mouth: I don’t think I can take that ticket… Neither of us are in Indiana :stuck_out_tongue:

Anyway, here’s the video 8)

That was a great video! I love the pose in the middle. It seemed like there was slight servo hunting when it went back to center but not bad at all.

The torso weighs in at 12.4 ounces. He had a 475 rotating it. He’s changing it to a 645 to prevent the oscillations. 8)

Thats awesome! Scary cool 8)

I love the running leds in front and the rotating torso!