Joystick control of 2 motors w/ 08M chips

DTB Radio

Member
I have 2 DC boat motors that I want to control using only 08M chips. My current configuration is independent motor control with 1 chip for 1 motor (like a bulldozer or skidloader control scheme for example), each chip reading a single POT to determine direction and speed for its own motor. This current system works very nicely, but I want to eliminate the double controls and use a joystick instead. However, I want to implement it with only two 08M's (Yes, I know the 28X will do it nicely, but I want to do it with what I have on hand now, no extra $$ layout).

I'm having trouble figuring out exactly how to tackle this challenge. My thought is to have each 08M read both joystick POT's (one POT for speed and forward/reverse control and one for directional control), and from those ADC results, determine the direction and speed of its own motor. Its easy enough to read the ADC's and assign them to variables, then output the interpreted data for each motor, but coming up with the algorithms and code to have each chip interpret that data is giving me a brain fart. I need someone to point me in the right direction here. I don't think I need the full code, just the basic concept and/or algorithm to manipulate the data. Any help and thoughts would be appreciated.

If I need to give more detail, let me know.
 

Andrew Cowan

Senior Member
- Read throttle axis
- Read steering axis
- Mix together to create channels A and B (hint - seach the forum for 'RC mixer')
- Calculate PWM rates
- Send a (serial?) command to the second 08M, saying the percentage duty to set the motor at.
- Send a PWM signal (see PWMout) from both 08Ms.

Do you need help on how to drive the motors? Do you need reverse? (FETs, H-Bridges etc).

A
 

hippy

Ex-Staff (retired)
Welcome to the PICAXE forum.

What you are suggesting is certainly possible. All you really need to do is write a routine which takes two pot values and gives back an equivalent of the pot value which you had before; the rest of the code should work unchanged.

As to the algorithm; that depends on what code you are already using and exactly how you want the joystick control to work.
 

DTB Radio

Member
- Read throttle axis
- Read steering axis
- Mix together to create channels A and B (hint - seach the forum for 'RC mixer')
- Calculate PWM rates
- Send a (serial?) command to the second 08M, saying the percentage duty to set the motor at.
- Send a PWM signal (see PWMout) from both 08Ms.

Do you need help on how to drive the motors? Do you need reverse? (FETs, H-Bridges etc).

A
Thanks for the reply. I do need reverse, so the speed pot values will need to be split (with a small window for all-stop). Interface to the motors is already taken care of and tested. I just need to tackle the problem of joystick data interpretation/mixing.

I did a search for RC mixer, but all I'm seeing is bits and pieces about reading and mixing servo pulses, not POT voltages. The principal may be the same, but I'm not getting there from here if it is.

Here are the responses I want from the motors for extreme joystick positions:

1. straight forward = both motors full speed forward
2. front-left corner = right motor full speed forward, left motor stopped
3. front-right corner = left motor full speed forward, right motor stopped
4. straight left = left motor full speed reverse, right motor full speed forward
5. straight right = left motor full speed forward, right motor full speed reverse
6. rear-left corner = left motor full speed reverse, right motor stopped
7. rear-right corner = left motor stopped, right motor full speed reverse
8. center = all stop

Naturally I want the speed to be variable in between the extremes, as well.

Hope that helps with suggestions and ideas. After thinking it over, I'm not too proud to ask for code, either!
 

Andrew Cowan

Senior Member
The principle is the same - the numbers just need scaling differently.

Rc signals at pulsin = 75 to 225, with 150 neutral.

Readadc with pots = 0 to 255, with 127 neutral.

The numbers just need scaling.
 

DTB Radio

Member
Ok, I've spent over four hours Googling and trying to come up with usable formulas, and I'm getting nowhere. If someone can break it down simply, code or formulas, I'd appreciate it. If you know of a site or forum post that already has control mixing formulas posted or shown, post the link.

If I still haven't posted enough detail about what I need, let me know.
 

BeanieBots

Moderator
It's just a question of adding values but with the slight complication that you need to limit when 'full' is obtained.

Think about each quadrant independantly for a moment.
Both 08Ms need to read both pots so that they can send the appropriate value to the motors.

Stick central in both axis makes both motors stop.
Each pot will be central so will give a (ideal) value of 128 for 'off'.

Moving the stick up makes both motors go full speed.
Moving the stick to the left needs to increase one motor but decrease the other.
However, both motors are at full speed so one of them cannot go any faster but the other can slow down.
So, motor1 speed = motor1 speed plus an amount determined by the left/right movement but limited to a maximum value.

