Serial.available > 0 not working

I'm trying to get communications between a Raspberry Pi and a mega working. They are connected via the USB port. My Pi script sends a series of numbers separated by commas, 1,2,3, the mega sends those numbers back plus the sum of the three numbers. The Pi then increments each number by one and repeats. My sketch has an if statement that checks to see if there is data in the serial buffer with the condition, "Serial.available() > 0". When I use that it returns all 0's. I replace the "Serial.available() > 0" with "true" in the if condition and it works fine with one exception. The first reply should be 1,2,3,6 it's always blank, the next response is correct 2,3,4,9 and all after are also correct

Why does "Serial.available() > 0" not work in my if statement? My sketch is below

// Sending data to the Arduino

int a = 0;
int b = 0;
int c = 0;
int d = 0;

void setup() {
  Serial.begin(9600);
  Serial.read(); // Clear serial buffer
}

void loop() {
  
while (!Serial){} // read from Pi
  
    if(Serial.available() > 0){ // Serial.available() > 0
      a = Serial.parseInt();
      b = Serial.parseInt();
      c = Serial.parseInt();
    }
   
  // Add numbers from Pi then return to Pi 
  d = a + b + c;
  Serial.print(a); Serial.print(",");
  Serial.print(b); Serial.print(",");
  Serial.print(c); Serial.print(",");
  Serial.println(d);
  
  // delay(500);
}

Thanks
John

I see only one conclusion from your description. the PI side doesn't send anything until it receives something

The pi script first prints the values, to the shell, then writes the same values to the serial port. It must be writing because when I change the condition of the if statement in the Arduino sketch it works.

Here is the Pi script

#!/usr/bin/python3

# Send data to Arduino

import serial
import time


#Define serial port and variables
ser = serial.Serial('/dev/ttyACM0', 9600, timeout = 1)
a = 1
b = 2
c = 3


while True:
    # Create string to send
    print() #clear print buffer?
    valList = [str(a),str(b),str(c)]
    sendStr = ','.join(valList)
    
    print(sendStr)

    ser.write(sendStr.encode('utf-8'))
    
    time.sleep(0.1)
    
    # Read returned string
    recStr = ser.readline().decode('utf-8')[:-2]
    print(recStr)

        
    # Increment variables
    a = a + 1
    b = b + 1
    c = c + 1

connection from python resets the Arduino and until it boots it misses the first set of data

Have a look at this Python - Arduino demo

Note how the Python program waits until it receives a message from the Arduino to let it know that the Arduino has completed its reset.

...R

You should only calculate once you have received, so that part should probably inside the if block.

Why do you have * while (!Serial) {} // read from Pi* inside loop()?

Per the book I'm following, and using to learn more about PI's, it says the while(!Serial){} is testing that the serial connection is made. While no connection, wait in while loop until there is, there may be better ways to test but is this not correct? The Serial.available statement confirms there's data in the connection

As far as adding the numbers in the Arduino instead of the Pi, this is just a program to demonstrate PI to Arduino communications by doing the math in the Arduino you've confirmed it received the correct series of numbers.

Waiting until the Arduino is ready and sends back a response makes sense, that would answer why the first set of numbers doesn't get the proper reply but the second does. I'll dig into the example you referenced as to how to confirmed the Arduino is reset and ready.

Thanks for all the feedback, most appreciated
John

On Mega, Uno, Nano the MCU doesn't know about the USB communication state. The USB communication is done by the USB chip on the board. The "while (!Serial);" works only for MCUs with native USB port like the MCUs on Leonardo, Micro, Zero, M0, MKR

Juraj

Interesting fact which I'm sure is correct. The book I got this example from uses an Uno. I used a mega because I have one and have used it on past projects. This isn't the first error I've found. That's why when it didn't work I asked the forum. Thanks for the useful information.

John

Robin2

I can't seem to get your examples to work. I tried the simplified one, ArduinoPC2.ino & ComArduino2.py. I assume I'm not doing something right, maybe you could point me in the right direction. I loaded ArduinoPC2 into a mega 2560, I'm running ComArduino2. in python 3.5.3. I'm sure my connections and port configuration is OK I confirmed them by running the programs I originally posted about and they do communicate.

The LED's on the Arduino are blinking and the servo went to a position when I first loaded the sketch in, it hasn't moved since.

The first problem I had was I got an error message "Syntax Error, Missing parentheses in call to print". None of the print statements had parentheses, so I added them. (Which seems odd to me so I'm wondering if I have the right program or right python revision)

Now when I run the python script first it prints out "Serial port /dev/ttyACM0 opened Baudrate 9600" then it stalls for about 30 seconds and I get the following errors,

Traceback (most recent call last):
File "/home/pi/Forum Comm Pi to Arduino/ComArduino2.py", line 160, in
waitForArduino()
File "/home/pi/Forum Comm Pi to Arduino/ComArduino2.py", line 101, in waitForArduino
msg = recvFromArduino()
File "/home/pi/Forum Comm Pi to Arduino/ComArduino2.py", line 79, in recvFromArduino
ck = ck + x
TypeError: Can't convert 'bytes' object to str implicitly

Appears to be waiting for the Arduino to say it's ready. After it crashes I open the serial monitor in Arduino and it does have

What am I doing wrong?

Thanks
John

My demo was written with Python 2.7. I believe the attached version will work with Python 3.

Just change the filetype to .py

...R

PS.. It's a useful skill to learn how to convert Python 2.7 to Python 3

ComArduino2PY3.txt (4.89 KB)

Awesome! I knew the problem was on my end, I had even mentioned that I might not be using the right revision of python. What I should have done, and didn't think of, was to run it in 2.7 which I do have on my pi. I went back and downloaded a clean copy of the first script and ran that in 2.7 and of course it worked fine. I also ran this version in 3.5 with the same results.

This is terrific, my project will have communications back and forth and I'll incorporate this into my project. I need to review it more so I understand everything you're doing. I don't want to just copy, I want to learn. I'll go back and try your first example as well.

Thanks so much for your help and patience.

John

Robin2

I added the code for to the original script that started this thread. It helped the Serial.available > 0 issue. I still get some bogus readings for the first couple of lines but I think that's more the method they used to send and receive data. Your example works great so I'll use that method in future projects. I do have one last question, for now anyways :).

The shebang, "#!/usr/python3". A couple of other people on this thread were pretty insistent that I should add that. I notice your script does not have it. I made your script executable so I could run it from the command line in terminal, I thought it was needed to run as an executable. I tried it with both the shebang and without it and it worked every time. I did read about the function of the shebang but can you tell me why, or why not, you would have that in the script?

Thanks again
John

The idea of the shebang is so the operating system can figure out the name of the program needed to run the script. I confess that I almost always run my Python programs like this python myProg.py which obviously does not require the shebang.

...R

That makes perfect sense, no need to include what version of python your program is when you told it when you started it.

Thanks so much for all your help
John

Juraj:
The "while (!Serial);" works only for MCUs with native USB port like the MCUs on Leonardo, Micro, Zero, M0, MKR

No, it is only needed on these processors, you put it into code running on any other processor and it will piss right through it. It doesn’t cause a problem if it is not required.

Thanks Grumpy_Mike

Sounds like good coding practice to me. If you need it it's there if you don't it doesn't change anything.

Stumpy_L:
Sounds like good coding practice to me. If you need it it's there if you don't it doesn't change anything.

Exactly, that is why it is in the IDE examples that need it these days. That is the ones that use the serial port.