Переглянути джерело

Loop-based reading of values, controlling a single motor

Jason Tarka 4 роки тому
коміт
65f8e8c467
1 змінених файлів з 177 додано та 0 видалено
  1. 177 0
      rc_receiver_driving.ino

+ 177 - 0
rc_receiver_driving.ino

@@ -0,0 +1,177 @@
+
+//#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;
+}