pbasic question

I have a question referring to my dead reckoning autonomous program. On my last post I asked how to make the robot go straight and stop, after reviewing the answers posted, and my own tinkering, I was able to do that. I also am able to go reverse and turn, by simply modifying the pwm values to the motor. However when I write a sequence of things to do, such as go forward, pause, go left, pause, go reverse, the robot only performs the last action in the sequence of movements I create (in that case, reverse.) I suspect this is some nuance of PBASIC that I do not understand, so any help would be appreciated. Also, I am doing this in ver 2.0, and if you believe somehow 2.5 will resolve this problem I’d be even more glad to hear that.

Thanks again guys,

Mike

Could we see some of your code? It is hard to troubleshoot with almost nothing to work off of. I’m guessing it is either a problem with what variables for the loops are set to, or something with goto’s.

you must only do one thing per cycle. for example…


py_1 = 127  'PWM 1 is set to neutral
py_1 = 254  'PWM 1 is set to full foward
py_1 = 0      'PWM 1 is set to full reverse

SEROUT [255,255,py_1,<var>,<var>,...]

in that example, the first PWM output would only output 0, because that’s what it was last set to. the signal is only sent to the motors DURING the SEROUT command. anything changed before is not recognized, so you need something to count loops, so it goes straight for x cycles, then turns left, and so on. it’s a bit more complicated, and i don’t have anything done yet, and well, i’m still adjusting my mind to the backwards logic of PBASIC 2 (we don’t have 2.5 yet, so 2 it is).

2.5 will make it much easier, but you can do it in 2.0 if you want. Here would be the 2.5 code:


counter VAR word
counter=0

mainloop:
serin...

if auton_mode then
  counter=counter+1
  SELECT counter
    CASE 0 to 100
       'go forward
    CASE 101 to 200
       'pause
    CASE 201 to 300 
       'turn
    CASE else
       'pause
    ENDSELECT
ELSE
   'regular robot code
ENDIF

serout
goto mainloop

thanks Ian, I sawsome people use serout in response to my initial question, but did not understand its function. I suspect that will work andl try it first thing Monday.

I tried implementing the serouts with no luck, still just does the last thing in the list. Here is the code, if anyone can spot a problem, I’d highly appreciate hearing from you.

'----------- Another Feeble Attempt at Autonomy------------------------'Declare Variables
auto_mode VAR bit
desired_on VAR byte
motor_fwd VAR byte
motor_stop1 VAR byte
motor_left VAR byte
motor_stop2 VAR byte
motor_rev VAR byte
motor_right VAR byte

auto_mode=1

'Check autonomous mode
if auto_mode = 0 then skip_auto:

'Program 1:
if motor_fwd>300 then next_step1:
p1_y=200
p2_y=200
motor_fwd=motor_fwd+1
Serout USERCPU, OUTBAUD, [255,255,p1_y,relayA,p2_y]
next_step1:

'Program 2:
if motor_stop1>200 then next_step2:
p1_y=127
p2_y=127
motor_stop1=motor_stop1+1
Serout USERCPU, OUTBAUD, [255,255,p1_y,relayA,p2_y]
next_step2:

'Program 3:
if motor_left>300 then next_step3:
p1_y=127
p2_y=200
motor_left=motor_left+1
Serout USERCPU, OUTBAUD, [255,255,p1_y,relayA,p2_y]
next_step3:

skip_auto:

First, because you are using byte-sized variables, you’re never going to have values greater than 300. It seems odd, but 255+1=0.

Second, I don’t see any gotos. If I understand your code correctly, you are trying to create three separate loops, no? If so, add a quick goto after each serout that sends the code back to the beginning of that section (ie “goto Program1:”, etc).

Third, you’re going to need to initialize your counters. Just set them all to zero immediately after declaring them. Otherwise, operations like “motor_fwd=motor_fwd+1” have no meaning since there is not motor_fwd to increment the first time through the loop.

–Rob

