Using python serial, Raspberry pi, and arduino

Hello,
I have been working on a project that uses the Raspberry Pi and python to send serial data over to the Arduino to control 2 DC motors. My problem is, When Send a serial character over to the Arduino, the motor moves for a millisecond because I have the code state that

if(Serial.read() == 'F')
{
    Forward();
}

However I would like it to be when the Arduino continuously reads the 'F' character, it goes forward. and as of now that is not the case. Any ideas? Is there something easier than just sending a character over serial for the Arduino to read or am I doing something wrong?

You need to give more information.
We can have no idea what the function 'Foward()' is doing. Please post more code.

The Arduino will continously read 'F' if the RPi continously send it. I do not think that is the best design. I would send some command meaning forward or reverse together with the speed. The Arduino will follow that command until another is received. No need for continuous signalling.

Please post more code.

No please post ALL the code.

Sorry for the lack of information!

Here is the Arduino code:

int pinI1=8;//define I1 interface
int pinI2=11;//define I2 interface 
int speedpinA=9;//enable motor A
int pinI3=12;//define I3 interface 
int pinI4=13;//define I4 interface 
int speedpinB=10;//enable motor B
int spead =127;//define the spead of motors
byte input;

void setup()
{
  pinMode(pinI1,OUTPUT);
  pinMode(pinI2,OUTPUT);
  pinMode(speedpinA,OUTPUT);
  pinMode(pinI3,OUTPUT);
  pinMode(pinI4,OUTPUT);
  pinMode(speedpinB,OUTPUT);
  Serial.begin(9600);
}

void forward()
{
  analogWrite(speedpinA,spead);//input a simulation value to set the speed
  analogWrite(speedpinB,spead);
  digitalWrite(pinI4,HIGH);//turn DC Motor B move clockwise
  digitalWrite(pinI3,LOW);
  digitalWrite(pinI2,LOW);//turn DC Motor A move anticlockwise
  digitalWrite(pinI1,HIGH);
}
void backward()//
{
  analogWrite(speedpinA,spead);//input a simulation value to set the speed
  analogWrite(speedpinB,spead);
  digitalWrite(pinI4,LOW);//turn DC Motor B move anticlockwise
  digitalWrite(pinI3,HIGH);
  digitalWrite(pinI2,HIGH);//turn DC Motor A move clockwise
  digitalWrite(pinI1,LOW);
}
void left()//
{
  analogWrite(speedpinA,spead);//input a simulation value to set the speed
  analogWrite(speedpinB,spead);
  digitalWrite(pinI4,HIGH);//turn DC Motor B move clockwise
  digitalWrite(pinI3,LOW);
  digitalWrite(pinI2,HIGH);//turn DC Motor A move clockwise
  digitalWrite(pinI1,LOW);
}
void right()//
{
  analogWrite(speedpinA,spead);//input a simulation value to set the speed
  analogWrite(speedpinB,spead);
  digitalWrite(pinI4,LOW);//turn DC Motor B move anticlockwise
  digitalWrite(pinI3,HIGH);
  digitalWrite(pinI2,LOW);//turn DC Motor A move clockwise
  digitalWrite(pinI1,HIGH);
}
void stop()//
{
  digitalWrite(speedpinA,LOW);// Unenble the pin, to stop the motor. this should be done to avid damaging the motor. 
  digitalWrite(speedpinB,LOW);
  delay(1000);

}

void loop()
{
  input = Serial.read();

  if (input == 'F') 
  {
      forward(); 
  }
  if (input == 'B')
  {
      backward();
  }
  if (input == 'L') 
  {
      left();
  }
  if(input == 'R')
  {
      right();
  }
  else
    stop();
}

and here is the python code which is ran on the raspberry pi which the Arduino is plugged into:

from Tkinter import *
import serial
import time

board = serial.Serial("/dev/ttyACM0", 9600, timeout = 1)
time.sleep(2)

root = Tk()

root.title("Robot Controller")

def forward():
    board.write("F")
    print("Forward")
def backward():
    board.write("B")
    print("Backward")
def left():
    board.write("L")
    print("Left")
def right():
    board.write("R")
    print("Right")
def stop():
    board.write("S")
    print("Stop")

app = Frame(root)
app.grid()
button1 = Button(app, text="Forward", width=20,command=forward)
button1.pack(side='top', padx = 15, pady = 15)

button1 = Button(app, text="Backward", width=20,command=backward)
button1.pack(side='bottom', padx = 15, pady = 15)

button1 = Button(app, text="Left", width=20,command=left)
button1.pack(side='left', padx = 15, pady = 15)

button1 = Button(app, text="Right", width=20,command=right)
button1.pack(side='right', padx = 15, pady = 15)

root.mainloop()

Now to better explain the problem: if I hit the 'forward' button once, in theory 'F' would be send once and the arduino would process that 'F' once but, the arduino is acting like that 'F' is being sent over and over and over again because when i hit forward the motors to not stop, they continue to go. I do not want this. I would like it so where if I hold down say 'F', it will go forward and stop when I release the key. Same goes with all the other directions.

if I hit the 'forward' button once, in theory 'F' would be send once and the arduino would process that 'F'

Yes

the arduino is acting like that 'F' is being sent over and over and over again

No

because when i hit forward the motors to not stop, they continue to go

Yes that is what you have programmed it to do. If the arduino receives no more commands then there is nothing to stop the motors.

I would like it so where if I hold down say 'F', it will go forward and stop when I release the key.

Well program it like that. In your python program you must detect for a key up event and when you receive that send the stop command to your arduino.
So key down event for the F key send the forward command, key up for the F key ( or perhaps any key ) send the stop command.

If you use the events function in the pygame package you can detect both key down and key up events.

Okay thanks for your help. I should have remembered about key up events. Thank you.

UPDATE

I rewrote my code using keyUp and keyDown events in pygame. It seems to be working better now.

Here is the python code:

import serial
import time
import pygame

board = serial.Serial("\\.\COM3", 9600, timeout = 1)
time.sleep(2)

screen = pygame.display.set_mode([300,100])
screen.fill([255,255,255])
pygame.display.set_caption("Windows Controller")

def forward():
    board.write("F")
    print("Forward")
def backward():
    board.write("B")
    print("Backward")
def left():
    board.write("L")
    print("Left")
def right():
    board.write("R")
    print("Right")
def stop():
    board.write("S")
    print("Stop")

while 1:
    key = pygame.key.get_pressed()
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            break
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_w:
                    print"Forward"
                    forward()
            if event.key == pygame.K_a:
                    print"Left"
                    left()
            if event.key == pygame.K_s:
                    print"Backward"
                    backward()
            if event.key == pygame.K_d:
                    print"Right"
                    right()
            if event.key == pygame.K_ESCAPE:
                    break
        elif event.type == pygame.KEYUP:
                    print"Stop"
                    stop()
    pygame.display.update()
pygame.quit

The arduino code stayed the same.

Thanks everyone for their help :slight_smile: