Serial read and write (RX,TX) equal endless loop

Hi

I'm really learning a lot reading the forum and I found many solutions to my problems, however I'm not able to find an answer to my latest problem. I would like to exchange data between raspberry pi and arduino so I have connected raspberry pi with arduino over serial RX/TX (UART) like this Easy Arduino - Raspberry Pi serial over GPIO - Raspberry Pi Forums and this is the code I use.

Arduino code:

#include <stdlib.h>                                                             
byte num = 0;                                                                   
                                                                                
void setup ()                                                                   
{                                                                               
    Serial.begin (9600);                                                        
}                                                                               
                                                                                
void loop ()                                                                    
{                                                                               
    if ( Serial.available() > 0 )                                               
    {                                                                           
        num = Serial.read ();                                                   
                                                                                
        Serial.print( "RX: " );                                                 
        Serial.write(num);                                                      
        Serial.write(" ");                                                      
        Serial.println(num);                                                    
    }                                                                           

    delay(500);                                                                 
}

rPi Python code:

#!/usr/bin/python                                                               
                                                                                
# code from                                                                     
# http://shallowsky.com/blog/2011/Oct/16/                                       
                                                                                
import serial                                                                   
import time                                                                     
import select                                                                   
import sys                                                                      
                                                                                
serialport = serial.Serial("/dev/ttyAMA0", 9600, timeout=0.5)                   
                                                                                
while True:                                                                     
    # Check whether the user has typed anything (timeout of .2 sec):            
    inp, outp, err = select.select([sys.stdin, serialport], [], [], .2)         
                                                                                
    # If the user has typed anything, send it to the Arduino:                   
    if sys.stdin in inp :                                                       
        line = sys.stdin.readline()                                             
        serialport.write(line)                                                  
                                                                                
    # If the Arduino has printed anything, display it:                          
    if serialport in inp :                                                      
        line = serialport.readline().strip()                                    
        print "Arduino:", line

I connect all the wires, open serial monitor, run python script and all seems fine. Python waits for input, arduino is waiting for data on serial, but the moment I enter some character in python, arduino starts an endless loop of displaying its own printed characters.

// edited 10. mar 2013
In this example I entered "a" in python script and arduino returns "RX: a 97" but then it also thinks that string "RX: a 97" was sent to him over serial.
// end of edit

a
Arduino: RX: a 97
Arduino: RX: R 82
Arduino: RX: X 88
Arduino: RX: : 58
Arduino: RX:   32
Arduino: RX: a 97
Arduino: RX:   32
Arduino: RX: 9 57
Arduino: RX: 7 55
....

I know that Serial.print adds bytes to serial buffer, so i tried to clear the buffer at the end of the loop like this

delay(20);                                                                
while (Serial.read() != -1);
delay(500);

With this code it works almost as intended, but sometimes characters are not registered, I guess they get deleted when clearing the buffer. Maybe optimizing delays?

So I was wondering what would be the right/best way to receive data on arduino (only one character for example) and send a response over serial without having an effect on buffer or lost characters? Maybe disabling RX when transmitting over TX and vice-versa?

Thank you

I know that Serial.print adds bytes to serial buffer, so i tried to clear the buffer at the end of the loop like this

It adds bytes to the outgoing serial buffer, not the incoming serial buffer.

Without knowing what you entered, and seeing more of the Pi's output, all I can say is that the delays are useless, as is discarding serial data.

Why are you sending data TO the Arduino?

Hi, I tried your first script on a Mac with the standard USB connection and had different results. No endless loop (good), but on the other hand most characters sent by the Arduino were received by the python script, and only a few by the serial monitor (the two sets were complementary). If only the serial monitor or the python script are open the behavior is normal.

So I would say there was nothing wrong in your first attempt, and you should probably concentrate on configuration settings. Did you follow the other instructions given in the link (changes in inittab and console settings, connecting the ground)? I also wonder what are your results if you run only the serial monitor or the python script.

PaulS:
Without knowing what you entered, and seeing more of the Pi's output, all I can say is that the delays are useless, as is discarding serial data.

In the above example I entered "a" in python script and then it prints "Arduino: RX: a 97" but then arduino also thinks that string "RX: a 97" was sent to him over serial, since that is what he printed to serial. And the loop begins with python telling me "Arduino: RX: R 82", "Arduino: RX: X 88" and so on.

PaulS:
Why are you sending data TO the Arduino?

I need arduino to respond to raspberry pi instructions.

spatula:
Hi, I tried your first script on a Mac with the standard USB connection and had different results. No endless loop (good), but on the other hand most characters sent by the Arduino were received by the python script, and only a few by the serial monitor (the two sets were complementary). If only the serial monitor or the python script are open the behavior is normal.

That seems normal, since Serial.read() removes the read byte from serial, as far as I know. So if you're running two serial monitors on the same computer, than its just a matter of who reads it first and deletes it so the second doesn't have anything to read.

