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.
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).
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
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.
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 >_<’’
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?
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.
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.
You know Eddie, I think you might be on to something!
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.
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.