LoPy and Time-based Events
-
@fuzzy You can do that, but do not start a new thread within a running thread, because then you will run out of memory very soon. use a main loop which starts threads, (or the BLINK), if required at all. And you can use global symbols for communication.
Besides that:
BLINK, since interrupt driven, does not require an own thread. Once started, it will run independent of any thread. The thread you have is practically empty. If it should run forever, just chose a large number for duration, like 1e32.
If you want to use threading for it, you can use a much simpler implementation, not using BLINK, like:def switchSchedule(low, high, duration): from time import sleep print("THREAD RE-STARTED!") pin = Pin(PUMP_PIN, mode=Pin.OUT) for i in range(duration): pin(0) sleep(low) pin(1) sleep(high) pin(0) # Drop that line, if the final state should be 1 print('THREAD switchSchedule EXITED!') -
@robert-hh Thanks... once more! Can you please explain (if possible by an example) how this (the program logic outlined in my previous email) can be achieved in the main loop?
Thanks!
-
@fuzzy Sorry no. I do not full understand your intentikon. One additional note to using the BLINK example.
Once you created the blink object with blink = BLINK(...) and it expired, you can restart this object again with:
blink.start(pin, low, high, duration)
That means, you do not have to create a new thread to start over a new switchSchedule cycle. You can do something like:def switchSchedule(low, high, duration): print("Switch THREAD STARTED!") pin = Pin(PUMP_PIN, mode=Pin.OUT) blink = Blink(pin, low, high, duration) while True: while blink.cycles > 0: idle() print('Switch cycle terminated!') onTime, offTime, program, duration = getSchedules(rtc.now()) blink.start(pin, onTime, offTime, duration)And you can stop it anytime with either calling blink.stop() of setting blink.cycles = 0.
-
@robert-hh You are right. It is better this way. Will give it a try and let you know.
-
@robert-hh hi! I tried the code, but now due to the
while True:loop in the function no other code of my program is executed. Any ideas?Thanks (once more...)!
-
@fuzzy Try using a short sleep_ms, like sleep_ms(100) instead of idle() in the inner loop.
-
@fuzzy Hello, I made a short test code around both variants, and they seem to run. Variant 1 with the ISR timer:
# from machine import Pin, Timer, idle, RTC from time import sleep_ms, sleep import _thread DEFAULT_HIGH = const(2) DEFAULT_LOW = const(4) DEFAULT_CYCLES = const(10) PUMP_PIN = "P5" class BLINK: def __init__(self, pin, high = DEFAULT_HIGH, low = DEFAULT_LOW, cycles = DEFAULT_CYCLES): self.start(pin, high, low, cycles) def start(self, pin, high, low, cycles): self.pin = pin self.times = [high, low] self.cycles = cycles self.state = 0 self.pin(self.state) self.timer = Timer.Alarm(self.timerCallback, self.times[self.state], periodic=False) def stop(self): self.timer.cancel() def timerCallback(self, timer): self.cycles -= self.state if self.cycles > 0: self.state = 1 - self.state self.pin(self.state) self.timer = Timer.Alarm(self.timerCallback, self.times[self.state], periodic=False) def getSchedules(x): return (1,2,5,5) def switchSchedule(low, high, duration): rtc = RTC() print("Switch THREAD STARTED!") pin = Pin(PUMP_PIN, mode=Pin.OUT) blink = BLINK(pin, low, high, duration) while True: while blink.cycles > 0: idle() print('Switch cycle terminated!') onTime, offTime, program, duration = getSchedules(rtc.now()) blink.start(pin, onTime, offTime, duration) def otherSchedule(time): print("Enters other Thread") while True: sleep(time) print("Other thread is alive") def run(): id1 = _thread.start_new_thread(otherSchedule, [2]) id2 = _thread.start_new_thread(switchSchedule, (1,2,5)) run()Variant 2 with just a loop and sleeps:
# from machine import Pin, Timer, idle, RTC from time import sleep_ms, sleep import _thread DEFAULT_HIGH = const(2) DEFAULT_LOW = const(4) DEFAULT_CYCLES = const(10) PUMP_PIN = "P5" def getSchedules(x): return (1,2,5,5) def switchSchedule(low, high, duration): print("Switch THREAD STARTED!") rtc = RTC() pin = Pin(PUMP_PIN, mode=Pin.OUT) while True: for _ in range (duration): pin(0) sleep(low) pin(1) sleep(high) print('Switch cycle terminated!') onTime, offTime, program, duration = getSchedules(rtc.now()) def otherSchedule(time): print("Enters other Thread") while True: sleep(time) print("Other thread is alive") def run(): id1 = _thread.start_new_thread(otherSchedule, [2]) id2 = _thread.start_new_thread(switchSchedule, (1,2,5)) run() -
@robert-hh Thanks again! I tested the first variant (without threading, justing calling the function once). I think there is something wrong with the way
cyclesis reduced. The expected behaviour is to havecyclesreducing every 1 second. But I do not think this is the case, but I might be wrong.The expected behaviour is to having the pin
pinLOW forlowseconds and then the same pin HIGH forhighseconds. This change between LOW and HIGH needs to last in totaldurationseconds.Maybe the issue is with the following line of code.
self.cycles -= self.stateWhat do you think?
(lots of) thanks!
-
@fuzzy The way it's written at the moment is to reduce cycles by one after every high/low transition, not every second. Given that, the line you point at is perfectly right, but maybe not obvious. self.state toggles between 0 and 1. So every second time this line is executed, 0 is subtracted from self.cycles.
If you have a duration in seconds, you must determine cycles as:
cycles = duration // (low + high)
If that value is 0, the loop will still be executed at least once. -
@fuzzy OK. here is a variant of the fist version which counts down the total duration every second:
from machine import Pin, Timer, idle DEFAULT_HIGH = const(2) DEFAULT_LOW = const(4) DEFAULT_DURATION = const(10) class BLINK: def __init__(self, pin, high = DEFAULT_HIGH, low = DEFAULT_LOW, duration = DEFAULT_DURATION): self.start(pin, high, low, duration) def start(self, pin, high, low, duration): self.pin = pin self.times = [high, low] self.duration = duration self.state = 0 self.count = self.times[self.state] self.pin(self.state) self.timer = Timer.Alarm(self.timerCallback, 1.0, periodic=True) def timerCallback(self, timer): self.duration -= 1 if self.duration <= 0: self.pin(0) # or whatever final state you like self.stop() else: self.count -= 1 if self.count <= 0: self.state = 1 - self.state self.count = self.times[self.state] self.pin(self.state) def stop(self): self.timer.cancel() def run(): pin = Pin("P5", mode=Pin.OUT) blink = BLINK(pin, 1, 1, 10) while blink.duration > 0: idle() run()
Hello! It looks like you're interested in this conversation, but you don't have an account yet.
Getting fed up of having to scroll through the same posts each visit? When you register for an account, you'll always come back to exactly where you were before, and choose to be notified of new replies (either via email, or push notification). You'll also be able to save bookmarks and upvote posts to show your appreciation to other community members.
With your input, this post could be even better 💗
Register Login