Matt
Matt

Reputation: 11

Controlling Adruino through Python via pySerial

Hello and thank you in advance for your time,

I'm attempting to control a series of relays connected to my Arduino via a python script using pySerial and Tkinter. The problem is that, although I know my code is connecting to my Arduino (I hear the same flutter of relays that I get when I upload code using the Arduino software), I can't get the relays to respond to commands sent from my Tkinter GUI. Here is my python code:

ser = Serial(port=3, timeout=1, writeTimeout=1, baudrate=9600)  # ensure non-blocking

class Application(Frame):

    print("Arduino Dish Control Ready")

    def __init__(self, parent):  # create constructor
        Frame.__init__(self, parent)  # define parent
        self.parent = parent  # save reference of parent widget
        self.initUI()  # delegate creation of the initUI() method

    def initUI(self):
        self.parent.title("Dish Control")  # title of window

        Style().configure("TButton", padding=(0, 5, 0, 5), font='serif 10')

        self.columnconfigure(0, pad=4)
        self.columnconfigure(1, pad=4)
        self.columnconfigure(2, pad=4)
        self.columnconfigure(3, pad=4)
        self.columnconfigure(4, pad=4)

        self.rowconfigure(0, pad=3)
        self.rowconfigure(1, pad=3)
        self.rowconfigure(2, pad=3)
        self.rowconfigure(3, pad=3)

        def UP():  # define the UP command.
            ser.write(str(32))  # convert "32" to ASCII and send it via serial port (USB) to arduino.
            print ser.write(str(64))
            # sleep(0.1)
        up = Button(self, text="Up", command=UP)  # create button UP and set the command.
        up.grid(row=0, column=1)  # define position of UP button.


        self.pack()

And here is the relevant Arduino code:

void loop(){
  if(Serial.available() > 0){
    Serial.begin(9600);
    int inByte = Serial.read(); //read the incoming data
    Serial.print("I received: ");
    Serial.println(inByte, DEC);

    if(Serial.read() == 32){//If the serial reads 32...
      digitalWrite(8, LOW); //Motor Select Low
      digitalWrite(9, LOW);
      digitalWrite(10, LOW); //Motor 1 Low
      digitalWrite(11, LOW);
      digitalWrite(12, LOW); // Motor 2 Low
      digitalWrite(13, LOW);
      digitalWrite(6, HIGH); //Motor Power High
      digitalWrite(7, HIGH);
    }
  }
}

Sorry for include so much, but I'm uncertain as to where my error is.

EDIT:It has been requested that I include the traceback for the error given when I simply include ser.write(32) instead of ser.write(str(32)) in the python code:

Traceback (most recent call last):
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1536, in __call__
    return self.func(*args)
  File "C:/Users/Radio Astro 4/PycharmProjects/untitled/DishControl.py", line 46, in UP
    ser.write(32)  # convert "1" to ASCII and send it via serial port (USB) to arduino.
  File "C:\Python27\lib\site-packages\serial\serialwin32.py", line 283, in write
    data = to_bytes(data)
  File "C:\Python27\lib\site-packages\serial\serialutil.py", line 75, in to_bytes
    for item in seq:
TypeError: 'int' object is not iterable

Upvotes: 1

Views: 818

Answers (1)

Finwood
Finwood

Reputation: 3981

The Arduino documentation says about the Serial.read() command:

Returns

the first byte of incoming serial data available (or -1 if no data is available) - int

You are sending the string "32" to the micro controller, this actually is two bytes [51, 50] being sent. When checking if(Serial.read() == 32), you check for the byte value 32, but the byte value 32 (ASCII space) is never being sent.

Change your send command to transmit the byte value directly:

ser.write(32)  # without str()

Edit:

Serial.write() takes a (byte-)string as argument, so you'll have to do the following:

ser.write(bytes([32]))  # convert the list `[32]` to a bytestring

Upvotes: 1

Related Questions