Problem with delay in serial communication

I have been working with communicating between a Raspberry Pi and Arduino through serial. I am using the USB cable to conduct the communication. My RPi and Arduino are talking to each other and getting along swimmingly... well almost.

I am using the following code for a simple task that could be done without a Raspberry Pi (or without the Arduino). I have a ultrasonic sensor and a led hooked up to the Arduino and I am feeding the distance results (in inches) from the ultrasonic sensor to the RPi. The RPi is taking the results of the ultrasonic sensor and depending on the distance telling the Arduino to turn on the led. I am currently using the RPi as a way to start the process.

I have a raw input with the RPi "To start the ultrasonic sensor, please type "Start":". This works but after the two start communicating there is approximately a five second delay from when an object is close enough to light the led and when the led actually turns on. I would like to eventually use this on a robot and need a quicker reaction time.

I know that I do not need both to complete this task but would like to use them both in my final robotics project and this will be a starting point for other projects.

Here is the Arduino Code (sorry for the lack of comments in the code):

int led = 10;
const int pingPin = 2;
long duration, distanceInches, distanceCm;


void setup()
{
  pinMode(led, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delay(2);
  digitalWrite(pingPin, HIGH);
  delay(5);
  digitalWrite(pingPin, LOW);
  
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);
  
  distanceInches = microsecondsToInches(duration);
  distanceCm = microsecondsToCentimeters(duration);
  Serial.print(distanceInches);
  Serial.println();
  
  delay(200);
   
  char ch = Serial.read();
  if (ch == 'a') digitalWrite(led, HIGH);
  else if (ch == 's') digitalWrite(led, LOW);
   
  delay(10);
}

long microsecondsToInches(long microseconds)
{
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
  return microseconds / 29 / 2;
}

Here is the code I am working with on the Raspberry Pi in Python 2.7:

import serial
import time
import sys

chip = '/dev/ttyACM0'
baud = 9600

ser = serial.Serial(chip, baud)
ser.flush()

def run():
     while True:
         x = ser.readline()
         y = int(x)
         if y < 14 :
             ser.write('a')
         else :
             ser.write('s')
         time.sleep(0.010)

def start():
    while True:
        on = raw_input('To start the ultrasonic sensor, please type "Start": ')
        if on == "Start":
            run()
        else :
            print('Invalid command. Please try again')


start()

I appreciate any help.

Thank you,

Robb

try replacing this

  delay(200);
   
  char ch = Serial.read();
  if (ch == 'a') digitalWrite(led, HIGH);
  else if (ch == 's') digitalWrite(led, LOW);
   
  delay(10);

by

if (Serial.available() > 0)
{
  char ch = Serial.read();
  if (ch == 'a') digitalWrite(led, HIGH);
  else if (ch == 's') digitalWrite(led, LOW);
  else errorcount++;
}

optional you could have a blocking wait util data arrives

while (Serial.available() ==0);


Serial.print(distanceInches);
Serial.println();

can be a oneliner

Serial.println(distanceInches);

Thank you for the help but this did not assist with faster communications. It did get me thinking though and I worked on another way to work on the problem. I was able to make some of the modifications you recommended and I think they helped the code overall. This new code works well and provides a window with a couple of buttons.

Here is the code on Arduino (I need to be better about writing comments):

int led = 10;
const int pingPin = 2;
long duration, distanceInches;

void setup()
{
  pinMode(led, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  if (Serial.available())
  {
    char ch = Serial.read();
    while (ch == 'a')
    {
      pinMode(pingPin, OUTPUT);
      digitalWrite(pingPin, LOW);
      delay(2);
      digitalWrite(pingPin, HIGH);
      delay(5);
      digitalWrite(pingPin, LOW);
  
      pinMode(pingPin, INPUT);
      duration = pulseIn(pingPin, HIGH);
  
      distanceInches = microsecondsToInches(duration);
      Serial.println(distanceInches);
      if (distanceInches < 14)
      {
        digitalWrite(led, HIGH);
      }
      else
      {
        digitalWrite(led, LOW);
      }
      delay(200);
      char ch = Serial.read();
      if (ch == 's')
      {
        break;
      }
    }
  }
  delay(10);
}
long microsecondsToInches(long microseconds)
{
  return microseconds / 74 / 2;
}

and here is the code on the Raspberry Pi:

from Tkinter import *
import serial
import time
import sys

uno = '/dev/ttyACM0'
baud = 9600
ser = serial.Serial(uno, baud)

root = Tk()

def ledon() :
    ser.write('a')
    print 'The ultrasonic sensor is on'
    return

def ledoff() :
    ser.write('s')
    print 'The ultrasonic sensor is off'
    return

def key_input (event):
    key_press = event.char

    if key_press.lower() == 'a':
        ledon()
    elif key_press.lower() == 's':
        ledoff()

      
Button(text='Press "a" for on', fg = 'white', bg = 'black', command=ledon).pack() 
root.bind('<KeyPress>', key_input)
Button(text='Press "s" for off', fg = 'white', bg = 'black', command=ledoff).pack() 
root.bind('<KeyPress>', key_input)
root.mainloop()