Project tutorial
Speed controller for power motors, with reverse

Speed controller for power motors, with reverse © GPL3+

This project describes how to make a DIY speed controller for DC motors for Remote Controlled (RC) models, using one power transistor.

  • 2,491 views
  • 0 comments
  • 6 respects

Components and supplies

A000066 iso both
Arduino UNO & Genuino UNO
×1
Resistor 10K
×1
6V Motor (up to 8A or 48W)
×1
MJ11016 Motorola Darlington Power Transistor
×1
G6CU-2117P-US OMRON latching relay
×2
6V Lead acid battery
×1

About this project

I have a small RC tugboat, built in the '80s, with 2 channels (throttle and rudder) and 2 servos. All I would like to do was to replace the old fashioned Forward-Reverse switch of the motor with an electronic speed controlled device so that I can vary the speed of the propeller from neutral to full forward (or full reverse) in a variable way rather than in a "step" ON-OFF one.

The first thing to do is to understand what kind of signals the RC receiver sends to the servo motors.

A typical receiver sends pulses PWM to the servos. Arduino has a built-in function to detect these pulses and it is called pulseIn(). This function reads a pulse, measures the time of the duration and returns the length of the pulse in microseconds. The simple sketch below "The intermediate code" is for understanding the values that the RC receiver sends over and prints the raw input of the receiver to the serial monitor.

