I've been working on the code to control two hoverboard motors using RioRand ZS-X11H and HotRC DS-600 transmitter and receiver. I have both motors working with the RC as intended except when the motors run in reverse the motor in reverse status comes to a hard stop while the other motor coasts to a stop. I've been busting my brain to figure out how to have both motors coast to a stop instead of hard stops. I'm still learning Arduino and I've had many bumps and bruises to get to this point. Any help or guidance will be appreciated.
#define SERIAL_PORT_SPEED 115200
#define RC_NUM_CHANNELS 2
#define RC_CH1_INPUT 2 // RC Channel 1 Input Pin
#define RC_CH2_INPUT 3 // RC Channel 2 Input Pin
uint16_t RC_VALUES[RC_NUM_CHANNELS];
uint32_t RC_START[RC_NUM_CHANNELS];
volatile uint16_t RC_SHARED[RC_NUM_CHANNELS];
uint16_t RC_LOW[RC_NUM_CHANNELS] = { 1013, 1013 };
uint16_t RC_MID[RC_NUM_CHANNELS] = { 1508, 1508 };
uint16_t RC_HIGH[RC_NUM_CHANNELS] = { 2005, 2005 };
uint16_t RC_CHANNEL_MODE[RC_NUM_CHANNELS] = { 0, 0 };
uint16_t RC_INVERT[RC_NUM_CHANNELS] = { 1, 0 }; // Uncommented this line to fix the error
float RC_TRANSLATED_VALUES[RC_NUM_CHANNELS];
float RC_TRANSLATED_LOW[RC_NUM_CHANNELS] = { -50, -50 };
float RC_TRANSLATED_MID[RC_NUM_CHANNELS] = { 0, 0 };
float RC_TRANSLATED_HIGH[RC_NUM_CHANNELS] = { 50, 50 };
uint16_t RC_DZPERCENT[RC_NUM_CHANNELS] = { 5, 5 };
// Motor Configuration
const int PIN_PWM_MOTOR1 = 9; // Left motor speed control (PWM) pin
const int PIN_DIR_MOTOR1 = 4; // Left motor direction control pin
const int PIN_PWM_MOTOR2 = 10; // Right motor speed control (PWM) pin
const int PIN_DIR_MOTOR2 = 7; // Right motor direction control pin
const int DELAY = 20;
int _pwmCtrl_Motor1 = 0; // PWM control signal for Motor 1 (0-255)
bool _dir_Motor1 = 1; // Direction of Motor 1
// Variables for Motor 2
int _pwmCtrl_Motor2 = 0; // PWM control signal for Motor 2 (0-255)
bool _dir_Motor2 = 0; // Direction of Motor 2
void setup() {
Serial.begin(SERIAL_PORT_SPEED);
pinMode(RC_CH1_INPUT, INPUT);
pinMode(RC_CH2_INPUT, INPUT);
attachInterrupt(digitalPinToInterrupt(RC_CH1_INPUT), READ_RC1, CHANGE);
attachInterrupt(digitalPinToInterrupt(RC_CH2_INPUT), READ_RC2, CHANGE);
pinMode(PIN_PWM_MOTOR1, OUTPUT);
pinMode(PIN_DIR_MOTOR1, OUTPUT);
pinMode(PIN_PWM_MOTOR2, OUTPUT);
pinMode(PIN_DIR_MOTOR2, OUTPUT);
}
unsigned long current = 0;
unsigned long prev = 0;
const unsigned long interval = 100000UL;
void loop() {
rc_read_values();
rc_invert_values();
rc_deadzone_adjust();
rc_translate_values();
// Motor Control
int motorSpeed = map(RC_VALUES[0], RC_LOW[0], RC_HIGH[0], -127, 127);
motorSpeed = constrain(motorSpeed, -150, 150);
int turnValue = map(RC_VALUES[1], RC_LOW[1], RC_HIGH[1], -127, 127);
turnValue = constrain(turnValue, -150, 150);
int leftMotorSpeed = motorSpeed + turnValue;
int rightMotorSpeed = motorSpeed - turnValue;
// Determine motor directions
bool leftMotorForward = leftMotorSpeed >= 0;
bool rightMotorForward = rightMotorSpeed >= 0;
// Set motor directions
digitalWrite(PIN_DIR_MOTOR1, leftMotorForward ? HIGH : LOW);
digitalWrite(PIN_DIR_MOTOR2, rightMotorForward ? LOW : HIGH);
// Set motor speeds
analogWrite(PIN_PWM_MOTOR1, abs(leftMotorSpeed));
analogWrite(PIN_PWM_MOTOR2, abs(rightMotorSpeed));
// Output RC Controller Data
current = micros();
if (current - prev >= interval) {
prev += interval;
for (int i = 0; i < RC_NUM_CHANNELS; i++) {
Serial.print("CH");
Serial.print(i);
Serial.print(":");
Serial.print(RC_TRANSLATED_VALUES[i]);
Serial.print(",");
}
Serial.print("LOW:");
Serial.print(RC_TRANSLATED_LOW[0]);
Serial.print(",");
Serial.print("HIGH:");
Serial.print(RC_TRANSLATED_HIGH[0]);
Serial.println("");
}
// Perform movements with delays
if (RC_VALUES[0] > RC_HIGH[0]) {
// Move forward
moveForward();
delay(1000); // Adjust the delay time as needed
} else if (RC_VALUES[0] < RC_LOW[0]) {
// Move backward
moveBackward();
delay(1000); // Adjust the delay time as needed
} else if (RC_VALUES[1] > RC_HIGH[1]) {
// Turn left
turnLeft();
delay(1000); // Adjust the delay time as needed
} else if (RC_VALUES[1] < RC_LOW[1]) {
// Turn right
turnRight();
delay(1000); // Adjust the delay time as needed
}
}
// Add your movement functions here
void moveForward() {
// Set motor speeds for forward movement
_pwmCtrl_Motor1 = 50; // Max speed
_pwmCtrl_Motor2 = 50; // Max speed
}
void moveBackward() {
// Set motor speeds for backward movement
_pwmCtrl_Motor1 = -25; // Max speed in reverse
_pwmCtrl_Motor2 = -25; // Max speed in reverse
}
void turnLeft() {
// Set motor speeds for left turn
_pwmCtrl_Motor1 = 10; // Max speed for left turn
_pwmCtrl_Motor2 = -10; // Max speed for left turn
}
void turnRight() {
// Set motor speeds for right turn
_pwmCtrl_Motor1 = -15; // Max speed for right turn
_pwmCtrl_Motor2 = 15; // Max speed for right turn
}
void READ_RC1() {
Read_Input(0, RC_CH1_INPUT);
}
void READ_RC2() {
Read_Input(1, RC_CH2_INPUT);
}
void Read_Input(uint8_t channel, uint8_t input_pin) {
if (digitalRead(input_pin) == HIGH) {
RC_START[channel] = micros();
} else {
uint16_t rc_compare = (uint16_t)(micros() - RC_START[channel]);
RC_SHARED[channel] = rc_compare;
}
}
void rc_read_values() {
noInterrupts();
memcpy(RC_VALUES, (const void *)RC_SHARED, sizeof(RC_SHARED));
interrupts();
}
void rc_invert_values() {
for (int i = 0; i < RC_NUM_CHANNELS; i++) {
if (RC_INVERT[i] == 1) {
RC_VALUES[i] = (RC_HIGH[i] + RC_LOW[i]) - RC_VALUES[i];
}
if (RC_VALUES[i] > RC_HIGH[i]) {
RC_VALUES[i] = RC_HIGH[i];
}
if (RC_VALUES[i] < RC_LOW[i]) {
RC_VALUES[i] = RC_LOW[i];
}
}
}
void rc_translate_values() {
for (int i = 0; i < RC_NUM_CHANNELS; i++) {
RC_TRANSLATED_VALUES[i] = translateValueIntoNewRange((float)RC_VALUES[i], (float)RC_HIGH[i], (float)RC_LOW[i], RC_TRANSLATED_LOW[i], RC_TRANSLATED_HIGH[i]);
}
}
void rc_deadzone_adjust() {
for (int i = 0; i < RC_NUM_CHANNELS; i++) {
float newval = 0;
if (RC_CHANNEL_MODE[i] == 0) {
newval = translateValueIntoNewRange((float)RC_VALUES[i], (float)RC_HIGH[i], (float)RC_LOW[i], 50.0, -50.0);
if (abs(newval) < RC_DZPERCENT[i]) {
RC_VALUES[i] = RC_MID[i];
}
} else if (RC_CHANNEL_MODE[i] == 1) {
newval = translateValueIntoNewRange((float)RC_VALUES[i], (float)RC_HIGH[i], (float)RC_LOW[i], 50.0, 0.0);
if (abs(newval) < RC_DZPERCENT[i]) {
RC_VALUES[i] = RC_LOW[i];
}
}
}
}
float translateValueIntoNewRange(float currentvalue, float currentmax, float currentmin, float newmax, float newmin) {
return (((currentvalue - currentmin) * (newmax - newmin)) / (currentmax - currentmin)) + newmin;
}