Let's say your maximum speed value is 255 and this is held in w0.

For motor1
w0 = w0 + (left/right stick value) MAX 255.
Motor 1 is already at 255 and will stay at 255 because of the MAX command.

For motor2
w0 = w0 - (left/right stick value)
Motor 2 will slow down because the left/right amount is subtracted from 255.

Have a look at the MAX (and MIN) operator in the manual.
Then consider the process for each quadrant of your stick positions.
 

DTB Radio

Member
That helps a bit, but it still doesn't quite cover what I need. The control is broken down into octants more than quadrants for what I'm trying to do, or at least that's how I'm breaking it down in my head.

Lets say that the joystick is kept at its maximums in the following examples. At 90 degrees, I want full ahead both motors. At 112.5 degrees, I want half speed forward on left motor, full on right. At 135 degrees, I want full stop on left motor, full speed forward on right. At 157.5 degrees, I want half speed reverse on left, full speed forward on right. At 180 degrees, I want full speed reverse on left, full speed forward on right. At 202.5 degrees, I want full speed reverse on left, and half speed forward on right. At 225 degrees, I want full speed reverse on left, full stop on right. At 247.5 degrees, I want full speed reverse on left, half speed reverse on right. At 270 degrees, I want full speed reverse on both motors. Etc, etc, etc. Keep in mind that I'm also looking for fully variable speeds at positions less than maximums.

I'm just not quite able to wrap my math-weak brain around how to come up with the formulas needed, and so far, I've not found quite what I need in my searching. If there's a simple formula or formulas that I can use, that would be great, but so far, its looking like I'm going to need to work out multiple nested if-then structures to process this. I do understand that it will boil down to more-or-less simple adding and subtracting, followed by scaling for the PWM data. If someone can simply show me the formulas I need based on a 0-255 range of POT values, I can come up with the code from there.

For now, I'm working on breaking down the control into 4 major quadrants (if-then structures) , then breaking those down into two further divisions (nested if-then structures), and working from there. I'm not sure if that's the best approach, but its the only idea I've been able to come up with so far.

Don't get me wrong, I definitely appreciate the responses I've gotten, and parts of them do help, but its not quite enough.
 

hippy

Ex-Staff (retired)
I'd suggest drawing a circle ( possibly a square - depends on mechanics ) which represents the joystick possible positions. Then plot what the motor speeds will be (+/-100%) at various extremities. Split that into two parts, how left motor behaves and how right motor behaves. Then work out the correlation of each joystick to those requirements. That will give you your mathematical algorithm which should then be fluid across the entire range of positions, no 'jerky' IF-THEN-ELSE tables.
 

BeanieBots

Moderator
I only suggested breaking it down into quadrants to help get your head around it. The 'sums' should be smooth and not require loads of if/then breaks.

Having said that, to help get around the issue of negative numbers, I often split things into positives & negatives which for two pots brings us back to quadrants.

So, now (thinking in quadrants again) it comes down to if/then's which simply determine if the 'other axis' should be added or subtracted. That's all there is to it really. (don't forget to MAX the values).

For the purists, it's actually vector arithmatic, but as you only have two axis at 90 degrees the vector component works out at 0.5 which is really handy.
It means you simply add them and divide by two but each quadrant is only 1/2 the total so even the divide by 2 is already done.
 

hippy

Ex-Staff (retired)
Not sure a simple add or subtract works for the joystick position and desired motor speeds, though I'm not sure if this is correct because the angles given and motor directions didn't match up as I read them.

Motor pairs <left> <right> as % of full speed ...

Code:
               +100 +100
                   |
          0 +100   |   +100 0
               \   |   /
                 \ | /
-100 +100 ------- 0 0 ------- +100 -100
                   |
                   |
                   |
                   |
               -100 -100
 

BeanieBots

Moderator
@Hippy, you may have a point. I didn't pay too much attention to the (slightly confusing) description and assumed the 'conventional' mix

@Haku, "V-tail" mixing is the same as the system I was trying to describe (but not as pointed out by Hippy) but it works on servo signals in and gives servo signals out. My understanding was that the requirement was for analogue in and PWM out.
 

Andrew Cowan

Senior Member
I programmed this for my robot (the code is at school).

It was something like:
Code:
Read throttle (b1)
Read steering (b2)
Motor A speed (b3) = b1
Motor B speed (b4) = b1

If steering is 127 (neutral), then goto PWMout routine
If steering is less than 127 then goto TurnLeft routine
If steering is more than 127 then goto TurnRight routine

TurnLeft:
Steering = 127 - steering (this makes it a value of 0-126)
Motor A = throttle - steering (min 0)
Motor B = throttle + steering (max 255)
goto PWMout routine

TurnRight:
Steering = steering - 127 (this makes it a value of 0-126)
Motor A = throttle + steering (max 255)
Motor B = throttle - steering (min 0)
goto PWMout routine

etc
Note that min 0 doesn't work (I'll let someone else tell you why).