For this purpose, the following configuration is necessary:

  • Connect the signal pin cable ("white' cable in my case) of the RC receiver's throttle channel to Arduino pin no. 5
  • Connect the negative pin cable ("black' cable in my case) of the RC receiver's throttle channel to Arduino earth pin
  • Connect the RC receiver to its power supply
  • Switch on the RC transmitter
  • Move slowly the throttle from "neutral" to "upmost forward" position. Then move slowly the throttle from "neutral" to "undermost reverse" position
  • Keep track of the readings in the monitor.

By running the aforementioned sketch I get values from 800 to 1700μs; in particular:

  • From "neutral" to "upmost forward" position, values from 1250 up to 800μs
  • From "neutral" to "undermost reverse" position, values from 1250 to 1700μs

The second thing to do is modify the above values into context, that is translate the values into voltage signal of 0-5V in order to drive the motor through a power transistor.

For this I used the analogWrite() function which writes an analog value to a pin which drives the motor, in this case pin no. 3 (see "The final code"). The map() function translates the 1700-800μs range onto the 0-255 range which is appropriate for the analogWrite function. In other words, when the throttle moves from "neutral" to "forward", that is from values 1250 backwards, Arduino maps them as values from 0 to 255 and sends a variable voltage of 0-5V to pin no.3.

In the opposite direction, when the throttle moves from "neutral" to "reverse", that is from values 1250 onward, Arduino maps them as values from 0 to 255 and sends a variable voltage of 0-5V to pin no.3.

For safety reasons the if() function makes sure a dead section of 1000μs (500 each side of neutral position) is left without sending any signals.

The resistor just before the transistor's base (see the "Confifuration diagram") appears to be 10KΩ. Note that the exact value of the resistor needs to be calculated for optium results and depends on the technical characteristics of the motor. In this project the motor is relatively of low power (apprx. 5W), but in the case of more powerful motors, care should be taken as the rated current of the OMRON relays is limited to 8A.

From the above it is obvious that irrespective of the movement of the throttle, that is "forward" or "reverse" position, pin no.3 sends the same variable voltage 0-5V to the power transistor in order to drive the motor.

The third thing to do is to teach Arduino to reverse the polarity to the motor when throttle is in the "reverse" position.

For this, a pair of single coil latching relays is used and its operation is triggered by a pulse from Arduino. The pulse lasts for 30ms and is driven to pins no. 6 and 10 when the throttle is in "forward" position and to pins no. 9 and 11 when in "reverse".

In this way, both relays lock and retain the polarity to the motor until the next pulse from Arduino comes in.

Finally, the "Improved configuration diagram" differs from the aforementioned "Configuration diagram" in the way that instead having a separate 6V battery pack to power the RC receiver, the latter one is powered by the same 6V battery which powers both the motor and Arduino.

The speed controller inside the tugboat operates as it is shown on the video.

Code

The intermediate codeC/C++
This is the code for Arduino in order to understand the signals from the RC receiver.
/*
  Speed Controller (intermediate code) by G. Souris @2017
 */
int chnthr; //the name of the variable term for throttle channel's input signal

void setup() {
  pinMode(5, INPUT); //pin no. 5 to read the signal from receiver
  Serial.begin(9600);
}

void loop() {
  chnthr = pulseIn(5, HIGH, 25000); //this reads the duration of the reciver's signal in ms
  Serial.println(chnthr);

   delay(1); 
}
The final codeC/C++
This is the code for Arduino which takes the signal from the RC receiver, translates it into digital signal 0-5V, sends it to the power transistor which drives the motor.
The software also opens/closes the two latched relays for the forward/reverse direction of the motor.
/*
  Speed Controller by G. Souris @2017
 */
int chnthr; //the name of the variable term for throttle channel's input signal
int voltmotor; //the name of the variable term for voltage out to the power transistor which drives the motor

void setup() {
  pinMode(5, INPUT); //pin no. 5 to read the signal from receiver
  pinMode(3, OUTPUT); //pin no. 3 to drive the motor
  pinMode(6, OUTPUT); //pin 1 of latched relay coil No. 1 
  pinMode(9, OUTPUT); //pin 8 of latched relay coil No. 1
  pinMode(10, OUTPUT); //pin 1 of latched relay coil No. 2
  pinMode(11, OUTPUT); //pin 8 of latched relay coil No. 2
  analogWrite(6, 0); //pulse to pin 1 of latched relay coil No. 1
  analogWrite(9, 0); //pulse to pin 8 of latched relay coil No. 1
  analogWrite(10, 0); //pulse to pin 1 of latched relay coil No. 2
  analogWrite(11, 0); //pulse to pin 8 of latched relay coil No. 2
}

void loop() {
  chnthr = pulseIn(5, HIGH, 25000); //this reads the duration of the reciver's signal in ms

if(chnthr <1200 and chnthr> 800) //throttle is in forward motion
  {
  analogWrite(6, 250);  delay(30); analogWrite(6, 0); //pulse to open the relay No. 1 for forward motion
  analogWrite(10, 250);  delay(30); analogWrite(10, 0); //pulse to open the relay No. 2 for forward motion
  voltmotor=map(chnthr, 1200, 800, 0, 255); //this scales the receiver's signal from ms to 0-5V
  analogWrite(3,voltmotor);} //sends voltage to the power transistor to drive the motor
  
  else if(chnthr >1300 and chnthr< 1700) //throttle is in reverse motion
  {
  analogWrite(9, 250);  delay(30); analogWrite(9, 0);  //pulse to open the relay No. 1 for reverse motion
  analogWrite(11, 250);  delay(30); analogWrite(11, 0); //pulse to open the relay No. 2 for reverse motion
  voltmotor=map(chnthr, 1300, 1700, 0, 255); //this scales the receiver's signal from ms to 0-5V
  analogWrite(3,voltmotor);} //sends voltage to the power transistor to drive the motor
  
  else  //throttle is idle
  {voltmotor=0;
  analogWrite(3,voltmotor);} //sends no voltage to the power transistor

  delay(1); //Break of 1 ms until the next reading of signal
}
An improved final codeC/C++
Same as the final code but with some improvements in smoothing out signals.
/*
  Speed Controller
 */
int chnthr;
int chnthr1;
int chnthr2;
int chnthr3;
int chnthr4;
int chnthr5;
int voltmotor;
int bypassRLfwd;
int bypassRLbwd;

void setup() {
  pinMode(5, INPUT);
  pinMode(3, OUTPUT);
  pinMode(6, OUTPUT); //latched relay
  pinMode(9, OUTPUT); //latched relay
  pinMode(10, OUTPUT); //latched relay
  pinMode(11, OUTPUT); //latched relay
  analogWrite(6, 0);
  analogWrite(9, 0);
  analogWrite(10, 0);
  analogWrite(11, 0);
  bypassRLfwd=0; bypassRLbwd=0;
  //Serial.begin(9600);
}

void loop() {
  chnthr1 = pulseIn(5, HIGH, 25000);delay(1); 
  chnthr2 = pulseIn(5, HIGH, 25000);delay(1);
  chnthr3 = pulseIn(5, HIGH, 25000);delay(1);
  chnthr4 = pulseIn(5, HIGH, 25000);delay(1);
  chnthr5 = pulseIn(5, HIGH, 25000);
  chnthr=(chnthr1+chnthr2+chnthr3+chnthr4+chnthr5)/5;
  //Serial.println(chnthr);

if(chnthr <1200 and chnthr> 0) {
  if (bypassRLfwd==1) {goto motorfwd;}
  else {  
  analogWrite(6, 250);  delay(30); analogWrite(6, 0);
  analogWrite(10, 250);  delay(30); analogWrite(10, 0);
  bypassRLfwd=1;bypassRLbwd=0;}
  motorfwd:
  if (chnthr>=800) {voltmotor=map(chnthr, 1200, 800, 0, 255);}
  else {voltmotor=255;}
  //Serial.println (voltmotor);
  analogWrite(3,voltmotor);}
  
  else if(chnthr >1300 and chnthr< 2000) {
  if (bypassRLbwd==1) {goto motorbwd;}
  else { 
  analogWrite(9, 250);  delay(30); analogWrite(9, 0);
  analogWrite(11, 250);  delay(30); analogWrite(11, 0);
  bypassRLbwd=1;bypassRLfwd=0;}
  motorbwd:
  if (chnthr<=1700) {voltmotor=map(chnthr, 1300, 1700, 0, 255);}
  else {voltmotor=255;}
  //Serial.println (voltmotor);
  analogWrite(3,voltmotor);}
  
  else
  {voltmotor=0;
  //Serial.println (voltmotor);
  analogWrite(3,voltmotor);}

}

Custom parts and enclosures

Configuration diagram
This is the actual connection diagram.
real_config_J8k4ArihHd.dwg
Improved configuration diagram
This is an improved version of the connection diagram with no use of the RC receiver's battery pack but the use of the 6V battery which powers both Arduino and motor.
improved_config_AFxtxu0NHg.dwg

Schematics

Configuration diagram
This is the actual connection diagram.
Improved configuration diagram
This is an improved version of the connection diagram with no use of the RC receiver's battery pack but the use of the 6V battery which powers both Arduino and motor.

Comments

Similar projects you might like

@Tiny85 Sleep Controller : Power Saving with Arduino

Project tutorial by Shahariar

  • 4,944 views
  • 0 comments
  • 11 respects

Bubble Cannon Interactive Game Controller

Project tutorial by Jimmy Huang

  • 1,058 views
  • 0 comments
  • 0 respects

Take Control Over Lego Power Functions

Project tutorial by Patrick Müller

  • 43,674 views
  • 3 comments
  • 60 respects

Low Power RF Beacon for Remote Sensing & Communication

Project tutorial by Shahariar

  • 1,887 views
  • 0 comments
  • 16 respects

Using Android Smart Phone to Remote Controller

Project tutorial by Team Makewith

  • 2,147 views
  • 1 comment
  • 6 respects

PS3 Controller Control Servo Wireless

Project tutorial by Youssef Sabaa

  • 19,878 views
  • 2 comments
  • 12 respects
Add projectSign up / Login