//#define SCAN_MODE // If set, scan & output channel values, rather than driving the robot. ///////////////////////////////////////////////////////////////////////// // Configuration ////////////////////////////////////////////////// #define MAX_POWER_PERCENT 90 // The maximum percentage on time, used to decrease average voltage to the motor. #define OUTPUT_RANGE 255 // The maximum value for PWM output /////////////////////// #define SCAN_DELAY 100 // Delay between updates in ms #define AVG_PERIODS 10 // Number of periods to average the speed over (reduces random variances) ///////////////////////////////////////////////////////////////////////// // Channel pins ///////////////////////////////////////////////////////////////////////// #define LOW_CHANNEL 1 #define NUM_CHANNELS 6 // Channel pins. Using numbers 1-6 for clarity, so using a bad value in index 0. const byte channels[7] = {255, 8,9,10,11,12,13}; ///////////////////////////////////////////////////////////////////////// // Channel values ///////////////////////////////////////////////////////////////////////// // Right horizontal (steering) #define STEER_CHANNEL 1 #define STEER_LEFT 1300 #define STEER_RIGHT 1690 #define STEER_NONE 1500 #define STEER_DEAD_ZONE 30 // 10% of the range is dead zone // Right vertical (throttle) #define THROT_CHANNEL 2 #define THROT_MAX 1940 #define THROT_MIN 1160 #define THROT_NONE 1510// Halfway range #define THROT_DEAD_ZONE 30 // approx 10% of the range is dead #define THROT_OFF 0 // Anything below this means the throttle switch (upper right) is off #define CH_4_MIN 0 #define CH_4_MAX 0 // Right knob #define LIGHT_CHANNEL 5 #define LIGHT_MIN 990 #define LIGHT_MAX 1990 // Left knob #define SPEED_CHANNEL 6 #define SPEED_MIN 1000 #define SPEED_MAX 2000 ///////////////////////////////////////////////////////////////////////// // Output pins ///////////////////////////////////////////////////////////////////////// #define LEFT_MOTOR_PIN 5 #define LEFT_MOTOR_DIRECT_PIN 4 #define RIGHT_MOTOR_PIN 6 #define RIGHT_MOTOR_DIRECT_PIN 7 char outputStr[100]; int16_t averages[AVG_PERIODS]; void setup() { Serial.begin(9600); pinMode(LEFT_MOTOR_PIN, OUTPUT); pinMode(RIGHT_MOTOR_PIN, OUTPUT); pinMode(LEFT_MOTOR_DIRECT_PIN, OUTPUT); pinMode(RIGHT_MOTOR_DIRECT_PIN, OUTPUT); for(byte i = LOW_CHANNEL; i <= NUM_CHANNELS; i++) { pinMode(channels[i], INPUT); } delay(2000); } void loop() { #ifdef SCAN_MODE for(byte i = LOW_CHANNEL; i <= NUM_CHANNELS; i++) { readChannel(i); } #else Serial.println("============"); int throttle = getThrottle(); throttle = restrictThrottlePower(throttle); throttle = getAverage(throttle); digitalWrite(LEFT_MOTOR_DIRECT_PIN, throttle > 0 ? HIGH : LOW); analogWrite(LEFT_MOTOR_PIN, throttle > 0 ? throttle : -throttle); #endif Serial.println(); delay(SCAN_DELAY); } #define TIMEOUT_MICROS 30000 uint16_t readChannel(byte channel) { int val = pulseIn(channels[channel], HIGH, TIMEOUT_MICROS); #ifdef SCAN_MODE if(val > 100) val -= 1000; if(channel > 1) Serial.print(" "); Serial.print(val); #else sprintf(outputStr, "Channel %d:\t%d", channel, val); Serial.println(outputStr); #endif return val; } const int throtDeadHigh = THROT_NONE + THROT_DEAD_ZONE, throtDeadLow = THROT_NONE - THROT_DEAD_ZONE; int getThrottle() { int val = readChannel(THROT_CHANNEL); Serial.print("Channel value: "); Serial.print(val); Serial.print("\t"); if(val <= THROT_OFF) { Serial.println("Throttle is off"); return 0; } else if(val < throtDeadHigh && val > throtDeadLow) { Serial.println("Throttle in dead zone"); return 0; } int throttle = val < THROT_NONE ? map(val, THROT_MIN, THROT_NONE, -OUTPUT_RANGE, 0) : map(val, THROT_NONE, THROT_MAX, 0, OUTPUT_RANGE); throttle = constrain(throttle, -OUTPUT_RANGE, OUTPUT_RANGE); Serial.print("Throttle: "); Serial.println(throttle); return throttle; } int restrictThrottlePower(int throttle) { // Reduce the average voltage to something safe for the motor to consume. throttle = (throttle * MAX_POWER_PERCENT) / 100; Serial.print("Restricted throttle:\t"); Serial.println(throttle); // Use the current value of the knob to reduce the speed. int speedKnob = readChannel(SPEED_CHANNEL); speedKnob = map(speedKnob, SPEED_MIN, SPEED_MAX, 0, 100); speedKnob = constrain(speedKnob, 0, 100); throttle = (throttle * speedKnob) / 100; Serial.print("Speed knob:\t"); Serial.println(speedKnob); Serial.print("Speed adjusted throttle:\t"); Serial.println(throttle); return throttle; } int getAverage(const int throttle) { int total = throttle; for(byte i = 0; i < AVG_PERIODS-1; i++) { total += averages[i]; averages[i] = averages[i+1]; } averages[AVG_PERIODS-1] = throttle; total /= AVG_PERIODS; Serial.print("Average adjusted throttle:\t"); Serial.println(total); return total; }