RC to control DC motor

Hello All,
To begin, I have only been playing with the arduino and components for a few weeks so dont assume I know much.

My Setup: Servo, 2 dc motors, h-bridge controller, arduino uno.

I have been playing around with different settings, I am able to successfully control the motors, back forth yada yada.

Goal 1: Now I want to control the speed of the dc motor with a RC controller; the more I move the joysticks the faster the motor rotates etc

1st attempt: Connect receiver output pin directly to dc motor enable pin on h-bridge controller
1st result: The dc motor would activate when I toggled the joystick but its max speed when using the RC controller in this manner was only a fraction of its achievable max speed (when speed set in program).

2nd attempt: Connect receiver output to an input analog pin and then try to map this input to a digital output (using appropriate reads and writes) to get the correct signal to the dc motor.
2nd result: squat. nothing.

Goal 2: Get dc motor to rotate both directions (cw/ccw) with joystick movement. Tips?

I have a few attachments hopefully to make my setup and approach a little clearer.
code for 2nd attempt:
int rc1=A0;
int toH=6;
int rcvalue=0;

void setup() {
/pinMode(AO, INPUT);/
pinMode(6, OUTPUT);
Serial.begin(9600);
}
void loop() {
}
rcvalue = analogRead(rc1);
rcvalue = map(rcvalue, 0, 1023, 0, 255);
digitalWrite(6, rcvalue);
Serial.print("output value;");
Serial.println(6);
Serial.print("input value;");
Serial.println(A0);
Serial.print("rc value;");
Serial.println(rcvalue);
delay(1500);
}

Let me know if any more info would help.

Thank you!

allpics.pdf (672 KB)

Please post a circuit, hand drawn and photographed is ok. It takes too long to try and follow the wires.

Weedpharma

Basically an RC controller sends a multiplexed PWM signal. That is their is a PWM pulse for every control the joysticks have to offer sent rapidly one after the other.

This is a digital signal and you are wasting your time trying to measure this as an analogue signal. What you need to do is to read this stream and break it down into its component parts. Only then when you have extracted the correct pulse measurement from this stream can you then apply that number to a PWM capable output of the Arduino.

This is quite complex but you might find a library for this if you search.

However if you are getting a decoded signal from just one channel things are a bit simpler. You still need to decode the output but the sort of PWM signal you get is designed for driving a servo not a motor. The difference is the duty cycle is important in a motor, but it is just the pulse width that drives a servo. Basically measure this pulse with the pulse in function, then take that width and use it to set the output of an analogWrite function, this generates a signal suitable for a motor.

Look I cant write a wiring diagram for beans but I attached the best I could manage. Let me know if clarification is needed.

Thanks!

resjsu:
Look I cant write a wiring diagram for beans but I attached the best I could manage.

Then it is probably best if you learn how to before you start. If you can't read a schematic then you can't wire up anything. Just like it is best to learn to stand up before you can attempt to run.

Grumpy_Mike:
Then it is probably best if you learn how to before you start. If you can't read a schematic then you can't wire up anything. Just like it is best to learn to stand up before you can attempt to run.

Duly noted, needless to say and none too helpful. Im learning as I go and I feel like im picking it up pretty quickly. However, thank you very much for your previous post, it is very helpful!

You might find this page tells you about the PWM signal you need to drive a motor.
http://www.thebox.myzen.co.uk/Tutorial/PWM.html

What am I doing wrong?

int rc1 = A0; //from receiver channel 1
int dc1 = A1; //to enable A for motor 1
unsigned long duration; // from arduino example

void setup() {
pinMode(rc1, INPUT); //analog input from receiver
pinMode(dc1, OUTPUT);// analog output to h-bridge
}
void loop() {

duration = pulseIn(rc1, HIGH, 1000);
duration =map(duration, 0, 1023, 0, 255);
analogWrite(dc1, duration);
}

There is just nothing happening...

What am I doing wrong?

Not using code tags - read how to use this forum sticky.
There is no analogue input from the receiver, change the comment.

Pulsein does not return a number from 0 to 1023 so that map command is wrong.

Print out the numbers you get from pulsein to see what range you get.

Pin A0 is not capable of producing an analogue output. Use one of the PWM capable pins.

Please read this

// First Example in a series of posts illustrating reading an RC Receiver with
// micro controller interrupts.
//
// Subsequent posts will provide enhancements required for real world operation
// in high speed applications with multiple inputs.
//
// http://rcarduino.blogspot.com/ 
//
// Posts in the series will be titled - How To Read an RC Receiver With A Microcontroller

// See also http://rcarduino.blogspot.co.uk/2012/04/how-to-read-multiple-rc-channels-draft.html  

