Remote Controlled Car

So I am trying to get my car remotely controlled from one raspberry pi that send signals (wireless) to another that is onboard the car. The second raspberry pi then transmits those signals (wired) to the Arduino. This works. What doesn't work is the next step. This next step is for the Arduino to interpret these commands and then act on them.
This is my code below:

int enA = 9;
int in1 = 8;
int in2 = 7;
char inChar;
String input;
String Input;
int potenVal;
int pwm = 0;
void setup() {
  pinMode (enA, OUTPUT);
  pinMode (in1, OUTPUT);
  pinMode (in2, OUTPUT);
  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
  Serial.begin (9600);
}
void loop() {
  if (Serial.available()) {
    inChar = Serial.read();
    if (isDigit(inChar)) {
      Input +=  inChar;
    }
    if (inChar == '\n') {
      int potenVal = Input.toInt();
      unsigned n = potenVal;
      testStage();
    }
  }
}
void testStage() {
  //find  what was sent
  unsigned n = potenVal;
  unsigned a = (n / 10000U) % 10;
  if (a = 0) {
    specialStage();
  }
  if (a = 1) {
    normalStage();
  }
  if (a = 2) {
    backwardsStage();
  }
}
void specialStage() {
  unsigned n = potenVal;
  unsigned s = (n / 1000U) % 10;
  if (s = 0) {   
    pwm = 255;
    analogWrite (enA, pwm);
    digitalWrite (in1, HIGH);
    digitalWrite (in2, LOW);
    //uncomment when two motors
    /*analogWrite (enB, pwm);
    digitalWrite (in3, LOW);
    digitalWrite (in4, HIGH);
    delay (1000);*/
  }
  if (s = 1) {  
    pwm = 255;
    analogWrite (enA, pwm);
    digitalWrite (in1, HIGH);
    digitalWrite (in2, LOW);
    //uncomment when two motors
    /*analogWrite (enB, pwm);
    digitalWrite (in3, LOW);
    digitalWrite (in4, HIGH);
    delay (1000);*/
  }
}
void normalStage() {
  unsigned n = potenVal;
  unsigned n1 = (n / 100U) % 10;
  unsigned n2 = (n / 10U) % 10;
  unsigned n3 = (n / 1U) % 10;
  char no1 = n1;
  input += no1;
  char no2 = n2;
  input += no2;
  char no3 = n3;
  input += no3;
  pwm = input.toInt();
  analogWrite (enA, pwm);
  digitalWrite (in1, HIGH);
  digitalWrite (in2, LOW);
}
void backwardsStage() {
    unsigned n = potenVal;
  unsigned n1 = (n / 100U) % 10;
  unsigned n2 = (n / 10U) % 10;
  unsigned n3 = (n / 1U) % 10;
  char no1 = n1;
  input += no1;
  char no2 = n2;
  input += no2;
  char no3 = n3;
  input += no3;
  pwm = input.toInt();
  analogWrite (enA, pwm);
  digitalWrite (in1, LOW);
  digitalWrite (in2, HIGH);
  Serial.println (pwm);
}

What I believe the problem is is that the variable pwm's modifications are not saved when i move to the next function, however i could be wrong. The String that I am sending is '20123'. I am receiving '0'

I am using a raspberry pi 3b to send the signals, raspberry pi 4b to receive and a freenove Arduino board. The link is provided below:
https://www.ebay.com.au/itm/125062243815?chn=ps&norover=1&mkevt=1&mkrid=705-159824-816807-4&mkcid=2&itemid=125062243815&targetid=4585444530151280&device=c&mktype=&googleloc=&poi=&campaignid=412352395&mkgroupid=1309518645581565&rlsatarget=pla-4585444530151280&abcId=9300543&merchantid=136820&msclkid=256d33f0dabb1919a662520bed777fca
the motor is the one included in the kit, controlled by the L293D included. The Freenove board is powered by the raspberry pi 4. To deliver a high enough voltage to the motor and chip i have connected the breadboard power module (powered by a 9 volt battery)to the breadboard and all 5 volt and ground wires are connected to that.
Thanks in advance,
LemonHyena

