Joystick controlling PWM H-bridge, code issues.

I am currently attempting to drive 2 motors in both directions with variable speed using a Megamoto and a joystick.
I am using a borrowed code that I have modified slightly and it seems to work for the most part.

The problem is with my code, sometimes it will PWM both the high and low side at the same time. I'm sure it's easy to fix but I am lost.
I have some deadspace built in my code for the joystick and have verified that it has plenty of space with Analog read.

#include <Servo.h>



//turret and servo(s)

Servo scanservo ;
Servo Larmservo ;
Servo Harmservo ;


//motor pins and reverse

const int RTMPin     = 11 ;
const int RTRPin     = 3 ;
const int YMPin      = 9 ;
const int YRPin      = 10 ;

// pointometers/joystick

int joyx     = A4 ;
int joyy     = A2 ;


// variables
int joyxval = 0 ;
int joyyval = 0 ;
int RTval   = 0 ;
int LTval   = 0 ;
int LDval   = 0 ;
int RDval   = 0 ;
int RYval   = 0 ;
int LYval   = 0 ;
int YLDval   = 0 ;
int YRDval   = 0 ;

/////////////////////////////////////////////////////////////////////////////////////

void setup() {

Serial.begin(9600);

pinMode (RTMPin, OUTPUT);
pinMode (RTRPin, OUTPUT);
pinMode (YMPin, OUTPUT);
pinMode (YRPin, OUTPUT);
pinMode (joyx,   INPUT);
pinMode (joyy,   INPUT);
}

/////////////////////////////////////////////////////////////////////////////////////

void loop()
{
  LDval = analogRead(joyx);
  RDval = analogRead(joyx);
  LDval = map (LDval, 530, 1023, 0, 255);
  RDval = map (RDval, 500, 0, 0, 255);


if (analogRead(joyx)<500)
{
LTval = analogRead(joyx);
LTval = map(LTval, 0, 500, 0, 255);
RTval = analogRead(joyx);
RTval = map(RTval, 0, 500, 0, 255);


LTval = (LTval - constrain (RDval, 0, 255));
RTval = (RTval - constrain (LDval, 0, 255));

analogWrite  (RTMPin, constrain (LTval, 0, 255));
digitalWrite (RTRPin, HIGH);
}
if (analogRead(joyx)>530)
{
LTval = analogRead(joyx);
LTval = map(LTval, 530, 1023, 0, 255);
RTval = analogRead(joyx);
RTval = map(RTval, 530, 1023, 0, 255);


LTval = (LTval - constrain (RDval, 0, 255));
RTval = (RTval - constrain (LDval, 0, 255));

analogWrite  (RTMPin, constrain (LTval, 0, 255));
digitalWrite (RTRPin, LOW);
}

delay(0);

{
  YLDval = analogRead(joyy);
  YRDval = analogRead(joyy);
  YLDval = map (YLDval, 530, 1023, 0, 255);
  YRDval = map (YRDval, 500, 0, 0, 255);


if (analogRead(joyy)<500)
{
LYval = analogRead(joyy);
LYval = map(LYval, 0, 500, 0, 255);
RYval = analogRead(joyy);
RYval = map(RYval, 0, 500, 0, 255);


LYval = (LYval - constrain (YRDval, 0, 255));
RYval = (RYval - constrain (YLDval, 0, 255));

analogWrite  (YMPin, constrain (LYval, 0, 255));
digitalWrite (YRPin, HIGH);
}
if (analogRead(joyy)>530)
{
LYval = analogRead(joyy);
LYval = map(LYval, 530, 1023, 0, 255);
RYval = analogRead(joyy);
RYval = map(RYval, 530, 1023, 0, 255);


LYval = (LYval - constrain (YRDval, 0, 255));
RYval = (RYval - constrain (YLDval, 0, 255));

analogWrite  (YMPin, constrain (LYval, 0, 255));
digitalWrite (YRPin, LOW);
}


}
}

Any help is appreciated.