#define THROTTLE_SIGNAL_IN 0 // INTERRUPT 0 = DIGITAL PIN 2 - use the interrupt number in attachInterrupt
#define THROTTLE_SIGNAL_IN_PIN 2 // INTERRUPT 0 = DIGITAL PIN 2 - use the PIN number in digitalRead

#define NEUTRAL_THROTTLE 1500 // this is the duration in microseconds of neutral throttle on an electric RC Car

volatile int nThrottleIn = NEUTRAL_THROTTLE; // volatile, we set this in the Interrupt and read it in loop so it must be declared volatile
volatile unsigned long ulStartPeriod = 0; // set in the interrupt
volatile boolean bNewThrottleSignal = false; // set in the interrupt and read in the loop
// we could use nThrottleIn = 0 in loop instead of a separate variable, but using bNewThrottleSignal to indicate we have a new signal 
// is clearer for this first example

void setup()
{
  // tell the Arduino we want the function calcInput to be called whenever INT0 (digital pin 2) changes from HIGH to LOW or LOW to HIGH
  // catching these changes will allow us to calculate how long the input pulse is
  attachInterrupt(THROTTLE_SIGNAL_IN,calcInput,CHANGE);

  Serial.begin(9600); 
}

void loop()
{
 // if a new throttle signal has been measured, lets print the value to serial, if not our code could carry on with some other processing
 if(bNewThrottleSignal)
 {

   Serial.println(nThrottleIn);  

   // set this back to false when we have finished
   // with nThrottleIn, while true, calcInput will not update
   // nThrottleIn
   bNewThrottleSignal = false;
 }

 // other processing ... 
}

void calcInput()
{
  // if the pin is high, its the start of an interrupt
  if(digitalRead(THROTTLE_SIGNAL_IN_PIN) == HIGH)
  { 
    // get the time using micros - when our code gets really busy this will become inaccurate, but for the current application its 
    // easy to understand and works very well
    ulStartPeriod = micros();
  }
  else
  {
    // if the pin is low, its the falling edge of the pulse so now we can calculate the pulse duration by subtracting the 
    // start time ulStartPeriod from the current time returned by micros()
    if(ulStartPeriod && (bNewThrottleSignal == false))
    {
      nThrottleIn = (int)(micros() - ulStartPeriod);
      ulStartPeriod = 0;

      // tell loop we have a new signal on the throttle channel
      // we will not update nThrottleIn until loop sets
      // bNewThrottleSignal back to false
      bNewThrottleSignal = true;
    }
  }
}

Alright the following is what I got from a website, thank you BillHO those websites were very helpful. I am just trying to see if I can get any kind of signal in the serial window and currently I do not get anything except 0. I have the receiver output attached to pin 11 (PWM capable) and I am using the code below. The serial window just reads 0.

Ideas?

//assume that pin 32 is receiving PWM input
#define CHANNEL_1_PIN 11
//micros when the pin goes HIGH
volatile unsigned long timer_start;
long pulse_time;
//difference between timer_start and micros() is the length of time that the pin 
//was HIGH - the PWM pulse length. volatile int pulse_time; 
//this is the time that the last interrupt occurred. 
//you can use this to determine if your receiver has a signal or not. 
volatile int last_interrupt_time; //calcSignal is the interrupt handler 
void calcSignal() 
{
    //record the interrupt time so that we can tell if the receiver has a signal from the transmitter 
    last_interrupt_time = micros(); 
    //if the pin has gone HIGH, record the microseconds since the Arduino started up 
    if(digitalRead(CHANNEL_1_PIN) == HIGH) 
    { 
        timer_start = micros();
    } 
    //otherwise, the pin has gone LOW 
    else
    { 
        //only worry about this if the timer has actually started
        if(timer_start != 0)
        { 
            //record the pulse time
            pulse_time = ((volatile int)micros() - timer_start);
            //restart the timer
            timer_start = 0;
        }
    } 
} 
 
//this is all normal arduino stuff 
void setup() 
{
    timer_start = 0; 
    attachInterrupt(CHANNEL_1_PIN, calcSignal, CHANGE);
    Serial.begin(115200);
} 
 
void loop()
{
    Serial.print("P.W.M.");
    Serial.println(pulse_time);
    delay(20);
}
long pulse_time;

If a variable is used in an ISR and used outside it it MUST be declared volatile. It is the only one that needs it and it is the only one that is not.

I have the receiver output attached to pin 11 (PWM capable)

That is irrelevant, PWM capable is about it being ABLE to generate PWM. Using it as a straight digital input has no advantage over any other input pin.

Why have you abandoned code you were beginning to understand to code that you haven't got a clue about?

Have you read this

https://www.arduino.cc/en/Reference/AttachInterrupt