# Project#9 - The DS3231 Real Time Clock # Connections: No additional connections need to be made if you're coming here directly from project#8 # In this project, we're going to learn how to write and read from the RTC. This one is a little complicated, as there was no # import readily available for the RTC. That meant that I needed to write some code from scratch to deal with the RTC. # I am sure that programmers that are more talented than me could easily simplifiy this code. I'm relatively new to microPython, myself =) import machine # Think of "import" as importing a library. This library allows for us to use GPIOs import utime # This "library" allows for us to tell time if connected to the internet, and use delays like 'utime.sleep(1)' #The below declarations are new since project#8 sda=machine.Pin(0) # Setup GPIO pin 0 as the I2C Data line scl=machine.Pin(1) # Setup GPIO pin 1 as the I2C Clock line bytes = 0 # We're going to use this variable to change I2C read variables from HEX to BINARY val = 0 # This variable will also be used for RTC conversion i2c = machine.I2C(0,scl=scl, sda=sda, freq = 400000) # This line sets up I2C communications. cs = machine.Pin(5, machine.Pin.OUT) #Setup the CS (Chip select pin for the audio chip. GPIO5. Set as output. cs.value(1) # Set the CS line to 1 (HIGH/3.3v) # HeartSensor = machine.ADC(28) # The heart sensor connect internally to GPIO#28 which is an ADC pin. ASTOP = machine.Pin(6, machine.Pin.IN) #Setup the ASTOP (AUDIO STOP) pint o GPIO 6. Set it as an input. cs = machine.Pin(5, machine.Pin.OUT) #Setup the CS (Chip select pin for the audio chip. GPIO5. Set as output. cs.value(1) # Set the CS line to 1 (HIGH/3.3v) spi_sck=machine.Pin(2) # Set SPI clock to GPIO pin 2 spi_tx=machine.Pin(3) # Set SPI MASTER OUT to GPIO pin 3 spi_rx=machine.Pin(4) # Set SPI MASTER IN to GPIO pin 4 spi=machine.SPI(0,baudrate=500000,sck=spi_sck,mosi=spi_tx, phase=1, polarity=0) # Setup SPI communications settings utime.sleep(1) # Sleep/Wait for one second hold = '\x00' # 'hold' acts as the pointer for the little buddy talker chip. Load the HEX value of the audio bite that you want to play, then call the playaudio() function. # LightSensor = machine.ADC(26) # Setup GPIO26 to act as the ADC input for the light sensor. Buzzer = machine.Pin(22, machine.Pin.OUT) #Setup the Buzzer, which is connected to GPIO 22. Declare it as an output. Microphone = machine.ADC(27) # Setup GPIO27 to act as the ADC input for the microphone. This is the AD1 line Button = machine.Pin(15, machine.Pin.IN) #Setup the SEL1 button pin to GPIO 15. Set it as an input and name it "Button" Button2 = machine.Pin(14, machine.Pin.IN) #Setup the SEL2 button pin to GPIO 14. Set it as an input and name it "Button2" DIPA = machine.Pin(21, machine.Pin.IN) #Setup DIP Switch Channel-A as an output DIPB = machine.Pin(20, machine.Pin.IN) #Setup DIP Switch Channel-B as an output DIPC = machine.Pin(19, machine.Pin.IN) #Setup DIP Switch Channel-C as an output DIPD = machine.Pin(18, machine.Pin.IN) #Setup DIP Switch Channel-D as an output LEDRED = machine.Pin(16, machine.Pin.OUT) # Set up GPIO16 as an output, and name it LEDRED LEDBLU = machine.Pin(17, machine.Pin.OUT) # Do the same for GPIO17 LEDRED.value(0) # Turn the red LED off. If you set it to (1), then you'd be turning it on LEDBLU.value(0) # Turn the blue LED off. If you set it to (1), then you'd be turning it on state = 0 # state is a variable/storage register. Set it to a value of 0. hold = 0 # hold is another variable that we'll use to store data in hearthold = 0 counter = 0 conversion = 3.3/(65535) # Conversion helps us to turn ADC readings (Numeral values) into a voltage representation. # 3.3v is the full scale voltage. 0-65565 is the full 16-bit scale value used for ADC conversions. 0000000000000000-1111111111111111 ####################################################The following section is all for the RTC def print_date(): # This function has a lot going on, so try to stay with me here. The goal is to read the RTC, and print the date to the shell global address # Set the address variable/integer as a global so that it can be used across all functions address = 0 # Set address to 0 so that when the below function is called, there is a pointer. It will make sense when you see the function. secs = read_i2c() # Call this function to read back the "seconds" value in the RTC and place the value in "secs" to be used later address = 1 # Set address to 1 mins = read_i2c() # Now call the same read_i2c() function again with the address pointer set to 1. Place the result in "mins" address = 2 # Set the address pointer to 2 hours = return_hours_or_months() # For hours, we'll call a different function. This is because the hours and months registers are formtted... # differently than the seconds and minutes registers address = 3 # Set the address pointer to 3 day = read_i2c() # Call the read_i2c() function again and place the result in "day" if day == 1: # This fullowing section changes the value in "day" into a word. day = "Monday" # If day equals 1, then change day into "monday". The rest of this section shoud be self explanitory. elif day == 2: day = "Tuesday" elif day == 3: day = "Wednesday" elif day == 4: day = "Thursday" elif day == 5: day = "Friday" elif day == 6: day = "Saturday" else: # If day equals anything over than 6, then change day to "Sunday" day = "Sunday" address = 4 # Set the address pointer to 4. date = read_i2c() # Call the read_i2c function and place the result in "date" address = 5 # Set the address pointer to 5 month = return_hours_or_months() # Call this function and place the result in "month" if month == 1: # Look familiar? This is another decoder section that changes the value in month into a word. month = "January" elif month == 2: month = "February" elif month == 3: month = "March" elif month == 4: month = "April" elif month == 5: month = "May" elif month == 6: month = "June" elif month == 7: month = "July" elif month == 8: month = "August" elif month == 9: month = "September" elif month == 10: month = "October" elif month == 11: month = "November" else: month = "December" address = 6 # Set the address pointer to 6 year = read_i2c() # Call the read_i2c() function and place the result in year. year+=2000 # Add 2000 to the result. For 2021, the result would only be 21. print(day,"//",month,date,"//",day,"//","Time: ",hours,":",mins,":",secs, " // Year:",year) # Print the date to the shell! # This is the end of this function def new_time(): #My current time is Monday June 14th, 9:10.00 AM. This code writes your time to the RTC. Make changes as needed. i2c.writeto_mem(104, 0, b'\x00') # seconds // 0-60 seconds // Set to 0 seconds i2c.writeto_mem(104, 1, b'\x10') # minutes // minutes = 0-59 // Set to 10 minutes i2c.writeto_mem(104, 2, b'\x09') # hours // hours = 0-23 i2c.writeto_mem(104, 3, b'\x01') # day // 7th day (Sunday) i2c.writeto_mem(104, 4, b'\x14') # date // Month days (0-31) i2c.writeto_mem(104, 5, b'\x06') # month // Months 0-11 i2c.writeto_mem(104, 6, b'\x21') # year // 2021 def bytes_to_int(bytes): result = 0 for b in bytes: result = result + int(b) #print(result) return result def read_i2c(): # This function reads the RTC for time data, and changes it from a byte into a useable integer. #print(i2c.scan()) # This scans and prints out any I2C addresses on the line bytes = i2c.readfrom_mem(104,address,1)# The RTC address is 104. The data address is pointed to by "address" and we want to read "1" byte #utime.sleep(1)# sleep for one second x = bytes_to_int(bytes) # Call the butes_to_int function to turn the read-back value from a byte into an int, and return into x b = [] # Create a new and empty list (b) counter = 0 while(x>0): # while the value in x is more greater than 0 counter+=1 # we'll use this to see how many bits there are in b d=x%2 # Add 2 to x? b.append(d) # add d to the end of the list (b) x=x//2 # b.reverse() # #print("Binary Equivalent is: ") # The following section changes the returned byte into an integer. It was huge pain to get working! #print(b) #print(counter) val = 0 if counter > 0: if b[-1] == 1: val = val + 1 if counter > 1: if b[-2] == 1: val = val + 2 if counter > 2: if b[-3] == 1: val = val + 4 if counter > 3: if b[-4] == 1: val = val + 8 if counter > 4: if b[-5] == 1: val = val + 10 if counter > 5: if b[-6] == 1: val = val + 20 if counter > 6: if b[-7] == 1: val = val + 40 #print(val) return(val) def return_hours_or_months(): #print(i2c.scan()) # This scans and prints out any I2C addresses on the line bytes = i2c.readfrom_mem(104,address,1) # Tell RTC (104) to read back '1' byte of data from data address pointed to by the "address' pointer #utime.sleep(1) # sleep for one second x = bytes_to_int(bytes) # Call the butes_to_int function to turn the read-back value from a byte into an int, and return into x b = [] # Create a new and empty list (b) counter = 0 while(x>0): # while the value in x is more greater than 0 counter+=1 # we'll use this to see how many bits there are in b d=x%2 # Add 2 to x? b.append(d) # add d to the end of the list (b) x=x//2 # b.reverse() # #print("Binary Equivalent is: ") #print(b) #print(counter) # The following section changes the returned byte into an integer. val = 0 if counter > 0: if b[-1] == 1: val = val + 1 if counter > 1: if b[-2] == 1: val = val + 2 if counter > 2: if b[-3] == 1: val = val + 4 if counter > 3: if b[-4] == 1: val = val + 8 if counter > 4: if b[-5] == 1: val = val + 10 #print(val) return(val) ############################################################################################### This is the end of the RTC functions # This is the main code. new_time() # This function is only called once, as the following loop is set to loop forever. # Commenting out the new_tine() function will stop the TRC from being reprogrammed on power up. # So program it once, then comment new.time() time out, and the new time will be saved even after power off. while True: # Loop the following forever print_date() # This function does a ton of work. It reads all of the RTC timing registers, and prints them to the shell utime.sleep(5) # Wait five seconds, then loop again. # This is the end of the program