proj test_tc — Parallax Forums

proj test_tc

Posts: 3,837

I took the Jon time_temp.py code and broke out the time tic stuff. The code below runs without errors. I added some comments, hopefully somebody will fill in some of the blank spots.

Trying to get a better handle on how the show_time() function is running at constant one second. I suppose adding some more code this could become a stop watch, but I digress. If this function keeps running at one second , the next step would be to add code the increase the m(minute) value, and start the s(second) back at zero, so on and so on. Not sure if I am going about this in the correct manner.

Ray

```# test_tc.py
from microbit import *
import time

EVENT_MS = 1000  # Runs at 1 second

# Future reference
global h
h=0
global m
m=0
global s
s=0

# starts the tics
t_start = time.ticks_ms()
runtime = 0

# This the time tics engine
def show_time(rt):
rt = rt // 1000   # Not sure what this is doing                                  # convert to secs
h = rt // 3600    #      ''                                   # extract hours
rt = rt % 3600    #      ''                                    # remove hours
m = rt // 60      #      ''                                      # extract minutes
s = rt % 60       #      ''

# Show the time elapsing at the command line
print("%.2d:%.2d:%.2d   " % (h, m, s))

# Starts the show_time engine
show_time(0)

while True:    # loop

t_elapsed = time.ticks_ms() - t_start
if t_elapsed >= EVENT_MS:
runtime += EVENT_MS
show_time(runtime)  # This runs show_time @ 0

t_start += EVENT_MS  # Time tics

```

• Posts: 8,997
edited 2024-01-02 01:07

Not sure what this is doing

The run time (rt) is in milliseconds. Dividing by 1000 converts that down to seconds. There 3600 seconds in one hour -- dividing rt (seconds) by 3600 gives hours. The modulus opeator (%s) gives us the remaining seconds. Dividing those by 60 returns minutes; taking the modulus of 60 are the final seconds.

Note: Since h, m, and s are only used in the show_time() function they do not need to be declared as globals -- in fact, what you have now are two sets of variables with the same names. Python is different this way. If you really need a global variable you and need to modify it in a function, you need to specify that you're accessing the global, not a local. This is a function from a cosplay controller I wrote for a friend (@Harukofett on IG). The variable called state_timer is global I need to modify it in some functions.

```def do_flash1():
"""Alternate pixel between specified level and OFF."""
global state_tmr

state_tmr += 1
if (state_tmr >= 200):                             # 200 x 10ms = 2s
state_tmr = 0

if (state_tmr < 100):                              # on 1s
update_outs(brightness)
else:                                              # off 1s
update_outs(0)
```

t_elapsed = time.ticks_ms() - t_start

t_elapsed is the time elapsed since the last marker. The marker is called t_start. Think of time.ticks_ms() as right now.

