GUIs and serial communication between Pyhton and Arduino, the suggested approach to getting all the values over to Aruino

Hi everyone, this is my first post and it’s about suggestions to communicating with the Arduino using GUI components and other required signals and variables that must be sent to the Arduino to run a program accordingly.

I built a gui component in pyside6/qml on a raspberry pi that is used to control what the Arduino does next through serial communication.

My question to the more experienced developers (or anyone who has an opinion), is how would they go about getting their their variable values over to the Arduino?

Say I have 15-20-30 set up variables that must be set first on initialization and sliders, buttons and the like, values sent during operation, would you use getters and setters on the pyhton side to set all the required variables for operations and let Arduino call for those variables in the loop and set them so they will be their available for use when each function and switch cases need them?

I’m doing things the OOP way and have all the protected member variables in both Python and Arduino, identical (except on Arduino uses “qt_” and Python “cmd_” to identify the differences). In a public function in Arduino, I call “get_CmdFromQtQuick(T &protected variableName, cmd)” ((The GUI) which uses a a switch case to send the variable_name (cmd) request to Python and then read the value returned. This is all wrapped into a non blocking millis timer and done for all 15-30 variables. (Some variables are only required once and is called in whatever class constructor needs them.

So is it something that should be done? Time delaying 15-30 get_CmdFromQtQuick, and calling it every 200-2000 milli seconds?

Like I said, all opinions are welcomed.. Thanks.

I've written a small tutorial on interfacing with Python using a Serial connection. See Two ways communication between Python3 and Arduino

you could use a binary protocol if you find that encoding and decoding ASCII is too slow.

Take a look at the telemetrix framework. It consists of a "fixed" server on the Arduino and is written in C++. There is a Python client API to interact with the server. Both "standard" Python and asyncio clients are available. I have interfaced with Tkinter, kivy, and Flet GUIs without issue.

There are other "flavors" of telemetrix for:

  • ESP-8266
  • ESP-32
  • Arduino Uno R4 boards
  • Raspberry Pi Pico and Pico W
  • Arduino 2040 Nano

Hi there, maybe I wasn’t clear in my question. It’s more philosophical or algorithmic. On the Python side I have already written: a getter (getattr) function, a setter (setattr) function. A function to read serial, a function to format the get request in Qbytes and added both a Hex head and Hex tail. And send it over to Arduino using a thread. I used the basic Arduino serial communication tutorial to set up a get and send also. My question is, when developers create their GUIs, is it a good practice to get all the values required for operation in Arduino (checking for new value up dates every 200-2000 millis, or dis it preferable to call for (or recieve) the values over serial when a function is in need of it? Or Is it okay to have 30 millis timers checking for updates to Python variable changes ever few micro to seconds? Some of the variables required I. Arduino isn’t even touched in the GUI so Arduino has to go out and get them or Python has to set them in Arduino in any case. I only have experience with examples of one or two items being used for tutorials. But now how tens of variables should be used in the real development world. So not the coding as much as the experienced point of view - “Yeah it’s okay and preferable or No don’t do that and here’s why” sort of direction.. Thanks..

My belief is to keep communications to a minimum. That means polling on the Arduino and only reporting changes since the last poll.

Using Telemetrix4Arduino as an example, here is the code that does the analog input polling. Here is the code for the digital input polling.. There are also polling functions for specific hardware device (HC-SR04 distance sensors and DHT temperature sensors) which require relatively long periods between polls.

I hope that this answers what you are asking.

How do you structure your algorithm for the values from your gui components to be used in Arduino. Say your GUI has 10 buttons and sliders and ten backend config/settings values. Do you let Arduino wait until you send them or do you let Arduino just check on all of the values in your gui and import them into its own set of variables to be used on demand? So that your (state machine) isn’t looking for values over serial, but rather they’re using the values in variables that’s already there because another timer function has already set them? These variable values are only as stale as about 2 seconds because a timer function is always using serial to go to your gui (Python) and get updates.? Ho do you prefer Arduino to get the values from your GUI variables? Do you push a button that calls send this value to Arduino, or do you push a button and say, setter, set this value to thisButtonVariable, so Arduino can check the value of thisButtonVarible in 200-2000 milliseconds?

So for some clarity, the latter method dawned on me because at first I was goin to use a Nextion HDMI and it has a get command that Arduino uses to just go out and get any value defined in the Nextion. I decided to go the QtQuick/Qml way in stead and wanted to keep that client/server relationship. But I’m more open to experience over my just my point of view of a way to accomplish something.

That’s what I’m talking about.. “Keep polling to a minimum”. My intent was to keep all my class variables required by Arduino in one place and use basically one main serial communication function. That way I’m not having to go through hundreds of lines of code to find when and where serial communications are being used to set a variable. - For the most part, none of the functions are using serial communication, but rather, just the protected member variables. That way updates, and fixes to variables and serial, is only done in one place and that’s inside their respective class. Thanks, I’ll check out the link you recommended.

When the Python program requests to set a pin mode, the Arduino side adds an entry into an array of pin structures. In the Loop function of the Arduino, the structures are checked, and if a pin is enabled, then the Arduino polls the pin. Then, if the current value has changed since the last poll, a report will be generated and sent back to the Python client.
Analog pins are polled at about once every 19 ms. Digital inputs are polled continuously within the Loop. The HC-SR04 device is polled every 33 ms, and the DHT devices are polled every 2 seconds.

Here is GUI I created for a project. When one of the pins is checked off for digital inputs, a message is sent to the Arduino to set the pin mode and start monitoring that pin. The current state of the pin is indicated in the GUI by a change of color in the box next to the pin number.

1 Like

I think there are no unique answer to your question. It depends on the needs.

You can take a lazy approach and simulate a unified memory between the Arduino and the computer. When one party needs data owned by the other party, you send a request to fetch the data. It's not super fast of course but you get the latest value.

You can take the "cached" approach. Every x ms you update the cache with all the values that have changed since last update. When one party needs some remote data, you read from the cache and assume it's fresh enough to go. With the right architecture (like an ESP32 with 2 cores and shared memory) this can be all happening in the background with a bit of syncing (mutex).

Both models work but have their built in limits : performance versus most up to date information.

I guess you need to look at your requirements to decide what's the best option for your project

1 Like