1
votes

I try to make a my Arduino microcontroller and my Mac talk together, and have created a functional serial connection. My computer is sending data to my Arduino, and my Arduino is sending a '1' when it is ready to receive a new piece of data.

I have created an if-else statement (Python script below), which is either sending a new line of data to the Arduino or waiting for the Arduino to be ready for receiving a new line of data.

The problem is that ser.read() in the first part of the Python script always returns '1', which means that the script is sending the individual data lines faster than the Arduino connected stepper motors can possible react.

In the Arduino script you can see that I am sending the state-status in the first line of the serialEvent() function, which in my world should let the Arduino finish its job, before a new "task" is coming. However, it is for some reason not working. Can anybody help me out here?

Python script

import os
import time
import serial

# Name of csv file with drawing coordinates
csvFile = "scaled_coordinates.csv"

# Create serial connection
ser = serial.Serial(port='/dev/tty.usbserial-A9005bDh', baudrate=9600)

wd = os.getcwd()
myFile = open(wd + "/coordinates/" + csvFile)

state = '1'

while True: # Exits when there is no more lines to read

    if state == '0': # Wait for Arduino to be ready
        state = ser.read()

    elif state == '1': # Send one more line to Arduino
        line = myFile.readline()
        if not line:
            break
        print line
        ser.write(line)
        #time.sleep(1)

        state = '0' # Wait for Arduino before reading next line

myFile.close

Arduino loop function

void loop() {

  serialEvent(); // Call the serial function

  if (coord_complete) {

    // Steps to move from currrent to new point
    target1 = steps(x_current, y_current, x_new, y_new, 1);
    target2 = steps(x_current, y_current, x_new, y_new, 2);

    // Start moving
    stepper1.move(target1);
    stepper2.move(target2);

    // Update current position
    x_current = x_new;
    y_current = y_new;

    // Reset variables
    x_complete = false;
    y_complete = false;
    coord_complete = false;
  }

  // Stay in while loop until steppermotors is done
  while ((stepper1.distanceToGo() != 0) && (stepper2.distanceToGo() != 0)) {
    stepper1.run();
    stepper2.run();
  }
}

Arduino serialEvent function

void serialEvent() {

  Serial.write('1'); // Tell Python that Arduino is ready for one more line

  while (Serial.available() && coord_complete == false) {
    char ch = Serial.read(); // Get new character
    Serial.print(ch);

    // If digit; add it to coord_string
    if (isDigit(ch)) {
      coord_string[index++] = ch;

    // Else if ch is ","; then rename to x_new
    } else if (ch == ',') {
      coord_string[index++] = NULL;                   // Finish coord_string
      x_new = atoi(coord_string);                     // Convert to integer
      x_complete = true;                              // Change x_complete to true
      index = 0;                                      // Reset index
      memset(coord_string, 0, sizeof(coord_string));  // Reset coord_string

    // Else if ch is a new line; then rename as y_new
    } else if (ch == ';') {
      //Serial.write('0');
      coord_string[index++] = NULL;
      y_new = atoi(coord_string);
      y_complete = true;
      index = 0;
      memset(coord_string, 0, sizeof(coord_string));
    }

    // Ends while-loop when true
    coord_complete = x_complete * y_complete;
  }
}

Edit

The current Python code looks like this:

import os
import time
import serial

# Name of csv file with drawing coordinates
csvGraphic = "Scaled_coordinates.csv"

# Create serial connection
ser = serial.Serial(port='/dev/tty.usbserial-A9005bDh', baudrate=9600)

wd = os.getcwd()
myFile = open(wd + "/graphics/" + csvGraphic)

state = '1'

while True: # Exits when there is no more lines to read

  print "state", state

  if state == '0': # Wait for Arduino to be ready
    state = str(ser.read())

  elif state == '1': # Send one more line to Arduino
    line = myFile.readline()
    if not line:
      ser.close()
      break
    print line
    ser.write(line)
    state = '0' # Wait for Arduino before reading next line

