Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
229 views

Reading PWM Signals From An RC Receiver With Arduino

This document discusses two methods for reading pulse-width modulation (PWM) signals from a radio control (RC) receiver with an Arduino. The easy method uses the Arduino pulseIn() function but can be slow when reading multiple channels. The better method uses hardware interrupts to read the pin state changes, allowing other tasks to run concurrently. An example interrupt-based sketch is provided that prints the PWM pulse times in microseconds for a single receiver channel.

Uploaded by

runar library
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
229 views

Reading PWM Signals From An RC Receiver With Arduino

This document discusses two methods for reading pulse-width modulation (PWM) signals from a radio control (RC) receiver with an Arduino. The easy method uses the Arduino pulseIn() function but can be slow when reading multiple channels. The better method uses hardware interrupts to read the pin state changes, allowing other tasks to run concurrently. An example interrupt-based sketch is provided that prints the PWM pulse times in microseconds for a single receiver channel.

Uploaded by

runar library
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 4

Reading PWM Signals From An RC Receiver

With Arduino
So you want to create a remote controlled device using an Arduino? To put an Arduino between
your RC receiver and servos, you’re going to need to know how to read PWM signals. Getting
your Arduino to read signals from an RC receiver is an easy task if you don’t mind doing it badly.
If you want to do it elegantly, it’s slightly more challenging. First we’ll go over some PWM theory.

PWM Signals

RC receivers output pulse width modulated (PWM) signals on each channel. These pulses
generally are between one and two milliseconds long. I say generally because there are probably
some manufacturers who deviate from this rule of thumb. A pulse length of 1500 microseconds
will drive a standard servo to half way. 1000 microseconds is full travel in one direction and 2000
seconds is full travel in the other direction. There are 20 milliseconds between each pulse.

A 1.5ms PWM signal like this would drive a standard RC servo to its centre point.

PWM Pulses. Pulses are shown 6ms apart, but this space depends entirely on the brand and manufacturer.

Reading PWM Signals – The Easy Way

Arduino comes with a beautifully simple function called pulseIn().


So to read from a PWM source you could do something like this

#define PWM_SOURCE 34

...

pwmin = pulseIn(PWM_SOURCE, HIGH, 20000);

This would read PWM from a single channel connected to digital pin 34. More channels could be
easily added in the same way. It’s simple, it works.
The downside is that each call to pulseIn() could take 20 milliseconds. This is because pulseIn()
waits for the pin to go from digital LOW to HIGH and back to LOW again. If you’ve got 5
channels, for example, it could take up to 100 milliseconds just to read from the receiver. For
most intents and purposes this is far too slow.

READING PWM SIGNALS – THE GOOD WAY

It’s possible to read PWM signals using hardware interrupts. A hardware interrupt is a signal that
is generated by the hardware that literally interrupts the processor. With Arduino, hardware
interrupts can be generated by a pin changing value, going LOW, going HIGH, rising or falling.
The processor responds to interrupts by suspending its current activity and handling the interrupt
with an interrupt handler function (also known as an ISR – interrupt service routine). After the
interrupt handler has returned, the processor resumes its previous activity.
Unlike the easy way, reading PWM inputs with interrupts allows the processor to continue with
other tasks except for that very brief moment when an interrupt is handled.

To read PWM inputs we must know when a pin goes HIGH and LOW, and so we are only really
interested in CHANGE interrupts. When a PWM pin goes HIGH, a timer is started. When the pin
goes LOW, we can measure the pulse time by checking how much time has passed.

Arduino has the function attachInterrupt(), which allows us to supply an interrupt handler for a
particular event and pin number. The micros() function allows us to measure the time, in
microseconds, between the pin going HIGH and returning to LOW.
The micros() function isn’t particularly precise on AVR based Arduinos. Gabriel Staples over
at electricrcaircraftguy.blogspot.com has written a library for precision timing. It’s available here.
Here is an example sketch. It simply prints out the PWM pulse time in microseconds over the
serial port.

//assume that pin 32 is receiving PWM input

#define CHANNEL_1_PIN 34

//micros when the pin goes HIGH

volatile unsigned long timer_start;

//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.println(pulse_time);

delay(20);

You might also like