In my case, I don't have arduino connected to raspberry pi with USB. They communicate over wires via GPIO RX/TX (pi) and RX/TX pins (on arduino). I have arduino connected to another computer with USB for uploading scripts and monitoring.

spatula:
So I would say there was nothing wrong in your first attempt, and you should probably concentrate on configuration settings. Did you follow the other instructions given in the link (changes in inittab and console settings, connecting the ground)? I also wonder what are your results if you run only the serial monitor or the python script.

I've changed all the settings and connected the ground as described in linked post. It also doesn't change anything if I close down one serial monitor.

Thanks for the responses, you gave me think that it might not be the code. So I looked at the wiring (disclaimer: I'm better with software than with electrical circuits :slight_smile: ).

I changed the wiring just a little and only the raspberry pi to arduino part. So instead of transistor I used diode, for that small protection.
to:

pi(TX) >-------▶|-----|----[1k ohm]-------[ground]
                      |
                      |-----> ar(RX)

With this circuit it works as it should, no magic loops. So the initial problem solved.

However, I'm not completely sure what actually changed, why wouldn't it work properly with transistor and how should I fix it? If I change resistors or voltage in the circuit with transistor, it works even less, or am I missing something. One question answered two new appear :slight_smile:

Thank you

In the above example I entered "a" in python script and then it prints "Arduino: RX: a 97" but then arduino also thinks that string "RX: a 97" was sent to him over serial, since that is what he printed to serial. And the loop begins with python telling me "Arduino: RX: R 82", "Arduino: RX: X 88" and so on.

What the Arduino sent TO the serial port, and what it reads FROM the serial port are two different things. If the Arduino is seeing what it wrote to the serial port, the fault is on the Pi end.

PaulS:
What the Arduino sent TO the serial port, and what it reads FROM the serial port are two different things. If the Arduino is seeing what it wrote to the serial port, the fault is on the Pi end.

I understand they are two different things and thats what bugs me. From where is Arduino receiving his own response? I don't believe its pi fault. If he would receive it from pi, wouldn't it try to print "Arduino: RX: a 97" or something different and not just the string he sent "RX: a 97". Even if I remove all serialport.write() lines from python or even disconnect wire from pi(TX), this still happens, the moment arduino receives any byte to ar(RX) it starts the loop.

As I mentioned in my previous post, I got it working the way it should by removing transistor from the circuit and just connecting pi(TX) straight to ar(RX) with 1k ohm resistor. So I assume there is something wrong with the circuit I used (https://pbs.twimg.com/media/A7g86KCCQAAgwds.jpg). And now I'm wondering why this happens only when I add transistor to the circuit.

Regards

bossek:
I changed the wiring just a little and only the raspberry pi to arduino part. So instead of transistor I used diode, for that small protection.
to:

pi(TX) >-------?|-----|----[1k ohm]-------[ground]

|
                      |-----> ar(RX)




With this circuit it works as it should, no magic loops. So the initial problem solved. 

However, I'm not completely sure what *actually* changed, why wouldn't it work properly with transistor and how should I fix it? If I change resistors or voltage in the circuit with transistor, it works even less, or am I missing something. One question answered two new appear :)

Thank you

Well it seems you are just cutting any signal from ar(RX) to pi(TX) -- which shouldn't have been there in the first place. I wonder what the 1k ohm to ground actually does. My impression is that your solution just masks the problem that produced the loopback effect.

Honestly, I'm not good at understanding circuits but the more I look at the original the less I understand what it was supposed to do. Take away the transistors and you have a voltage divider that protects the PI on the ar(TX) -> pi(RX) side (good) and also reduces the voltage on the pi(TX) -> ar(RX) side (why this?).

Now assume that the two GND are connected together, but they are just wires that you call GND without them actually being connected to the GND of either the PI or the Arduino, and you have created a loopback.

Then I'm confused by the transistors and the two 3.3V and 5V sources, but I guess they are not adding any useful effect.

bossek:
I have connected raspberry pi with arduino over serial RX/TX (UART) like this http://www.raspberrypi.org/phpBB3/viewtopic.php?f=37&t=22736

Did you also connect the grounds?

If your question is why the 3.3V to 5V level conversion circuit in schematic A7g86KCCQAAgwds.jpg does not work, the answer is that as soon as the output voltage (V across the emitter resistor, call it "Re") approaches 2.7V (3.3V less Vbe approximately 0.6V) the forward bias current of the transistor approaches zero cutting off the 2N2222 transistor thus limiting the output voltage to around 2.7V not 5V.

The 5V to 3.3V circuit does work because the input voltage is 5V and the maximum output voltage across Re is 3.3V. Therefore the Vbe never drops below the 0.6V junction base to emitter junction voltage of the transistor.

I have attached an Oscilloscope image of the 3.3V to 5V conversion circuit. The 3.3V input is the yellow trace and the blue trace is the output. You can see that the output never excees 2.7V.