I’ve seen a few schemes to alter joystick profiles allowing the driver better control at the low end. Routines have simple offsets, dead bands and still maintain a linear relationship to the joystick. I’d like to try a response curve that increases throttle positions exponentially, similar to a charging capacitor. Such a curve would have a lot of motion for low/mid speed maneuverability and limited motion for high speed where normally you would be going straight. Calculating this curve is a few lines of code in ‘C’ but can’t find an easy way with PBASIC other than making a lookup table which wastes a lot of space…Anybody do this before??

ALSO… Is there a shift operation in PBASIC??..like x = X << 5 or do you have to divide and multiply?

Thanks

<<, as well as >> are both valid operators in PBASIC and behave exactly the same as their C equivalents. If you could post/email me the equivalent C code I can probably convert it in a few minutes.

–Rob

Thanks for the offer…I don’t have the code here, will send it tomorrow
-phil

If a WRITE [destination], [value] command is used in a program running in bank 2, is the destination in all the other banks altered. I would assume all banks have seperate EEPROM space.

I.E:

’ Running in Bank 0
WRITE 0, 1
RUN 1

’ Now running in bank 1
WRITE 0, 0

’ Did the contents of location 0 of bank 0 get overwritten with 0 ??

They are COMPLETELY separate blocks of 2048k. The only things that carry over between banks are scratchpad RAM and regular variables. Using the scratchpad is more reliable, as using variables requires that you align the variables the same way between slots.

What is needed for this is called a state machine.

The code goes through the main loop many times and does different things each times. Some information about the state of the system is kept from loop to loop (in variables).

There should only be one SERIN/SEROUT set in the loop.

The example posted with the SELECT command uses the counter variable as the only state. More complex machines can use additional state variables.

Flow charts are commonly used to understand the workings of state machines.

There are no gotos in the example because the SELECT-CASE command implies them for you (like IF-THEN-ELSE). Both are new with PB2.5.

This code would be better written:


'----------- Another Feeble Attempt at Autonomy---------
'Declare Variables

auto_mode VAR bit
desired_on VAR byte
motor_fwd VAR byte
motor_stop1 VAR byte
motor_left VAR byte
motor_stop2 VAR byte
motor_rev VAR byte
motor_right VAR byte

'--init variables--
motor_fwd    = 0
motor_stop1 = 0
motor_left     = 0
auto_mode=1

loop:

'Check autonomous mode
if auto_mode = 0 then skip_auto:



'Program 1:
if motor_fwd>200 then next_step1:
p1_y=200
p2_y=200
motor_fwd=motor_fwd+1
goto output
next_step1:

'Program 2:
if motor_stop1>200 then next_step2:
p1_y=127
p2_y=127
motor_stop1=motor_stop1+1
goto output
next_step2:

'Program 3:
if motor_left>200 then next_step3:
p1_y=127
p2_y=200
motor_left=motor_left+1
goto output
next_step3:

skip_auto:

'regular control code goes here


output:
Serout USERCPU, OUTBAUD, [255,255,p1_y,relayA,p2_y]
goto loop


First, in the previous code, in each cycle it would set the motor forward, serout, set it stop, serout, set it left, serout… there was no breaks in the code.

Second, only one serout is better programming practice.

Third, changed the 300s to 200s. This means that they are actually achieveable numbers in PBASIC. If you need to go higher, I would suggenst somthing like the following:


CountNumber VAR bit
motor_fwd      VAR byte

CountNumber = 0
motor_fwd = 0

'Program 1:
if motor_fwd > 254  and CountNumber = 1 then next_step1:
p1_y=200
p2_y=200
motor_fwd=motor_fwd+1
if motor_fwd > 254 and CountNumber = 0 then CountNumber = 1
goto output
next_step1:


Originally posted by Don Reid

What is needed for this is called a state machine.

Now your talkin’…I could see executing from some variable function pointers or scripts… While we’re at it how 'bout a few interrupts to do a PID loop for the PWMs. At least a real time ISR.

Let’s put some lipstick on this pig