Good to see you are progressing with the micropython on the GIGA. As you indicate you are putting up your code with helping others use mp on a GIGA in mind, I give you some thoughts on the code as presented. Not that your code does not work but perhaps its used in a way that is not 'normal' as regard you use of classes. However having said all that, the most important part of writing any code is the YOU can read and understand it when you return to it some time later, and for that its best you go with a programming style that suits you. But I give the following for your consideration.
Python reads the code line by line and in doing so it will carry out any commands it finds as it trundles along it route of statements, and that includes being diverted along its route into the statements found in the imported files (modules) along its path. So, for instance, in your wifi.py module there is no need to put all those statements into a class and to then instantiate that class in the first part of the start program, the 'import wifi' would have done the job just as well if the statements where not put into a class so that seems unnecessary and my confuse newbies into thinking a class was necessary to get the code imported.
It may be that you wish to put the statements into a class or function and have those acted on later when you call the function or instantiate a class. A class is usually used to group a bunch of functions together that relate to a particular object, whence they then get to be known as methods. Taking the wifi.py then you could have put all those statements into a function rather then a class, say called wifi_connect().
You could import this function in your start program as follows:
from wifi import wifi_connect as wc
and then called this function with:
wc()
In the python code as illustrated in your code for a simple program then I think you may find its better to use functions rather than classes.
But for a demonstration of using a class then perhaps you may consider the LED's. Whilst not really applicable to such a small program, as you use more than one LED's and as LED's all work the same way, then its a classic use to illustrate the use of a class
So I put up two bits of code for your consideration. Firstly I show an LED class that has two methods, one to flash and LED at a run time specified blink rate and number of blinks and another to continuously blink and LED at a specified blink rate. (yes, well, it is really too simple to warrant a class I suppose but I hope you see what I'm getting at).
Secondly I show a function that returns the date and time in your specified string output format desires. I'm assuming the GIGA has a battery backed RTC so the time is not set in my example, but the time is just read from RTC. When the function is called it returns the date and time in the format along the lines you showed in your code.
For both of these examples I put them into separate modules (files) as per your demo, and show a DBmain.py file that uses the time and date function and the LED class from the example modules I created.
In the module DB_mytime.py I have shown the use of if __name__ == '__main__': to show that any code that comes after this is not actioned upon when the module is imported, but this code is run if DB_mytime.py is run directly.
Likewise in the DBBlink_test.py I put in a print statement that has not been put after the __name__ stuff, but nevertheless, even though one only imports the Blynk class from this module, nevertheless the whole of the imported file is read and any statements found are executed upon import. This catches a few folk new to python out.
A final point to note is that be careful of having a main.py file until you have tested it out as a file with this name will be automatically run when the microprocessor is connected to power. Some erroneous code could mean you get your board into a state where it always errors on power up but the the program is also refusing to quit leaving your board locked until you reload mp again. In any main.py file I always start it with a small bit of code to sleep for 5 seconds to give enough time to issue a Ctrl C to exit the program is necessary.
DB_mytime.py
from machine import RTC def rtc_time(): rtc = RTC() year, month, day, weekday, hours, minutes, seconds, subseconds = rtc.datetime() # time string if (hours >= 12): pm_hours = hours - 12 my_time = "{}:{}".format(pm_hours, minutes) + "pm" else: my_time = "{}:{}".format(hours, minutes) + "am" # date string my_date = str(month)+':'+str(day)+':'+str(year) return (my_date, my_time) if __name__ == '__main__': print('Im running this code if this module is directly run') the_date, the_time = rtc_time() print(the_date) print(the_time)
DBBlink_test.py
from time import sleep class Blynk: def __init__(self, led_pin): self.led_pin = led_pin def blink(self, periodic, num_blinks): for blinks in range(1,num_blinks): self.led_pin.toggle() sleep(periodic) self.led_pin.off() # ensure blink ends with the LED off. def blink_forever(self, periodic): while True: self.led_pin.toggle() sleep(periodic) print('just to show this statement will be actioned even if only \ from Blink_test import Blynk is used')
DBmain.py (running on my rpi pico - amend for your variables file and pin names etc and include the creation of another class instance for your LED_RED along the same lines as the LED_GREEN, and then perhaps blink the jolly old red LED with a different blink rate and number of blinks such as LED_RED.blink(1,2)
from machine import Pin from DBBlink_test import Blynk from DB_mytime import rtc_time LED_GREEN = Blynk(Pin('LED', Pin.OUT)) LED_GREEN.blink(0.5,10) # blink for 0.5 second 5 times on 5 times off mydate, mytime = rtc_time() print(mydate) print(mytime)
I don't know if any of this helps, but my fingers got itchy when I saw the code you presented and thought you might like to see another angle.
https://mc.scsiraidguru.com/index.php/giga-project/
@byron, I appreciate your help and ideas. I usually build the separate .py files and test them before adding them to main.py.
variables.py is working great.
i2c.py: I added a Mega 2560 as I2C address 0x15.
dst.py: calculates Day Light Savings Time for each year and compares the current date to adjust time
blink_test.py: blinks two LED on D52 and D53 of the Giga
wifi.py: creates the wifi from the variables.py
I was going to add def statements to clean up the code more.
@scsiraidguru I am curious about your DST code, is it just for the place you live, or are you doing it for all of North America? If it's the later, would you mind sharing the web site that has all the DST boundaries and the exceptions. I understand there are even some small towns that do not switch as well as bigger entities like county, Province and State? I know about Arizona (with the exception of the Navajo Nation) but I understand there are more.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
I am in Michigan.
In main.py
EST_TIME lines are set to EST and EDST.
now-18000 is -5 hours in seconds for EST
now-14400 is -4 hours in seconds for EDST
I tested the code for HHMarch and HHNovember for several years to set the start and end of daylight savings time.
# Set RTC Clock properly now=time.time() if now < d.HHMarch : # we are before last sunday of march EST_TIME = time.localtime(now-18000) # EST: UTC-5H hour_number = EST_TIME[3] if hour_number < 13: hour_12 = hour_number am_pm = 'am' else: hour_12 = hour_number - 12 am_pm = 'pm' print("Today's Date: {:02d}/{:02d}/{:02d}".format(EST_TIME[1],EST_TIME[2],EST_TIME[0])) print("Time: {:02d}:{:02d}:{:02d} {}".format(hour_12,EST_TIME[4],EST_TIME[5],am_pm)) elif now < d.HHNovember : # we are before last sunday of march EST_TIME = time.localtime(now-14400) # EDST: UTC-4H hour_number = EST_TIME[3] if hour_number < 13: hour_12 = hour_number am_pm = 'am' else: hour_12 = hour_number - 12 am_pm = 'pm' print("Today's Date: {:02d}/{:02d}/{:04d}".format(EST_TIME[1],EST_TIME[2],EST_TIME[0])) print("Time: {:02d}:{:02d}:{:02d} {}".format(hour_12,EST_TIME[4],EST_TIME[5],am_pm)) else : EST_TIME = time.localtime(now-18000) # EST: UTC-5H hour_number = EST_TIME[3] if hour_number < 13: hour_12 = hour_number am_pm = 'am' else: hour_12 = hour_number - 12 am_pm = 'pm' print("Today's Date: {:02d}/{:02d}/{:02d}".format(EST_TIME[1],EST_TIME [2],EST_TIME[0])) print("Time: {:02d}:{:02d}:{:02d} {}".format(hour_12,EST_TIME[4],EST_TIME[5],am_pm)
@scsiraidguru Ok, that's what I thought.
First computer 1959. Retired from my own computer company 2004.
Hardware - Expert in 1401, and 360, fairly knowledge in PC plus numerous MPU's and MCU's
Major Languages - Machine language, 360 Macro Assembler, Intel Assembler, PL/I and PL1, Pascal, Basic, C plus numerous job control and scripting languages.
My personal scorecard is now 1 PC hardware fix (circa 1982), 1 open source fix (at age 82), and 2 zero day bugs in a major OS.
Byron, it is working much better now. Still working on running parts of it only once.
DST Start: 03/10/2024
DST END: 11/03/2024
Today's Date: 04/14/2024
Time: 06:46:48 pm
I2C SCANNER
i2c devices found: 1
I2C hexadecimal address: 0x15
Blink
from time import sleep from wifi import WIFI from dst import DST import ntptime, time from blink_test import Blynk from i2c import * devices_found = 0 def wifi_function_once(_has_run=[]): a = WIFI() if _has_run: return print('\n') print("first time") print("Connected to ",a.WIFI_NETWORK) print(a.wlan) wifi_ran = True _has_run.append(1) def I2C_function_once(_has_run=[]): if _has_run: for device in devices: print("I2C hexadecimal address: ", hex(device)) print('\n') return i = I2CScanner() print('\n') print('I2C SCANNER') devices = i.i2c.scan() if len(devices) == 0: print("No i2c device !") else: print('i2c devices found:', len(devices)) for device in devices: print("I2C hexadecimal address: ", hex(device)) print('\n') def blynk_function(): print("Blink") Red_LED = Pin(variables.D52, Pin.OUT) Green_LED = Pin(variables.D53, Pin.OUT) Red_LED.on() time.sleep(1) Red_LED.off() time.sleep(1) Green_LED.on() time.sleep(1) Green_LED.off() time.sleep(1) return def dst_function(_has_run=[]): if _has_run: return d = DST() print("DST Start: {:02d}/{:02d}/{:02d}".format(d.DST_START[1],d.DST_START[2],d.DST_START[0])) print("DST END: {:02d}/{:02d}/{:02d}".format(d.DST_END[1],d.DST_END[2],d.DST_END[0])) # Set RTC Clock properly now=time.time() if now < d.HHMarch : # we are before last sunday of march EST_TIME = time.localtime(now-18000) # EST: UTC-5H hour_number = EST_TIME[3] if hour_number < 13: hour_12 = hour_number am_pm = 'am' else: hour_12 = hour_number - 12 am_pm = 'pm' print("Today's Date: {:02d}/{:02d}/{:02d}".format(EST_TIME[1],EST_TIME[2],EST_TIME[0])) print("Time: {:02d}:{:02d}:{:02d} {}".format(hour_12,EST_TIME[4],EST_TIME[5],am_pm)) elif now < d.HHNovember : # we are before last sunday of march EST_TIME = time.localtime(now-14400) # EDST: UTC-4H hour_number = EST_TIME[3] if hour_number < 13: hour_12 = hour_number am_pm = 'am' else: hour_12 = hour_number - 12 am_pm = 'pm' print("Today's Date: {:02d}/{:02d}/{:04d}".format(EST_TIME[1],EST_TIME[2],EST_TIME[0])) print("Time: {:02d}:{:02d}:{:02d} {}".format(hour_12,EST_TIME[4],EST_TIME[5],am_pm)) else : EST_TIME = time.localtime(now-18000) # EST: UTC-5H hour_number = EST_TIME[3] if hour_number < 13: hour_12 = hour_number am_pm = 'am' else: hour_12 = hour_number - 12 am_pm = 'pm' print("Today's Date: {:02d}/{:02d}/{:02d}".format(EST_TIME[1],EST_TIME[2],EST_TIME[0])) print("Time: {:02d}:{:02d}:{:02d} {}".format(hour_12,EST_TIME[4],EST_TIME[5],am_pm)) if __name__=="__main__": while True: dst_function() wifi_function_once() I2C_function_once() blynk_function() sleep(3)
@scsiraidguru - I caught this post as I had a quick flick through some forums I peruse from time to time, so dont forget, if you want to draw something to my attention to address it to @byron, as a plain old byron may easily get missed and I will not get an email about a post.
It passed my bedtime, so I may have some comments in a day or so when I have a chance for some better consideration, but the obvious initial comment is that I wonder why, if you only want to call a function once, you continually call the function in a never ending loop. Surely just call it once before you call the stuff you do want to be in a loop. Think of the Arduino Setup and Loop functions.
Anyway I see you are making good progress with your GIGA and mp, and I'm looking forward to see what project you are using it for. 😀
I am getting the base components setup first. I am looking for a 60V 3 channel bench power supply for VIN. I need to solder pins for RTC battery. Looking at OTA connection. It is going in a good direction. I am working on advanced python coding. I thought it would be interesting to do run once.
https://mc.scsiraidguru.com/index.php/arduino/30-days-in-space/day-1-rfid/
This project is part of Inventr.io 30 Days in Space project. Here is an Arduino project I will be adding the Giga R1 WIFI to. This project has I2C LCD screens. RFID reader. Photoresistor to simulate solar panels. Switches for lights and simulate opening viewers. I have an I2C Temperature and Humidity sensor that will be added.
The Giga adds wifi, rtc, and will be the I2C master
Single Source Logic Level Converter will transfer 3.3V devices (Giga and Rpi 4B) to 5V devices ( Arduino and sensors. I connected the I2C bus path through the device.
Thats looks like a project worthy of your GIGA 😀
I do have a remark related to the code you previously presented.
When publishing some code for the consumption of others I do suggest is best to accompany your code with the relevant comments and remarks about what you are attempting to illustrate or the code could easily be confusing.
The you code you showed to check that a function runs one could easily mislead. In achieving this in the way you illustrate you are of course relying on what may be considered a bit of a python 'gotcha' where a functions default arguments are evaluated at the time the function definition is read, and not when the function is actually called. Thus you would get a different outcome should you have created the list in the body of the function code instead of in the function parameters. Maybe this sort of 'runs once check' would be better illustrated by using closures or maybe a global list (or maybe a global dictionary).
Ok, that was just my opinion of course, and you may disagree, but without comments to accompany the code you present, anyone not too familiar with python could get mislead (and of course, as previously said, this check should not really be needed).
I will see if I can clean up the posts and code. I should put comments in the code. It would make it easier when I go back to it. I could move the wifi outside the loop to run once.
It has been a while since I worked with Python on my Rpi 4B. I have been reviewing the best practices for micropython and python.
The code runs 7 seconds with the 3 second pause. The RTC results show this. This is a work in progress.