Problems with R/C 6ch transmission

Hi,

I´m trying to read the RC signal on the receiver with pulseIn() function, i am using 6 ch rx tx turnigy equip.
What i am trying is to read the value and print in the serial monitor but
I´ve tryed:
-Power the receiver with arduino regulator and power with 7805 regulator
-Connect the GND pin in the receiver´s channel slot to arduino gnd pin

  • Read the high value and the low value time
  • Use analogRead too

Allways I´ve readed 17731 value,in the beggining I was trying to read the six values
but now I am trying to read only one value,and if I disconnect the receiver from arduino´s pins in the serial monitor read 17731 again,but a bit slowly.
someone knows why or what is happening????
Thanks!!!!!!

I can probably help.

First of all, are you reading the channels individually through six three wire connections or are you reading a PPM Stream which contains all of the six channels in a single connection ?

Duane B

rcarduino.blogspot.com

I am reading the channels individually,first I connected six single wire,the receiver signal pin to arduino I/0 and then y tryed to connect the receiver gnd pin to arduino gnd pin too
(six double wire)

That sounds fine.

Lets try and read one signal first, try the sketch in this link

connect one of your channels to pin 2 of your Arduino to read it

Duane B

thanks, I will read and try this afternoon.

Let me know how you get on, I can point you to the links for more channels and when your up and running - my new library.

Duane B

rcarduino.blogspot.com

hi!!!
I read and try your sketch for one channel and work perfectly.
Thanks!!! now I will start with the oder two tutorial(for more channels),I will tell you.

Its good to read and understand this one -

but if your feeling brave try this one -

Its going to be a big benefit with six channels, the sensitive parts of the code are much faster than the original link.

If you need help with it let me know.

Duane B

rcarduino.blogspot.com

Hi again,
I was understanding the first one, but when upload the example code,
the servo start to move like little crazy.
So I added a serial print inside the interrups,in the else stament,just before updating the flag,for see the variable
that is passed to the servo but it was randomly,always between 17000 and 25000.
I have use first the 2,03 version and them 1.81 library,but no.
it´s that normal????

thanks for your help :smiley:

Hi,
Its going to be something simple, my first guess is that you have the receiver channel connected to digital pin 2 still.

The multi channel code expects channels to be connected to pins 5,6,7

// Assign your channel in pins
#define THROTTLE_IN_PIN 5
#define STEERING_IN_PIN 6
#define AUX_IN_PIN 7

And servos to 8,9,10 so that the channel on pin 5 drives the servo on pin 8, 6 drives 9, 7 drives 10

// Assign your channel out pins
#define THROTTLE_OUT_PIN 8
#define STEERING_OUT_PIN 9
#define AUX_OUT_PIN 10

I would also suggest that you remove the serial commands you have added, they are not the problem, but they should not be inside any of the time sensitive sections of code.

If this doesn't help, PM me the sketch and what board you are using.

Duane B

rcarduino.blogspot.com

Good morning!!!
No, I have connected well the receiver channel and servo,now I am using one nano v3.0.But when RC works i want to use in oder proyect in ARduino Mega 2560.
I put the code for try to understand what´s happening,or see what is reading from the receiver.
Thanks!!!!

the sketch:


// MultiChannels
//
// rcarduino.blogspot.com
//
// A simple approach for reading three RC Channels using pin change interrupts
//
// See related posts -
// http://rcarduino.blogspot.co.uk/2012/01/how-to-read-rc-receiver-with.html
// RCArduino: Need More Interrupts To Read More RC Channels ?
// RCArduino: Can I Control More Than X Servos With An Arduino ?
//
// rcarduino.blogspot.com
//

// include the pinchangeint library - see the links in the related topics section above for details
#include <PinChangeInt.h>

#include <Servo.h>

// Assign your channel in pins
#define THROTTLE_IN_PIN 5
#define STEERING_IN_PIN 6
#define AUX_IN_PIN 7

// Assign your channel out pins
#define THROTTLE_OUT_PIN 8
#define STEERING_OUT_PIN 9
#define AUX_OUT_PIN 10

// Servo objects generate the signals expected by Electronic Speed Controllers and Servos
// We will use the objects to output the signals we read in
// this example code provides a straight pass through of the signal with no custom processing
Servo servoThrottle;
Servo servoSteering;
Servo servoAux;

// These bit flags are set in bUpdateFlagsShared to indicate which
// channels have new signals
#define THROTTLE_FLAG 1
#define STEERING_FLAG 2
#define AUX_FLAG 4

// holds the update flags defined above
volatile uint8_t bUpdateFlagsShared;