I'd add a couple Serial.print()s of Input, potentVal to make sure you are receiving what you think you're receiving. If you did send '20123', then you should be able to print it and the 2 your code should be translating it into.

/////////

Oh-- the int and unsigned here make these local variables so you aren't writing into the globals. Take them out inside the functions if you want to refer to the global vars.

Okay, i think I found the problem. So after following your advice i found that the conversion of int n1 to char no1 kind of broke it. I don't know how or why but it did. Fortunately, when I remove it the code works mostly. The bit that doesn't work is the

It isn't returnng input as an int but instead 0. Any Ideas? Here's my updated code:

int enA = 9;
int in1 = 8;
int in2 = 7;
char inChar;
String input;
String Input;
int potenVal;
unsigned n;
int pwm;
void setup() {
  pinMode (enA, OUTPUT);
  pinMode (in1, OUTPUT);
  pinMode (in2, OUTPUT);
  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
  Serial.begin (9600);
}
void loop() {
  if (Serial.available()) {
    inChar = Serial.read();
    if (isDigit(inChar)) {
      Input +=  inChar;
    }
    if (inChar == '\n') {
      potenVal = Input.toInt();
      n = potenVal;
      testStage();
    }
  }
}
void testStage() {
  //find  what was sent
  n = potenVal;
  unsigned a = (n / 10000U) % 10;
  if (a = 0) {
    specialStage();
  }
  if (a = 1) {
    normalStage();
  }
  if (a = 2) {
    backwardsStage();
  }
}
void specialStage() {
  unsigned n = potenVal;
  unsigned s = (n / 1000U) % 10;
  if (s = 0) {   
    pwm = 255;
    analogWrite (enA, pwm);
    digitalWrite (in1, HIGH);
    digitalWrite (in2, LOW);
    //uncomment when two motors
    /*analogWrite (enB, pwm);
    digitalWrite (in3, LOW);
    digitalWrite (in4, HIGH);
    delay (1000);*/
  }
  if (s = 1) {  
    pwm = 255;
    analogWrite (enA, pwm);
    digitalWrite (in1, HIGH);
    digitalWrite (in2, LOW);
    //uncomment when two motors
    /*analogWrite (enB, pwm);
    digitalWrite (in3, LOW);
    digitalWrite (in4, HIGH);
    delay (1000);*/
  }
}
void normalStage() {
  unsigned n = potenVal;
  unsigned n1 = (n / 100U) % 10;
  unsigned n2 = (n / 10U) % 10;
  unsigned n3 = (n / 1U) % 10;
  char no1 = n1;
  input += no1;
  char no2 = n2;
  input += no2;
  char no3 = n3;
  input += no3;
  pwm = input.toInt();
  analogWrite (enA, pwm);
  digitalWrite (in1, HIGH);
  digitalWrite (in2, LOW);
}
void backwardsStage() {
  unsigned n1 = (n / 100U) % 10;
  unsigned n2 = (n / 10U) % 10;
  unsigned n3 = (n / 1U) % 10;
  input += n1;
  input += n2;
  input += n3;
  Serial.println (input);
  pwm = input.toInt;
  Serial.println (input);
  Serial.println (pwm);
  analogWrite (enA, pwm);
  digitalWrite (in1, LOW);
  digitalWrite (in2, HIGH);
  Serial.println (pwm);
}

Thanks, LemonHyena.

It sounds like you are expecting the number (char)0 == '0' but (int8_t)'0' == 48 because ASCII.

If I understand correctly, the intention here is to take the last three decimal digits of an unsigned integer like 54321 and turn it into the number 321?

Instead of the String munging , why not do it with arithmetic: pwm = n % 1000 ?

So I have made to suggested edits and the code works the first 5-10 times (I can get a more precise number if required) but after that the serial works and the motor fails to turn. After a reset of the board, however, the motor starts spinning again. Help would be greatly appreciated. This is the new code:

