Basic Atom Pro / Bot Board / IRPD (remcon) Program

Actually the pin changing state (for example) is typically what initiates the background process. It doesn’t have to be a pin, it can be lots of things like timers expiring, a serial port sending the last bit of a character, a packet of data arriving from a network, anything that dedicated hardware might be doing that needs some software attention.
Yes it is a very powerful tool, but but by the same token it can be a massive headache when there is a bug in the handler routine.
:wink:

I hereby second that motion.

.<"

Interupts are lovely, but don’t be like me and try to write your first micro program with them.
It was…
brutal.
:laughing:

well, what did you put the bug in it for then?

Yeah Nick, what he said-----^ :stuck_out_tongue:

Setting bit3 of the PMR5 register sets pin 3 as a Wakeup(when pin goes low) interrupt instead of a normal I/O. The WKPINT_3 is the Wakeup3 interrupt. Ther are 6 possible wakeup ints(0-5). I used WKPINT_3 because Jim has the signal from the IRPD wired to pin 3 and I didn’t want to change his wireing since he’s making an assembly guide for this as well.

Also, TMA=4 is setting the TimerA timer to increment every 256 osc pulses(osc runs at 16000000 hz) so TimerA increments 62.5 times ever millisecond. I’m using TimerA to time the pulse widths coming from the Sony remote(technically it’s a universal set to a Sony model).

The Sony singal format is a 2.4ms start pulse(low at the AtomPro’s pin) followed by .6ms idle(high), then 12 data pulses(1=1.2ms low folled by .6ms high, 0=.6ms low folled by .6ms high).

So given that, there are three possible times between any two lows. Either 3ms,1.8ms or 1.2ms.

In TimerA time that is 187.5, 112.5 and 75.

I calculate the time from one low to the next by subtracting the last value of TimerA from the next value of TimerA. I then determine if a bit is either a start or data bit. If it’s a start I initialize the handler. If it’s a databit I load it(0 or 1) into my data variable(irpd_data). When I’ve received 12 bits I copy the command(low 7 bits) into the Command variable and the Address(high 4 bits) into the Address variable.

Note that Sony’s system actually sends out 13 pulses(1start 7command and 5address) but I only read 12(1start 7command and 4address) because this way I use very little time in the interrupt. In order to get that last bit I would have to actually wait inside the interrupt for the length of all pulses(minimum of 16.2ms).

Since the 5th bit of the address bit is almost never used I’m not going to worry about it. Just so you know the only loss is that the address is only good for 16 devices(addresses) instead of Sony’s full spec which supports 18 devices(assuming you found a remote that supported all 18 possible devices).

Nathan

I’m having difficulty with the program. I added some simple servo pulse commands to the main loop and it’s acting up. Here is the code.

[code]ONINTERRUPT WKPINT_3,handle_irpd
PMR5.bit3 = 1
TMA=4 ;increments on clock/256
ENABLE WKPINT_3

lasttime var long
currenttime var long
datacount var byte
irpd_data var word
command var byte
address var byte
ServoP var word

lasttime = -1 ;indicate next data should be a startpulse
low 15

main

pulsout 15,servop
pause 20

if(command<>0xFF)then

’ serout S_OUT,i115200,"Address = ",hex address,13,"Command = ",hex command,13]

if (command = 0) then 
	servop = 4000
endif
if (command = 1) then 
	servop = 3000
endif 
if (command = 2) then 
	servop = 2000
endif 

	Command=0xFF
endif
goto main

handle_irpd
currenttime=TCA
if(lasttime<0)then
datacount=0
lasttime=currenttime
else
datacount=datacount+1
if(currenttime<lasttime)then
lasttime=lasttime-256
endif
lasttime=currenttime-lasttime
irpd_data=irpd_data>>1
if(lasttime>175 AND lasttime<195)then
irpd_data=0
elseif(lasttime>100 and lasttime<120)
irpd_data.bit10=1
elseif(lasttime>65 and lasttime<85)
irpd_data.bit10=0
endif
if(datacount=12)then
lasttime=-1
command = irpd_data&0x7F
address = irpd_data>>7
else
lasttime = currenttime
endif
endif
resume[/code]

It apears to work at first. When I press the [2] button it moves to the center, when I press the [1] button it moves to the +45° position, when I press the [3] button it moves to the -45° position. It does this fine for a while then only the [1] button will move it to the correct place, and the one or both of the other two will not work. I also notice some jitter in the servo when pressing and holding the buttons.

Maybe I’m doing something wrong. :frowning:

Jim doing something wrong? :astonished:! Impossible :laughing:.

So, as far as I understand, it works fine… But after you press the [1] button (center the servo) the [0] and [2] buttons don’t work?

Not sure what the issue is, but try and make it print out the address and command for every time it goes through the main loop. Also, isn’t command a hex value? not a dec value? Or you can have a hex value but still use it as a dec?

