0

I am writing code for a live car turn signal.

I can make an LED flash, and I can make a polygon change its fill color to simulate a turn signal.

This worked for the led:

def blink_arrow():
    leftBlinker.blink(on_time=.7, off_time=.3, n=3)

and this worked for the shape fill:

def blink_arrow(count=0):
    global arrow_color
    global left_arrow
    if arrow_color == "green":
        left_arrow = c.create_polygon(50, 100, 150, 75, 150, 125, fill="gray")
    elif arrow_color == "gray":
        left_arrow = c.create_polygon(50, 100, 150, 75, 150, 125, fill="green")

    if count <5:
        w.after(300 if left_arrow=="green" else 700, blink_arrow, count+1)

Here is what I tried, but didn't work:

from tkinter import Canvas
from gpiozero import Button, LED

button = Button(23)
leftBlinker = LED(17)

def blink_arrow(count=0):
    leftBlinker.blink(on_time=.7, off_time=.3, n=1)
    global arrow_color
    global left_arrow
    if arrow_color == "green":
        left_arrow = c.create_polygon(50, 100, 150, 75, 150, 125, fill="gray")
    elif arrow_color == "gray":
        left_arrow = c.create_polygon(50, 100, 150, 75, 150, 125, fill="green")

    if count <5:
        w.after(300 if left_arrow=="green" else 700, blink_arrow, count+1)

#Build window, canvas, shape 

button.when_pressed = blink_arrow

HERE IS THE NEW CODE ACCORDING TO YOUR SUGGESTION:

def blink_arrow(count=0)
    #code for function as written in my first example
    pass

def blink_leftLED():
    leftBlinker.blink(on_time=.7, off_time=.3, 3)
    pass

def left_signal():
    l1 = Thread(blink_arrow)
    l2 = Thread(blink_leftLED)
    l1.start()
    l2.start()

left_button.when_pressed = left_signal

Here is the error:

...line 28 in left_signal
l1 = Thread(blink_arrow)
...line reference to threading.py...
assert group is None, "group argument must be none for now"

Please help. :)

I expected the polygon and the LED to "flash" in sync. I can make them blink individually with discreet functions, but not together. When I try to call both in a single function, as above, the light turns on and the fill color changes once.

KenS
  • 31
  • 4
  • Yes it is possible, however we need to see how the Blinker object handles `on_time`, and `off_time`. As your code sample currently stands, its scope make it hard for us to help you; here is a [great resource](http://stackoverflow.com/help/mcve) to get you started on that. Good luck with your code! – Reblochon Masque May 04 '19 at 00:59
  • You sent me instructions on how to ask a question. I followed toe guidelines as I could understand them. I don't understand what more you need. Will you please explain? I added some stuff to my code sample. – KenS May 04 '19 at 04:30
  • Sorry for not pointing this out; 'pass' is a placeholder command. If you don't have a function to do, using pass just skips it. To use the code, replace the 'pass' keyword with your code and it will work. – Andereoo May 04 '19 at 16:04

2 Answers2

0

Probably the most efficient way to make two functions run at once is using the threading or the multiprocessing module. Threading comes pre-installed and is often used for multiprocessing, which is what you seem to want to do here (run two functions in parallel). Here is an example:

from threading import Thread

#rest of code

def function2():
   pass
def function1():
   pass

t1 = Thread(group=None,target=function1)
t2 = Thread(group=None,target=function2)
t1.start()
t2.start()

Or, with a button to call the events:

from gpiozero import Button, LED    
from threading import Thread

#rest of code

def function2():
   pass
def function1():
   pass

def main_functions():
   t1 = Thread(group=None,target=function1)
   t2 = Thread(group=None,target=function2)
   t1.start()
   t2.start()
button.when_pressed = main_functions

Those are just some examples.

Note that there are NO brackets behind the 'function1' or 'function2' targets in the Threads (it's easy to miss that and then the code won't work). I hope this helps!

Andereoo
  • 834
  • 1
  • 8
  • 24
0

You can simply turn on/off the LED and the arrow inside same function using .after(...) instead of using threads:

def left_signal(count=0, arrow_color='green'):
    blink_on = arrow_color == 'green'
    if blink_on:
        leftBlinker.on()
    else:
        leftBlinker.off()
    c.itemconfig(left_arrow, fill=arrow_color)
    if count < 5:
        w.after(300 if blink_on else 700, left_signal, count+1, 'gray' if blink_on else 'green')
acw1668
  • 40,144
  • 5
  • 22
  • 34