Shop OBEX P1 Docs P2 Docs Learn Events
1st proj temp gauge — Parallax Forums

1st proj temp gauge

Small but works OK. I have this on my desktop, it updates every 20 seconds, logs the data. Now I have to figure out how to turn on/off the logging part. Using the buttons is not feasible at the moment because the way I have the microbit placed.

Ray

# new_log.py
# Imports go at the top
from microbit import *
import log


log.set_labels( 'value')
log.delete(full=True)

temp=(((1.8*temperature())+32)-4.5 )

# Set the timer to log data every 5 seconds
# @run_every(s=5)
@run_every(s=20) # This should be 20 seconds.
# This seems to be the max time setting.

def log_temp():
    display.show(temp,delay=1000)  # 1 sec delay.
    display.show("F")
    log.add(temp=((1.8*temperature())+32)-5.9 )



while True:
    # Needed so that the program 
    # doesn't end.
    sleep(100)

Comments

  • "input()" will take keyboard input.

    Here is a modified version of your 1st proj temp gauge with keyboard input added

    # new_log.py
    # Imports go at the top
    from microbit import *
    import log
    
    log.set_labels( 'value')
    log.delete(full=True)
    
    x="n"
    
    # Set the timer to log data every 5 seconds
    # @run_every(s=5)
    @run_every(s=5)
    
    def log_temp():
        temp=(((1.8*temperature())+32)-4.5 )
        temp_string=str(temp) + 'F'
        if x=="y":
            display.show(temp_string,delay=1000,wait=False)  # 1 sec delay.
        elif x=="n":
            display.clear()
    
    
    while True:
    
        if x=="y":
            print("logging")
        elif x=="n":
            print("not logging")
    
        x=input("Log y / n ?:  ")
    
        sleep(100)
    
    
  • Gave the program more options. Not sure how to make the temp() module run all the time, when selected.

    Ray

    # test_dir.py
    # Imports go at the top
    from microbit import *
    import os
    
    
    def listDir():
        x=os.listdir()
        print(x)
    
    def uname():
        y=os.uname()
        print(y)
    
    def menu():
        print("       System Menu")
        print("dir - System directory.")
        print("system - System information.")
        print("temp - Run temperature gauge.")
    
    def temp():
    
        temp = (((1.8*temperature())+32)-4.5)
        temp_string=str(temp)+"F"
        display.show(temp_string,delay=1000,wait=False)
    
    print("Type help for system menu.")
    while True:
        print("> ",end='')
        inbuff = input()
        if inbuff == "dir":
            listDir()
        elif inbuff == "system":
            uname()
        elif inbuff == "help":
            menu()
        elif inbuff == "temp":    
            temp()
        else:
            print("??")
    
        sleep(300)
    
    
  • I used this program, dir command to show what is on the flash file system, so far no files are showing up. maybe I missed something in listDir().

    I think I will have to by another micro:bit, so I can start trying out the radio command. So, far the only thing I, sort of, dislike is having to use alligator clips or attaching a breadboard. I am now using my Raspberry pi 5 as the PC for working with the micro:bit. If i break down and purchase some specific alligator clips, then I will probably try out the uart facility.

    Ray

  • UnsoundcodeUnsoundcode Posts: 1,530
    edited 2023-12-31 22:34

    Here is an example of your previous program using uart instead of input to make your menu choices. The program now measures elapsed time to allow the display to do its thing in the background before calling the method again.

    #test_dir.py
    # Imports go at the top
    import time
    from microbit import *
    from time import sleep
    import os
    
    uart.init(115200)
    start_time = time.ticks_ms()
    t=0
    display.clear()
    
    def listDir():
        x=os.listdir()
        print(x)
        uart.write("\n>>>")
    
    def uname():
        y=os.uname()
        print(y)
        uart.write("\n>>>")
    
    def menu():
        print("       System Menu")
        print("dir - System directory.")
        print("system - System information.")
        print("start - Run temperature gauge.")
        print("stop - Stop temperature gauge.")
    
    def temp():
        temp = (((1.8*temperature())+32)-4.5)
        temp_string=str(round(temp,1))+"F"
        display.show(temp_string,delay=1000,wait=False)
    
    
    uart.write("Type help for system menu.\n>>>")
    menu()
    uart.write("\n>>>")
    
    while True:
        inbuff=""
        if uart.any():
            inbuff=uart.read().strip().decode()
            if inbuff == "dir":
                 listDir()
            elif inbuff == "system":
                uname()
            elif inbuff == "help":
                menu()
            elif inbuff == "start":
                t=1
                uart.write("\n>>>")
            elif inbuff == "stop":
                t=0
                display.clear()
                uart.write("\n>>>")
            else:
                uart.write("not an option")
                uart.write("\n>>>")
    
        end_time = time.ticks_ms()
        elapsed_time = end_time - start_time
    
        if t == 1 and elapsed_time >= 5000:
            temp()
            start_time = time.ticks_ms()
        elif t == 0 and elapsed_time >= 5000:
            display.clear()
            start_time = time.ticks_ms()
    
        sleep(0.5)
    

    Import time and sleep it makes a difference on your timing

  • These make it much easier to use the Micro:Bit IO pins:

    https://parallax.com/product/edge-i-o-adapter-compatible-with-bbc-microbit/

    dgately

  • I want to stay away from using a breadboard, but it looks like that may be the only option. I did notice, a seller was selling some alligator clips with the other end that has a female pin adapter, that could work for hooking up to a RPi 4/5.

    Ray

  • JonnyMacJonnyMac Posts: 8,889

    This will help you get signals from a micro:bit to something else using Dupont wires.
    -- https://www.amazon.com/KEYESTUDIO-Sensor-Shield-BBC-Micro/dp/B07H9X63CR

  • RsadeikaRsadeika Posts: 3,790

    @Usoundcode, your version of test_dir.py is working on my new Win 10 Thonny PC. I will have to study your code for a while, interesting how you got the temp to run constantly while keeping the I/O part alive.

    Ray

  • UnsoundcodeUnsoundcode Posts: 1,530
    edited 2024-01-01 15:48

    @Rsadeika the main difference is in the while loop, our fist program uses "inbuff=input()" which will sit there forever until you enter a choice via the keyboard, this is known as blocking code and we must try and avoid it in most mcu programs.

    The second program uses the uart (serial protocol) module using the default usb connection which is connected to the PC and displayed in the Thonny REPL (shell) or it could be some other serial interface of your choosing.

    The good thing about the uart is that you can use it without blocking, the "uart.any()" method checks the serial once everytime through the while loop and if there is nothing in the serial buffer it keeps on trucking allowing the mcu to do other things.

    Another thing to be careful about is putting delays in your code, "sleep(5)" for example is blocking code and will prevent your mcu from doing anything else for 5 seconds (note you must import time and sleep to get the correct timing values eg. sleep/sleep_ms/sleep_us/ticks_ms/ticks_us).

    To overcome this blocking feature you can monitor the mcu's internal clock and take action after a certain length of time has passed. In our programs second version we use this method by creating 3 new variables "start_time" , "end_time" and "elapsed_time". The way this works is by initializing "start_time=time.ticks_ms" ,the same method is used throughout to "reset" the time period. Now every time through the program loop we take the current time which is "end_time" and subtract it from the "start_time" which will give us the "elapsed_time" eg: "start_time - end_time = elapsed_time" , when we reach our target say 5000 mS we take action then reset the timer for the next time period. To reset "start_time = ticks_ms", all this is done without blocking.

    Why do we do this in our program, well I am not completely familiar with the display functions but it seems that by putting "wait=False" in the "display.show()" method it will keep updating the display in the background in other words non blocking, this is great but if we keep calling the "temp()" method in the while loop then we are going to be calling the function before the display has completely finished updating and this will make a mess of our display. So using our non blocking elapsed time method which calls the "temp()" method every 5 seconds this gives the display time to finish before calling again.

    One last thing limiting the temperature display to 1 decimal place using "temp_string=str(round(temp,1))+"F"" seemed to work a little better.

  • JonnyMacJonnyMac Posts: 8,889
    edited 2024-01-01 16:02

    What @Unsoundcode has done is create a scheduler. This is allowing the temperature to be checked every 5000ms without the use of blocking delays, which allows the serial input to be processed at the same time.

    This is done by having a base-time variable for an event and then checking to see if the desired event period has elapsed (or been exceeded, which is why >= is used). In that case, the event is fired and the base-time is updated by the desired event duration.

    Here's a simple program that outputs a count every second but doesn't use delays. This is a good technique to know; it's very useful.

    # scheduler.py
    
    import time
    
    EVENT_MS = 1000                                        # run every 1000ms
    
    t_start = time.ticks_ms()                              # initialize base time
    count = 0                                              # initialize count
    
    while True:
        t_elapsed = time.ticks_ms() - t_start              # check elapsed time
        if t_elapsed >= EVENT_MS:                          # time to run?                             
            count += 1                                     # yes, update count
            print(count)                                   # show it
            t_start += EVENT_MS                            # update base time
    
  • RsadeikaRsadeika Posts: 3,790

    After running the temp, for maybe an hour or so, the temp readings are not what they are supposed to be. When I first start it up it shows 74.3 F, consistently, after an hour or so, it is showing, 7.9 F. No, it did not put the microbit in the freezer. Maybe the scheduler is having an impact on the reading of the temperature().

    Has anybody done a softRTC for the microbit. Not even sure if the micrcobit/micropython could handle threading, or it would have enough memory.

    Ray

  • JonnyMacJonnyMac Posts: 8,889
    edited 2024-01-01 20:06

    This isn't an RTC, per se, but it does show elapsed time and temperature -- again using the technique shared by @Unsoundcode. It's useful to master one technique before moving on to another.

    # time_temp.py
    
    from microbit import *
    import time
    
    EVENT_MS = 5000                                        # event every 5000ms
    
    t_start = time.ticks_ms() 
    runtime = 0
    
    
    def show_time_temp(rt):
        tf = temperature() * 9 / 5 + 32.0
    
        rt = rt // 1000                                    # convert to secs
        h = rt // 3600                                     # extract hours
        rt = rt % 3600                                     # remove hours
        m = rt // 60                                       # extract minutes
        s = rt % 60                                        # extract seconds
    
        print("%.2d:%.2d:%.2d   %3.1f" % (h, m, s, tf))
    
    
    show_time_temp(0)                                      # initial reading
    
    while True:                                            # loop
        t_elapsed = time.ticks_ms() - t_start 
        if t_elapsed >= EVENT_MS:
            runtime += EVENT_MS
            show_time_temp(runtime)
            t_start += EVENT_MS  
    

    A while later...
    No change in temperature -- but my code is using very specific formatting in the output.

    Still going, and the temperature is starting to come up. It's a beautiful day in Los Angeles.

  • dgatelydgately Posts: 1,619
    edited 2024-01-05 23:07

    I think I will have to by another micro:bit, so I can start trying out the radio command.

    Since you had mentioned that you wanted to try Micro:Bits radios to send temperature data from one to another... Save a copy of this python source as "main.py" on two Micro:Bits and pressing the A button on either will send its temp for display on the other.

    Quick example of using the radios to communicate between 2 Micro:Bits:

    # radio receive/transmit
    from microbit import *
    import radio
    
    radio.config(group=23)
    
    radio.on()
    
    while True:
        message = radio.receive()
    
        if message:
            display.scroll(message)
            message = ""
        else:
            if button_a.was_pressed(): # send temperature to other Micro:Bit
                display.scroll('A')
                temp=(((1.8*temperature())+32)-4.5 )
                temp_string=str(temp) + 'F'
                radio.send(temp_string)
            else:
                if button_b.was_pressed(): # display local temperature
                    temp=(((1.8*temperature())+32)-4.5 )
                    temp_string=str(temp) + 'F'
                    display.scroll(temp_string)
                else:
    
                    display.show(Image('00300:'
                                       '03630:'
                                       '36963:'
                                       '03630:'
                                       '00300'))
                    sleep(300)   
                    display.show(Image('00300:'
                                       '03930:'
                                       '39693:'
                                       '03930:'
                                       '00300'))
                    sleep(300)   
                    display.show(Image('00900:'
                                       '09690:'
                                       '96369:'
                                       '09690:'
                                       '00900'))
                    sleep(300)           
                    display.show(Image('00300:'
                                       '03930:'
                                       '39693:'
                                       '03930:'
                                       '00300'))
                    sleep(300)   
    

    dgately

Sign In or Register to comment.