Another suggest you can try. Instead of making it just an if then statement, try and if elseif statement. make the whole thing a big elseif statement.

Also, could it be possible that so much IR light is coming from the remote that the IRPD is flooded with it and understands it wong?

Try this for the main loop:

main
	pulsout 15,servop
	pause 20
	
	if(command <> 0xFF) then
		serout S_OUT,i115200,"Address = ",hex address," ","Command = ",hex command]
		if(command = 0) then
			servop = 4000
		elseif(command = 1) then
			servop = 3000
		elseif(command = 2) then
			servop = 2000
		endif
		serout S_OUT,i115200," Servo Pulse = ",dec servop,13]
		Command=0xFF
	endif
goto main

That might work. Only reason I can think of for why it doesn’t work anymore is that the command the IRPD is getting is not the same as before. Try that out, make sure its connected to PC so it can print out the stuff. I have never tried running a programming in MBasic so sorry if I am wrong about the syntex. I am guessing that serouting 13 to S_OUT prints a \n.

Oh, and uhhh question. What does
command <> 0xFF
do? I forgot what <> means >_<’’

What if you try this?

[code]
servop = 750 '<----- Added

main

Command=0xFF '<---- Added

pulsout 15,servop
pause 20

if(command<>0xFF)then
’ serout S_OUT,i115200,"Address = ",hex address,13,"Command = ",hex command,13]

    if (command = 0) then 
    servop = 4000 
    endif 
    if (command = 1) then 
    servop = 3000 
    endif 
    if (command = 2) then 
    servop = 2000 
         else goto main '<-----Added
    endif 


  'Command=0xFF      '<----- possibly take this out ?

endif
goto main[/code]

This is what I would try. I really am not sure. Let me know what results this gives.

Hmm, ok. <> is not equal. same as != if I understand correctly.
In that case, I don’t think it will work. You need to set the command to 0xFF so that it won’t go through the if statement again. Well, actually. Won’t matter since 2 is != to 0xFF =/ so nevermind about that.

Oh, wait, you took it out of the if and put it at the top. What is your reasoning behind that? Wouldn’t it always skip the if statement if you have it equal to 0xFF at the beginning? If I understand, Jim is using an inturrupt which brings him back to the what ever line he was before he pressed a button on the remote. If he was at the top of main or at the bottom of main after the endif then he would never be able to control anything because it would always be set to 0xFF? Wouldnt it? Just wondering. Get what I mean though?

huh? I have no idea what you are talking about

Note: I went back and made some quick changes to the code. Sorry…

Edit
This wait is killing me, Jim… Are you done yet?.. :open_mouth:

Mike, If I read it right you are using the command variable as a semaphore between the interrupt handler and the main loop. When a command is received by the irpd it puts the value in the command variable. Once you see in the main loop that the command variable has been updated you act on it and then reset it.

Sorry, I made the changes and although it does work, it’s still having the same problems. I think it’s in the interupt code. Or how I’m trying to wrap basic around it. :frowning:

I was kidding about the wait comment. :laughing:

I figured there was something more to the problem then what meets the eye. I gave it my best shot though. :laughing:

So some how with the interupt, varables are getting jumbled up I guess. Acidtech is the best person to provide an answer.

is there a way to block the interrupt while you are accessing the command variable? or force the code to always load the variable from memory every time it is accessed? there is a problem with optimized and compiled languages where a frequently used variable might be held in a register for a few operations rather than pulled from memory every time it is needed. If an interrupt is changing the contents of that variable at the same time though the main loop won’t see the change and could possible overwrite it. In C/C++ there is a storage class called volatile that is specifically to address this problem. I don’t know if the basic stuff you are using has that same type of issue, but if it does there may be a similar fix to the problem.

I forgot to mention that a reset brings it back to life for a little while, so I think it’s the interupt code that is causing it to act up.

You know Eddie, I think you might be on to something! :laughing:

In both Pbasic and Mbasic, you can write variables to the eeprom. This might be a good thing to try. This could help “protect” the variable from being affected from the interrupt.

What about what Eddie said about writing the variables to eeprom, could this possibly help?

I am currently experimenting with the enable and disable commands. They allow you to enable and disable the interupt. Nothing good to say yet, but I am still working.

I tried disabling the interupt when the decisions are being made.

[code]main
disable WKPINT_3
if(command<>0xFF)then
’ serout S_OUT,i115200,"Address = ",hex address,13,"Command = ",hex command,13]

if (command = 0) then 
	servop = 4000
endif
if (command = 1) then 
	servop = 3000
endif 
if (command = 2) then 
	servop = 2000
endif 
	Command=0xFF
endif

enable WKPINT_3

pulsout 15,servop
pause 20

goto main[/code]

But it’s still loosing interest in behaving after a while.