How do you handle passing data between threads concurrently (3 while True loops)?

Viewed 110

Brief explanation of what I'm working with: There are 3 boards that need to communicate over serial.

  1. BB AI
  2. Nucleo STM32 L4XX (A)
  3. Nucleo STM32 L4XX (B)

Now the BB AI works as a hub connecting both 2 Nucleo boards together using a python script. The serial communication is handled by using pyserial (in the python script that resides in the BB AI).

Nucleo A handles solenoid valves via commands that are sent over serial from the BB AI (input() function to get users commands) and nucleo B reads sensor values which the requirement is to read sensor values 20 times per second.

Needed: Run two functions that handle nucleo A and nucleo B from the BB AI using threads since the task is more IO bound than CPU bound.

Problem: The function_A that handles nucleo A from the BB AI is needed to get the sensor values that function_B gives 20 times every seconds.

At the same time function_A needs to read user input using:

while True:
       user_in = input("> ")

So far I can get the function_B values from Nucleo B in function_A for Nucleo A (using threading).

Running threading like:

with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
    f1 = executor.submit(function_A)
    f2 = executor.submit(function_B)

and in function_B the while loop that reads user input:

while True:
    #before sending values to Nucleo A try to print them
    #to check they can run concurrently as users input commands.
    #both is a global variable from function_B
    print(both , end='\r' , flush=True)

    # get user commands and service
    user_in = input("> ")
    user_in = user_in.lower()
    comand_check(user_in)

Is there a way to print without stopping and use input() function too?

1 Answers

You will want to have a dedicated thread processing input(). It looks like you already have two threads for two input()s. Great!

Now they need to talk to each other while avoiding any race condition. A message queue works well as it handles locking for you.

Note that input() blocks the thread until an answer is ready. Nothing else can happen on this thread while blocked, and when it is not blocked it should quickly process whatever input it just received and then promptly jump back into being blocked in input().

This Non-blocking, multi-threaded example answer might help you implement what you are looking for.

How to Break from input()

The classic approach to tell a thread to die is to set a flag then rely on that thread checking that flag in a timely fashion. Press CTRL-C aka ^C to break out of input:

stop = False
While not stop:
    try:
        a = input()
        queue.add(a)
    except KeyboardInterrupt:
        stop = True
Related