int enA = 9;
int in1 = 8;
int in2 = 7;
char inChar;
String input;
String Input;
int potenVal;
unsigned n;
int pwm;
void setup() {
  pinMode (enA, OUTPUT);
  pinMode (in1, OUTPUT);
  pinMode (in2, OUTPUT);
  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
  Serial.begin (9600);
}
void loop() {
  if (Serial.available() > 0) {
    inChar = Serial.read();
    if (isDigit(inChar)) {
      Input +=  inChar;
    }
    if (inChar == '\n') {
      potenVal = Input.toInt();
      n = potenVal;
      testStage();
    }
  }
}
void testStage() {
  //find  what was sent
  n = potenVal;
  unsigned a = (n / 10000U) % 10;
  if (a = 0) {
    specialStage();
  }
  if (a = 1) {
    normalStage();
  }
  if (a = 2) {
    backwardsStage();
  }
}
void specialStage() {
  unsigned n = potenVal;
  unsigned s = (n / 1000U) % 10;
  if (s = 0) {   
    pwm = 255;
    analogWrite (enA, pwm);
    digitalWrite (in1, HIGH);
    digitalWrite (in2, LOW);
        Input = "";
    //uncomment when two motors
    /*analogWrite (enB, pwm);
    digitalWrite (in3, LOW);
    digitalWrite (in4, HIGH);
    delay (1000);*/
  }
  if (s = 1) {  
    pwm = 255;
    analogWrite (enA, pwm);
    digitalWrite (in1, HIGH);
    digitalWrite (in2, LOW);
        Input = "";
    //uncomment when two motors
    /*analogWrite (enB, pwm);
    digitalWrite (in3, LOW);
    digitalWrite (in4, HIGH);
    delay (1000);*/
  }
}
void normalStage() {
  unsigned n = potenVal;
  unsigned n1 = (n / 100U) % 10;
  unsigned n2 = (n / 10U) % 10;
  unsigned n3 = (n / 1U) % 10;
  char no1 = n1;
  input += no1;
  char no2 = n2;
  input += no2;
  char no3 = n3;
  input += no3;
  pwm = input.toInt();
  analogWrite (enA, pwm);
  digitalWrite (in1, HIGH);
  digitalWrite (in2, LOW);
      Input = "";
}
void backwardsStage() {
  pwm = n % 1000;
  analogWrite (enA, pwm);
  digitalWrite (in1, LOW);
  digitalWrite (in2, HIGH);
  Serial.println (pwm);
  delay (1000);
  Serial.println (pwm);
  digitalWrite (in1, LOW);
  digitalWrite (in2, LOW);
      Input = "";
}

Thanks, LemonHyena.

I'd use arithmetic in normalStage() as well.

These are problems in testStage() -- rather than assignment operators =
they should be equality operators == like this:

  if (a == 0) {
    specialStage();
  }

I'm always suspicious of String operations for strange operation, so I'd try to do the parsing with arithmetic as well per Gammon Forum : Electronics : Microprocessors : How to process incoming serial data without blocking

void loop() {
  if (Serial.available() > 0) {
    inChar = Serial.read();
    if (isDigit(inChar)) {
      potenVal *= 10;
      potenVal += inChar - '0'; // convert char to numeric
    }
    if (inChar == '\n') {
      n = potenVal;
      testStage();  // process the last number
      potenVal = 0; // clear number 
    }
  }
}

However I didn't trace out how the other functions that use potenVal, and they might need to use the global n instead.

Your alternative way seems a lot more complicated. Why do you think it is better?

Oops

(Many)

because of:

and

and

In some ways it is less complicated to change each character into a number and then accumulate them arithmetically into the target value as they come in versus accumulating them in character space with String concatenations (See ArduinoCore-API/api/String.cpp at 438172bdf14c3916c27dca6a32df9549b9cbf5a7 · arduino/ArduinoCore-API · GitHub for the code behind each the "+" in Input += inChar;

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.