0

Here's the Arduino code:

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

  pinMode(7, INPUT_PULLUP);
}

void loop() {
    int val = digitalRead(7);
    if (val == HIGH) {
        Serial.print("1");
    } else {
        Serial.print("0");    
    }
    Serial.println("");  // new line

}

Python code:

import time
import serial

# setup Arduino USB communication
try:
    arduinoSerialData = serial.Serial('com3', 9600)

except: # not connected/damaged
    pass

while True:
    if arduinoSerialData.inWaiting() > 0:
        datastr = arduinoSerialData.readline()
        print datastr
        time.sleep(1)

WHat I want to add is, if Python program exits, or crashes, let the Arduino know somehow. More specifically turn on a LED in pin 8.

  • You didn't provide the information you were asked for. What does your existing serial protocol consist of? How does your "program" operate? We need DETAIL! – Majenko Sep 20 '15 at 17:40
  • And anyway, you just asked the same question, not the question you were told to ask! – Majenko Sep 20 '15 at 17:42
  • 2
  • You were told the exact terms to ask about, and the exact information that was required, neither of which you have given. The question should have been more along the lines of "I have written a program in Python that does XXX. It communicates with the Arduino using a protocol that consists of YYY, ZZZ, etc. How can I implement keepalive in this situation?" – Majenko Sep 20 '15 at 17:44
  • Majenko, I asked you what I needed to ask. You said to ask something I didn't understand what even meant and refused to explain so I'd know it is what I indeed need to ask. Give me a break. – Leo Ervin Sep 20 '15 at 17:44
0

There is no way to know if the connection has closed or not, you can only know if the connection was working at some point in the past.

Your communication protocol as shown is only half duplex (i.e., it's only one way - the Arduino sends to Python but never the other way around) which simplifies things somewhat.

There are a number of strategies you can employ in your case, and any number of them can be combined to create a system as robust (and complex) as you like.

First you would need to make your protocol full duplex. This is, you need your Python program to be able to send information to the Arduino. Since you aren't doing that at the moment the implementation of it can be in any way you like.

One method you can use is called Keepalive. In this system the Python program will periodically send an "I am here" message to the Arduino. The Arduino receives these messages and remembers when the last one was (hint: use the millis() function). If a message hasn't been received for more than a pre-defined timeout period the link is assumed to be dead.

Another method which is good if you are sending data very regularly from the Arduino to the Python program is to use a system of acknowledgements. In this situation every bit of data sent to the Python program is followed by the Python replying with an "I got that" message. If the Arduino doesn't get that response after sending its data within a certain timeout period (can be much shorter than for a keepalive timeout) then the link is assumed to be dead.

Wrapped around both these methods you can add an "I have arrived" and an "I am leaving" message. These are sent by the Python program when it starts and just before it's about to exit so the Arduino knows when the link should be alive and when it shouldn't. If it gets an "I am leaving" message then it knows that it shouldn't care whether it gets any acknowledgement or keepalive messages, so it doesn't need to think about timeouts. Only after it has received an "I have arrived" message should it start caring.

So for instance your protocol, with all these things implemented, might look like this (>> = message from Arduino to Python, << is message from Python to Arduino):

>> 1
>> 1
>> 1
>> 0
>> 0
>> 1
<< A    - I have arrived
>> 1
<< Y    - Yes, I got that
>> 1
<< Y    - Yes, I got that
>> 0
<< Y    - Yes, I got that
<< K    - keepalive - we know the link is alive and working.
>> 0
<< Y    - Yes, I got that
>> 1
<< Y    - Yes, I got that
(Program crashes now.)
>> 1
*no Y received - assume connection is closed*
>> 1
... etc ...

In this instance the 0 and 1 are what you are sending at the moment. A is an "I have Arrived" message, Y is a "Yes I got that" message, K is a "Keepalive" message, and if the program had exited cleanly an L would have been an "I am Leaving" message.

Keeping the messages simple (single characters) means it's really easy for the Arduino to parse those messages and work out what is going on.

There is a certain amount of balancing act to be performed when implementing your system between how often you are sending data and how long you are willing to wait for a valid response or message to flag the connection closed.

Expanding your existing example program to incorporate these messages might look like:

unsigned long lastKA = 0;
unsigned long lastSent = 0;
boolean isConnected = false;

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

  pinMode(7, INPUT_PULLUP);
}

void loop() {

    // Check the timeouts if we are connected
    if (isConnected) {

        // First check to see if the Keepalive timeout has passed
        if (millis() - laskKA > 5000) { // 5 second keepalive timeout)
            isConnected = false;
        }

        // If we have sent data...
        if (lastSent > 0) { 
            // ... check that we got a response in time
            if (millis() - lastSent > 100) { // 100ms Y timeout
                isConnected = false;
            }
        }

    }

    // If we are connected then send some data
    if (isConnected) {

        int val = digitalRead(7);
        if (val == HIGH) {
            Serial.print("1");
        } else {
            Serial.print("0");    
        }
        Serial.println("");  // new line

        // and set the timer for the response
        lastSent = millis();
    }

    // Now process incoming messages.
    if (Serial.available()) {
        int c = Serial.read();

        // If the message is an A then turn on the connection and
        // treat it as a Keepalive as well.
        if (c == 'A') { // Arrived
            isConnected = true;
            lastKA = millis();

        // If it's a Leaving message then turn off the connection.
        } else if (c == 'L') { // Leaving
            isConnected = false;

        // If it's a Keepalive then reset the timer.
        } else if (c == 'K') { // Keepalive
            lastKA = millis();

        // A Y acknowledgement will disable the sent timer.
        } else if (c == 'Y') { // Yes
            lastSent = 0; // Cancel the sent timer
        }
    }
}
| improve this answer | |
  • This is odd, serial.Serial.write('1') in Python doesn't seem to write anything to the buffer, print serial.Serial.readline() doesnt show what it wrote. Otherwise will work. – Leo Ervin Sep 20 '15 at 18:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.