proj baseSta
This is the start of the baseSta code. I put in the temp task just to see if it runs correctly with the RTC running also. So far it looks like no problems. Next thing I will start a logger task and see how far I get with logging the temp data with a time attached. Something like this:
sta day time temp
s0 , 01/03/24 ,12:12:24, 72.0
Not sure how I will handle the actual day heading. This will be a csv file, hopefully I will be able to use pandas and may load it to an SQLite3 database.
The next task will be using the radio for collecting other data and placing it in the csv file.
Ray
# mc_mb2.py # from microbit import * import sys, time uart.init(115200) TMP_MS = 5000 t_tmp = time.ticks_ms() tmpmode = 0 temp = 0 # Station ID global sid sid=0 def menu(): print(" System Menu") print("quit - End the program.") print("settime - Set the clock.") print("showtime - Show the current time.") print("ontemp - Turn on the temp.") print("offtemp - Turn off the temp.") uart.write(">>>") hr = 0 mn = 0 sc = 0 # This starts the clock engine immediately. @run_every(s=1) # run every second def update_rtc(): global hr, mn, sc sc += 1 if (sc == 60): sc = 0 mn += 1 if (mn == 60): mn = 0 hr += 1 if (hr == 24): hr = 0 def show_rtc(): global hr, mn, sc print("%.2d:%.2d:%.2d" % (hr, mn, sc)) def set_time(): global hr, mn, sc inhour = input("hour(xx): ") inmin = input("minutes(xx): ") insec = input("seconds(xx): ") hr = int(inhour) mn = int(inmin) sc = int(insec) print("%.2d:%.2d:%.2d" % (hr, mn, sc)) uart.write(">>>") def show_tempf(): global tmpmode tmpmode += 1 if tmpmode % 2: #ts = str(round(temperature() * 9 / 5 + 32.0)-4.5) + "F " ts = str(round(temperature() * 9/5 +32)-4.5)+"F"+" S0" else: ts = str(round(temperature())) + "C " display.show(ts, delay=700, wait=False) uart.write("Microbit softRTC.\n>>>") menu() while True: inbuff="" if uart.any(): inbuff=uart.read().strip().decode() if inbuff == "quit": print("sys_dir program has ended.") sys.exit() elif inbuff == "settime": set_time() elif inbuff == "showtime": show_rtc() uart.write("\n>>>") elif inbuff == "ontemp": temp=1 uart.write("\n>>>") elif inbuff == "offtemp": temp=0 uart.write("\n>>>") else: uart.write("not an option") uart.write("\n>>>") now = time.ticks_ms() # this for the temp task 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()
Comments
I am having a bit of a problem with the write_logger(). It seems when I do the settime() and then start the logger, the global_log file does not show the time correctly, it just keeps capturing the same time. Is this a problem with the append process. Not sure how to get around that.
The other problem is when I type in a command sometimes it comes back with uart.write("not an option") response even though I have that command available. Is that a problem with my keyboard or
process. This really an annoying problem.
Ray
Try this for your menu, just fill in each of the elif's with the function calls.
To log your values you only need to open the log file once and keep the file open until you have finished logging so to open and close the file you need separate functions from the "write_logger()" function. The for loop in your "write_logger()" function is just going to write the same values 20 times because they have never been refreshed. Think about something like the following
OPEN THE LOG FILE AND WRITE THE HEADER
WRITE DATA TO THE LOG FILE ONCE EVERY MINUTE ---- REFRESH THE TIME VALUES ---- REPEAT
WHEN YOU FINISH LOGGING CLOSE THE FILE
QUIT THE PROGRAM
Don't use the List to contain the data just separate the data with commas and terminate with a newline ("\n") every time you write to file.
I also found the following in the microbit module that I thought might be useful, it's a way of scaling values and the example they give just happens to be temperature deg C to deg F
temp_fahrenheit = microbit.scale(30, from_=(0, 100), to=(32, 212))
I am not sure if I am getting this logging stuff correctly. Below is a small program. In theory every time I do the write command, it should append a new line. For me it looks like it just keeps over writing the first line. This should be a simple enoug program to make a correction, if I have the concept wrong.
Ray
Every time you open a file in w mode it is overwritten if it already exists.
The micropython on Micro:Bit does not support the 'a' (append) mode. In order to append to a file, you have to read it into a buffer, add any new text to that buffer, then re-write the file. This is unlike micropython on other microcontroller boards, which do support the append ('a') mode.
Unfortunately you won't see this detail in the generic micropython documentation, right? You have to get this information from the Micro:Bit micropython documentation...
It's here:
https://microbit-micropython.readthedocs.io/en/latest/tutorials/storage.html
And, contains this (search for 'append' in your browser from the linked page above):
dgately
I just keep missing the obvious. Below, the program works, first I do an open, then I can do multiple write and then either quit or close.
Ray
Surprised it works (due to the docs), but that's good news!
dgately
@Rsadeika your on the right track, here is the same code with a boolean variable called "write_enable" that is either True or False depending on whether you want to write to file or not write to file, you can see this variable inside of your write_log method which I have now set to run every 5 seconds. As long as you only open the file once and only close it when your done you can log for a long time.
I am having trouble figuring out how to f.write() numbers to a file. It does strings very well but numbers... I was trying to do something like x=x+1, and have the incremented number written. I tried doing a str(x) or a chr(x), and that did not work. Any suggestions.
Ray
str(x) should work
You probably don't want to write numbers into what is a text file for this. Convert the numbers to a string before writing them. Then, convert the strings back to numbers when read back from the file...
This example creates a .csv file of numbers (as text). Then, it reads the them back in and converts them back to numbers for use.
EDIT: writes and reads both integer & floating point numbers...
dgately
I added some stuff, the program seems to run without errors. This version you have to do a manual write command to put something in the csv file. I am sure that this is not crash proof, if you do not put everything in. This is a proof test. Any improvements that are suggested will be appreciated.
Ray
Looks very good!
I'm able to crash the program, choosing the 'write' command if the date and time have not yet been set. On program start you might want to set a date-time_set=False flag for the date & time not being set that can be checked in the write() function. Set that flag to True once date & time have been set.
dgately
Thanks for the observation, I have to start thinking about error proofing the system. My next step is to automate a logging procedure for the temperature sensor. I also have to keep in mind that when I get to using the radio I will be collecting other Sta information , which will be placed in the global_log.csv. Plus I hope to make use of the other sensors that are available.
Ray
I automated the onlog so it starts capturing the temperature and writing it to the log. The problem I am having is error proofing the settime/setdate as suggested. I tried a couple of different things, and it is not working for me. I guess I need some expert advice.
Ray
I just edited the "onlog" case... It just gives the warning if date & time not set... But, If date & time have been set, it opens the log file, writes the header and sets write_enable to True. Seems to work.
You might want to add a 'clearlog' command and a command that just prints the log (or a portion of it) to the shell. Even if those commands are only available while testing & debugging the code. And, maybe a "?" command that just prints the menu again.
Oh and it appears that (some, like setdate & settime) commands return with a '>> ???' after printing the date/time. Something is left in the input buffer, I guess.
Just some ideas (take with a grain of salt)...
dgately
Here is my latest version, so far it runs without errors. I added def system_stat(), which I ended up using @run_every(s=5). I tried using Jon's task method, but I guess I could not get the timing right, it just would not work correctly. '>> ???', this one I cannot figure out, I do not know how to fix that one, at this point.
Another weird thing, in the quit command I added a Image.SMILE, when I do a quit, the smile shows up very quickly, but is overtaken by the Image.YES. Not sure what is going on there.
Ray
I am trying to figure out a simplified way of doing a calendar thing. Will the code that I added to the update_rtc() do what I think it will do. I guess another opinion is needed for this. Is there a simpler way of doing this.
Ray
Use an external I2C RTC chip that will hold time and date (using a battery) between power outages. Your master controller can always update the slave controllers (just like your cell phone gets the time and date from cell towers).
Ray,
Parallax sells a DS3231 AT24C32 Real Time Clock Module at $4.95 (US)...
https://parallax.com/product/ds3231-at24c32-real-time-clock-module/
Here's 'mostly' your code running with the DS3231 RTC module in-place of the software RTC. It still uses the task method to initiate logging, but the date & time data comes from the DS3231 RTC...
The RTC was set earlier today and has been running even while the Micro:Bit has been unplugged.
dgately
@dgately, if you get a chance could you provide a picture of your hardware setup. I am trying keep away from doing the breadboard stuff, but you may have a neat setup.
I was looking for a plug and play solution for the RTC, but there is virtually nobody selling a solution that I like. But did come across one outfit that is selling something interesting, the drawback, all of their sample code is using that make software.
Ray
Just a prototype breadboard setup. Small breadboard, Parallax Edge I/O Adapter & RTC module and 2 15K pull-up resistors. You could replace the breadboard with something like this: tinyurl.com/35d2jzt6 OR https://www.adafruit.com/product/571?gad_source=1 for a permanent solution.
dgately
I think that RTC module already has pull-ups, so you may not need to add them to the breadboard.
Thanks dgately, that looks simple enough. I know I have an RTC and a BME somewhere, in my parts box. I will have to see what other sensors I have, that are not on the micro:bit. Now if Parallax would provide an official schematic for these sensors as it would used with the micro:bit, that would make things a little easier. I am hoping that dgately will provide the source code for working with these sensors.
Ray
Waiting for Parallax to do everything you want in exactly the manner you want it will leave you unhappy. It's a tiny company with next to no resources.
The internet can be your friend. I used the words MICROBIT and RTC in a search engine that lead to lots of options; surely, there is something in that mix that will help you.
I looked in my parts drawer and found a ds1302 RTC board that Parrallax used to sell. The pins MISO, MOSI, SCK might be for serial connection, not sure about that. I think the micro:bit is looking for an SCL and SCA connection. I will have to look at micro:bit pinout to see if the ds1302 can be connected.
Ray
As JonnyMac stated, the pull-ups are not needed, so wiring is even easier
Parallax provides a datasheet for the RTC module, which gives the details on what needs to be sent to it and what data the module returns. BTW: It can also return temperature values (I have an code example of that as well). I found an example of how you would wire it up to an Arduino Uno, then looking at a Micro:Bit pinout image (https://tech.microbit.org/hardware/edgeconnector/), found scl & sda on pins 19 & 20.
As far as source code, I used the following site, then melded the example code from there with your demo program. There's not a lot of error checking & definitely needs optimization (uart vs print, etc) at some point. I left the software RTC code in the program for now, but would 'optimize' that out, for my use.
multiwingspan.co.uk/micro.php?page=rtc
Most of the details of what & how came from quick Google searches and from these sites:
https://microbit-micropython.readthedocs.io/en/v2-docs/
https://docs.micropython.org/en/latest/
dgately
Concerning te ds1302, I noticed that the micro:bit has MISO, MOSI, SCK pins. I guess as an experiment I could use some alligator clips to connect up to the micro:bit and the ds1302. Looking at the dgately def set_time_rtc(), I think that should work for the ds1302. The last time I used the ds1302 was when I had it hooked up on the Activity Board and I was using SimpleIDE. SimpleIDE had a function for the ds1302, that made life so much easier. The thing that I do not remember is if the ds1302 needs pull-ups.
Ray
I went ahead and ordered a couple of micro:bit boards, edge connector, and RTC. Now I can start thinking more about the NoT, and how I will proceed. I also found, in my parts box a BME680, and I noticed it uses scl and sda. Since the RTC uses those pins, it may be a little more difficult to figure out how the micro:bit uses more than one I2C device, let alone trying to find the API to work the BME680.
Ray