// shared variables are updated by the ISR and read by loop.
// In loop we immediatley take local copies so that the ISR can keep ownership of the
// shared ones. To access these in loop
// we first turn interrupts off with noInterrupts
// we take a copy to use in loop and the turn interrupts back on
// as quickly as possible, this ensures that we are always able to receive new signals
volatile uint16_t unThrottleInShared;
volatile uint16_t unSteeringInShared;
volatile uint16_t unAuxInShared;

// These are used to record the rising edge of a pulse in the calcInput functions
// They do not need to be volatile as they are only used in the ISR. If we wanted
// to refer to these in loop and the ISR then they would need to be declared volatile
uint32_t ulThrottleStart;
uint32_t ulSteeringStart;
uint32_t ulAuxStart;

void setup()
{
Serial.begin(9600);

Serial.println("multiChannels");

// attach servo objects, these will generate the correct
// pulses for driving Electronic speed controllers, servos or other devices
// designed to interface directly with RC Receivers
servoThrottle.attach(THROTTLE_OUT_PIN);
servoSteering.attach(STEERING_OUT_PIN);
servoAux.attach(AUX_OUT_PIN);

// using the PinChangeInt library, attach the interrupts
// used to read the channels
PCintPort::attachInterrupt(THROTTLE_IN_PIN, calcThrottle,CHANGE);
PCintPort::attachInterrupt(STEERING_IN_PIN, calcSteering,CHANGE);
PCintPort::attachInterrupt(AUX_IN_PIN, calcAux,CHANGE);
}

void loop()
{
// create local variables to hold a local copies of the channel inputs
// these are declared static so that thier values will be retained
// between calls to loop.
static uint16_t unThrottleIn;
static uint16_t unSteeringIn;
static uint16_t unAuxIn;
// local copy of update flags
static uint8_t bUpdateFlags;

// check shared update flags to see if any channels have a new signal
if(bUpdateFlagsShared)
{
noInterrupts(); // turn interrupts off quickly while we take local copies of the shared variables

// take a local copy of which channels were updated in case we need to use this in the rest of loop
bUpdateFlags = bUpdateFlagsShared;

// in the current code, the shared values are always populated
// so we could copy them without testing the flags
// however in the future this could change, so lets
// only copy when the flags tell us we can.

if(bUpdateFlags & THROTTLE_FLAG)
{
unThrottleIn = unThrottleInShared;
}

if(bUpdateFlags & STEERING_FLAG)
{
unSteeringIn = unSteeringInShared;
}

if(bUpdateFlags & AUX_FLAG)
{
unAuxIn = unAuxInShared;
}

// clear shared copy of updated flags as we have already taken the updates
// we still have a local copy if we need to use it in bUpdateFlags
bUpdateFlagsShared = 0;

interrupts(); // we have local copies of the inputs, so now we can turn interrupts back on
// as soon as interrupts are back on, we can no longer use the shared copies, the interrupt
// service routines own these and could update them at any time. During the update, the
// shared copies may contain junk. Luckily we have our local copies to work with :slight_smile:
}

// do any processing from here onwards
// only use the local values unAuxIn, unThrottleIn and unSteeringIn, the shared
// variables unAuxInShared, unThrottleInShared, unSteeringInShared are always owned by
// the interrupt routines and should not be used in loop

// the following code provides simple pass through
// this is a good initial test, the Arduino will pass through
// receiver input as if the Arduino is not there.
// This should be used to confirm the circuit and power
// before attempting any custom processing in a project.

// we are checking to see if the channel value has changed, this is indicated
// by the flags. For the simple pass through we don't really need this check,
// but for a more complex project where a new signal requires significant processing
// this allows us to only calculate new values when we have new inputs, rather than
// on every cycle.
if(bUpdateFlags & THROTTLE_FLAG)
{
if(servoThrottle.readMicroseconds() != unThrottleIn)
{
servoThrottle.writeMicroseconds(unThrottleIn);
}
}

if(bUpdateFlags & STEERING_FLAG)
{
if(servoSteering.readMicroseconds() != unSteeringIn)
{
servoSteering.writeMicroseconds(unSteeringIn);
}
}

if(bUpdateFlags & AUX_FLAG)
{
if(servoAux.readMicroseconds() != unAuxIn)
{
servoAux.writeMicroseconds(unAuxIn);
}
}

bUpdateFlags = 0;
}

// simple interrupt service routine
void calcThrottle()
{
// if the pin is high, its a rising edge of the signal pulse, so lets record its value
if(digitalRead(THROTTLE_IN_PIN) == HIGH)
{
ulThrottleStart = micros();
}
else
{
// else it must be a falling edge, so lets get the time and subtract the time of the rising edge
// this gives use the time between the rising and falling edges i.e. the pulse duration.
unThrottleInShared = (uint16_t)(micros() - ulThrottleStart);
// use set the throttle flag to indicate that a new throttle signal has been received
bUpdateFlagsShared |= THROTTLE_FLAG;
Serial.println(unThrottleInShared,DEC);
}
}

void calcSteering()
{
if(digitalRead(STEERING_IN_PIN) == HIGH)
{
ulSteeringStart = micros();
}
else
{
unSteeringInShared = (uint16_t)(micros() - ulSteeringStart);
bUpdateFlagsShared |= STEERING_FLAG;
Serial.println(unSteeringInShared,DEC);
}
}

void calcAux()
{
if(digitalRead(AUX_IN_PIN) == HIGH)
{
ulAuxStart = micros();
}
else
{
unAuxInShared = (uint16_t)(micros() - ulAuxStart);
bUpdateFlagsShared |= AUX_FLAG;
Serial.println(unAuxInShared,DEC);
}
}

Hi,
Can you take the serial commands out of the interrupt routines, thats the last place you would want to put them.

Lets focus on just the throttle channel for now, put a serial print inside this section in the main loop -

if(bUpdateFlags & THROTTLE_FLAG)
  {
    if(servoThrottle.readMicroseconds() != unThrottleIn)
    {
      servoThrottle.writeMicroseconds(unThrottleIn);
    }
    // Serial print here ....
  }

The only reasons I would expect random values are -

  1. Floating inputs - your ISR is pointing to a pin that is not connected

  2. No common ground - check that the receiver ground is connected to the arduino ground

  3. Some difference in pin/port mappings on Nano3.0 that makes pinchangeint reference the incorrect pin

It might not be any of these, but an easy way to check is to connect each digital pin to ground one by one and watch the output, if the output stop we know that the pin you just grounded was the one that the signal was being read from.

Use a 10K resistor as the connection to ground to limit the current in case one of the pins is set to output.

Does this make sense ? let me know how you get on

Duane B

So, the experiment will be, throttle thah is pin 5 in arduino, trought a 10k resistor conected to ground, and the output in the serial monitor will stop becouse there is no change for interrupt no???, and if this don´t happen change looking for the real pin.
I will do, but yesterday when I power down the transeiver (buttom off),the serial monitor stop. well I´ll try and say what happend in a moment.

Let me know what happens, I am eager to get to the bottom of this ...

Duane.

Worksss!!!!!!!!!!
it was my foult I sopouse that first i try reading the serial monitor and when i saw the random read values i connected the servos and nothing works.
it was what you say I must read out of the interrupt,but i don´t understand this so well.What was the diference between read the shared value just before give this value to the loop, and read the value when you use in the loop???

Thanks a lot!!!!!!

There is a lot of good information in this link

Your question relates specifically to this part of the post -

  1. Variable Access

And the reason you should not put serial print in the time sensitive parts of the code -

  1. Fast Interrupt Service Routines

Let me know if that makes sense of not.

Duane B

Yes,I´ve read it yesterday and i thing i understand, but what i don´t understand well is if i read something
in the interrupt but just when all is finish is not the same that read when we go back to the loop.
I am thinking in this particular case, when we hava the variable that is needed update and we go back to the loop for make a copy.
is not the same read this variable that we will copy in the loop??? well is not the same and i see the real case no when i did this i have unexpected values and when i read in the loop i have expected values.... but for me it´s a little extrange.

When you are in the interrupt, no other interrupts can happen.

If you do something slow in the interrupt like Serial.println no interrupts can happen for a long time, this means that we will get inaccurate values because we are not able to respond to the new interrupts until we finish the current one. When we do get to respond the values we read will be wrong.

So it is the same variable, but by using Serial.println in the interrupt we were ensuring that it would become inaccurate.

You want to get in and out of interrupts as quickly as possible

If you look here you will see that I am reading timers directly instead of using micros, you can also see the improvement in accuracy in the graphs -

Stay with the code you are using for now, once you are a familiar I would like to help you try this code, its faster but a bit new.

Duane B

aha, i understand you, thanks a lot Duane. now i ill try to update the RC to my proyect, i am doing a puppet.
but i will follow your web, and in some days i hope to probe your fast library.
Only one thing , I want to include you in the acknowlegement of my proyect,you have help me a lot,
Can you mail me your name to alehop@mononokeproducciones.com

THANKS Duane B!!!!!

Hi,
If you keep some variation of this with a link to the RCArduino blog, that would be great as acknowledgement.

Also if you let me know what you build I will put a link to your project on the RCArduino blog.

Duane B

// MultiChannels
//
// rcarduino.blogspot.com
//
// A simple approach for reading RC Channels using pin change interrupts
//
// See related posts -
// http://rcarduino.blogspot.co.uk/2012/01/how-to-read-rc-receiver-with.html
// http://rcarduino.blogspot.co.uk/2012/03/need-more-interrupts-to-read-more.html
// http://rcarduino.blogspot.co.uk/2012/01/can-i-control-more-than-x-servos-with.html
//
// rcarduino.blogspot.com
//