Python Forum
Function to Continuasly monitor serial port and control other functions - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Function to Continuasly monitor serial port and control other functions (/thread-8687.html)

Pages: 1 2


Function to Continuasly monitor serial port and control other functions - ricardons - Mar-03-2018

Hi

I need to built a pythonfile.py that starts to do a task (monitor at all time a serial port)
And when a certain condition is true(receive a certain byte in serial) start/stop certain functions that I already have.

But is important that the task of reading the serial port is always running and never stops.

So imagine that I have

Readserial() 
  While true:
    Read the serial port (I know how to do this) 

    If readbyte = 0x65: #(for example) 
       Kill or start function1() #(but at the same time Readserial() should continue monitoring serial port) 

    If read byte = 0xFF: #example
       Kill or start function2() #(again readSerial() should continue to run) 

Function1() 
  Do something

Function2()
  Do something 
What is my best solution for this
Threading?
callback?
Watchdog?

If someone give a possible structure I would appreciate since I'm an not an expert at programming
thanks


RE: Function to Continuasly monitor serial port and control other functions - Larz60+ - Mar-03-2018

what is the device that you are using, raspberry pi, arduino?
I'm thinking there must be a way to trigger an interrupt (event in python)
when there is a charater in the UART buffer.
Tell me device you are using, and type of serial (i2c, usart, spi, etc.)
Once I know this, I can look at your available options.


RE: Function to Continuasly monitor serial port and control other functions - marsokod - Mar-03-2018

You may want to use a thread or a process depending on what your function1 and function2 are doing.

You can either start them manually, use a library like APScheduler to have a pool of threads/process and add your function to the job queue, or start thread/processes at the beginning of your code and have them read elements in a queue.

In the last case, your ReadSerial function would only have to put an element in a queue, which should minimize any interruption to the monitoring.


RE: Function to Continuasly monitor serial port and control other functions - ricardons - Mar-03-2018

(Mar-03-2018, 09:08 PM)Larz60+ Wrote: what is the device that you are using, raspberry pi, arduino? I'm thinking there must be a way to trigger an interrupt (event in python) when there is a charater in the UART buffer. Tell me device you are using, and type of serial (i2c, usart, spi, etc.) Once I know this, I can look at your available options.
Hi
I'm reading from uart (tx rx) of raspberry pi gpio.
Is there a trigger?
In the serial uart I'm reading the bytes sent from a NEXTION touch display (if this is important)

(Mar-03-2018, 09:33 PM)marsokod Wrote: You may want to use a thread or a process depending on what your function1 and function2 are doing. You can either start them manually, use a library like APScheduler to have a pool of threads/process and add your function to the job queue, or start thread/processes at the beginning of your code and have them read elements in a queue. In the last case, your ReadSerial function would only have to put an element in a queue, which should minimize any interruption to the monitoring.

Function1() acquires sensor data and show it on lcd
Function2() is the same as 1 but also writes the data to a text file

So threading?


RE: Function to Continuasly monitor serial port and control other functions - marsokod - Mar-03-2018

(Mar-03-2018, 10:16 PM)ricardons Wrote: Function1() acquires sensor data and show it on lcd
Function2() is the same as 1 but also writes the data to a text file

So threading?

Yes, threading since you will be mostly IO-bound so there is very little risk of suffering from global interpreter lock.

Unless Larz60+ has a better solution, I would advise going with the third option I gave you:

At the beginning of your code, create 2 queue.Queue() and start 2 threads fetching data from these queues with a timeout. This timeout shall be big enough not to impact your performances with too many loops, but small enough as it will be the time you may have to wait to shut down your program. I run CAN bus monitoring on a Raspberry Pi and had no problem with a loop of 10ms, but 100ms should be even safer.

Your serial monitor will just put a meaningful value in the corresponding queue. Your threads will pick this value up and act accordingly.

When the main program shuts down, you can put a None value in the queues and make sure that your threads interpret that as a signal they should leave the queue monitoring loop and return. This way, your threads close nicely.


RE: Function to Continuasly monitor serial port and control other functions - ricardons - Mar-04-2018

(Mar-03-2018, 11:08 PM)marsokod Wrote:
(Mar-03-2018, 10:16 PM)ricardons Wrote: Function1() acquires sensor data and show it on lcd Function2() is the same as 1 but also writes the data to a text file So threading?
Yes, threading since you will be mostly IO-bound so there is very little risk of suffering from global interpreter lock. Unless Larz60+ has a better solution, I would advise going with the third option I gave you: At the beginning of your code, create 2 queue.Queue() and start 2 threads fetching data from these queues with a timeout. This timeout shall be big enough not to impact your performances with too many loops, but small enough as it will be the time you may have to wait to shut down your program. I run CAN bus monitoring on a Raspberry Pi and had no problem with a loop of 10ms, but 100ms should be even safer. Your serial monitor will just put a meaningful value in the corresponding queue. Your threads will pick this value up and act accordingly. When the main program shuts down, you can put a None value in the queues and make sure that your threads interpret that as a signal they should leave the queue monitoring loop and return. This way, your threads close nicely.
Thank you for your advicebut I'm not sure I have enough knowledge to put all that in a syntax code. Do you have any similar code. Thread +queue


RE: Function to Continuasly monitor serial port and control other functions - Larz60+ - Mar-04-2018

You could use polling, and it is certainly an easier method to code, but it is extremely costly as far as CPU
usage is concerned, using up to 12 % of all allotted CPU cycles.

I have found two articles on how to wrap your code around the interrupt method.
First your Pi has two Uart's available, the PL011 (data sheet here: http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183g/DDI0183G_uart_pl011_r1p5_trm.pdf
or online here: http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0183g/index.html

I found two worthwhile articles on using the PL011 in interrupt mode.
The first: https://www.raspberrypi.org/forums/viewtopic.php?t=9207 gives some general information, and
the second: https://projects.drogon.net/raspberry-pi/wiringpi/functions/ gets down and dirty, showing
what you have to do to use this method.

You would have to spend some time developing this method, but the rewards received in speed would be great,
and you'd have something valuable to share with other Pi developers.
With a little more searching, perhaps here: http://nullege.com/ you might actually find completed code that does this.


RE: Function to Continuasly monitor serial port and control other functions - DeaD_EyE - Mar-04-2018

There is a asyncio module for pyserial. But you must be sure that there is no other blocking function called. For example time.sleep will block the whole loop.


RE: Function to Continuasly monitor serial port and control other functions - Larz60+ - Mar-04-2018

So, there you go. As per DeaD_EyE, check out asyncio/pyserial


RE: Function to Continuasly monitor serial port and control other functions - ricardons - Mar-04-2018

(Mar-03-2018, 09:33 PM)marsokod Wrote: You may want to use a thread or a process depending on what your function1 and function2 are doing. You can either start them manually, use a library like APScheduler to have a pool of threads/process and add your function to the job queue, or start thread/processes at the beginning of your code and have them read elements in a queue. In the last case, your ReadSerial function would only have to put an element in a queue, which should minimize any interruption to the monitoring.


Whoud the class threading.Event be helpful?
https://docs.python.org/3.5/library/threading.html?highlight=threading#threading.Event.wait