Hello,
I am attempting to create a motor control loop for a small stepper motor to drive a clock. It must turn at 1rpm and I am setting it up to "tick" once per second. Using the real time clock, I set up a repeating alarm every second and an interrupt handler that simply sets a global flag, once per second. The main control loop looks for that flag and if it is true, calculates how many steps the motor must take to move 6degrees (1 second) and calls a step routine that does that.
My problem is that I'd like to idle the controller between steps so as to keep the outputs energized, but the irq doesn't seem to wake from idle as expected. It only works when I sleep the controller, but that de-energizes the outputs which will cause missed steps if I am half-stepping. I can't see what I am doing wrong and would appreciate any insights. I am using MicroPython 1.8.3. Here is my code:
[code]
import machine
from machine import RTC
from machine import Pin
import time
import untplib
rtc = RTC()
rtc_wake = False
mota = Pin('GP14', mode=Pin.OUT)
motb = Pin('GP15', mode=Pin.OUT)
motc = Pin('GP16', mode=Pin.OUT)
motd = Pin('GP17', mode=Pin.OUT)
state = 0
def step( n ):
global state
for i in range (0,n) :
time.sleep_ms(20)
if ( state == 0 ) :
mota.value(1)
motb.value(0)
motc.value(0)
motd.value(0)
state = 1
elif ( state == 1 ) :
mota.value(0)
motb.value(1)
motc.value(0)
motd.value(0)
state = 2
elif ( state == 2 ) :
mota.value(0)
motb.value(0)
motc.value(1)
motd.value(0)
state = 3
else:
mota.value(0)
motb.value(0)
motc.value(0)
motd.value(1)
state = 0
def wakeup(rtc_o) :
global rtc_wake
rtc_wake = True
def tt() : #get correct current time for future timekeep feature
global rtc
ntpc = untplib.NTPClient()
ntpresp = ntpc.request('north-america.pool.ntp.org', version=3, port=123)
CSToffset = 5*60*60
rtc.init(time.localtime(time.time() - CSToffset + ntpresp.offset ))
def go() :
global rtc
global rtc_wake
steps = 63488 #integer number of steps (for 28BYJ-48 512step/rev motor from Adafruit)
secs = 7425 #for integer number of seconds (for 28BYJ-48 512step/rev motor from Adafruit)
oldsteps = 0
newsteps = 0
currsecs = 0
deltasteps = 0
tt()
rtc.alarm(time=1000, repeat=True) # wake up once per second
rtci = rtc.irq( trigger=RTC.ALARM0, handler=wakeup, wake=( machine.SLEEP | machine.IDLE ) ) # wake from any state
while True: # event loop
machine.sleep() # this works but shuts off the outputs
#machine.idle() # this doesn't work (but should as far as I can see)
if rtc_wake:
rtc_wake = False
currsecs = currsecs + 1
newsteps = ( currsecs * steps ) // secs
deltasteps = newsteps-oldsteps
oldsteps = newsteps
if oldsteps == steps:
oldsteps = 0
currsecs = 0
step( deltasteps )
go()
[/code]
Also, I haven't seen reference to how many alarms can be active at any given time, does anyone here know?
Again, any insight or recommendations would be appreciated.
Best regards,
Jason Doege
RTC not waking from IDLE
Re: RTC not waking from IDLE
I haven't played with the RTC stuff much.
machine.idle will return the NEXT time ANY interrupt happens on the system. So it probably is working fine. The system tick timer interrupts every millisecond. So normally you use micahine.idle() in a loop waiting for the event you're interested in.
Since you're driving a motor, I suspect the current consumed by the motor will totally dwarf the current consumed by the CPU.
Lowering the clock rate on the CPU will also yield lower power consumption.
machine.idle will return the NEXT time ANY interrupt happens on the system. So it probably is working fine. The system tick timer interrupts every millisecond. So normally you use micahine.idle() in a loop waiting for the event you're interested in.
Since you're driving a motor, I suspect the current consumed by the motor will totally dwarf the current consumed by the CPU.
Lowering the clock rate on the CPU will also yield lower power consumption.
Re: RTC not waking from IDLE
Thanks. I'm not so worried about power consumption. It doesn't work if I have neither machine.sleep() nor machine.idle() calls, too. It only appears to work properly if I have the machine.sleep() call in the event loop, that's the only reason I have that there, but, because that de-energizes the IOs, that is ultimately unsuitable for my application.
Re: RTC not waking from IDLE
Lacking response on the forum, does anyone have guidance for how to obtain some help?
-Jason
-Jason
- pythoncoder
- Posts: 5956
- Joined: Fri Jul 18, 2014 8:01 am
- Location: UK
- Contact:
Re: RTC not waking from IDLE
It might help if you explained why you want to idle between steps if you're not concerned about power consumption. What are you actually trying to achieve?
Peter Hinch
Index to my micropython libraries.
Index to my micropython libraries.
Re: RTC not waking from IDLE
Hi Jason,
I just tried the following in my WiPy running 1.8.3:
timer3.py
I was hoping to monitor by checking 'timer3.count' from the REPL, but the REPL hangs immediately I run the go() function, as per the discussion in http://forum.micropython.org/viewtopic.php?f=11&t=2127 (the FTP server also dies, and the normal heartbeat LED flashes stop...).
So I'm wondering: are you sure your 'wakeup' is being called, do you still get the heartbeat LED flashes, and do you still have the REPL?
Jim
I just tried the following in my WiPy running 1.8.3:
timer3.py
Code: Select all
import machine
count = 0
def wakeup():
global count
count += 1
return
def go():
global count
count = 0
rtc = machine.RTC()
# wake up once per second
rtc.alarm(time=1000, repeat=True)
# wake from any state
rtci = rtc.irq( trigger=machine.RTC.ALARM0, handler=wakeup, wake=( machine.SLEEP | machine.IDLE ) )
return
So I'm wondering: are you sure your 'wakeup' is being called, do you still get the heartbeat LED flashes, and do you still have the REPL?
Jim