Driving a DC motor forward and reverse with a RC throttle trigger potentiometer

I am trying to build a control system for follow focusing a camera, this will utilize two DC brushed motors and hopefully be controlled both by wire and wireless utilizing RC throttle trigger potentiometer for the wired portion and Wii classic controller hacked to a Anarduino -HW-915 9HW 915Mhz for wireless.

The fist step is to get the wired side of things working but I’m running into issues with the code I have been hobbling together. I am utilizing an arduino UNO and a Adafruit v2 motorshield and have run the DC motor test from the library and have proven that the voltage is correct and the motor can run in forward and reverse and ramp up and down in speed.

Next I found a sketch that allowed me to read the values from the arduino of the throttle trigger potentiometer and the reading are as follows; at home it reads 5252 if the trigger is deflected forward it tops out at 5353 and when it’s deflected back it bottoms out at 5151. Measuring resistance with a ohm meter saw 4.58K across the leads and 2.27 and 2.38K with a lead and wiper.

This is my code;

/* 
This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2
controlling a focus follow DC motor with a RC throttle trigger potentiometer
forward and reverse at variable speeds

For use with the Adafruit Motor Shield v2 
---->	http://www.adafruit.com/products/1438
*/

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();  

// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
// You can also make another motor on port M2
//Adafruit_DCMotor *myOtherMotor = AFMS.getMotor(2);

 int potPinDrive = 0;

 int potVal;    // variable to read the value from the analog pin

void setup() {

  AFMS.begin();  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz
  
  // Set the speed to start, from 0 (off) to 255 (max speed)
  myMotor->setSpeed(150);
  myMotor->run(FORWARD);
  // turn on motor
  myMotor->run(RELEASE);
}



void loop() {
     
  potVal = analogRead(potPinDrive);            // reads the value of the potentiometer 
  delay(100);                           // waits for the value to get there 
 
  if(potVal > 5272)
  {
    myMotor->run(FORWARD);
    myMotor->setSpeed((potVal - 5252) / 2);
  }

  if(potVal < 5232)
  {
    myMotor->run(BACKWARD);
    myMotor->setSpeed((5252 - potVal) / 2);
  
  }
 
  else
  {
    myMotor->run(RELEASE);
    myMotor->setSpeed(0);
  }
}

Right now when I upload the code the motor spins slowly but I am expecting the motor to be idle, when the trigger is deflected back the motor speeds up and when it is deflected forward the motor stops I am hoping someone can point out the obvious code change I need look at and the reasoning behind it so to make this work as I am intending it to.

Thank you for your time and support,
Bloody bold

I am utilizing an arduino UNO

  potVal = analogRead(potPinDrive); 
 ...
  if(potVal > 5272)

Doesn’t look like that branch will ever be taken, does it?

potVal can only be between 0 and 1023 (the result of the analogRead).

So the first if in loop() will always evaluate to false.

Next you need to check the parameters for the setSpeed() method by analyzing the library

void Adafruit_DCMotor::setSpeed(uint8_t speed) {
  ...
  ...
}

Note the type of the variable that you need to pass; it's an uint8_t (also know as byte). I don't know what the practical maximum value can be, but it can never be larger than 255.

AWOL:  potVal = analogRead(potPinDrive); ...  if(potVal > 5272)

Doesn't look like that branch will ever be taken, does it?

AWOL, Thanks for your replay, however I am not experienced our bright enough to understand about the branch being taken. Could you offer a little more direction.

analogRead on a Uno can only return a value in the range 0 to 1023 inclusive. Testing to see if the value returned by analogRead is greater than 5272 is pointless - it never can be.

AWOL: analogRead on a Uno can only return a value in the range 0 to 1023 inclusive. Testing to see if the value returned by analogRead is greater than 5272 is pointless - it never can be.

I see so what is the best method for attaining the values?

You could reinstate the map code you commented-out in your original post that is no longer there at all.

Or you could skip the map altogether and just use the raw analogue values.

AWOL, thank you for taking the time and sterretje as well for getting me steered in the right direction. However I believe I should call it a night as I need to rest my brain and it will all make more sense in the morning. I did however make some changes to the values.

/* 
This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2
controlling a focus follow DC motor with a RC throttle trigger potentiometer
forward and reverse at variable speeds

For use with the Adafruit Motor Shield v2 
---->	http://www.adafruit.com/products/1438
*/

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();  

// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
// You can also make another motor on port M2
//Adafruit_DCMotor *myOtherMotor = AFMS.getMotor(2);

 int potPinDrive = 0;

 int potVal;    // variable to read the value from the analog pin

void setup() {

  AFMS.begin();  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz
  
  // Set the speed to start, from 0 (off) to 255 (max speed)
  myMotor->setSpeed(150);
  myMotor->run(FORWARD);
  // turn on motor
  myMotor->run(RELEASE);
}



void loop() {
     
  potVal = analogRead(potPinDrive);            // reads the value of the potentiometer 
   
  delay(100);                           // waits for the value to get there 
 
  if(potVal > 522)
  {
    myMotor->run(FORWARD);
    myMotor->setSpeed((potVal - 512) / 2);
  }
  if(potVal < 502)
  {
    myMotor->run(BACKWARD);
    myMotor->setSpeed((512 - potVal) / 2);
  
 
  }
 
  else
  {
    myMotor->run(RELEASE);
    myMotor->setSpeed(0);
  }
}

With this change the motor does not run at start and works in the BACKWARD direction but does not move in the forward direction. I then deleted the BACKWARD script and it work in the FORWARD direction.
So I know I am close I just need to figure out how to attain the correct values to allow both directions at once but as I said I’m tired wore out. Any tips would be great on how I should go about it.

Thanks and good night Mrs. Kalabash where ever you are!

Follow your logic (let’s say potVal is 600).

first if: condition satisfied, so motor will run forward
second if: not satisfied so the else block will be executed and stop the motor

This happens in an endless loop.

You’re missing an else

  if (potVal > 522)
  {
    myMotor->run(FORWARD);
    myMotor->setSpeed((potVal - 512) / 2);
  }
  else if (potVal < 502)        // <------------------ else added
  {
    myMotor->run(BACKWARD);
    myMotor->setSpeed((512 - potVal) / 2);
  }
  else
  {
    myMotor->run(RELEASE);
    myMotor->setSpeed(0);
  }

Hi,
Welcome to the forum.

I am having problems perceiving how you project is going to work.

I am trying to build a control system for follow focusing a camera,

Does this mean you want to control/adjust the focus of a camera?
If so then controlling the speed/direction of the motor directly will not give you precise control.

Can you explain you application please?

Thanks… Tom… :slight_smile:

sterretje:
Follow your logic (let’s say potVal is 600).

first if: condition satisfied, so motor will run forward
second if: not satisfied so the else block will be executed and stop the motor

This happens in an endless loop.

You’re missing an else

@strerretje :o I knew it was close, thank you for helping me understand that the loop statement was incomplete, my hat’s off to you!

Here is the working code;

/* 
This is a test sketch for the Adafruit assembled Motor Shield for Arduino v2
controlling a focus follow DC motor with a RC throttle trigger potentiometer
forward and reverse at variable speeds

For use with the Adafruit Motor Shield v2 
---->  http://www.adafruit.com/products/1438
*/

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"

// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();  

// Select which 'port' M1, M2, M3 or M4. In this case, M1
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
// You can also make another motor on port M2
//Adafruit_DCMotor *myOtherMotor = AFMS.getMotor(2);

 int potPinDrive = 0;

 int potVal;    // variable to read the value from the analog pin

void setup() {

  AFMS.begin();  // create with the default frequency 1.6KHz
  //AFMS.begin(1000);  // OR with a different frequency, say 1KHz
  
  // Set the speed to start, from 0 (off) to 255 (max speed)
  myMotor->setSpeed(150);
  myMotor->run(FORWARD);
  // turn on motor
  myMotor->run(RELEASE);
}



void loop() {
     
  potVal = analogRead(potPinDrive);            // reads the value of the potentiometer 
   
  delay(100);                           // waits for the value to get there 
 
  if(potVal > 530)
  {
    myMotor->run(FORWARD);
    myMotor->setSpeed((potVal - 520) / 2);
  }
  else if(potVal < 510)
  {
    myMotor->run(BACKWARD);
    myMotor->setSpeed((520 - potVal) / 2);
  
 
  }
 
  else
  {
    myMotor->run(RELEASE);
    myMotor->setSpeed(0);
  }
}

Along with that fine bit of information I also learned my code for reading the trigger potentiometers was fubar! Hear is a working but not ideal code which was able to help find the values I was looking for thank you to Mr. Bill at adafruit for helping me correct it

 /* Read Jostick
  * ------------
  *
  * Reads two analog pins that are supposed to be
  * connected to a jostick made of two potentiometers
  *
  * We send three bytes back to the comp: one header and two
  * with data as signed bytes, this will take the form:
  *    Jxy\r\n
  *
  * x and y are integers and sent in ASCII 
  * 
  * http://www.0j0.org | http://arduino.berlios.de
  * copyleft 2005 DojoDave for DojoCorp
  */

 int ledPin = 13;
 int joyPin1 = 0;                 // slider variable connecetd to analog pin 0
 int joyPin2 = 1;                 // slider variable connecetd to analog pin 1
 int value1 = 0;                  // variable to read the value from the analog pin 0
 int value2 = 0;                  // variable to read the value from the analog pin 1

 void setup() {
  pinMode(ledPin, OUTPUT);              // initializes digital pins 0 to 7 as outputs
  Serial.begin(9600);
 }

 int treatValue(int data) {
  return (data * 9 / 1024) + 48;
 }

 void loop() {
  analogRead(joyPin1);   // throw away the first reading
  Serial.print("X = :");
  Serial.println(analogRead(joyPin1));  // print the second reading
  analogRead(joyPin2);   // throw away the first reading
  Serial.print("Y = :");
  Serial.println(analogRead(joyPin2));  // print the second reading
 }

With this I was able to see at zero the pot read 520, deflected forward 625 and defected backward 370. I added and subtracted 10 for the 520 for margin of error in reading as the starting points for forward and reverse. So far it’s behaving quite nicely and the motor ramp is smooth but yet not excessively fast.

@TomGeorge, yes my statement maybe a little miss leading as I will not be able to have the precision I’d like to have say if I were using a servo or stepper motor but these motors are from a run and gun system on the market that is quick and dirty for pulling focus and zoom. However they do not offer a wireless option that I am aware of for a gimbal system I believe they have something for a drone setup and for what they wanted for just a 2 channel wired controller I thought I could build in wireless control at a third of it’s cost.

For right now it will do, I may look into expanding the system with different motors but believe to add and encoder setup to these motors would be difficult due to there form factor, unless you have an easy solution? Right now my goal is to be able to sit with my wife and control a video camera from my seat at my granddaughters wedding in October.

So next is to add a second motor to this code, after that is hacking a Wii classic controller and building it into the code. Question since my next steps no longer will be dealing with this subject matter should I start a new post or just keep updating here as I don’t want to go against form protocol.

Thanks again,
Bloodybold

Different problem, different thread. You can always refer to this one if needed.

It would also help if you defined how you setup your pot and what voltages you measured on the wiper at the three points, all forward, center and all back. So far you have just thrown what look like arbitrary numbers. Show your work! Dwight

@dwighttinker, I am a little confused by your statement? ("So far you have just thrown what look like arbitrary numbers")

If you read in post #1 I submit the following; Next I found a sketch that allowed me to read the values from the arduino of the throttle trigger potentiometer and the reading are as follows; at home it reads 5252 if the trigger is deflected forward it tops out at 5353 and when it's deflected back it bottoms out at 5151. Measuring resistance with a ohm meter saw 4.58K across the leads and 2.27 and 2.38K with a lead and wiper.

In post #8 I will admit these were random numbers I play'd with in order to I identify and understand what was explained to me by AWOL and strerretje, helping me to understand that the numbers provided to me by the code I was utilizing to read the value of the analog input 0 was incorrect and had to fall within a value range of 0 to 1023

In post #11 I identified the analog read program was fubar! and a fix was put in place and the correct values were were identified, I then posted this code so someone else could use if they found it beneficial. Believing my code I was working on only needed the value for the zero position (520) I allowed a little less then 4% as a margin of error in resistance when I chose 530 in which to start the motor forward and 510 for backward.

My apology if it appeared I was not demonstrating my methodology, I am not sure what else I could have posted, oh and I never did read the voltage across the lead and the wiper as I believed the readings from the analog input were more than sufficient, now in hind sight maybe they were more beneficial than I realized but Mama never said I was the brightest bulb on the tree!

Cheers, Robb

I do wonder how you got the 5000 numbers. If me, I would have calculated the expected values and then seen how they compared to the actual value measure on the arduino. Going with the values you measured is fine but you should compare them with the expected values. It will give you confidence that there isn't a circuit error or something else. Dwight