TV remote controlled BRAT project

I moved this from the Bot Board section to here…

BRAT TV remote control redo!

I really wanted to get this into a tutorial, but that’s not going to happen very quickly. So here is the new program for the BRAT with Bot Board, Atom Pro 28, IRPD, for TV style remote control. It works great! I have my BRAT walking forward and backwards, long and short strides, left turns, kick, headbutt, rest, get up from laying on it’s front or back… all from the TV remote control. I have several more buttons that are not programmed yet.

The generic TV remote control is set to Sony #218. The IRPD sensor output (yellow) is connected to pin 3. The blue and violet lines (LED enable) lines are connected to pins 2 and 1. They’re not used yet. The servo connection information is in the program. This version requires the new Pro IDE version 8.0.0.0 beta. I’m really in a time crunch so I’m just putting the code right here in a code box.

The only thing you will have to do is calculate your servos offset value. The HSERVO command uses +/- 24000 for the servo pulses with 0 being 1500us. Each count is worth 0.0625uS. If you know the pulse value to set the servo to exact center you can figure the offset.

Left knee servo example:

Centered value - 1500uS = correction

1470uS -1500uS = -30

-30 / 0.0625 = -480

then put this in the program…

leftknee_start con -480

All the hard work is done, just put in the angles from your Sequencer files to add your own sequences to the bot.

[code];System variables
righthip con p15
rightknee con p14
rightankle con p13
lefthip con p12
leftknee con p11
leftankle con p10

;calibrate steps per degree.
stepsperdegree fcon 166.6

;calibrate servos to “zero”.
;When homed in and servos are at 0 degrees
;the robot should be standing strait with
; irpd pointing up and AtomPro chip pointing forward.
righthip_start con -560
rightknee_start con -720
rightankle_start con 0

lefthip_start con -560
leftknee_start con -480
leftankle_start con -160

;Interrupt init
ENABLEHSERVO

ONINTERRUPT WKPINT_3,handle_irpd
ONINTERRUPT TIMERAINT,handle_timera
PMR5.bit3 = 1
TMA=4 ;increments on clock/256
ENABLE WKPINT_3
ENABLE TIMERAINT

lasttime var long
overflowtime var long
currenttime var long
diff var long
datacount var byte
irpd_data var word
command var byte

lasttime = -1 ;indicate next data should be a startpulse
;End of System setup. Add user variables below this line.

;Init positions
;Note, movement subroutine arguments are Rightankle,Rightknee,Righthip,Leftankle,Leftknee,Lefthip,speed
gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
low 1
low 2
pause 1000

command=0xFF
main
if(command<>0xFF)then
if(command = 1) then ;(Button 2) Walk Forwards
gosub movement -7.0, 20.0, 20.0, 7.0,-20.0,-20.0, 500.0]
gosub movement 7.0, 20.0, 20.0, -7.0,-20.0,-20.0, 500.0]
gosub movement 7.0,-20.0,-20.0, -7.0, 20.0, 20.0, 500.0]
gosub movement -7.0,-20.0,-20.0, 7.0, 20.0, 20.0, 500.0]
elseif(command = 4) ;(Button 5) Walk Backwards
gosub movement -7.0,-20.0,-20.0, 7.0, 20.0, 20.0, 500.0]
gosub movement 7.0,-20.0,-20.0, -7.0, 20.0, 20.0, 500.0]
gosub movement 7.0, 20.0, 20.0, -7.0,-20.0,-20.0, 500.0]
gosub movement -7.0, 20.0, 20.0, 7.0,-20.0,-20.0, 500.0]
elseif(command = 18) ;(Up Vol) long stride forward
gosub movement -12.0, 45.0, 45.0, 12.0,-45.0,-45.0, 750.0]
gosub movement 12.0, 45.0, 45.0,-12.0,-45.0,-45.0, 750.0]
gosub movement 12.0,-45.0,-45.0,-12.0, 45.0, 45.0, 750.0]
gosub movement -12.0,-45.0,-45.0, 12.0, 45.0, 45.0, 750.0]
elseif(command = 19) ;(Dn Vol) long stride backward
gosub movement -12.0,-45.0,-45.0, 12.0, 45.0, 45.0, 750.0]
gosub movement 12.0,-45.0,-45.0,-12.0, 45.0, 45.0, 750.0]
gosub movement 12.0, 45.0, 45.0,-12.0,-45.0,-45.0, 750.0]
gosub movement -12.0, 45.0, 45.0, 12.0,-45.0,-45.0, 750.0]
elseif(command = 2) ;(Button 3) Kick
gosub movement 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, 500.0]
gosub movement 0.0,-32.0, 41.0,-23.0, 0.0, 0.0, 500.0]
gosub movement 0.0, 24.0,-20.0,-23.0, 0.0, 0.0, 250.0]
gosub movement 0.0, 0.0, 0.0,-18.0, 0.0, 0.0, 500.0]
gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 500.0]
sound 9,[50\3960]
pause 50
sound 9,[50\4400]
pause 50
sound 9,[50\3960]
elseif(command = 16) ;(Channel Up) Get up from front
gosub movement 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, 500.0]
gosub movement 40.0, 90.0,-37.0, 0.0, 90.0, 45.0, 500.0]
gosub movement 0.0, 90.0,-65.0, 0.0, 90.0,-65.0, 500.0]
pause 500
gosub movement 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 750.0]
sound 9,[50\4400]
pause 50
sound 9,[50\4400]
pause 50
sound 9,[50\3960]
elseif(command = 17) ;(Channel Dn) Get up from back
gosub movement 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,1000.0]
gosub movement 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]
sound 9,[50\3960]
pause 50
sound 9,[50\3960]
pause 50
sound 9,[50\4400]

	elseif(command = 0)												;(Button 1) Home Position
		gosub movement   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 = 5)												;(Button 6) Headbutt
		gosub movement   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, 500.0]
		gosub movement   0.0, 32.0,-58.0,  0.0, 32.0,-58.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, 500.0]
		sound 9,[50\4400]
		pause 50
		sound 9,[50\3960]
		pause 50
		sound 9,[50\3960]
	elseif(command = 6)												;(Button 7) Turn
		gosub movement   0.0,-35.0,-40.0,  0.0, 35.0, 37.0,500.0]
		gosub movement   0.0, 35.0, 37.0,  0.0,-35.0,-40.0,500.0]
		gosub movement -14.0, 35.0, 37.0, 20.0,-35.0,-40.0,500.0]
		gosub movement -14.0, 35.0, 37.0, 20.0, 35.0, 37.0,500.0]
		gosub movement  20.0, 35.0, 37.0,-14.0, 35.0, 37.0,500.0]
		gosub movement  20.0,-35.0,-40.0,-14.0, 35.0, 37.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 = 3)												;(Button 4) Rest Position
		gosub movement   0.0, 45.0, 45.0,  0.0, 45.0, 45.0, 500.0]
	endif
	Command=0xFF