ser.close()
myFile.close

The Python output is shown below. The code is executed in one go, without waiting for the Arduino. It seems like the line state = str(ser.read()) reads data which is in some kind of serial buffer. I guess the solution is to clear the buffer. I just don't know how.

state 1
239,275;

state 0
state 1
1100,275;

state 0
state 1
300,400;

state 0
state 1
200,400;

state 0
state 1
200,300;

state 0
state 1
[Finished in 0.1s]
2
Not 100 % suer what you mean. But I suppose i open the connection in the line saying ser = serial.Serial(port='/dev/tty.usbserial-A9005bDh', baudrate=9600).Christoffer

2 Answers

1
votes

Think I found it. Your SerialEvent() is called at the begining of your loop. The first thing it does is write('1') meaning each time loop is executed it tells your python code it's ready for new instructions (Even if no instructions were given!) and filling buffer with lot on '1' which you read one by one

Try this:

void SerialEvent(){
    if((stepper1.distanceToGo() == 0) && (stepper2.distanceToGo() == 0)){
        Serial.write('1');
    }
    //Rest of the function

Also I think at the end of your loop you want

while((stepper1.distanceToGo() != 0) || (stepper2.distanceToGo() != 0))

Instead of while((stepper1.distanceToGo() != 0) && (stepper2.distanceToGo() != 0))

1
votes

Thanks to Mr. E I found a solution. Basically I needed to clear the serial buffer before I read or write (flushInput() and flushOutput() in Python and flush() in Arduino) new data between Python and Arduino. Also, a small delay in the Python and Arduino code was necessary to implement in order to make it work.

Pyhton

import os
import time
import serial

# Name of csv file with drawing coordinates
fileName = "coordinates.csv"

# Create serial connection
ser = serial.Serial(port='/dev/tty.usbserial-A9005bDh', baudrate=9600)

wd = os.getcwd()
myFile = open(wd + "/graphics/" + fileName)

#num_lines = sum(1 for line in myFile)

state = '0'
idx = 0

while True: # Exits when there is no more lines to read

    #print "state", state

    while state == '0': # Wait for Arduino to be ready
        ser.flushInput() # Clear input buffer
        state = str(ser.read())

    if state == '1': # Send one more line to Arduino
        line = myFile.readline()
        if not line:
            break
        print "Coordinate", idx
        print line
        ser.flushOutput() # Clear output buffer
        ser.write(line)

        time.sleep(0.1)

        idx = idx + 1
        state = '0' # Set waiting flag – make Arduino wait for next line

ser.close()
myFile.close

Arduino serialEvent function

void serialEvent() {

  if ((stepper1.distanceToGo() == 0) && (stepper2.distanceToGo() == 0)) {
    Serial.write('1'); // Tell Python that Arduino is ready for one more line
    delay(10);
    Serial.flush(); // clear buffer
  }

  while (Serial.available() && coord_complete == false) {
    char ch = Serial.read(); // Get new character
    Serial.flush();

    // If digit; add it to coord_string
    if (isDigit(ch)) {
      coord_string[index++] = ch;

    // Else if ch is ","; then rename to x_new
    } else if (ch == ',') {
      coord_string[index++] = NULL;                   // Finish coord_string
      x_new = atoi(coord_string);                     // Convert to integer
      x_complete = true;                              // Change x_complete to true
      index = 0;                                      // Reset index
      memset(coord_string, 0, sizeof(coord_string));  // Reset coord_string

    // Else if ch is a new line; then rename as y_new
    } else if (ch == ';') {
      //Serial.write('0');
      coord_string[index++] = NULL;
      y_new = atoi(coord_string);
      y_complete = true;
      index = 0;
      memset(coord_string, 0, sizeof(coord_string));
    }

    // Ends while-loop when true
    coord_complete = x_complete * y_complete;
  }
}