Think of it this way: You mix up a batch of 5-minute epoxy and look at your watch. The time is 4:55 (we'll call this t_start). A while later you look at your watch again and it's 4:58. 4:58 (now) minus 4:55 (t_start) is three minutes, so you know you have a couple more minutes to work. Once five or more minutes have elapsed you have to mix a new batch and reset the start time.

Since we don't have any delays between events, we can simply add the event duration to the initial t_start to update it.

Once this technique sinks in it will seem very easy and you can create what looks like a multi-tasking system (that said, you have to make sure your tasks don't take a lot of time).

• Posts: 8,997

I have no idea why the first line of the quoted text is so large. @Wuerfel_21?

• Posts: 4,674

@JonnyMac said:
I have no idea why the first line of the quoted text is so large. @Wuerfel_21?

Because you're quoting code outside a codeblock and markdown turns `# Something` into `<h1>Something</h1>`

• Posts: 8,997

Thanks

• Posts: 4,674

Do note that control characters can always be bypassed using a backslash

# Something

• Posts: 3,837

Thanks Jon. "...and you can create what looks like a multi-tasking system..." I am going to try to separate and run the tics , temperature as separate items. That should give me an indication as to whether this concept is sinking in. Have to get my old brain working a little bit faster and better.

Ray

• Posts: 3,837

This my first attempt at running two tasks. It runs without errors, but the temp part values that are shown gets corrupted. Not sure how to slow the showing of the temp values down, it seems to run very quickly. Their must be a better way to do this, I am sure.

Ray

```from microbit import *
import time
#
EVENT_MS = 1000  # Runs at 1 second

# starts the tics
t_start = time.ticks_ms()
tic_runtime = 0
temp_runtime = 0

# Future reference
global hh
hh=0
global mmm
mm=0
global ss
ss=0

def show_time(rt):
global mm
global hh

rt = rt // 1000   # Not sure what this is doing                                  # convert to secs
h = rt // 3600    #      ''                                   # extract hours
rt = rt % 3600    #      ''                                    # remove hours
m = rt // 60      #      ''                                      # extract minutes
s = rt % 60       #      ''

if s == 60:
mm = m + 1
if m >= 59:
hh = h + 1
# Show the time elapsing at the command line
print("%.2d:%.2d:%.2d   " % (hh, mm, s))

def show_temp(tt):
temp = (temperature() * 9 / 5 + 32.0)-4.5
temp_string=str(round(temp,1))+"F"
display.show(temp_string,delay=450,wait=False)

# Starts the show_time engine
show_time(0)
show_temp(0)

while True:    # loop
#show_temp()
t_elapsed = time.ticks_ms() - t_start
if t_elapsed >= EVENT_MS:
tic_runtime += EVENT_MS
show_time(tic_runtime)  # This runs show_time @ 0
t_start += EVENT_MS  # Time tics

if t_elapsed >= EVENT_MS:
tic_runtime += EVENT_MS
show_temp(temp_runtime)  # This runs show_temp
t_start += EVENT_MS  # Time tics

```
• Posts: 8,997
edited 2024-01-02 17:16

You're trying to handle two different events from the same task timer variable. Even if they run at the same rate, you should have a separate timer variable for each task.

I think this does what you want. Note that even though the display.show() function runs in the background, if you call it before it's finished it will restart.

Update: I made it a little fancier by alternating between F and C.

```from microbit import *
import time

RTC_MS = 1000                                          # update rtc every 1s
TMP_MS = 5000                                          # display temp every 5s

t_rtc = time.ticks_ms()
t_tmp = time.ticks_ms()

rtcsecs = 0
tmpmode = 0

def show_time(s):
h = s // 3600
s = s % 3600
m = s // 60
s = s % 60

print("%.2d:%.2d:%.2d" % (h, m, s))

def show_tempf():
global tmpmode

tmpmode += 1
if tmpmode % 2:
ts = str(round(temperature() * 9 / 5 + 32.0)) + "F "
else:
ts = str(round(temperature())) + "C "
display.show(ts, delay=500, wait=False)

show_time(0)
show_tempf()

while True:
now = time.ticks_ms()

if now - t_rtc >= RTC_MS:
rtcsecs += 1
show_time(rtcsecs)
t_rtc = now

if now - t_tmp >= TMP_MS:
show_tempf()
t_tmp = now
```
• Posts: 3,837

Thanks Jon. Now, I think I am starting to catch on. I wonder how many tasks can be run this way before the system starts to bog down. Is their a microbit command that shows how much memory is being used on the microbit. Now I will try to add the start/stop of tasks, then add the listdir and system commands. Still not sure how I will handle the delete file command.

Ray

• Posts: 8,997
edited 2024-01-02 18:54

I wonder how many tasks can be run this way before the system starts to bog down.

It will depend on how many tasks are running and how long they take. For my friend's cosplay controller I tried to use a 5ms time base but looking at a free output on a 'scope I found there was a lot of wobble (because some tasks states took a little too long). I bumped it up to 10ms (which is easier to deal with mentally, anyway) and all was fine. In her case the project is monitoring, debouncing, and auto-repeating three buttons (I created a simple class for that) and running the current state of the program which can be LED on, LED flashing (two different modes), or fading the LED on and off (which is why my time base needs to be short).

Micropython has a timer class built in, but I'm not sure how it's implemented on the micro:bit. This is why I still favor Spin1 and Spin2 above all other embedded languages: nothing is hidden "under the hood." That said, I can't run Spin on an RP2040 which is what my friend wants to use in her cosplays. Python (which mechanically inspired Spin) is closest.

• Posts: 3,837

This is my latest attempt. Almost everything works. I added an ontime, offtime and showtime commands. What I am trying to do is start the time with ontime, in the background, and then use showtime to show the current time. For some reason I cannot get this to work correctly. I got the temp to work fine.

Ray

```# mc_mb_test.py
#
from microbit import *
import time, sys, os
from time import sleep

RTC_MS = 1000                                          # update rtc every 1s
TMP_MS = 5000

t_rtc = time.ticks_ms()
t_tmp = time.ticks_ms()

rtcsecs = 0
tmpmode = 0

tics = 0
temp = 0

uart.init(115200)

print("quit - End the program.")
print("dir - System directory.")
print("system - System information.")
print("ontemp - Show the temperature.")
print("offtemp - Turn off the temperature.")
print("delfile - Delete a file, to be developed.")

def listDir():
x=os.listdir()
print(x)
uart.write("\n>>>")

def uname():
y=os.uname()
print(y)
uart.write("\n>>>")

def del_file():
print("Code to be developed")
uart.write("\n>>>")

def show_time(s):
global h
global m
#global s
h = s // 3600
s = s % 3600
m = s // 60
s = s % 60

#print("%.2d:%.2d:%.2d" % (h, m, s))

def showtime():
global h
global m
global s
print("%.2d:%.2d:%.2d" % (h, m, s))

def show_tempf():
global tmpmode

tmpmode += 1
if tmpmode % 2:
ts = str(round(temperature() * 9 / 5 + 32.0)-4.5) + "F "

else:
ts = str(round(temperature())) + "C "

display.show(ts, delay=700, wait=False)

uart.write("\n>>>")

while True:
inbuff=""
if uart.any():
if inbuff == "quit":
print("sys_dir program has ended.")
sys.exit()

elif inbuff == "help":
elif inbuff == "dir":
listDir()
elif inbuff == "system":
uname()
elif inbuff == "ontemp":
temp=1
uart.write("\n>>>")
elif inbuff == "offtemp":
temp=0
uart.write("\n>>>")
elif inbuff == "delfile":
del_file()
elif inbuff == "ontime":
tics=1
uart.write("\n>>>")
elif inbuff == "offtime":
tics=0
uart.write("\n>>>")
elif inbuff == "showtime":
showtime()
uart.write("\n>>>")
else:
uart.write("not an option")
uart.write("\n>>>")

now = time.ticks_ms()
# Not implemented yet, not sure what I will do.
#if tics == 1:
if tics == 1 and now - t_rtc >= RTC_MS:
rtcsecs += 1
show_time(rtcsecs)
t_rtc = now
if tics == 0 and now - t_rtc >= RTC_MS:
display.clear()

# This works, not sure it it can be improved.
if temp == 1 and now - t_tmp >= TMP_MS:
show_tempf()
t_tmp = now
if temp == 0 and now - t_tmp >= TMP_MS :
display.clear()

sleep(0.5)

```
• Posts: 1,532

the os Module contains 3 file functions "listdir()", "remove(filename)" and "size(filename)". If the file does not exist an OSError will occur.

Remove will delete the file "filename"

```def del_file(filename):
try:
os.remove(filename)
uart.write("\n>>>")
except:
print("something went wrong")

del_file("my.csv")
```

There is a small app called MicroFS that copies a file from the device or writes a local file to the microbit, I'm not sure if it will be of use to you or just muddy the waters. If you don't think you need it at this time make sure to keep a bookmark for later it's a neat little utility.

• Posts: 3,837

Thanks Unsoundcode. I have the readthedocs pdf, at some point I will print out a paper copy. I am old school, stuff like that I like to read a paper copy.

For the tasking stuff how do I no that the task has actually stopped (quit). I know for the offtemp, the task stops showing, so theoretically the task has quit. Now, when I get the ontime to work, that will be running in the background all the time. When I select offtime, how do I stop(quit) the task.

When I get the bugs worked out for the softRTC, I will start looking into the logging task, that should be interesting.

Ray