endif
goto main

;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
last_lefthippos var float
last_leftkneepos var float
last_leftanklepos var float
last_righthippos var float
last_rightkneepos var float
last_rightanklepos var float
lhspeed var float
lkspeed var float
laspeed var float
rhspeed var float
rkspeed var float
raspeed var float
speed var float
longestmove var float
;movement [lefthippos,leftkneepos,leftanklepos,righthippos,rightkneepos,rightanklepos,speed]
movement [rightanklepos,rightkneepos,righthippos,leftanklepos,leftkneepos,lefthippos,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],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
else
lhspeed=0.0;
lkspeed=0.0;
laspeed=0.0;
rhspeed=0.0;
rkspeed=0.0;
raspeed=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 (rightanklepos*stepsperdegree) + rightankle_start\TOINT raspeed]
hservowait [lefthip,righthip,leftknee,rightknee,leftankle,rightankle]
last_lefthippos = lefthippos
last_leftkneepos = leftkneepos
last_leftanklepos = leftanklepos
last_righthippos = righthippos
last_rightkneepos = rightkneepos
last_rightanklepos = rightanklepos
return

one var float
two var float
three var float
four var float
five var float
six var float
getlongest[one,two,three,four,five,six]
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(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
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

handle_irpd
currenttime=overflowtime+TCA
if(currenttime<0)then ;If we overflow to a negative number reset everything
overflowtime=0
currenttime=TCA
lasttime=-1
endif
if(lasttime<0)then ;If negtive lasttime, reset
datacount=0
lasttime=currenttime
else ;else process pulses
datacount=datacount+1
diff=currenttime-lasttime
irpd_data=irpd_data>>1
if(diff>175 AND diff<195)then ;If we get a start pulse reset datacount and irpd_data
irpd_data=0
datacount=0
elseif(diff>100 and diff<120) ;we got a “1” pulse
irpd_data.bit10=1
elseif(diff>65 and diff<85) ;we got a “0” pulse
irpd_data.bit10=0
else ;we got an invalid pulse so reset
lasttime=-1
resume
endif
if(datacount=11)then
lasttime=-1
command = irpd_data&0x7F
else
lasttime = currenttime
endif
endif
Resume

handle_timera
overflowtime=overflowtime+256
resume[/code]

wow, that is cool 8)

and that’s cool, you have tons of buttons! even more than a ps2 controller!

Oh snap! Is that how you pass variables to a label?

labelname [stuff here] ? Thats wicked awesome!

The only thing that needs to be worked out is the leg placement between commands. It’s ok the way it is, but there is room for improvement. I didn’t finish the turning right command either. Anyway post here if you work on it. :smiley:

Yes, just one gotcha. There is no error checking on subroutine arguments. If you place to many/few you are going to have problems without any error message telling you why. If you send a float/int type value to a int/float type argument you will also have wierd things happen(no auto conversion int to float or float to int in subroutine arguments). This will eventually be added though.

I have reread your notes and I believe I need the sequencer software to obtain these values?

Please let me know.

thanks

Hank

I am still at a loss. Where do I get the values to plug in to the initial points. I know how you calcualated the values but how do you read the initial data to do the calculatiion.

In the program what would happen if the offsets were set to “0”.

Hank

In this first version of the program the offsets were used in the area that looked like:
righthip_start con -560

I think I might have to rebuild my BRAT again. For the Hollidays that are coming.

Checking the prices on everything I need to get this version up and running …

Might have to see if it works with the Raptor remote as well :slight_smile:

I’m about to program the Pro. Could you explain where in the program the Pin 3 connected to the Sensor is associated with the variable irpd_data?

I presume that “command” gets its value from “command = irpd_data&0x7F”

If I understand your question, you are asking where in the code do we look at the value of Pin 3? This code is using interrupts to handle the input from the IRPD. At the beginning of the code there are some lines that enable the interrupt for IO pin 3 and set the interrupt handler:

ONINTERRUPT WKPINT_3,handle_irpd ONINTERRUPT TIMERAINT,handle_timera PMR5.bit3 = 1 TMA=4 ;increments on clock/256 ENABLE WKPINT_3 ENABLE TIMERAINT
I don’t know if this code matches the code Jim originally posted, but this code enables interrupts for changes on IO pin 3 and says that when a change happens call the function named handle_irpd. It also enables an interrupt for a built in timer and initializes it to specific mode and sets the interrupt handler to handle_timera.

Later in the code you will find the function handle_irpd. In this code it uses information from the timer to calculate how long each pulse is. It uses these pulse timings to calculate the value of which button was pressed.

When I was first trying to understand Jims (Robot Dude’s) code, I looked around the web for information on how the commands were encoded. One site that I found usefull was: scv.bu.edu/GC/shammi/ir/

Kurt

Kurt - Tnx
Does this mean that I could change the Sensor Pin to, say 10, to mathc the IRPD cable, by changing the line to “ONINTERRUPT WKPINT_10,handle_irpd” ?
red

I don’t Think pin 10 has an interrupt on it. There is a lot more details on this in the Atom Pro version 8.0 manual. It also mentions that the subject of interrupts is to complex to detail and they refer you to the H8 hardware manuals. But from my 2 minute look at the manuals I see that you have on pin change interrupts on pins (0-5). There are are other interrupts attached to other pins as well, but that is outside of this thread…

Kurt
Yes, only one Pin, RBO/INT on the 16F876 supports interrupts. But then why is the Sensor connected to Pin 3, and LEDS to 1 & 2.

Is there a Atom Pro 28 schematic to match up the Atom pins with the PIC pins?
red

The Atom Pro does not use a Pic chip, it instead uses a Renasis H8 microcontroller. You can download this manual from the Renesas web site.

The H8 has several external interrupts: NMI, IRQ0-3, WKP0-5.
I do not know for sure why Jim choose Pin 3. He had several possibilities and he probably hooked up the IRPD on other projects to pins 1-3. Currently the LEDS pins 1 and 2 are not used by the software. However someone may choose to use them in the future. You could for example instruct the brat to do a bow, and then use the IRPD to do a PING type of operation to find out how close you are to things…

It’s the H8/3664.

8-Dale

Lets give credit where credit’s due. I used pin 3 because Nathan at Basic Micro said, use pin 3. lol Acidtech wrote the program, I just tested it and directed the development. :smiley:

What is an “H8”? According the the Atom 28-M datasheet on the Basic Micro internet site, the chip is a 16F876. All the current Micro 24 & 28 appear to use the PIC device, so is this thread refering to an older (or newer unreleased version)?

Description
The Basic Atom is a tiny computer, or better known as a microcontroller.
The Basic Atom was designed for use in a wide array of applications. The
Basic Atom is built around the 16F876 PICmicro MCU®, which contains
internal memory (384 Bytes of RAM and 8K of FLASH / program space).

The Atom PRO is a Renesas H8 microcontroller, which is based on the H8/3664 chip. The Basic Atom is a Microchip 16F876 PIC. They are very different. :slight_smile:

8-Dale

Tnx everyone for the responses. My confusion was that I not realized the “28 PRO” vs “28 M” controller chip model and specs. :frowning:

I purchased and will use the Pro in the Bot Board for this project. The Atom Pro 28 datasheet very clearly states H8/3664, and a look at the Renesas 3664 chip datasheet shows Port 1 has 4 IRQs (P14-P17= chip Pins 39-42 or Pin 51-54 depending on package), which I presume are actually wired to Atom Pro 28 Pins 0 - 3.

Is there a Atom Pro 28 schematic available anywhere?
red