Hi guys'
Currently I am working on a small Rc project using a Arduino Nano. The project requires a small form factor therefore the Nano. Keep in mind that I am fairly new to Arduino but have a basic training in other programming languages such as java, visual basic, ..
The purpose of the the program is to interpret information from a standard Rc receiver, processes the information and use it to control a servo. I started from a from I found on rcaruino to interpret the information coming from the receiver using interrupts to minimize the amount of data processed by the arduino.
When the throttle of the Rc receiver is pushed the servo controlled by one of the channels should wait until a certain value is reached and then rotate a certain amount of degrees.
When pressed even further (full throttle) the servo should move even further by a set amount of degrees.
However as the first value is reached a certain delay about 1s should pass before moving the servo, the same when passed the second value
When giving full brake (or reverse) the servo should rotate in the other direction a set amount of degrees instantly so there can't be any delay.
The values for full brake and throttle I tested using serial monitor so these are correct.
Next I will show you the code I have so far
#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
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// twelve servo objects can be created on most boards
int pos = 0; // variable to store the servo position
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);
myservo.attach(9); // attaches the servo on pin 9 to the servo object
myservo.write(0);
}
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;
}
if((nThrottleIn) < 1400) // interval for braking
{
myservo.write(140); // tell servo to go to position 140 degrees
}
if((nThrottleIn) > 1400 && (nThrottleIn) < 1600 ) //interval for neutral
{
myservo.write(90); // tell servo to go to position neutral
if((nThrottleIn) > 1600 && (nThrottleIn) < 1800 ) // interval for first throttle
{
delay(1000);
myservo.write(20); // tell servo to go to position 20 degrees
}
if((nThrottleIn) > 1800 && (nThrottleIn) < 1900 )// interval for second throttle
{
delay(1000);
myservo.write(50); // tell servo to go to position 50 degrees
// waits 15ms for the servo to reach the position
}
}
if((nThrottleIn) > 1900) // interval for third throttle
{
delay(500);
myservo.write(90); // tell servo to go to position 90 degrees
}
}
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;
}
}
}
Now I noticed that It works partly but still some bugs like it doesn't seem to brake?
I also noticed that in the example program of the servo that the program a delay to wait until the servo reaches its position, but is this necessary?
In the future I would like to adjust the program so that movement is gradually(not full speed from a certain degree to an other) so maybe incorporating a loop with a smaller delay between each degree increment but don't know exactly how to do this. Still the time from neutral to full throttle should take approximately 2,5 Seconds. Also I noticed that servo movement is small no where near 180 degrees no matter which degree I enter.
If you could help me I would be grateful.