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

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.

Have you tried mine? Instead of having it send the servo pulse to the servo, make it print it to the terminal. I think its a better method of debugging. You might also want to stick a print into the label which checks for the command.

Well I didn’t think this was worth trying as it worked fine before I added the pulsout commands. However I did go back and put the terminal serial command back in. Low and behold it is getting corrupt. After working for a while it starts sending garbage to the screen…

At first it works…

Address = 1 Command = 1 Address = 1 Command = 1

Then after a while it sends this…

{Ønd = 0 Addresÿî = 0 Comý{Ønd = 0 {Ønd = 0 Addre^þ0 Com /Ï{ö^þ0 Addre^þ0 Com /Ï{ö^þ0 Addresÿî = 0 Comý{Ønd = 0 Addresÿî = 0 Comss{Ønd = 0 Addresÿî = 0 Comî = 0

Clicking dissconnect and then reconnect seems to fix it. But it’s just temporary…

This is with no pulsout commands. Thanks for making me go back to the beginning. :smiley:

LOL, but it’s not all bad though, it’s interesting to “see” what was going on… :laughing:

Yup, thought so. Nothing wrong with your servop stuff, had to be the commands/address it was getting.

It’s gona be a little longer before I can get back to this code. But until then…

The problem causing the data to become invalid is being caused because the IRPD is missing a pulse. When it does there is no recovering with the current code because it has no way of knowing it missed a pulse. What needs to be done is setup a TimerA interrupt that keeps track of the current pulse width. By keeping track of the time, if the pulse gets longer than a valid pulse(ie greater than 195) the sequence needs to be reset(setting lasttime = -1 will reset the sequence for the next valid pulse train from the remote).

So here’s the code(not tested and probably has bugs/typos):

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

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

currenttime=0
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 

;Modified handle_irpd routine
handle_irpd 
   if(lasttime<0)then 
      datacount=0 
      lasttime=currenttime+TCA
   else 
      datacount=datacount+1 
      lasttime=(currenttime+TCA)-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 
      else
         ;invalid pulse received
         lasttime=-1   
         resume   ;resume imediately   
      endif 
      if(datacount=12)then 
         lasttime=-1 
         command = irpd_data&0x7F 
         address = irpd_data>>7 
      else 
         lasttime = currenttime+TCA 
      endif 
   endif    
   resume

handle_timera
   currenttime=currenttime+256
   resume

That should work to handle bad pulses. I may have the wrong name for the TIMERA_OVF interrupt but the rest looks right.

Nathan

I moved this to the Bipeds section.

lynxmotion.net/viewtopic.php?t=1242