Skip to content

Instantly share code, notes, and snippets.

@sysrqbr
Last active Apr 10, 2017
Embed
What would you like to do?
Car-Project
// ###### RC_Car_Project ########
// Created by SysrqBR (Adail Junior)
// GitHub: https://github.com/sysrqbr
//
// Date : 21/02/2017
// Last Modification : 24/02/2017
// Version : 0.1.3
//
// Thanks to GeekySingh at: http://www.instructables.com/member/GeekySingh/
// for the Remote Controls code.
//
// Changelog Version 0.1.0 to 0.1.1
// - Created controls for the Servo
//
// Changelog Version 0.1.1 to 0.1.2
// - Add controls for the Brushmotor
// - Corrects 'parkinson' problem with the Servo
//
// Changelog Version 0.1.2 to 0.1.3
// - Correct incorrect position and aceleration calculations problems
// - Changed all comments to english (grammar lovers could cry with some comments...)
// ####### Includes
#include <Servo.h>
// ####### Servo defines
#define STEERING_SIGNAL_IN 0 // INTERRUPT 0 = DIGITAL PIN 2 - use the interrupt number in attachInterrupt
#define STEERING_SIGNAL_IN_PIN 2 // INTERRUPT 0 = DIGITAL PIN 2 - use the PIN number in digitalRead
#define NEUTRAL_STEERING 1480 // this is the duration in microseconds of neutral steering on an electric RC Car
#define SERVO 6 // Porta Digital 6 PWM
// ####### Brushmotor defines
#define THROTTLE_SIGNAL_IN 1
#define THROTTLE_SIGNAL_IN_PIN 3
#define NEUTRAL_THROTTLE 1480
#define BRUSHDCFWD 11 // PWM Digital port Foward
#define BRUSHDCRWD 5// PWM Digital port reverse
// ####### Servo constants
const int steeringNeutral = NEUTRAL_STEERING; // Neutral value
const float steeringSinalMin = 996; // Steering Min RC value
const float steeringSinalMax = 1964; // Steering Max RC value
// ####### Servo global variables
volatile int nSteeringIn = NEUTRAL_STEERING; // 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 bNewSteeringSignal = false; // set in the interrupt and read in the loop
Servo servoMotor; // Create Servo
int steeringPos; // Servo position
int steeringPosLast = 90; // Changed last position
float steeringPosFloat; // Servo temp position
int steeringSinal; // RC steering signal
float razaoSteering = ( steeringSinalMax - steeringSinalMin ) / 180; // quantum to convert RC signal to a 0 - 180 value interval
// ####### Brushmotor constants
const int throttleNeutral = 1480; // Valor do centro
const float throttleSinalMin = 994; // Valor minimo do manche
const float throttleSinalMax = 1972; // Valor maximo do manche
// ####### Brushmotor global variables
volatile int nThrottleIn = NEUTRAL_THROTTLE;
volatile unsigned long ulThrottleStartPeriod = 0;
volatile boolean bNewThrottleSignal = false;
int throttleSpeed; // Brushmotor speed
int throttleSpeedTemp; // Brushmotor temporary speed value
float throttleSpeedTempFloat; // Brushmotor temporary float speed value
int throttleSinal; // RC throttle signal
float razaoThrottle = ( throttleSinalMax - throttleSinalMin ) / 255; // quantum to convert RC signal to a 0 - 255 value interval
// Setup block
// #################
void setup ()
{
Serial.begin(9600);
// 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(STEERING_SIGNAL_IN,calcInputSteering,CHANGE);
attachInterrupt(THROTTLE_SIGNAL_IN,calcInputThrottle,CHANGE);
servoMotor.attach(SERVO);
servoMotor.write(90); // 90° motor initial position
pinMode(BRUSHDCFWD, OUTPUT); // Define pin to H-bridge circuit path to foward speed (Brushmotor)
pinMode(BRUSHDCRWD, OUTPUT); // Define pin to H-bridge circuit path to reverse speed (Brushmotor)
} // End Setup block
// ##################################################
void loop()
{
// SERVO Controls
// #################
if(bNewSteeringSignal) // if a new steering signal has been measured
{
steeringSinal = nSteeringIn;
// set this back to false when we have finished with nSteeringIn, while true, calcInput will not update nSteeringIn
bNewSteeringSignal = false;
}
steeringPosFloat = ( steeringSinal - ( steeringSinalMin - 3 )) / razaoSteering; // Change to 0 to 180 range value
steeringPos = (int) steeringPosFloat; // Truncate float part
if ( steeringPos >= 89 and steeringPos <= 91 ) { // neutral area
steeringPos = 90;
if ( steeringPosLast != steeringPos ) {
servoMotor.write(steeringPos); // Rotates SERVO
}
steeringPosLast = steeringPos;
}
else {
if ( steeringPos >= 0 and steeringPos <= 180 ) {
servoMotor.write(steeringPos); // Rotates SERVO
steeringPosLast = steeringPos;
}
else if ( steeringPos > 180 ) { // Ensure valid interval
steeringPos = 180;
servoMotor.write(steeringPos); // Rotates SERVO
steeringPosLast = steeringPos;
}
else if (steeringPos < 0) { // Ensure valid interval
steeringPos = 0;
servoMotor.write(steeringPos); // Rotates SERVO
steeringPosLast = steeringPos;
}
}
servoMotor.write(steeringPos); // Rotates SERVO
// End SERVO Controls
// ###############################################################
// Brushmotor Controls
// #################
// if a new throttle signal has been measured
if(bNewThrottleSignal)
{
throttleSinal = nThrottleIn; // set this back to false when we have finished with nThrottleIn, while true, calcInput will not update nThrottleIn
bNewThrottleSignal = false;
}
Serial.print("razaoThrottle ");
Serial.println(razaoThrottle);
throttleSpeedTempFloat = ( throttleSinal - ( throttleSinalMin - 3 )) / razaoThrottle; // Convert to 0-255 range value
Serial.print("throttleSpeedTemp ");
Serial.println(throttleSpeedTemp);
throttleSpeedTemp = (int) throttleSpeedTempFloat; // Truncate float part
if ( throttleSpeedTemp >=126 and throttleSpeedTemp <=130 ){ // Stop Brushmotor movement
throttleSpeed = 0;
analogWrite(BRUSHDCFWD, throttleSpeed); // Brushmotor speed foward
analogWrite(BRUSHDCRWD, throttleSpeed); // Brushmotor speed reverse
}
else if ( throttleSpeedTemp < 126 ) { // reverse
if ( throttleSpeedTemp <= 1 ) {
throttleSpeed = 255;
}
else {
throttleSpeed = (int( ~( byte( throttleSpeedTemp + 127 ))))*2;
}
analogWrite(BRUSHDCFWD, 0); // Brushmotor speed foward
analogWrite(BRUSHDCRWD, throttleSpeed); // Brushmotor speed reverse
}
else if ( throttleSpeedTemp > 130) { // Foward
if ( throttleSpeedTemp >= 255 ) {
throttleSpeed = 255;
}
else {
throttleSpeed = ( throttleSpeedTemp - 128 )*2;
}
analogWrite(BRUSHDCRWD, 0); // reverse Brushmotor
analogWrite(BRUSHDCFWD, throttleSpeed); // foward Brushmotor
}
// End Brushmotor Controls
// ###############################################################
}// End loop
void calcInputSteering()
{
// if the pin is high, its the start of an interrupt
if(digitalRead(STEERING_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 && (bNewSteeringSignal == false))
{
nSteeringIn = (int)(micros() - ulStartPeriod);
ulStartPeriod = 0;
// tell loop we have a new signal on the steering channel we will not update nSteeringIn until loop sets
// bNewSteeringSignal back to false
bNewSteeringSignal = true;
}
}
} // End calcInputSteering
void calcInputThrottle()
{
// 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
ulThrottleStartPeriod = 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(ulThrottleStartPeriod && (bNewThrottleSignal == false))
{
nThrottleIn = (int)(micros() - ulThrottleStartPeriod);
ulThrottleStartPeriod = 0;
// tell loop we have a new signal on the steering channel we will not update nSteeringIn until loop sets
// bNewSteeringSignal back to false
bNewThrottleSignal = true;
}
}
} // End calcInputThrottle
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment