|
|
@@ -1,11 +1,17 @@
|
|
|
char outputStr[100];
|
|
|
-int16_t averages[AVG_PERIODS];
|
|
|
+int16_t leftAverages[AVG_PERIODS];
|
|
|
+int16_t rightAverages[AVG_PERIODS];
|
|
|
|
|
|
const int throtDeadHigh = THROT_NONE + THROT_DEAD_ZONE,
|
|
|
throtDeadLow = THROT_NONE - THROT_DEAD_ZONE;
|
|
|
|
|
|
+const int steerDeadHigh = STEER_NONE + STEER_DEAD_ZONE,
|
|
|
+ steerDeadLow = STEER_NONE - STEER_DEAD_ZONE;
|
|
|
+
|
|
|
+
|
|
|
void loop() {
|
|
|
const long startTime = millis();
|
|
|
+ deadmanSwitch();
|
|
|
|
|
|
#ifdef SCAN_MODE
|
|
|
for(byte ch = LOW_CHANNEL; ch <= NUM_CHANNELS; ch++) {
|
|
|
@@ -18,21 +24,24 @@ void loop() {
|
|
|
debugln();
|
|
|
debugln("===================");
|
|
|
|
|
|
- int throttle = getThrottle();
|
|
|
- throttle = restrictThrottlePower(throttle);
|
|
|
- throttle = getAverage(throttle);
|
|
|
+ int throttle = getThrottle(),
|
|
|
+ steer = getSteering();
|
|
|
|
|
|
- sprintf(outputStr, "Throttle:%d", throttle);
|
|
|
- Serial.println(outputStr);
|
|
|
+ driveWheel(throttle, steer, LEFT),
|
|
|
+ driveWheel(throttle, steer, RIGHT);
|
|
|
|
|
|
- digitalWrite(LEFT_MOTOR_DIRECT_PIN, throttle > 0 ? HIGH : LOW);
|
|
|
- analogWrite(LEFT_MOTOR_PIN, throttle > 0 ? throttle : -throttle);
|
|
|
+ Serial.println();
|
|
|
#endif
|
|
|
|
|
|
const long now = millis();
|
|
|
- delay(SCAN_DELAY + (startTime - now));
|
|
|
+ const long sleepTime = SCAN_DELAY + (startTime - now);
|
|
|
+ delay(sleepTime);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+/**
|
|
|
+ * Return the throttle value between -THROT_RANGE (reverse) and +THROT_RANGE (forward)
|
|
|
+ */
|
|
|
int getThrottle() {
|
|
|
int val = channelVals[THROT_CHANNEL];
|
|
|
|
|
|
@@ -46,20 +55,58 @@ int getThrottle() {
|
|
|
debugln("Throttle in dead zone");
|
|
|
return 0;
|
|
|
}
|
|
|
-
|
|
|
|
|
|
+ // Map the value to a value from 0 to THROT_RANGE range (or -THROT_RANGE to 0)
|
|
|
int throttle = val < THROT_NONE
|
|
|
- ? map(val, THROT_MIN, THROT_NONE, -OUTPUT_RANGE, 0)
|
|
|
- : map(val, THROT_NONE, THROT_MAX, 0, OUTPUT_RANGE);
|
|
|
+ ? map(val, THROT_MIN, THROT_NONE, -THROT_RANGE, 0)
|
|
|
+ : map(val, THROT_NONE, THROT_MAX, 0, THROT_RANGE);
|
|
|
|
|
|
- throttle = constrain(throttle, -OUTPUT_RANGE, OUTPUT_RANGE);
|
|
|
+ // Constrain the value in case the receiver outputs a value
|
|
|
+ // outside the expected range.
|
|
|
+ throttle = constrain(throttle, -THROT_RANGE, THROT_RANGE);
|
|
|
|
|
|
debugln("Throttle: ", throttle);
|
|
|
|
|
|
return throttle;
|
|
|
}
|
|
|
|
|
|
-int restrictThrottlePower(int throttle) {
|
|
|
+
|
|
|
+/**
|
|
|
+ * Get the value for steering, between -STEER_RANGE (left) and +STEER_RANGE (right).
|
|
|
+ */
|
|
|
+int getSteering() {
|
|
|
+ int val = channelVals[STEER_CHANNEL];
|
|
|
+
|
|
|
+ debug("Steer channel: ");
|
|
|
+ debug(val);
|
|
|
+ debug("\t");
|
|
|
+
|
|
|
+ if(val < steerDeadHigh && val > throtDeadLow) {
|
|
|
+ debugln("Steering in dead zone");
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Map the value to a value from 0 to STEER_RANGE range (or -STEER_RANGE to 0)
|
|
|
+ int steer = val < STEER_NONE
|
|
|
+ ? map(val, STEER_LEFT, STEER_NONE, -STEER_RANGE, 0)
|
|
|
+ : map(val, STEER_NONE, STEER_RIGHT, 0, STEER_RANGE);
|
|
|
+
|
|
|
+ // Constrain the value in case the receiver outputs a value
|
|
|
+ // outside the expected range.
|
|
|
+ steer = constrain(steer, -STEER_RANGE, STEER_RANGE);
|
|
|
+
|
|
|
+ debugln("Steer: ", steer);
|
|
|
+
|
|
|
+ return steer;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Restrict the motor power based on the speed control dial.
|
|
|
+ * Takes int from 0-255
|
|
|
+ * Returns int 0-255
|
|
|
+ */
|
|
|
+int restrictThrottlePower(long throttle) {
|
|
|
// Reduce the average voltage to something safe for the motor to consume.
|
|
|
throttle = (throttle * MAX_POWER_PERCENT) / 100;
|
|
|
|
|
|
@@ -73,11 +120,21 @@ int restrictThrottlePower(int throttle) {
|
|
|
|
|
|
debugln("Speed knob:\t", speedKnob);
|
|
|
debugln("Speed adjusted throttle:\t", throttle);
|
|
|
+
|
|
|
+ throttle = map(throttle, -THROT_RANGE, THROT_RANGE, -OUTPUT_RANGE, OUTPUT_RANGE);
|
|
|
+ debugln("Range adjusted throttle:\t", throttle);
|
|
|
|
|
|
return throttle;
|
|
|
}
|
|
|
|
|
|
-int getAverage(const int throttle) {
|
|
|
+
|
|
|
+/**
|
|
|
+ * Get the average throttle for the last AVG_OVER_MILLIS ms
|
|
|
+ *
|
|
|
+ * Input: value from 0-255
|
|
|
+ * Return: value from 0-255
|
|
|
+ */
|
|
|
+int getAverage(const int throttle, int16_t* averages) {
|
|
|
long long total = throttle;
|
|
|
for(byte i = 0; i < AVG_PERIODS-1; i++) {
|
|
|
total += averages[i];
|
|
|
@@ -90,3 +147,55 @@ int getAverage(const int throttle) {
|
|
|
|
|
|
return total;
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+/**
|
|
|
+ * Using the current throttle and steering values, determine the needed output
|
|
|
+ * value for a given wheel (LEFT or RIGHT), then drive that motor.
|
|
|
+ */
|
|
|
+int driveWheel(int throttle, const int steer, const byte wheel) {
|
|
|
+ // Negative steer = turn left = left backwards + right forwards
|
|
|
+ // Positive steer = turn right = left forwards + right backwards
|
|
|
+ int16_t* averages;
|
|
|
+ debugln();
|
|
|
+
|
|
|
+ switch(wheel) {
|
|
|
+ case LEFT:
|
|
|
+ debugln(F("=== LEFT ==="));
|
|
|
+ Serial.print(F("Left:"));
|
|
|
+ throttle += steer;
|
|
|
+ averages = leftAverages;
|
|
|
+ break;
|
|
|
+ case RIGHT:
|
|
|
+ debugln();
|
|
|
+ debugln(F("=== RIGHT ==="));
|
|
|
+ Serial.print(F("Right:"));
|
|
|
+ throttle -= steer;
|
|
|
+ averages = rightAverages;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ debugln("Adjusted throttle:\t", throttle);
|
|
|
+
|
|
|
+ // Make sure steering didn't throw it out of range
|
|
|
+ throttle = constrain(throttle, -THROT_RANGE, THROT_RANGE);
|
|
|
+ debugln("Constrained throttle:\t", throttle);
|
|
|
+
|
|
|
+ // Restrict it to the max power dial
|
|
|
+ throttle = restrictThrottlePower(throttle);
|
|
|
+
|
|
|
+ // Average the power so it doesn't overwhelm the wheel
|
|
|
+ throttle = getAverage(throttle, averages);
|
|
|
+
|
|
|
+ debug("Wheel power: ");
|
|
|
+ Serial.print(throttle);
|
|
|
+ Serial.print(F("\t"));
|
|
|
+
|
|
|
+ digitalWrite(
|
|
|
+ wheel == LEFT ? LEFT_MOTOR_DIRECT_PIN : RIGHT_MOTOR_DIRECT_PIN,
|
|
|
+ throttle > 0 ? HIGH : LOW
|
|
|
+ );
|
|
|
+ analogWrite(
|
|
|
+ wheel == LEFT ? LEFT_MOTOR_PIN : RIGHT_MOTOR_PIN,
|
|
|
+ throttle > 0 ? throttle : -throttle);
|
|
|
+}
|