简体   繁体   中英

Why aren't my two while loops running concurrently?

I'm pretty new to coding and stuff. I'm working on a digital weighing scale with a HX711 breakout board and outputting the values through a 4 digit 7 segment display.

The weighing() loop read values at a slower rate than my display multiplexing time so the code wouldn't continue until a value has been read resulting in the display flashing like hell. So i tried running the weighing() loop and the displaying() loop simultaneously via concurrent.futures . But the code would execute weighing() only once and then get stuck in the display() loop, so they are not running concurrently?

There must be something wrong with my code, please help me clarify and leave any suggestions for other methods.

import time
import RPi.GPIO as GPIO
import concurrent.futures


GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

segments = [2, 3, 4, 5, 6, 7, 8, 9]
digits = [12, 13, 18, 19]


GPIO.setup(segments, GPIO.OUT)
GPIO.output(segments, GPIO.HIGH)
GPIO.setup(digits, GPIO.OUT)
GPIO.output(digits, GPIO.LOW)

nums ={
    0:(1,1,1,1,1,1,0),
    1:(0,1,1,0,0,0,0),
    2:(1,1,0,1,1,0,1),
    3:(1,1,1,1,0,0,1),
    4:(0,1,1,0,0,1,1),
    5:(1,0,1,1,0,1,1),
    6:(1,0,1,1,1,1,1),
    7:(1,1,1,0,0,0,0),
    8:(1,1,1,1,1,1,1),
    9:(1,1,1,1,0,1,1)}
switchpolarity = {1: 0,
                  0:1}

def display(value):
    while 1:
        s = [int(d) for d in str(value)]        
        for digit in range(0,len(s)):
            for segment in range(0,7):
                GPIO.output(segments[segment], switchpolarity[nums[s[digit]][segment]])
            GPIO.output(digits[digit], 1)
            time.sleep(0.01)
            GPIO.output(digits[digit], 0)


EMULATE_HX711=False

if not EMULATE_HX711:
    from hx711 import HX711
else:
    from emulated_hx711 import HX711

def weighing():
    while 1:
        val = round(abs(hx.get_weight(1)))
        print(val)
        hx.power_down()
        hx.power_up()
        return(val)

hx = HX711(9, 10)
hx.set_reading_format("MSB", "MSB")
hx.set_reference_unit(754)
hx.reset()
hx.tare()

print("Tare done! Add weight now...")


try:

        with concurrent.futures.ProcessPoolExecutor() as executor:
            weighing = executor.submit(weighing)
            displaying = executor.submit(display, (t1.result()))


except(KeyboardInterrupt):
    GPIO.cleanup()

I am very sorry for the typo in the code as I was posting i changed the processes names without testing. This is my new code which i can say is without stupid mistakes:

import time
import RPi.GPIO as GPIO
import concurrent.futures


GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

segments = [2, 3, 4, 5, 6, 7, 8, 9]
digits = [12, 13, 18, 19]


GPIO.setup(segments, GPIO.OUT)
GPIO.output(segments, GPIO.HIGH)
GPIO.setup(digits, GPIO.OUT)
GPIO.output(digits, GPIO.LOW)

nums ={
    0:(1,1,1,1,1,1,0),
    1:(0,1,1,0,0,0,0),
    2:(1,1,0,1,1,0,1),
    3:(1,1,1,1,0,0,1),
    4:(0,1,1,0,0,1,1),
    5:(1,0,1,1,0,1,1),
    6:(1,0,1,1,1,1,1),
    7:(1,1,1,0,0,0,0),
    8:(1,1,1,1,1,1,1),
    9:(1,1,1,1,0,1,1)}
switchpolarity = {1: 0,
                  0:1}

def display(value):
    while 1:
        s = [int(d) for d in str(value)]        
        for digit in range(0,len(s)):
            for segment in range(0,7):
                GPIO.output(segments[segment], switchpolarity[nums[s[digit]][segment]])
            GPIO.output(digits[digit], 1)
            time.sleep(0.01)
            GPIO.output(digits[digit], 0)


EMULATE_HX711=False

if not EMULATE_HX711:
    from hx711 import HX711
else:
    from emulated_hx711 import HX711

def weighing():
    while 1:
        val = round(abs(hx.get_weight(1)))
        print(val)
        hx.power_down()
        hx.power_up()
        return(val)

hx = HX711(9, 10)
hx.set_reading_format("MSB", "MSB")
hx.set_reference_unit(754)
hx.reset()
hx.tare()

print("Tare done! Add weight now...")


try:

        with concurrent.futures.ProcessPoolExecutor() as executor:
            weighing1 = executor.submit(weighing)

            displaying1 = executor.submit(display, (weighing1.result()))


except(KeyboardInterrupt):
    GPIO.cleanup()

This is the main function for your "weighing" thread:

def weighing():
    while 1:
        val = round(abs(hx.get_weight(1)))
        ...
        return(val)

The return(val) statement will cause the function to return at the end of the first iteration of the loop. Once the function returns, the thread is finished. It won't ever run again.

This is how you start your threads:

weighing = executor.submit(weighing)
displaying = executor.submit(display, (t1.result()))

If I understand correctly,* The executor.submit(weighing) call returns a future , and the t1.result() ** awaits the completion of the future, and then returns whatever value was returned by the weighing function.

That means, that the executor.submit(display, ...) will not happen until t1.result() returns a value, which means that the second thread can not even start until the first thread is finished.


IMO;

  • Your weighing() function should update a global variable and continue looping forever instead of returning a value, and

  • Your display() function should get the value that it displays by copying from the global variable, and

  • You can just ignore the futures that are returned by the ProcessPoolExecutor . You aren't really using it as an executor service: You're just using it as a way to create two threads.


* I'm not actually a Python guru.

** I'm assuming that t1.result() is a copy/paste error, and that you meant to say weighing.result() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM