4

I was trying to send and receive data between Raspberry pi and Arduino UNO. I'm able to send and receive a string from Arduino to Pi using Serial.println. I spent hours searching a better tutorial or a solution. Couldn't find any.

The code below will send an answer('Got') to Arduino when it recieves a 'Hi' from Arduino.

Simple Python code I'm using:

import serial
import time
ser = serial.Serial('/dev/ttyACM0',9600)
ser.flushInput()

while True:
s= ser.readline()
s= s.strip()
print (s.decode("utf-8"))
if (s.decode("utf-8") == "Hi"):
    print("sending")
    ans = "Got"
    ans = ans.encode("utf-8")
    ser.write(ans)
time.sleep(0.5)

Arduino code:

void setup() {
    Serial.begin(9600); As        
    Serial.println("Hi");   // send the data
}

void loop() {
    delay(1000);
    if (Serial.available()) {

        //define SerIn here
        SerIn = //code for reading string goes here 

        if (SerIn=='Got') { 
            Serial.println('I got it');
        }else{
            Serial.println('Oopz');
        } 

    } 
}

I tried this:

String SerIn;    
SerIn = Serial.readStringUntil('\n');

This throws an error while compiling.

error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
In file included from /usr/share/arduino/hardware/arduino/cores/arduino/Arduino.h:192:0,
                 from RPI_ARDSerial.ino:2:
/usr/share/arduino/hardware/arduino/cores/arduino/WString.h:130:16: note:   initializing argument 1 of ‘unsigned char String::operator==(const char*) const’
  unsigned char operator == (const char *cstr) const {return equals(cstr);}
smc
  • 315
  • 1
  • 5
  • 17
  • 1
    Instead of `String SerIn;` try `char SerIn[];` If that works I'll make it a proper answer. A string is really a character array, and that is what it is expecting. – evildemonic May 31 '19 at 15:50
  • 1
    I just tried this `char SerIn[]; SerIn = Serial.readStringUntil('\n');` gives an error: `storage size of ‘SerIn’ isn’t known` Is this `Serial.readStringUntil('\n');` part correct? – smc May 31 '19 at 15:52
  • 1
    That looks ok to me. Initialize `SerIn[];` with a big enough buffer. Maybe `char SerIn[16];` – evildemonic May 31 '19 at 15:57
  • 1
    In c and c++ double quotes must be used for string literals. – crasic May 31 '19 at 15:58
  • 1
    @crasic Good catch, the next part of his code will fail otherwise. – evildemonic May 31 '19 at 16:00
  • 1
    `char SerIn[16];` throwing an error: incompatible types in assignment of ‘String’ to ‘char [16]’ as it is `readStringUntil`. and I if use `String` this error comes - `error: incompatible types in assignment of ‘String’ to ‘String [16]’` . – smc May 31 '19 at 16:10
  • Ok, sorry I am confused why this isn't working then. You could try your assignment at initialization...this *should* work: `String SerIn = Serial.readStringUntil('\n');` unless SerIn is already initialized elsewhere. – evildemonic May 31 '19 at 16:53
  • 1
    I should also mention, working with strings on serial inputs sucks, it might be better to do this code one character at a time. – evildemonic May 31 '19 at 16:55
  • ...and as crasic mentioned, change to double quotes on your string literals. – evildemonic May 31 '19 at 17:05
  • The python code will do nothing. You read a line but do nothing with the value read then read another. – Milliways May 31 '19 at 21:59
  • For python serial, I recommend the data type "bytes". For examples, you may like to read the following posts: https://raspberrypi.stackexchange.com/questions/96343/error-while-using-wiringserial https://raspberrypi.stackexchange.com/questions/96184/serial-to-arduino-totally-non-responsive https://raspberrypi.stackexchange.com/questions/96271/data-packet-of-hex-values-sent-over-serial/96292#96292 – tlfong01 Jun 01 '19 at 01:13
  • @Milliways I have edited python code. Now it will send data only if it receives a `hi` from Arduino. – smc Jun 01 '19 at 05:06

2 Answers2

4

Finally I was able to find a solution. I used the example 2 from this post posted in Arduino forum https://forum.arduino.cc/index.php?topic=396450.0. I have edited python code also.

Arduino code

// Example 2 - Receive with an end-marker

const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data

boolean newData = false;

void setup() {
    Serial.begin(9600);

}

void loop() {
  //This code will continuously send '<Arduino is ready>' python.
  Serial.println("<Arduino is ready>");
  delay(10);// must be added.
  recvWithEndMarker();
  showNewData();
}

void recvWithEndMarker() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;

    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            receivedChars[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        Serial.println("This just in ... ");
        Serial.println(receivedChars);
        newData = false;
    }
}

Edited Python code:

import serial
import time
ser = serial.Serial('/dev/ttyACM0',9600)
ser.flushInput()

while True:
    s= ser.readline()
    s= s.strip()
    print (s.decode("utf-8"))
    if (s.decode("utf-8") == "<Arduino is ready>"):
        print("sending")
        ans = 'hello Arduino"\n"'
        ans = ans.encode("utf-8")
        ser.write(ans)
smc
  • 315
  • 1
  • 5
  • 17
2

I appreciate that you've since circumnavigated the problem by implementing your own version of readStringUntil()/readBytesUntil() but, as @crasic and @evildemonic alluded to in the comments, I think the error message you are seeing is down to this part of your code:

if (SerIn=='Got') { 
  Serial.println('I got it');
}else{
  Serial.println('Oopz');
} 

And not about the attempt to use readStringUntil() beforehand. As "Got", "I got it" and "Oopz" are strings you need to use " around them, not '. Using the ' tells the compiler to use the ASCII values for the character hence the error being about you using an integer instead of a const character array and, specifically, "unsigned char String::operator==(const char*) const" is referring to your if() line not comparing two strings.

You've used the correct notation for the string in your Serial.println("Hi"); line in setup() (although I think there's a typo on the previous line, extra As; on the end?).

Roger Jones
  • 1,479
  • 5
  • 14