Hello, I am trying to create a program that will take in two digital inputs (forward and backward) and read the analog input from a joystick to generate a digital signal, always beginning with four pulses with a width of 1500 microseconds as a synchronization segment (to let the receiver know a valid signal is arriving) and then a command section with a varied number of pulses and a varied pulse width (chosen by the RC car direction and turn angle, respectively). Much of the information about the signal is recorded in the many constants in the code below.
The problem I'm having is that the code is not working at the moment. I only got a flash of a square wave a couple days ago when testing the joystick (in other words, only turning, no forward/backward direction), but it was so brief (and I got distracted by another problem with the joystick) that I couldn't measure any of its parameters. Regardless, any help would be appreciated in helping to fix my code.
Note that I want the output to be, for every iteration of the loop() function, one cycle of the total command signal from pin 10, consisting of four synchronization pulses and some number of pulses with a set pulse width depending on the current mode of operation. For example, if the Arduino was told to only go forward, then the four synchronization pulses would be executed and then 15 pulses with a pulse width of 750 microseconds would be generated.
Hopefully my question was clear, despite its length. Let me know if anything needs to be clarified. Thank you for any help given.
Below is my code (Note that Forward and Backward are separate inputs as I want there to exist no movement in the RC car, if not commanded. Additionally, the angle formula in the commandSignal() method is an equation I derived; I can give the derivation if anyone deems it necessary):
int forwardPin = 12;
int backwardPin = 13;
int commandPin = 10;
// Pulse Widths
const int centerPW = 750; // Standard Pulse Width for no turning
const int minPW = 500; // Minimum Pulse Width for turning
const int maxPW = 1000; // Maximum Pulse Width for turning
const int syncPW = 1500; // Synchronization Segment Pulse Width
const float maxSig = 1023.0; // Joystick minimum and maximum serial outputs
const float minSig = 0.0;
const float restSig = 501.0; // Resting joystick serial output
const float shiftSig = 30.0; // Serial output shift of joystick to apply deadzone
// Pulse Counts for each mode of operation
const int forwardPC = 15;
const int backwardPC = 40;
const int leftPC = 25;
const int rightPC = 30;
const int forwardLeftPC = 10;
const int backwardLeftPC = 20;
const int forwardRightPC = 35;
const int backwardRightPC = 45;
const float period = 1 / 490;
const float conversion = 255; // Number gotten to convert Duty Cycle percentages to analogWrite() output
float w_min = 0.12495*(((maxPW - minPW)/(maxSig - minSig))*minSig + minPW);
float w_max = 0.12495*(((maxPW - minPW)/(maxSig - minSig))*maxSig + minPW);
float w_rest = 0.12495*(((maxPW - minPW)/(maxSig - minSig))*restSig + minPW);
const int syncDutyCycle = syncPW / period;
const int centerCommandDutyCycle = centerPW / period;
const int syncInterval = conversion*syncDutyCycle;
const int centerCommandInterval = conversion*centerCommandDutyCycle;
void setup() {
pinMode(forwardPin, INPUT);
pinMode(backwardPin, INPUT);
pinMode(commandPin, OUTPUT);
}
void loop() {
int F = digitalRead(forwardPin);
int B = digitalRead(backwardPin);
float Turn = analogRead(A0);
int L = 0;
int R = 0;
int command = 0;
// Joystick center serial output is 500 to 501, so +/- 30 to
// include an artificial dead zone to not create sudden turns
if (Turn > restSig + shiftSig) {
L = 0;
R = 1;
}
else if (Turn < restSig - shiftSig) {
L = 1;
R = 0;
}
else {
L = 0;
R = 0;
}
command = 1000*F + 100*B + 10*L + R;
// commandSignal(a, b, c, d)
// If b == 0, no back/forth; if b == 1, forward; if b == -1, backward
// If c == 0, no turn; if c == 1, wheels angle right; if c == -1, wheels angle left
switch (command) {
case 1000:
commandSignal(forwardPC, 1, 0, Turn);
break;
case 0100:
commandSignal(backwardPC, -1, 0, Turn);
break;
case 0010:
commandSignal(leftPC, 0, -1, Turn);
break;
case 0001:
commandSignal(rightPC, 0, 1, Turn);
break;
case 1010:
commandSignal(forwardLeftPC, 1, -1, Turn);
break;
case 0110:
commandSignal(backwardLeftPC, -1, -1, Turn);
break;
case 1001:
commandSignal(forwardRightPC, 1, 1, Turn);
break;
case 0101:
commandSignal(backwardRightPC, -1, 1, Turn);
break;
default:
command = 0;
}
delay(1000); // Temporary
}
void sync() {
int i;
for (i = 0; i <= 3; i++) {
analogWrite(commandPin, syncInterval);
}
}
void commandSignal(int pulseCount, int motorDir, int turnDir, float turn) {
int i;
float anglePWM = 0;
sync();
if (motorDir != 0 && turnDir == 0) {
for (i = 0; i <= pulseCount - 1; i++) {
analogWrite(commandPin, centerCommandInterval);
}
}
else if (turnDir == -1) {
anglePWM = ((w_rest - w_min)/((restSig - shiftSig) - minSig))*turn + w_min;
for (i = 0; i <= pulseCount - 1; i++) {
analogWrite(commandPin, anglePWM);
}
}
else {
anglePWM = ((w_max - w_rest)/(maxSig - (restSig + shiftSig)))*turn + w_rest;
for (i = 0; i <= pulseCount - 1; i++) {
analogWrite(commandPin, anglePWM);
}
}
}