Hope this helps.

A
 

DTB Radio

Member
Again I appreciate the reply. I understand roughly what you mean and I've already been thinking in those terms, but since I am NOT strong at all with mathematics, its still going to be a very hard job for me to translate that into usable formulas I can plug into my code. Running a business means I have little free time to put into the hobby end of my profession, and even less to put into trying to come up the hard formulas for something like this. Since I've not been able to locate the info I need, and since no-one on the forums where I've posted seem to be able to supply it (or links to it), I'm going to have to put the joystick idea on the back burner.
 

Haku

Senior Member
My understanding was that the requirement was for analogue in and PWM out.
I wasn't sure if the OP wanted wired or wireless control, from the way the discussion is going it appears they want wired control.

A v-tail mixer could simplify the problem, just use a single 08M to read the value of the joystick's two potentiometers and then directly convert the ADC values to servopos values, the v-tail mixer can take care of the tank-like control from there.
 

hippy

Ex-Staff (retired)
Loking at the diagram I did in post #11, I'm not sure if the specification is correct, nor at all sure what anyone would want in practice.

In the top left quadrant, the right motor always runs at +100%, in the top right the left motor always runs at +100%, and both flat out in reverse in the respective quadrants ... except when exactly on the vertical forward-reverse line.

That the function isn't proportional to both axises (sp?) across the surface area is I think what makes the maths almost impossible - and the concept unlikely workable in practice.

I've done some pretty complex proportional control in my time in cross-fading lights from one level to another and that ended up being physically modelled as a 3D cube with each edge built out of long IC tubes. A 3D surface could be determined which showed all the points within the cube depending on how the two faders / joystick moved. Ultimately all that was needed was to determine where on that surface one was, which was a line in 3D, but the maths was not simple to discover.
 

DTB Radio

Member
This is the best info I've seen so far towards getting the result I'm looking for. I had actually come up with the same idea in code, but a VERY long way around, lol! What this code (and the mess that I came up with on my own) doesn't do is give in-place rotation (one side full ahead, other side full astern), unless I'm missing something. It looks like its probably a simple matter of adding some if-then statements based on the Motor A and Motor B values, similar to what I've already done for the individual tank-style control I'm using now.

I programmed this for my robot (the code is at school).

It was something like:
Code:
Read throttle (b1)
Read steering (b2)
Motor A speed (b3) = b1
Motor B speed (b4) = b1

If steering is 127 (neutral), then goto PWMout routine
If steering is less than 127 then goto TurnLeft routine
If steering is more than 127 then goto TurnRight routine

TurnLeft:
Steering = 127 - steering (this makes it a value of 0-126)
Motor A = throttle - steering (min 0)
Motor B = throttle + steering (max 255)
goto PWMout routine

TurnRight:
Steering = steering - 127 (this makes it a value of 0-126)
Motor A = throttle + steering (max 255)
Motor B = throttle - steering (min 0)
goto PWMout routine

etc
Note that min 0 doesn't work (I'll let someone else tell you why).

Hope this helps.

A
Thank you, Andrew, for confirming and simplifying my own muddled mess, and for taking the time to come up with, and post, the code.

I do have one other question that would pretty much clinch this up. Is there a command, or simple routine, that I can use in the 08M to take a range of values and reverse them? For example, part of Motor A's derived speed is in the range of 63 to 0. Can I flip any given value in that range, after its calculated, to be its opposite on the other end of the range? In other words, say values of 3, 4, and 5 come up as the joystick moves. How do I flip them to be their opposites in that range (IE 3 becomes 60, 4 becomes 59, etc)? I've used a for-next loop with if-then statements comparing every number and changing it to the opposite, but it led to jerky operation in reverse modes, presumably due to the time it took to iterate the loop. I also used a number of individual if-then's to do the same job, without the jerky operation, but since memory is limited, I could only squeeze in 16 if-then's, leading to a not-so-smooth acceleration curve in reverse. Any ideas on that one? Or have I made the question as clear as mud, lol?

Oh, just to clear up some confusion, for now this is a wired project. RC will come later, after I get this part sewn up to my satisfaction. Thanks again to all who have posted so far, and in advance to anyone else who sheds any further light.
 

BeanieBots

Moderator
To 'flip' a range of numbers from say 0 to 60 to be 60 to 0 is simple.
Just subtract from the maximum value.

Let's say your number is in b0 and has the range 0 to 60.
b0 = 60 - b0

0 becomes 60
1 becomes 59
2 becomes 58 etc, etc.
60 becomes 0

The only thing to be careful of is if your number ever exceeds the maximum.
If your number was 61, the result would be 255.
 

DTB Radio

Member
Simplicity itself. And I was using the lookup function with 64 numbers inside of () separated by commas..... Told you I had no head for math, lol! Thanks, Beanie!

To 'flip' a range of numbers from say 0 to 60 to be 60 to 0 is simple.
Just subtract from the maximum value.

Let's say your number is in b0 and has the range 0 to 60.
b0 = 60 - b0

0 becomes 60
1 becomes 59
2 becomes 58 etc, etc.
60 becomes 0

The only thing to be careful of is if your number ever exceeds the maximum.
If your number was 61, the result would be 255.
I think that Hippy in post 11 and 17 is correct in that what I'm trying to achieve is a lot more complex than I originally thought. Hippy, your diagram in post 11 was right, that's what I was shooting for. I think I'm going to skip the control I'm after, and just set up a special case for center throttle and any steering to run both motors equal peeds in opposite directions. It will save time, aggravation, and my hair.

Thanks again to all of you who offered advice and info. If someone does come up with the math for what I'm ultimately trying to do, please continue posting!
 

BeanieBots

Moderator
Andrew's code in post #14 is about as close as you'll get without someone having your exact hardware and knowing how you've implemented the existing POT to speed code.

One issue is that joysticks rarely travel much more than 50% of the POT movement so your ADC readings are not likely to change much more than between 64 and 192 rather than the full 0 to 255.
To try and devise code using algebra that you can slot YOUR specific limits into would be a major effort which is probably why nobody has offered such a solution.

I still think you could work it out yourself if you sit down with a pen and paper.
Have another read through Andrew's code.
He's right about the "MIN" function not working in the 'ideal' way for zero but I bet once your POT limits have been taken into account the problem will simply not arise.

Don't give up just yet.
What are your ADC values for:-
Mid position, (both pots)?
Full up?
Full down?
Full left?
Full right?

What PWM values do you need for full forward and full reverse on both motors or are you using a direction command as well?
 

DTB Radio

Member
ADC values from POT's are 0 - 255, not counting glitches due to age and worn carbon strips in the POT's. This is already verified in my currently-working dual-lever tank-style control code.

Using Adrew's post as a reference, I've written the following code (not tested yet, I'm not at the shop until later this morning):

Code:
'Code for left-side motor

'2,31,127 = 31.4khz PWM data for max motor speed

symbol throttle = b0 				'assign variable to throttle axis
symbol steering = b1 				'assign variable to turn axis
symbol motor = b2    				'assign variable to motor speed
symbol backwards = 0				'output 0 is direction control

'*****************************************

Initialize:
	pause 250				'pause to allow circuit stabilization
	low backwards				'shut off reversing control
	pwmout 2,31,0  				'shut off motor
	
Main:
	readadc 1,throttle			'read throttle axis
	readadc 4,steering			'read steering axis
	
AllStop:					'reserve all-stop area at center position
	if throttle > 123 and throttle < 131 and steering > 123 and steering < 131 then
		low backwards			'shut off reversing control
		pwmout 2,31,0  			'shut off motor
	end if
	goto main				'go read joystick again
	
MotorControl:					'Routine for direction and speed control
	motor = throttle - steering MIN 0	'determine PWM and direction data
	if motor < 128 then			'check for reverse condition
		high backwards			'send reverse motor command
		motor = 127 - motor MIN 0	'data-swap for proper reverse acceleration curve
	end if
	if motor > 127 then			'confirm forward range
		low backwards			'reverse control is off in forward range
		motor = motor - 127		'scale range for PWM at 31.4khz
	end if
	pwmout 2,31, motor			'send motor speed control data
	goto main				'go read joystick again
Yes, I know MIN 0 isn't supposed to work as one might think, but I want to see what happens for myself before I change it to MIN 1
 

vttom

Senior Member
Awhile ago, I was trying to solve a very similar problem, but never quite got my head around it. This post was the impetus I needed to pick up that work again and finish it.

I started by entered 8 discrete joystick "bearings" in Excel (E, NE, N, NW, W, etc) and plotting the results against the angle of the joystick. It looked very sine-wave line. This allowed me to come up with a mathematical relationship between the L and R motor speeds and the angle of the joystick.

In the following equations, the L and R values will vary between +1 and -1. +1 is full throttle forward and -1 full throttle backward. "a" is the angle of the joystick in degrees, with 0 degrees being "East", 90 degress being "North" and so on...

L = sin(a+45)
R = sin(a-45)

So this takes me from joystick angle to motor speed. But I expect to be reading independent X and Y values from the joystick, so I'll need to convert those to the joystick angle.

tan(a) = Y/X
=> a = arctan(Y/X)

That's where I'm at so far. Now I just need to cook up what you get when you take the sin of an arctan so that I can compute L and R directory from X and Y without having to go through the trig functions, if that is, in fact, possible.
 

BeanieBots

Moderator
The trig cancels out.
Push forward and both motors go foward.
Push to the right, the left motor goes forward, the right motor goes backward.
Now do both forward and to the right.
We'd like the left to go faster but it can't. it's max'ed out.
What about the right motor, it CAN slow down. Right down to zero for right stick.

Imagine we have 50% forward stick.
Both motors are at 50% forwards.
Now add in 100% right stick.
Left motor speeds up because it can by another 50%, but is limited to 100% (50% + 100% = 150% MAX 100% = 100%)
Right motor is 50% - 100% = -50% ie half speed backward.

It really is just a case of ADDING the stick movements.
Just make sure your sums don't go above max or below zero and handle whatever is required if a reverse value is reached. Also pay attention to signs for each quadrant.
 

DTB Radio

Member
So it IS a matter of simple additon/subtraction. I just wasn't quite able to wrap my brain around when to do which.

Didn't work this out, its just a quick thought. Why not say we have 200%, and call 100% the center position? Then scale after computation.
 
Last edited:

BeanieBots

Moderator
Makes no difference. It all comes out the same which ever way around you do it.

PICAXE can't do negative numbers but it helps to think in positive and negative terms.

I'll use compass points for the stick and L & R for the motors.
100% for full forward. -100% for full backwards on the motors.
100% for fully towards each compass point for the stick.

Stick towards N, say 60%
R=60%, L=60%
ADD some E to the stick, say 80%
R=60+80=140% (limit to 100%)
L=60-80= (-20) The right motor has changed direction.

Stick towards W say 40% (no S or N component)
R=0-40 = (-40%) Right motor goes backwards.
L=0+40 = 40% Left motor goes forwards.
ADD some S, say 70% (remember, S is negative.)
R=-70-40 = (-110%) (there is still 40% W)
L=-70+40 = (-30%)

Then just use MAX to limit to 100% and 0% (but include 0% to -100%).

Hopefully you can now see that it REALLY IS JUST ADDITION.
Maybe some kind sole will write it in positive integer maths for you.
 

vttom

Senior Member
I played around with some numbers in Excel. I found that if I represent X and Y in the range -1 to +1, then the following, remarkably simple relationship exists:

L = Y + X
R = Y - X

Although I'm some logic to keep L and R within the +1/-1 range.

Now I'm trying to figure out what I need to do with these relationships if Y and X vary between 0 and 255, with 127 representing center.
 

BeanieBots

Moderator
Again, think in quadrants.
Take the first half (upper and lower two quadrants), lets call it Y.

ReadADC... '(gets value between 0 and 255.
Y=0 '(special case for when ADC = 127)
If ADC > 127 then
Y=ADC-127 'converts 127 to 255 into 0 to 127
Direction = forward.
endif

If ADC < 127 then
Y=127-ADC 'converts 127 to 0 into 0 to 127.
Direction = backward
endif

Y will now always have a 'speed' value between 0 and 127 and a direction control. With a value of zero for mid stick.

Do the same for X axis and integrate into the if/then structure to produce four quadrants with the required + or - and scale accordingly using MAX/MIN as required.
 

Andrew Cowan

Senior Member
This is the best info I've seen so far towards getting the result I'm looking for. I had actually come up with the same idea in code, but a VERY long way around, lol! What this code (and the mess that I came up with on my own) doesn't do is give in-place rotation (one side full ahead, other side full astern), unless I'm missing something. It looks like its probably a simple matter of adding some if-then statements based on the Motor A and Motor B values, similar to what I've already done for the individual tank-style control I'm using now.



Thank you, Andrew, for confirming and simplifying my own muddled mess, and for taking the time to come up with, and post, the code.
It does do in place rotation!

Say throttle is neutral (127), and steering is hard right (255).

That will set motor A at (throttle (127) plus steering (127)) = 255 = full forward.

It will set motor B at (throttle (127) minus steering (127)) = 0 = full reverse.

That will turn on the spot. Remember that in my code, a motor value of 127 = neutral, 0 = full back, and 255 = full forward.

My code does everything you want to do, pretty simply.

A



Just beware it overflowing. I had set the neutral point at 127, however, it drifted slightly to 126.

While 127 - 127 = 0 (robot stopped), 126 minus 127 = 255 (full forward).

That happened to my 'bot once, and sent a 60kg robot into part of my school's DT lab's sink at about 20mph. I think overall, the robot came off worse. The sink did slightly better. It now has a system where any acceleration of over 4 'bytes' per code loop triggers a complete shutdown and error messages. It has never needed it, however!
 
Last edited:

DTB Radio

Member
Oops, you're right, it DOES turn in place! I'll just make judicious use of the MIN and MAX values to avoid overflows. A MIN of 1 for PWM is as good as stopped in this application.
 

DTB Radio

Member
Ok, here's the code I've come up with. This is based on Andrew's earlier code post. Tests show that it works mostly, except some odd glitches that haven't yet figure out.

I'd appreciate comments on the logic flow. Let me know if I've missed something, or if I've processed the controls incorrectly.
Code:
'pwmout 2 , 31, 127 = PWM data for max speed at 31.4khz period

'This code assumes that for the steering axis, 0 is full left, 255 is full right
'This code assumes that for the throttle axis, 255 is full reverse, 0 is full ahead

symbol th = b0		'assign throttle to b0
symbol st = b1		'assign steering to b1
symbol lmo = b2		'assign left motor to b2
symbol rmo = b3		'assing right motor to b3
symbol rv = 0		'assign reverse control to output 0
 
main:

'read joystick position:

	readadc 1, th
        th = 255 - th
	readadc 4, st
	
'check for all-stop region:	

	if th > 118 and st > 118 and th < 134 and st < 134 then
		lmo = 0
		rmo = 0
		low rv
		pwmout 2,31,0
		goto main
	end if
	
'check for steering:

	If st < 128 then goto TurnLeft   
	If st > 127 then goto TurnRight

'process left turn:

TurnLeft:
	st = 127 - st MIN 1
	lmo = th - st MIN 1
	rmo = th + st MAX 255
	goto sendpwm

'process right turn:

TurnRight:
	st = st - 127 MIN 1
	lmo = th + st MAX 255
	rmo = th - st MIN 1
	goto sendpwm
	
'process no-steering throttle levels	

	lmo = th
	rmo = th
	
'process and send motor control data
	
sendpwm:

'check for forward or reverse, adjust data, send reverse commands

	if lmo > 127 then
		lmo = lmo - 127 MIN 1
		low rv
                goto senddata
        goto 
	end if
	if lmo < 128 then
		lmo = 127 - lmo MIN 1
		high rv
                goto senddata
	end if
	if rmo > 127 then
		rmo = rmo - 127 MIN 1
		low rv
                goto senddata
	end if
	if rmo < 128 then
		rmo = 127 - rmo MIN 1
		high rv
                goto senddata
	end if
	
'use lmo for left motor code, rmo for right motor code:

senddata:	
	pwmout 2, 31, lmo 'or rmo
	goto main
 
Last edited:

Andrew Cowan

Senior Member
Skimmed through your code briefly - are you able to reverse each motor separately?

After:
If st < 128 then goto TurnLeft
If st > 127 then goto TurnRight

you need a 'Goto sendpwm'

Will it ever get to if rmo > 127 then?

It seems it would not get there unless lmo is 128, which would only happen very rarely.

A
 

DTB Radio

Member
I also found a couple other logic flow errors in my code after I ran tests. Well, at least I now understand how it needs to work. Its just a matter of debugging the code I have and correcting the flow errors.

Thanks again to all who have posted their thoughts.
 

DTB Radio

Member
Ok, I've finally managed to get a result that is satisfactory. I ended up breaking down and buying a couple of 28X2 chips to simplify the design, and allow PWM for two motors with a single chip.

Here is the code that finally worked for me with no glitches, other than what seem to be rare and very short-term freeze-ups in code execution, unexplained as yet. If anyone sees something that can be shortened or done better, please feel free to post the code you come up with.



symbol throttle = b0
symbol steering = b1
symbol lmotor = b2
symbol rmotor = b3
symbol lmode = b.0
symbol rmode = b.1

double_speed:
'setfreq m8

main:
readadc 0,throttle
readadc 1,steering

allstop:
if throttle > 123 and throttle < 132 and steering > 123 and steering < 132 then
rmotor = 0
lmotor = 0
low rmode
low lmode
goto sendpwm
end if

straight:
if steering > 123 and steering < 132 then
if throttle > 127 then
throttle = throttle - 127
low lmode
low lmode
lmotor = throttle
rmotor = throttle
goto sendpwm
end if
if throttle < 127 then
throttle = 127 - throttle
high lmode
high rmode
lmotor = throttle
rmotor = throttle
goto sendpwm
end if
end if

rotate:
if throttle > 123 and throttle < 132 then
if steering > 127 then
lmotor = steering - 127
rmotor = steering - 127
high rmode
low lmode
goto sendpwm
end if
if steering < 127 then
rmotor = 127 - steering
lmotor = 127 - steering
high lmode
low rmode
end if
end if

rightfwd:
if steering > 127 and throttle > 127 then
steering = steering - 127
throttle = throttle - 127
lmotor = throttle + steering max 127
low lmode
rmotor = throttle - steering
if rmotor > 127 then
rmotor = rmotor - 127
rmotor = 128 - rmotor
high rmode
else
low rmode
end if

goto sendpwm
end if

leftfwd:
if steering < 127 and throttle > 127 then
steering = 127 - steering
throttle = throttle - 127
rmotor = throttle + steering
lmotor = throttle - steering
low rmode
if lmotor > 127 then
lmotor = lmotor - 127
lmotor = 128 - lmotor
high lmode
else
low lmode
end if
goto sendpwm
end if

rightrev:
if steering > 127 and throttle < 127 then
throttle = 127 - throttle
lmotor = steering - throttle
if lmotor > 127 then
lmotor = lmotor - 127
low lmode
else
high lmode
lmotor = 127 - lmotor
end if
rmotor = steering - 127 + throttle max 127
high rmode
goto sendpwm
end if

leftrev:
if steering < 127 and throttle < 127 then
throttle = 127 - throttle
steering = 127 - steering
lmotor = steering + throttle max 127
rmotor = steering - throttle
rmotor = 127 - rmotor
if rmotor > 127 then
high rmode
rmotor = rmotor - 127
else
low rmode
rmotor = 127 - rmotor
end if
high lmode
goto sendpwm
end if

sendpwm:
pwmout c.1, 31, lmotor
pwmout c.2, 31, rmotor
goto main




Thanks again to all of you who posted your thoughts. Hopefully this thread will help many more.
 

DTB Radio

Member
I left the command there for future changes. its easier to remove a ' than retype the whole line again.

As for the PWM, the same values work at all PICAXE freqs, at least for my application. The PWM frequency is not critical for the transistors I will be using. I've tested them at both 4mhz and 8mhz with the same results.
 

DTB Radio

Member
Just wanted to post a quick update. The control system was put through its first full-scale test on a life-sized boat, and passed with mostly flying colors. I did find that I need a bit more heatsinking on the drive transistors, but even pushing them hard and purposely overheating them didn't seem to bother them (I'm using NTE 181 bipolars). I also found that I need to rethink my steering, since the motors show distinctly higher propulsion in forward than reverse due to the resistance of the boat's transom panel, meaning that tank-style steering isn't really going to work nearly as well as I thought. I may end up putting each motor on a pivot, link them together, and use a heavy servo to turn them in unison, but I haven't gotten that far yet. At any rate, it was cool as heck to see a full-sized boat moving around with no-one in it, and no visible means of remote control.
 
Top