void loop()
{
  LDval = analogRead(joyx);
  RDval = analogRead(joyx);
  LDval = map (LDval, 530, 1023, 0, 255);
  RDval = map (RDval, 500, 0, 0, 255);


if (analogRead(joyx)<500)
{
LTval = analogRead(joyx);
LTval = map(LTval, 0, 500, 0, 255);
RTval = analogRead(joyx);
RTval = map(RTval, 0, 500, 0, 255);

You are reading one pin, and assigning the result to 4 different variables. Why?

I don't know Paul. This is a code I borrowed and probably has some bugs, Maybe I need to start fresh with a code that works.
This is the only code I can find that is using a joystick to control a DC motor with speed and direction.

If someone is willing to share a code that would work for me please do.

Thanks for the reply Paul.

Nick

This is a code I borrowed and probably has some bugs

Yes, it does.

If someone is willing to share a code that would work for me please do.

What is the purpose of this project? If it isn't homework, you should make the effort to understand what that code is doing, and why it is wrong. For instance, the map function expects the input value to be in some range, but you never check that the value IS in that range. Garbage in produces garbage out, but you don't check that, either.

If it is homework, you should say that up front, so we can tell you to do it yourself.

im also trying to get two motors to go forward and reverse based on the joystick position. i got them to go forward but haven't gotten them to reverse direction yet.
heres what i got so far. the last two "if" statments need both the dir & pwm signals "high" to go in reverse. im still working on getting the last two "if"statement right.

this code was written useing Arduino IDE 0023 running on a rev2 UNO with arduino motor sheild.

int UPDOWN = A5;
int LEFTRIGHT = A3;
int dirB = 13;
int dirA = 12;
int pwmA = 11;
int pwmB= 3;

void setup() {

Serial.begin(9600);

pinMode(dirA, OUTPUT);
pinMode(dirB, OUTPUT);
pinMode(pwmA, OUTPUT);
pinMode(pwmB, OUTPUT);
pinMode(LEFTRIGHT, INPUT);
pinMode(UPDOWN, INPUT);
}

void loop()
{
Serial.print(analogRead(UPDOWN));
Serial.print(",");
Serial.println(analogRead(LEFTRIGHT));

int val1 = analogRead(UPDOWN);
int val2 = analogRead(LEFTRIGHT);

if (val1 >550)(digitalWrite(dirA, HIGH));

else digitalWrite(dirA, LOW);

if (val2 >550)(digitalWrite(pwmB, HIGH));
else digitalWrite(pwmB, LOW);

if (val1 <400)(digitalWrite(pwmA, HIGH));
else digitalWrite(pwmA, LOW);

if (val2 <400)(digitalWrite(pwmB, HIGH));
else digitalWrite(pwmB, LOW);

First work on data aquisition. read and display your values, there are code examples that show how to calibrate on the fly. Your rest positions will be a calibration point too. Once you have your aquisition code working then deal with motor control.

Serial.print(analogRead(UPDOWN));
Serial.print(",");
Serial.println(analogRead(LEFTRIGHT));

Read and throw away some values.

  int val1 = analogRead(UPDOWN);
  int val2 = analogRead(LEFTRIGHT);

Read and use some different values, but don't print them. That might give away what is happening.

Well, OK. It's your program.

Look at the symmetry of your program. If dirN is less than 400, do something to pwmX. If dirN is greater than 550, do something to dirA and pwmB. Not quite symmetric, is it?

I doubt anyone really wants to write your program for you, but If it were me controlling a motor pair via gimbal I would use 2 instances of the servo class, one for each PWM pin, 2 variables for the brake pins, and 2 for the direction pins.

#include "Servo.h"
//for the sake of arguement I will assume the x axis is on A0 and the y axis on A1.
long X_Raw;
long Y_Raw;
long X_Max;
long X_Min;
long Y_Min;
long Y_Max;
long X_Rate;
long Y_Rate;
long X_Center;
long Y_Center;
bool IsCalibrated_X;
bool IsCalibrated_Y;
bool CanRunNow;
Servo X_Axis;
Servo Y_Axis;
void setup()
       {
          X_Axis = new Servo;
          Y_Axis = new Servo;
          X_Axis.attatch(A_ChannelPWM); // You will have to provide this as I have a Motor3 and do not know the topology of your shield.
          Y_Axis.attatch(B_ChannelPWM);
          X_Max = 0;
          Y_Max = 0;
          X_Min = 1023;
          Y_Min = 1023;
          
          //todo: add code to enter a calibration mode via a pushbutton.
           }
void calibrate_X()
       {
          long mCalSample;
          while ((IsCalibrated_X = False) && ((mCalSample != X_Max) ||(mCalSample!=X_Min)))
              {//Read and test the A0 pin and store values in X_Max and X_Min. If mCalSample is greater than X_Min then store current Value in X_Min.
               //Likewise if mCalSample is less than X_Min then store it in X_Min.
               if (mCalSample > X_Max)
                  {X_Max = mCalSample;}
               else if (mCalSample < X_Min)
                  {X_Min = mCalSample;}
               else
                  {mCalSample = analogRead(A0);}
               // Add a loop counter to trap instances where stick movement is no longer adjusting limit values.
               }
          }
// Divide the difference of X_Max and X_Min by 2 and that will be your center ideally neglecting trims on the joystick gimbal.
// When reading the channel for control subtract center from the current channel value, use the absolute value to control the servo instance and
//the sign to control the the direction. Establish a deaband around the center value to control the brake pin.

This is by no means complete but I do believe it will give you a good start on your control.

Ok thanks for the replys. and ideas

I'm using a robot power megamoto, really slick.

I got stuck on this project back in september and set it down till this last week.
Getting too fustrated.
Made some progress this evening, alot.

//turret and servo(s)

Servo scanservo ;
Servo Larmservo ;
Servo Harmservo ;

//motor pins and reverse

const int RTMPin     = 11 ;
const int RTRPin     = 3 ;
const int YMPin      = 9 ;
const int YRPin      = 10 ;

// pointometers/joystick

int joyx     = A4 ;
int joyy     = A2 ;


// variables
int joyxval = 0 ;
int joyyval = 0 ;
int RTval   = 0 ;
int RTAval = 0 ;
int LTval   = 0 ;
int LTAval  = 0 ;
int LDval   = 0 ;
int RDval   = 0 ;
int RYval   = 0 ;
int LYval   = 0 ;
int YLDval   = 0 ;
int YRDval   = 0 ;

/////////////////////////////////////////////////////////////////////////////////////

void setup() {

Serial.begin(9600);

pinMode (RTMPin, OUTPUT);
pinMode (RTRPin, OUTPUT);
pinMode (YMPin, OUTPUT);
pinMode (YRPin, OUTPUT);
pinMode (joyx,   INPUT);
pinMode (joyy,   INPUT);
}

/////////////////////////////////////////////////////////////////////////////////////

void loop()
{

if (analogRead(joyx)<500)
{
LTval = analogRead(joyx);
LTval = map(LTval, 500, 1, 0, 255);
RTAval = analogRead(joyx);
RTAval = map(RTAval, 500, 1, 0, 255);
LTval = (LTval - constrain (RDval, 0, 255));

analogWrite  (RTRPin, constrain (LTval, 0, 255));

}
if (analogRead(joyx)>530)
{
LTAval = analogRead(joyx);
LTAval = map(LTAval, 530, 1023, 0, 255);
RTval = analogRead(joyx);
RTval = map(RTval, 530, 1023, 0, 255);
RTval = (RTval - constrain (LDval, 0, 255));
analogWrite  (RTMPin, constrain (LTAval, 0, 255));

}
{
if (analogRead(joyy)<500)
{
LYval = analogRead(joyy);
LYval = map(LYval, 500, 1, 0, 255);
RYval = analogRead(joyy);
RYval = map(RYval, 500, 1, 0, 255);
LYval = (LYval - constrain (YRDval, 0, 255));
analogWrite  (YRPin, constrain (LYval, 0, 255));
}
if (analogRead(joyy)>530)
{
LYval = analogRead(joyy);
LYval = map(LYval, 530, 1023, 0, 255);
RYval = analogRead(joyy);
RYval = map(RYval, 530, 1023, 0, 255);
RYval = (RYval - constrain (YLDval, 0, 255));
analogWrite  (YMPin, constrain (LYval, 0, 255));

}
}
}

Needs some more work but it now functions 98%

pinMode (joyx,   INPUT);
pinMode (joyy,   INPUT);

The pinMode function only operates on digital pins. You don't connect a joystick to a digital pin.

if (analogRead(joyx)<500)
{
LTval = analogRead(joyx);
LTval = map(LTval, 500, 1, 0, 255);
RTAval = analogRead(joyx);
RTAval = map(RTAval, 500, 1, 0, 255);
LTval = (LTval - constrain (RDval, 0, 255));

analogWrite  (RTRPin, constrain (LTval, 0, 255));

}
if (analogRead(joyx)>530)
{
LTAval = analogRead(joyx);
LTAval = map(LTAval, 530, 1023, 0, 255);
RTval = analogRead(joyx);
RTval = map(RTval, 530, 1023, 0, 255);
RTval = (RTval - constrain (LDval, 0, 255));
analogWrite  (RTMPin, constrain (LTAval, 0, 255));

}

All this code is reading from the pin in joyx. The pin is read 6 times? Why? One read would be sufficient.

What do LTval, RTAval, LTAval, and RTval mean? They mean something to you, apparently, but they don't mean anything to me. Perhaps if you used meaningful names, this code wouldn't be so confusing.

Try explaining exactly what the x joystick is controlling.

OK cleaned it up some.

//motor pins and reverse

const int XMPin     = 11 ;
const int XRPin     = 3 ;
const int YMPin      = 9 ;
const int YRPin      = 10 ;

// pointometers/joystick

int joyx     = A4 ;
int joyy     = A2 ;


// variables
int joyxval = 0 ;
int joyyval = 0 ;
int Xval   = 0 ;
int XAval = 0 ;
int Yval   = 0 ;
int YAval   = 0 ;


/////////////////////////////////////////////////////////////////////////////////////

void setup() {

Serial.begin(9600);

pinMode (XMPin, OUTPUT);
pinMode (XRPin, OUTPUT);
pinMode (YMPin, OUTPUT);
pinMode (YRPin, OUTPUT);
(joyx,   INPUT);
(joyy,   INPUT);
}

/////////////////////////////////////////////////////////////////////////////////////

void loop()
{

if (analogRead(joyx)<471)
{
Xval = analogRead(joyx);
Xval = map(Xval, 471, 1, 0, 255);
analogWrite  (XRPin, constrain (Xval, 0, 255));

}
if (analogRead(joyx)>550)
{
XAval = analogRead(joyx);
XAval = map(XAval, 550, 1023, 0, 255);
analogWrite  (XMPin, constrain (XAval, 0, 255));

}
{
if (analogRead(joyy)<471)
{
Yval = analogRead(joyy);
Yval = map(Yval, 471, 1, 0, 255);
analogWrite  (YRPin, constrain (Yval, 0, 255));
}
if (analogRead(joyy)>550)
{
YAval = analogRead(joyy);
YAval = map(YAval, 550, 1023, 0, 255);
analogWrite  (YMPin, constrain (YAval, 0, 255));

}
}
}

Now it's in a much more understandable form.
I think I can explain how it works.
Breaking the loop into 4 sections

The first half is joystick X
The first quarter is joystick X reverse
The second quarter is joystick X forward

The same thing with the Second half of the loop, only for the Y axis.

(joyx,   INPUT);
(joyy,   INPUT);

And this is doing what? Nothing harmful, but nothing useful, either. Delete them to remove the clueless newbie impression they give.

if (analogRead(joyx)<471)
{
Xval = analogRead(joyx);
Xval = map(Xval, 471, 1, 0, 255);
analogWrite  (XRPin, constrain (Xval, 0, 255));

}
if (analogRead(joyx)>550)
{
XAval = analogRead(joyx);

You are still reading the pin more times than needed.

Try this:

Xval = analogRead(joyx);
if(Xval < 471)
{
   Xval = map(Xval, 471, 1, 0, 255);
   analogWrite (XRPin, constrain (Xval, 0, 255));
}
else if(Xval > 550)
{
   Xval = map(Xval, 550, 1023, 0, 255);
   analogWrite(XMPin, constrain (Xval, 0, 255));
}

I still don't see why pushing the joystick forward or right controls one pin and pushing it backward or left controls a different pin.

Typically, pushing the joystick forward or backward controls PWM on one (analog) pin and direction on another (digital) pin.

So, I'd STILL like to know what you are controlling with the joystick.

Thanks for the help Paul.

//motor pins and reverse

const int XMPin     = 11 ;
const int XRPin     = 3 ;
const int YMPin      = 9 ;
const int YRPin      = 10 ;

// pointometers/joystick

int joyx     = A4 ;
int joyy     = A2 ;


// variables
int Xval   = 0 ;
int Yval   = 0 ;



/////////////////////////////////////////////////////////////////////////////////////

void setup() {

Serial.begin(9600);

pinMode (XMPin, OUTPUT);
pinMode (XRPin, OUTPUT);
pinMode (YMPin, OUTPUT);
pinMode (YRPin, OUTPUT);
}

/////////////////////////////////////////////////////////////////////////////////////

void loop()
{
Xval = analogRead(joyx);
if(Xval < 471)
{
   Xval = map(Xval, 471, 1, 0, 255);
   analogWrite (XRPin, constrain (Xval, 0, 255));
}
else if(Xval > 550)
{
   Xval = map(Xval, 550, 1023, 0, 255);
   analogWrite(XMPin, constrain (Xval, 0, 255));
}
{
Yval = analogRead(joyy); 
if(Yval < 471)
{
   Yval = map(Yval, 471, 1, 0, 255);
   analogWrite (YRPin, constrain (Yval, 0, 255));
}
else if(Yval > 550)
{
   Yval = map(Yval, 550, 1023, 0, 255);
   analogWrite(YMPin, constrain (Yval, 0, 255));  
}
}
}

I have learned how my MegaMoto board works!

There are 2 pins for each motor. Both are analog pins(forward and reverse)
Instead of the usual: 1 analog (speed) and 1 digital (direction).

Thanks so much!

The motors are at the machine shop and I should be receiving replacement (I let the smoke out) H-bridges tommorow.
If all goes well I will get this up and running over the weekend.

Ill work on hosting some pictures as well.