# Python & Arduino communication with serial port

**URL:** <https://forum.arduino.cc/t/python-arduino-communication-with-serial-port/1326415>\
**Category:** Programming\
**Created:** [November 27, 2024, 1:13pm UTC](https://forum.arduino.cc/t/python-arduino-communication-with-serial-port/1326415 "2024-11-27T13:13:44Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![shukolza](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/shukolza/32/1123926_2.png) [@shukolza](https://forum.arduino.cc/u/shukolza)\
**Post date:** [November 27, 2024, 1:13pm UTC](https://forum.arduino.cc/t/python-arduino-communication-with-serial-port/1326415/1 "2024-11-27T13:13:44Z")

</div>

I have a small project to show how to communicate between Arduino and python project. The idea is to create python ap to control the traffic light. Arduino (UNO) part is just a small traffic light with only 3 LEDs (red - 2, yellow-3,green-4). Also the Python part is a simple tkinter app with 2 buttons: set 10 sec delay, and set 5 sec delay. They are communicating with serial port. All codes (py and arduino parts) will be below. An issue is when i press 'set 5 sec' button, in the next loop iteration, delay becomes 5 sec. But when i press 'set 10 sec' button, nothing happens. I am noob at arduino and c++, but know python very well. Also english is not my native language, so dont scold me for some mistakes.

python:

```arduino
import serial
from time import sleep
import tkinter
from tkinter import ttk

# Укажите порт, к которому подключена Ваша плата Arduino.
ARDUINO_PORT = 'COM4'
BAUDRATE = 9600

def on():
    command = '10'
    arduino.write(command.encode())
    sleep(0.1) # Добавляем небольшую задержку для обработки

def off():
    command = '5'
    arduino.write(command.encode())
    sleep(0.1) # Добавляем небольшую задержку для обработки

main_window = tkinter.Tk()
main_window.title('Управление arduino')
main_window.geometry('800x600')

button1 = ttk.Button(text='Задержка 10 сек.', command=on)
button0 = ttk.Button(text='Задержка 5 сек.', command=off)
buttons = [button1, button0]

for button in buttons:
    button.pack()

status_label = ttk.Label()
status_label.pack()

try:
    arduino = serial.Serial(ARDUINO_PORT, BAUDRATE, timeout=1)
    sleep(2)
    status_label.config(text='Подключено к Arduino')
except serial.SerialException:
    status_label.config(text='Не удается подключиться')

main_window.mainloop()

```

arduino:

```arduino
int main_delay = 10000;
int sign_delay = main_delay - 3000;
int yellow_delay = 3000;
int green_morg_delay = 1000;

void setup() {
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    Serial.begin(9600);
}

void loop() {
    if (Serial.available() > 0) {
        char command = Serial.read();
        if (command == '10') {
            main_delay = 10000;
        } else if (command == '5') {
            main_delay = 5000;
        }
    }

    digitalWrite(2, HIGH);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    delay(main_delay);
    
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, LOW);
    delay(yellow_delay);
    
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
    delay(main_delay);
    
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    delay(green_morg_delay);
    
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
    delay(green_morg_delay);
    
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    delay(green_morg_delay);
    
    digitalWrite(2, LOW);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    delay(yellow_delay);
}

```

I already tried to talk with chat-gpt but it cant help me. Also all hardware is working correctly.

---

<div class="post-metadata">

**Author:** ![DaveX](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/davex/32/751443_2.png) [@DaveX](https://forum.arduino.cc/u/DaveX)\
**Post date:** [November 27, 2024, 1:27pm UTC](https://forum.arduino.cc/t/python-arduino-communication-with-serial-port/1326415/2 "2024-11-27T13:27:31Z")

</div>

Multiple character commands are more difficult to use because of the timing of serial data transfer. If you change your “10” command into a single character (‘a’ perhaps?) it should work.

If you really need multiple character parsing look for the “serial input basics” tutorial.

> [@Best first 5 topics to read to reach Trust Level 1?](https://forum.arduino.cc/t/best-first-5-topics-to-read-to-reach-trust-level-1/1287592/1):
>
> - [Serial Input Basics - updated](https://forum.arduino.cc/t/serial-input-basics-updated/382007) by @Robin2 -- How to read serial input without blocking other code from running. ([HT](https://forum.arduino.cc/t/best-first-5-topics-to-read-to-reach-trust-level-1/1287592/2) @DeltaG)
> - Other Serial processing:
> - [pcRead](https://forum.arduino.cc/t/servo-tool-needed-for-setup/1313733/8) by @gcjr -- one-character parsing diagnostic/control tool (w/ [Simulation](https://wokwi.com/projects/412448490504844289)).
> - [Two ways communication between Python3 and Arduino](https://forum.arduino.cc/t/two-ways-communication-between-python3-and-arduino/1219738)
> - ([off-site: @nickgammon on serial](https://gammon.com.au/serial))
> - [Wokwi simulations of Serial processing](https://forum.arduino.cc/t/wokwi-simulations-for-arduino-built-in-examples/1304754#p-7875211-non-arduino-serial-communication-simulations-7)

---

<div class="post-metadata">

**Author:** ![blh64](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/blh64/32/605986_2.png) [@blh64](https://forum.arduino.cc/u/blh64)\
**Post date:** [November 28, 2024, 1:16am UTC](https://forum.arduino.cc/t/python-arduino-communication-with-serial-port/1326415/3 "2024-11-28T01:16:28Z")

</div>

First off, thank you for posting your code inside code tags! +1.

> [@shukolza](#):
>
> ```arduino
> if (command == '10') {
> 
> ```

Using single quotes in C/C++ specifies a single char and you are using 2 in that expression. If you change your preferences inside the IDE and increase your warning level, the compiler would have told you about that.

As @DaveX pointed out, it is much easier to just have each command be a single character.

---

<div class="post-metadata">

**Author:** ![shukolza](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/shukolza/32/1123926_2.png) [@shukolza](https://forum.arduino.cc/u/shukolza)\
**Post date:** [November 28, 2024, 12:13pm UTC](https://forum.arduino.cc/t/python-arduino-communication-with-serial-port/1326415/4 "2024-11-28T12:13:17Z")

</div>

Thank you! I can't make all commands be only 1 character, because in future, I want to let user choose any delay they want, just with entry. I made buttons just to test how it works.

---

<div class="post-metadata">

**Author:** ![shukolza](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/shukolza/32/1123926_2.png) [@shukolza](https://forum.arduino.cc/u/shukolza)\
**Post date:** [November 28, 2024, 12:13pm UTC](https://forum.arduino.cc/t/python-arduino-communication-with-serial-port/1326415/5 "2024-11-28T12:13:59Z")

</div>

Thank you!

---

<div class="post-metadata">

**Author:** ![DaveX](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/davex/32/751443_2.png) [@DaveX](https://forum.arduino.cc/u/DaveX)\
**Post date:** [November 28, 2024, 12:18pm UTC](https://forum.arduino.cc/t/python-arduino-communication-with-serial-port/1326415/6 "2024-11-28T12:18:49Z")

</div>

You can send and parse numbers a character at a time, like "12345d" for a **d** elay of 12345.

Look at the pcRead example:

> [@Best first 5 topics to read to reach Trust Level 1?](https://forum.arduino.cc/t/best-first-5-topics-to-read-to-reach-trust-level-1/1287592/1):
>
> - [pcRead](https://forum.arduino.cc/t/servo-tool-needed-for-setup/1313733/8) by @gcjr -- one-character parsing diagnostic/control tool (w/ [Simulation](https://wokwi.com/projects/412448490504844289)).

and some of the linked Wokwi simulations:

> [@Wokwi Simulations for Arduino Built-In Examples](https://forum.arduino.cc/t/wokwi-simulations-for-arduino-built-in-examples/1304754/1):
>
> ### Misc
> 
> - Serial parsing RPN/Postfix:
> - [pcRead](https://forum.arduino.cc/t/servo-tool-needed-for-setup/1313733/8) by @gcjr -- one-character parsing diagnostic/control tool (w/ [Simulation](https://wokwi.com/projects/412448490504844289)).
> - Good [Forum thread on parsing a line into tokens with strtok()](https://forum.arduino.cc/t/commands-over-serial/1320091)
> - My adaptations of @nickgammon's state-machine parser into a switch-case single-letter post-fix parser for commands and numbers. E.g. `4500R 80S 3G` or '123 24 /p`:
> - V1: [Simple RPN number and command parsing](https://wokwi.com/projects/409963746798376961) and
> - V2: [RPN 4 function calculator+commands](https://wokwi.com/projects/411769421805937665)
> - V3: [Serial control of Stepper speed, acceleration and motion control with RPN calc](https://wokwi.com/projects/411834422059067393) -- Use Serial to control a stepper with real-time adjustment of Acceleration, Maximum speed and Position, with 4-function calculator.
> 
> - G-code parsers, commonly used in CNCs, 3Dprinters, laser cutters
> - [Marginally Clever G-code parser](https://wokwi.com/projects/390478474763185153) -- Accumulates a line of serial into a buffer then processes it. Written such that the parsing characters could be made non-blocking with a substitution of an 'while' with an 'if' in the `loop(){}`
> - [grbl](https://github.com/grbl/grbl/blob/master/grbl/protocol.c#L109) -- buffer characters and parse on end-of-line
> - [Teacup 3DP firmware](https://github.com/Traumflug/Teacup_Firmware/blob/208aba6232e76dbe522b8d937410c6e22ca3dbfa/gcode_parse.c#L123-L442) -- parse a character at a time
> - [Marlin](https://github.com/MarlinFirmware/Marlin/blob/70ef7978b418691904b1fe70f6c1009295eb5f7f/Marlin/src/gcode/parser.cpp#L113-L371) -- parse a buffered line.

This does a lot with single character-at-a-time processing:

> **[StepperWithSerialParsingRPNExample - Wokwi ESP32, STM32, Arduino Simulator](https://wokwi.com/projects/411834422059067393)**
>
> Run IoT and embedded projects in your browser: ESP32, STM32, Arduino, Pi Pico, and more. No installation required!

---

<div class="post-metadata">

**Author:** ![shukolza](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/shukolza/32/1123926_2.png) [@shukolza](https://forum.arduino.cc/u/shukolza)\
**Post date:** [November 29, 2024, 11:39am UTC](https://forum.arduino.cc/t/python-arduino-communication-with-serial-port/1326415/7 "2024-11-29T11:39:37Z")

</div>

Why can't I just do something like that:

```arduino
int main_delay = 10000;
int sign_delay = main_delay - 3000;
int yellow_delay = 3000;
int green_morg_delay = 1000;

void setup() {
    pinMode(2, OUTPUT);
    pinMode(3, OUTPUT);
    pinMode(4, OUTPUT);
    Serial.begin(9600);
}

void loop() {
    if (Serial.available() > 0) {
        int command = Serial.read();
        main_delay = command;
    }

    digitalWrite(2, HIGH);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    delay(main_delay);
    
    digitalWrite(2, HIGH);
    digitalWrite(3, HIGH);
    digitalWrite(4, LOW);
    delay(yellow_delay);
    
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
    delay(main_delay);
    
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    delay(green_morg_delay);
    
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, HIGH);
    delay(green_morg_delay);
    
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);
    digitalWrite(4, LOW);
    delay(green_morg_delay);
    
    digitalWrite(2, LOW);
    digitalWrite(3, HIGH);
    digitalWrite(4, HIGH);
    delay(yellow_delay);
}

```

No, characters, no problems!  
python:

```arduino
import serial
from time import sleep
import tkinter
from tkinter import ttk

# Укажите порт, к которому подключена Ваша плата Arduino.
ARDUINO_PORT = 'COM4'
BAUDRATE = 9600

def test_delay():
    command = str(int(delay_entry.get())*1000)
    arduino.write(command.encode())

main_window = tkinter.Tk()
main_window.title('Управление arduino')
main_window.geometry('800x600')

delay_entry = ttk.Entry()
button_test = ttk.Button(text='Задать задержку', command=test_delay)
delay_entry.pack()
button_test.pack()

status_label = ttk.Label()
status_label.pack()

try:
    arduino = serial.Serial(ARDUINO_PORT, BAUDRATE, timeout=1)
    sleep(2)
    status_label.config(text='Подключено к Arduino')
except serial.SerialException:
    status_label.config(text='Не удается подключиться')

main_window.mainloop()

```

But in this case, nothing happens at all. WHY

---

<div class="post-metadata">

**Author:** ![gcjr](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/gcjr/32/314015_2.png) [@gcjr](https://forum.arduino.cc/u/gcjr)\
**Post date:** [November 29, 2024, 11:49am UTC](https://forum.arduino.cc/t/python-arduino-communication-with-serial-port/1326415/8 "2024-11-29T11:49:45Z")

</div>

look this over

```arduino
const byte PinLeds [] = { 13, 12, 11, 10 };
const int Nled = sizeof(PinLeds);

enum { Off = HIGH, On = LOW };

// -----------------------------------------------------------------------------
void loop ()
{
    if (Serial.available ()) {
        char buf [90];
        int n = Serial.readBytesUntil ('\n', buf, sizeof(buf)-1);
        buf [n] = '\0'; // terminate string with nul

        char cmd [10];
        int val1;
        int val2;

        sscanf (buf, "%s %d %d", cmd, &val1, &val2);

        Serial.println (cmd);
        if (! strcmp (cmd, "ledOn"))
            digitalWrite (PinLeds [val1], On);
        else if (! strcmp (cmd, "ledOff"))
            digitalWrite (PinLeds [val1], Off);
    }
}

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

    for (int n = 0; n < Nled; n++)
        pinMode (PinLeds [n], OUTPUT);
}

```

---

<div class="post-metadata">

**Author:** ![DaveX](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/davex/32/751443_2.png) [@DaveX](https://forum.arduino.cc/u/DaveX)\
**Post date:** [November 29, 2024, 12:24pm UTC](https://forum.arduino.cc/t/python-arduino-communication-with-serial-port/1326415/9 "2024-11-29T12:24:50Z")

</div>

> [@shukolza](#):
>
> But in this case, nothing happens at all. WHY

Because this [Serial.read()](https://docs.arduino.cc/language-reference/en/functions/communication/serial/read/) reads one character at a time.

> [@shukolza](#):
>
> ```arduino
> int command = Serial.read();
> main_delay = command;
> }
> 
> digitalWrite(2, HIGH);
> digitalWrite(3, LOW);
> digitalWrite(4, LOW);
> delay(main_delay);
> 
> ```

main\_delay will be in the 0-255 range unless there was no character to read(), in which case (obviated by the availiable()\>0) the returned -1 would cause a 2^32-1ms delay.

Did you read @Robin2's discussion of how the arduino is so much faster than 9600 baud?

Also, this bit makes the number into a string of characters:

> [@shukolza](#):
>
> ```arduino
> command = str(int(delay_entry.get())*1000)
> arduino.write(command.encode())
> 
> ```

---

<div class="post-metadata">

**Author:** ![system](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/system/32/1140315_2.png) [@system](https://forum.arduino.cc/u/system)\
**Post date:** [May 28, 2025, 12:25pm UTC](https://forum.arduino.cc/t/python-arduino-communication-with-serial-port/1326415/10 "2025-05-28T12:25:47Z")

</div>

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.
