├── .gitignore ├── blink └── main.py ├── GPIO ├── blink │ └── main.py ├── pulse │ └── main.py ├── morse_code │ └── main.py └── morse_text │ └── main.py ├── neopixel ├── looplicht │ └── main.py ├── looplicht_kleur │ └── main.py ├── demo │ └── main.py └── README.md ├── input └── demo │ └── main.py ├── servo ├── demo │ └── main.py └── wave │ └── main.py ├── max7219 ├── main.py └── max7219.py ├── analog ├── demo │ └── main.py ├── omgekeerd │ └── main.py └── pulse │ └── main.py ├── sr04 ├── demo │ └── main.py └── led_indicator │ └── main.py ├── binair ├── walk │ └── main.py └── kitt │ └── main.py ├── lcd16x2 └── demo │ ├── main.py │ ├── pico_i2c_lcd.py │ └── lcd_api.py ├── rc522 ├── read │ ├── main.py │ └── rc522.py └── write │ ├── write.py │ └── rc522.py ├── serial ├── pico │ └── main.py └── PC-serial │ └── main.py ├── opdracht2 ├── pub.py └── sub.py ├── max7219_32x8 ├── main.py └── max7219.py └── lcd └── demo ├── main.py └── RGB1602.py /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .idea 3 | .git 4 | .micropico 5 | .DS_Store 6 | 7 | -------------------------------------------------------------------------------- /blink/main.py: -------------------------------------------------------------------------------- 1 | import machine 2 | import utime 3 | 4 | led = machine.Pin("LED", machine.Pin.OUT) 5 | 6 | while True: 7 | led.toggle() # Toggle the LED state 8 | utime.sleep(1) # Wait for 1 second 9 | -------------------------------------------------------------------------------- /GPIO/blink/main.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | import time 3 | 4 | gpio_pin = Pin(20, Pin.OUT) 5 | 6 | while True: 7 | gpio_pin.value(1) 8 | time.sleep(0.5) 9 | gpio_pin.value(0) 10 | time.sleep(0.5) 11 | -------------------------------------------------------------------------------- /neopixel/looplicht/main.py: -------------------------------------------------------------------------------- 1 | # NeoPixel looplicht 2 | from machine import Pin 3 | from time import sleep_ms 4 | from neopixel import NeoPixel 5 | 6 | np = NeoPixel(Pin(13), 8) 7 | 8 | while True: 9 | sleep_ms(1000) 10 | -------------------------------------------------------------------------------- /neopixel/looplicht_kleur/main.py: -------------------------------------------------------------------------------- 1 | # NeoPixel looplicht_kleur 2 | from machine import Pin 3 | from time import sleep_ms 4 | from neopixel import NeoPixel 5 | 6 | np = NeoPixel(Pin(13), 8) 7 | 8 | while True: 9 | sleep_ms(1000) 10 | -------------------------------------------------------------------------------- /input/demo/main.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | import time 3 | 4 | led_pin = Pin(20, Pin.OUT) 5 | switch_pin = Pin(19, Pin.IN, pull=Pin.PULL_DOWN) 6 | 7 | while True: 8 | if switch_pin.value(): 9 | led_pin.value(1) 10 | else: 11 | led_pin.value(0) 12 | time.sleep(0.1) 13 | -------------------------------------------------------------------------------- /servo/demo/main.py: -------------------------------------------------------------------------------- 1 | from machine import Pin, PWM 2 | from time import sleep 3 | 4 | pwm = PWM(Pin(21)) 5 | 6 | pwm.freq(50) 7 | 8 | while True: 9 | for duty in range(1000, 9000, 50): 10 | pwm.duty_u16(duty) 11 | sleep(0.01) 12 | for duty in range(9000, 1000, -50): 13 | pwm.duty_u16(duty) 14 | sleep(0.01) 15 | -------------------------------------------------------------------------------- /max7219/main.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from machine import SPI, Pin 4 | 5 | from max7219 import Max7219 6 | 7 | spi = SPI(1, baudrate=10000000, sck=Pin(10), mosi=Pin(11)) 8 | screen = Max7219(8, 8, spi, Pin(13)) 9 | 10 | while True: 11 | for x in range(48, 122): 12 | screen.fill(0) 13 | screen.text(chr(x), 0, 0, 1) 14 | screen.show() 15 | time.sleep(1) 16 | -------------------------------------------------------------------------------- /GPIO/pulse/main.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | import time 3 | 4 | gpio_pin = Pin(20, Pin.OUT) 5 | 6 | 7 | def pulse(pin, high_time, low_time): 8 | """ 9 | Geef een puls op de pin: 10 | Maak de pin pin_nr hoog, wacht high_time, 11 | maak de pin laag, en wacht nog low_time 12 | """ 13 | 14 | # implementeer deze functie 15 | 16 | 17 | while True: 18 | pulse(gpio_pin, 0.2, 0.2) 19 | -------------------------------------------------------------------------------- /analog/demo/main.py: -------------------------------------------------------------------------------- 1 | from machine import ADC, PWM, Pin 2 | import time 3 | 4 | led = PWM(Pin(20)) 5 | led.freq(1000) 6 | 7 | adc = ADC(Pin(26)) 8 | 9 | 10 | def led_brightness(value): 11 | """ 12 | Zet de led intensiteit. 13 | Waarde tussen de 0 en 65535 14 | """ 15 | 16 | led.duty_u16(value) 17 | 18 | 19 | while True: 20 | adc_value = adc.read_u16() 21 | led_brightness(adc_value) 22 | time.sleep(0.01) 23 | 24 | -------------------------------------------------------------------------------- /analog/omgekeerd/main.py: -------------------------------------------------------------------------------- 1 | from machine import ADC, PWM, Pin 2 | import time 3 | 4 | led = PWM(Pin(20)) 5 | led.freq(1000) 6 | 7 | adc = ADC(Pin(26)) 8 | 9 | 10 | def led_brightness(value): 11 | """ 12 | Zet de led intensiteit. 13 | Waarde tussen de 0 en 65535 14 | """ 15 | 16 | led.duty_u16(value) 17 | 18 | 19 | while True: 20 | adc_value = adc.read_u16() 21 | led_brightness(adc_value) 22 | time.sleep(0.01) 23 | 24 | -------------------------------------------------------------------------------- /analog/pulse/main.py: -------------------------------------------------------------------------------- 1 | from machine import ADC, PWM, Pin 2 | import time 3 | 4 | led = Pin(20, Pin.OUT) 5 | adc = ADC(Pin(26)) 6 | 7 | 8 | def pulse(pin, high_time, low_time): 9 | """ 10 | Geef een puls op de pin: 11 | Maak de pin pin_nr hoog, wacht high_time, 12 | maak de pin laag, en wacht nog low_time 13 | """ 14 | 15 | # implementeer deze functie 16 | 17 | 18 | while True: 19 | adc_value = adc.read_u16() 20 | time.sleep(0.01) 21 | -------------------------------------------------------------------------------- /sr04/demo/main.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | import time 3 | 4 | led_pin = Pin(0, Pin.OUT) 5 | 6 | trigger_pin = Pin(14, Pin.OUT) 7 | echo_pin = Pin(15, Pin.IN) 8 | 9 | while True: 10 | trigger_pin.value(1) 11 | time.sleep_us(10) 12 | trigger_pin.value(0) 13 | 14 | for i in range(0, 100): 15 | if echo_pin.value(): 16 | led_pin.value(1) 17 | time.sleep_ms(1000) 18 | break 19 | time.sleep_ms(1) 20 | 21 | led_pin.value(0) 22 | -------------------------------------------------------------------------------- /binair/walk/main.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | import time 3 | 4 | led_pins = [ 5 | Pin(0, Pin.OUT), 6 | Pin(1, Pin.OUT), 7 | Pin(2, Pin.OUT), 8 | Pin(3, Pin.OUT), 9 | Pin(4, Pin.OUT) 10 | ] 11 | 12 | 13 | def leds(value, delay): 14 | for led in led_pins: 15 | if value % 2 == 1: 16 | led.value(1) 17 | else: 18 | led.value(0) 19 | value = value // 2 20 | time.sleep(delay) 21 | 22 | 23 | delay = 0.2 24 | while True: 25 | leds(1, delay) 26 | leds(2, delay) 27 | leds(4, delay) 28 | leds(8, delay) 29 | leds(16, delay) 30 | -------------------------------------------------------------------------------- /binair/kitt/main.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | import time 3 | 4 | led_pins = [ 5 | Pin(0, Pin.OUT), 6 | Pin(1, Pin.OUT), 7 | Pin(2, Pin.OUT), 8 | Pin(3, Pin.OUT), 9 | Pin(4, Pin.OUT) 10 | ] 11 | 12 | 13 | def leds(value, delay_time): 14 | for led_pin in led_pins: 15 | if value % 2 == 1: 16 | led_pin.on() 17 | else: 18 | led_pin.off() 19 | value = value // 2 20 | time.sleep(delay_time) 21 | 22 | 23 | delay = 0.1 24 | while True: 25 | leds(1, delay) 26 | leds(2, delay) 27 | leds(4, delay) 28 | leds(8, delay) 29 | leds(16, delay) 30 | -------------------------------------------------------------------------------- /neopixel/demo/main.py: -------------------------------------------------------------------------------- 1 | # v1oict-examples: NeoPixel demo/test code 2 | from machine import Pin 3 | from time import sleep_ms 4 | from neopixel import NeoPixel 5 | 6 | NEOPIX_PIN = Pin(13) 7 | NEOPIX_LEN = 8 8 | 9 | # High Density Neopixel E497587 heeft nog een parameter nodig: 10 | np = NeoPixel(NEOPIX_PIN, NEOPIX_LEN, timing=(350, 700, 800, 600)) 11 | # WS2812B-8 werkt ook met de MicroPython standaard: 12 | # np = NeoPixel(NEOPIX_PIN, NEOPIX_LEN) 13 | 14 | while True: 15 | np[0] = [255, 0, 0] 16 | np[1] = [0, 255, 0] 17 | np[2] = [0, 0, 255] 18 | np.write() 19 | sleep_ms(1000) 20 | np[0] = [20, 0, 0] 21 | np[1] = [0, 20, 0] 22 | np[2] = [0, 0, 20] 23 | np.write() 24 | sleep_ms(1000) 25 | -------------------------------------------------------------------------------- /servo/wave/main.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | import time 3 | 4 | servo_pin = Pin(21, Pin.OUT) 5 | 6 | 7 | def pulse(delay1, delay2 ): 8 | """ kopier hier je implementatie van de pulse functie """ 9 | 10 | 11 | def servo_pulse(position): 12 | """ 13 | Send a servo pulse on the specified gpio pin 14 | that causes the servo to turn to the specified position, and 15 | then waits 20 ms. 16 | 17 | The position must be in the range 0 .. 100. 18 | For this range, the pulse must be in the range 0.5 ms .. 2.5 ms 19 | 20 | Before this function is called, 21 | the gpio pin must be configured as output. 22 | """ 23 | 24 | while True: 25 | for i in range(0, 100, 1): 26 | servo_pulse(i) 27 | for i in range(100, 0, -1): 28 | servo_pulse(i) 29 | -------------------------------------------------------------------------------- /GPIO/morse_code/main.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | import time 3 | 4 | gpio_pin = Pin(20, Pin.OUT) 5 | 6 | 7 | def pulse(pin, high_time, low_time): 8 | """ 9 | Geef een puls op de pin: 10 | Maak de pin pin hoog, wacht high_time, 11 | maak de pin laag, en wacht nog low_time 12 | """ 13 | 14 | # Kopier hier je implementatie van pulse 15 | 16 | 17 | def morse(pin, dot_length, text): 18 | """ 19 | Laat de text horen als morse code. 20 | De pin is de pin die gebruikt wordt. 21 | De text mag de volgende characters bevatten: spatie, streepje, punt. 22 | De dot_length is de lengte van een punt (dot). 23 | De lengte van de andere characters wordt daar van afgeleid. 24 | """ 25 | 26 | # implementeer deze functie 27 | 28 | 29 | morse(gpio_pin, 0.2, ".--. -.-- - .... --- -.") 30 | -------------------------------------------------------------------------------- /sr04/led_indicator/main.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | import time 3 | 4 | led_pins = [ 5 | Pin(0, Pin.OUT), 6 | Pin(1, Pin.OUT), 7 | Pin(2, Pin.OUT), 8 | Pin(3, Pin.OUT), 9 | Pin(4, Pin.OUT) 10 | ] 11 | 12 | trigger_pin = Pin(14, Pin.OUT) 13 | echo_pin = Pin(15, Pin.IN) 14 | 15 | 16 | def measure_distance(): 17 | """ 18 | Meet de afstand met de SR04 19 | """ 20 | 21 | # implementeer deze functie 22 | 23 | return 0 24 | 25 | 26 | def display_distance(distance): 27 | """ 28 | Laat de afstand d.m.v. de leds zien. 29 | 1 led = 10 cm 30 | 2 leds = 15 cm 31 | 3 leds = 20 cm 32 | 4 leds = 25 cm 33 | 5 leds = 30 cm 34 | """ 35 | 36 | while True: 37 | distance = measure_distance() 38 | display_distance(distance) 39 | time.sleep_ms(100) 40 | -------------------------------------------------------------------------------- /lcd16x2/demo/main.py: -------------------------------------------------------------------------------- 1 | from machine import I2C, Pin 2 | from pico_i2c_lcd import I2cLcd 3 | 4 | """ 5 | From the 1602A LCD Datasheet. The I2C 1602 LCD module is a 2 line by 16 character display interfaced to an I2C daughter board. 6 | Specifications: 2 lines by 16 characters 7 | I2C Address Range: 0x20 to 0x27 (Default=0x27, addressable) 8 | Operating Voltage: 5 Vdc 9 | Contrast: Adjustable by potentiometer on I2C interface 10 | Size: 80mm x 36mm x 20 mm 11 | Viewable area: 66mm x 16mm 12 | 13 | Drivers provided by https://www.circuitschools.com/ 14 | Note: Adjust the potentiometer when you do not see any characters on the display 15 | """ 16 | 17 | i2c = I2C(0, sda=Pin(8), scl=Pin(9), freq=400000) 18 | 19 | I2C_ADDR = i2c.scan()[0] 20 | lcd = I2cLcd(i2c, I2C_ADDR, 2, 16) 21 | while True: 22 | print(I2C_ADDR, "| Hex:", hex(I2C_ADDR)) 23 | lcd.move_to(0, 0) 24 | lcd.putstr("I2CAddress:" + hex(I2C_ADDR) + "\n") 25 | lcd.move_to(0, 1) 26 | lcd.putstr("LCD 16x2 demo.") -------------------------------------------------------------------------------- /rc522/read/main.py: -------------------------------------------------------------------------------- 1 | from rc522 import MFRC522 2 | from os import uname 3 | import time 4 | 5 | reader = MFRC522(sck=10, mosi=11, miso=12, rst=14, cs=15, spi_id=1) 6 | 7 | print("") 8 | print("Please place card on reader") 9 | print("") 10 | 11 | try: 12 | while True: 13 | 14 | reader.init() 15 | (stat, tag_type) = reader.request(reader.REQIDL) 16 | if stat == reader.OK: 17 | (stat, uid) = reader.SelectTagSN() 18 | if stat == reader.OK: 19 | print("Card detected {} uid={}".format(hex(int.from_bytes(bytes(uid), "little", False)).upper(), 20 | reader.tohexstring(uid))) 21 | defaultKey = [255,255,255,255,255,255] 22 | reader.MFRC522_DumpClassic1K(uid, Start=0, End=64, keyA=defaultKey) 23 | print("Done") 24 | else: 25 | pass 26 | time.sleep(1) 27 | 28 | except KeyboardInterrupt: 29 | pass 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /serial/pico/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | """ 5 | Oriëntatie op TI 6 | 7 | Voorbeeld voor communicatie met Raspberry Pi Pico. Flash dit bestand 8 | eerst naar de Raspberry Pi Pico. Start dan in de folder serial/PC-serial `main.py` op je laptop/PC. 9 | 10 | (c) 2022 Hogeschool Utrecht, 11 | Hagen Patzke (hagen.patzke@hu.nl) en 12 | Tijmen Muller (tijmen.muller@hu.nl) 13 | """ 14 | 15 | from machine import Pin 16 | import time 17 | 18 | # Use on-board led 19 | led = Pin("LED", Pin.OUT) 20 | 21 | # Blink led to confirm succesful flashing 22 | for _ in range(5): 23 | led(0) 24 | time.sleep(.1) 25 | led(1) 26 | time.sleep(.1) 27 | 28 | # Wait for data from the connection 29 | while True: 30 | data = input() 31 | 32 | print("Received '" + data + "'.") 33 | if data == '0': 34 | print("Turning led off.") 35 | led(0) 36 | elif data == '1': 37 | print("Turning led on.") 38 | led(1) 39 | else: 40 | print("Unknown command.") 41 | -------------------------------------------------------------------------------- /neopixel/README.md: -------------------------------------------------------------------------------- 1 | # V1OICT examples: NeoPixel 2 | 3 | ## Troubleshooting 4 | 5 | > Ik wil mijn NeoPixel met een kleur laten oplichten, maar hij toont alleen wit! Wat kan ik doen? 6 | 7 | Dit kan een gevolg zijn van onjuist timing in de communicatie tussen PICO en NeoPixel. 8 | 9 | Bijvoorbeeld de "High Density Neopixel E497587" toont dit probleem. 10 | 11 | Gelukkigerwijs kan dit makkelijk worden opgelost. 12 | 13 | Als jij in een programma deze lijn schrijf: 14 | 15 | ```np = NeopPixel(Pin(13), 8)``` 16 | 17 | dan vertaald de [MicroPython NeoPixel library](https://github.com/micropython/micropython-lib/blob/master/micropython/drivers/led/neopixel/neopixel.py) dit intern in een lijn met deze parameters: 18 | 19 | ```np = NeoPixel(Pin(13), 8, bpp=3, timing=(400, 850, 800, 450))``` 20 | 21 | Volgens het [WS2812 datasheet](https://www.alldatasheet.com/datasheet-pdf/download/553088/ETC2/WS2812.html) zijn deze instellingen voor het timing juist: 22 | 23 | ```np = NeoPixel(Pin(13), 8, bpp=3, timing=(350, 700, 800, 600))``` 24 | 25 | De parameter ```bpp=3``` kan je weglaten, dus kan je deze lijn gebruiken: 26 | 27 | ```np = NeoPixel(Pin(13), 8, timing=(350, 700, 800, 600))``` 28 | 29 | -------------------------------------------------------------------------------- /GPIO/morse_text/main.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | import time 3 | 4 | gpio_pin = Pin(20, Pin.OUT) 5 | 6 | 7 | def pulse(pin, high_time, low_time): 8 | """ 9 | Geef een puls op de pin: 10 | Maak de pin pin_nr hoog, wacht high_time, 11 | maak de pin laag, en wacht nog low_time 12 | """ 13 | 14 | # Kopier hier je pulse implementatie 15 | 16 | 17 | def morse(pin, dot_length, text): 18 | """ 19 | Laat de text horen als morse code. 20 | De pin_nr is de pin die gebruikt wordt. 21 | De text mag de volgende characters bevatten: spatie, streepje, punt. 22 | De dot_length is de lengte van een punt (dot). 23 | De lengte van de andere characters wordt daar van afgeleid. 24 | """ 25 | 26 | # Kopier hier je morse implementatie 27 | 28 | 29 | def morse_text(pin, dot_length, text): 30 | """ 31 | Laat de string s horen als morse code. 32 | De pin_nr is de pin die gebruikt wordt. 33 | De text mag de volgende characters bevatten: lowercase letters, spatie. 34 | De dot_length is de lengte van een punt (dot). 35 | De lengte van de andere characters wordt daar van afgeleid. 36 | """ 37 | 38 | # implementeer deze functie 39 | 40 | 41 | morse_text(gpio_pin, 0.2, "Hello world") 42 | -------------------------------------------------------------------------------- /rc522/write/write.py: -------------------------------------------------------------------------------- 1 | from rc522 import MFRC522 2 | 3 | ''' 4 | BE AWARE that sectors(3,7,11,15,...,63) are access block. 5 | if you want to change (sector % 4) == 3 you should 6 | know how keys and permission work! 7 | ''' 8 | 9 | 10 | 11 | def uidToString(uid): 12 | mystring = "" 13 | for i in uid: 14 | mystring = "%02X" % i + mystring 15 | return mystring 16 | 17 | reader = MFRC522(sck=10, mosi=11, miso=12, rst=14, cs=15, spi_id=1) 18 | 19 | print("") 20 | print("Please place card on reader") 21 | print("") 22 | 23 | key = [0xFF,0xFF,0xFF,0xFF,0xFF,0xFF] 24 | 25 | try: 26 | while True: 27 | 28 | (stat, tag_type) = reader.request(reader.REQIDL) 29 | 30 | if stat == reader.OK: 31 | (stat, uid) = reader.SelectTagSN() 32 | if stat == reader.OK: 33 | print(uid) 34 | print("Card detected %s" % uidToString(uid)) 35 | print("Test ! writing sector 2, block 0 (absolute block(8)") 36 | print("with TEST1234567890ABC") 37 | absoluteBlock=1 38 | value=[ord(x) for x in "TEST1234567890ABC"] 39 | status = reader.auth(reader.AUTHENT1A, absoluteBlock, key, uid) 40 | if status == reader.OK: 41 | status = reader.write(absoluteBlock,value) 42 | if status == reader.OK: 43 | reader.MFRC522_DumpClassic1K(uid,keyA=key) 44 | else: 45 | print("unable to write") 46 | else: 47 | print("Authentication error for writing") 48 | break 49 | except KeyboardInterrupt: 50 | print("Bye") 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /serial/PC-serial/main.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | """ 4 | Oriëntatie op TI 5 | 6 | Voorbeeld voor communicatie met Raspberry Pi Pico. Flash `main.py` in de folder serial/pico/ 7 | naar de Raspberry Pi Pico en start dit bestand op je laptop/PC. 8 | 9 | (c) 2022 Hogeschool Utrecht, 10 | Hagen Patzke (hagen.patzke@hu.nl) en 11 | Tijmen Muller (tijmen.muller@hu.nl) 12 | """ 13 | 14 | from serial.tools import list_ports 15 | import serial 16 | 17 | 18 | def read_serial(port): 19 | """Read data from serial port and return as string.""" 20 | line = port.read(1000) 21 | return line.decode() 22 | 23 | 24 | # First manually select the serial port that connects to the Pico 25 | serial_ports = list_ports.comports() 26 | 27 | print("[INFO] Serial ports found:") 28 | for i, port in enumerate(serial_ports): 29 | print(str(i) + ". " + str(port.device)) 30 | 31 | pico_port_index = int(input("Which port is the Raspberry Pi Pico connected to? ")) 32 | pico_port = serial_ports[pico_port_index].device 33 | 34 | # Open a connection to the Pico 35 | with serial.Serial(port=pico_port, baudrate=115200, bytesize=8, parity='N', stopbits=1, timeout=1) as serial_port: 36 | if serial_port.isOpen(): 37 | print("[INFO] Using serial port", serial_port.name) 38 | else: 39 | print("[INFO] Opening serial port", serial_port.name, "...") 40 | serial_port.open() 41 | 42 | try: 43 | # Request user input 44 | commands = ['off', 'on', 'exit'] 45 | while True: 46 | choice = input("Command? [" + ", ".join(commands) + "] ") 47 | 48 | if choice == 'off': 49 | # Turn led off by sending a '0' 50 | data = "0\r" 51 | serial_port.write(data.encode()) 52 | pico_output = read_serial(serial_port) 53 | pico_output = pico_output.replace('\r\n', ' ') 54 | print("[PICO] " + pico_output) 55 | elif choice == 'on': 56 | # Turn led on by sending a '1' 57 | data = "1\r" 58 | serial_port.write(data.encode()) 59 | pico_output = read_serial(serial_port) 60 | pico_output = pico_output.replace('\r\n', ' ') 61 | print("[PICO] " + pico_output) 62 | elif choice == 'exit': 63 | # Exit user input loop 64 | break 65 | else: 66 | print("[WARN] Unknown command.") 67 | 68 | except KeyboardInterrupt: 69 | print("[INFO] Ctrl+C detected. Terminating.") 70 | finally: 71 | # Close connection to Pico 72 | serial_port.close() 73 | print("[INFO] Serial port closed. Bye.") -------------------------------------------------------------------------------- /opdracht2/pub.py: -------------------------------------------------------------------------------- 1 | import network 2 | import time 3 | import ubinascii 4 | from umqtt.simple import MQTTClient 5 | import machine 6 | import dht 7 | 8 | # Wi-Fi Configuration, add your Wi-Fi SSID and password here 9 | SSID = '' 10 | PASSWORD = '' 11 | 12 | 13 | # MQTT Configuration, add your MQTT broker address and port here 14 | MQTT_BROKER = 'broker.hivemq.com' 15 | MQTT_PORT = 1883 16 | CLIENT_ID = ubinascii.hexlify(machine.unique_id()) 17 | # Add your unique MQTT topic for temperature here (your name + your date of birth + 'TEMP') 18 | TOPIC_TEMP = '' # 19 | # Add your unique MQTT topic for humidity here (your name + your date of birth + 'HUMID') 20 | TOPIC_HUMIDITY = '' 21 | 22 | # Set up DHT11 sensor 23 | dht_sensor = dht.DHT11(machine.Pin(21)) # Assuming DHT11 is connected to GPIO 21 24 | 25 | # Function to connect to Wi-Fi 26 | def connect_wifi(): 27 | wlan = network.WLAN(network.STA_IF) 28 | wlan.active(True) 29 | wlan.disconnect() # Disconnect in case it's already connected 30 | wlan.connect(SSID, PASSWORD) 31 | 32 | max_retries = 20 33 | retries = 0 34 | 35 | while not wlan.isconnected() and retries < max_retries: 36 | retries += 1 37 | time.sleep(1) 38 | print(f"Connecting to Wi-Fi... Retry {retries}/{max_retries}") 39 | 40 | if wlan.isconnected(): 41 | # extract from the returnvalue of the wlan.ifconfig() method the IP-address 42 | ip = 43 | print('Connected to Wi-Fi:', ip) 44 | return True 45 | else: 46 | print('Failed to connect to Wi-Fi') 47 | return False 48 | 49 | # Try to connect to Wi-Fi 50 | if not connect_wifi(): 51 | # If failed to connect, halt the program 52 | while True: 53 | time.sleep(1) 54 | 55 | # MQTT message callback (not used in publisher) 56 | def mqtt_callback(topic, msg): 57 | pass 58 | 59 | # Connect to MQTT Broker 60 | print("Connecting to MQTT broker...") 61 | client = MQTTClient(CLIENT_ID, MQTT_BROKER, port=MQTT_PORT) 62 | client.set_callback(mqtt_callback) 63 | 64 | try: 65 | client.connect() 66 | print('Connected to MQTT Broker:', MQTT_BROKER) 67 | 68 | # Publish loop 69 | while True: 70 | try: 71 | # Read DHT11 sensor data as float-values 72 | dht_sensor.measure() 73 | temp = dht_sensor.temperature() 74 | humidity = dht_sensor.humidity() 75 | 76 | # Print debug info over serial 77 | print(f"Temperature: {temp}C, Humidity: {humidity}%") 78 | 79 | # Publish encoded data to both MQTT topics with the client.publish() method 80 | # temperature 81 | # humidity 82 | time.sleep(5) # Publish data every 5 seconds (adjust as needed) 83 | 84 | except Exception as e: 85 | print("Error reading DHT11 sensor:", e) 86 | time.sleep(2) 87 | 88 | except Exception as e: 89 | print('Failed to connect to MQTT Broker:', e) 90 | 91 | -------------------------------------------------------------------------------- /max7219_32x8/main.py: -------------------------------------------------------------------------------- 1 | """ 2 | Oriëntatie op TI 3 | 4 | max7219 32x8 LED Matrix demo for Raspberry Pico and Pico W 5 | 6 | (c) 2022 Hogeschool Utrecht, 7 | Hagen Patzke (hagen.patzke@hu.nl) 8 | """ 9 | 10 | from machine import SPI, Pin 11 | from max7219 import Max7219 12 | from time import sleep_ms 13 | 14 | # Hardware-dependent definitions -------------------------------------------- 15 | 16 | # SPI interface 17 | spi_id = 1 18 | spi_sck = Pin(10) 19 | spi_mosi = Pin(11) 20 | spi_cs = Pin(13) 21 | 22 | # LED matrix dimensions 23 | matrix_width = 32 24 | matrix_height = 8 25 | 26 | # Helper functions ---------------------------------------------------------- 27 | 28 | global builtin_led 29 | 30 | 31 | def builtin_led_init(): 32 | """ Init the built-in LED pin. 33 | On the Pico W, the built-in LED is not directly attached to a GPIO pin, 34 | but to the wireless chip. MicroPython encapsulates this with a named Pin "LED". 35 | Older versions of MicroPython don't know this, so we fall back to pin 25. 36 | """ 37 | global builtin_led 38 | try: 39 | builtin_led = Pin("LED", Pin.OUT) 40 | except TypeError: 41 | builtin_led = Pin(25, Pin.OUT) 42 | 43 | 44 | def builtin_led_blink(): 45 | """ Flash the built-in LED for 200ms, then pause for 200ms. """ 46 | global builtin_led 47 | builtin_led.value(1) 48 | sleep_ms(400) 49 | builtin_led.value(0) 50 | sleep_ms(400) 51 | 52 | 53 | # main program -------------------------------------------------------------- 54 | 55 | """ 56 | Make sure the hardware is reset _after_ we have stable power. 57 | For this, we blink the built-in LED three times between init steps. 58 | This adds a delay that gives the power source time to get up to the necessary voltage. 59 | The Pico will be fine from 1.8V, but the LED matrix needs a higher voltage to work. 60 | This delay is important if we want to use e.g. a power bank or wall adaptor. 61 | """ 62 | 63 | builtin_led_init() 64 | builtin_led_blink() 65 | # Init SPI port 1 66 | spi = SPI(spi_id, baudrate=10000000, sck=spi_sck, mosi=spi_mosi) 67 | 68 | builtin_led_blink() 69 | # Init Max7219 matrix LED (width=32 if we have four 8x8 modules) 70 | screen = Max7219(matrix_width, matrix_height, spi=spi, cs=spi_cs, rotate_180=False) 71 | 72 | builtin_led_blink() 73 | # It's demo time! 74 | while True: 75 | for b in range(2): 76 | screen.brightness(b * 4) # 4 is already bright, 15 is VERY bright 77 | # Show the characters from 32 to 126 78 | for x in range(32, 127): 79 | s = chr(x) 80 | if x < 100: 81 | s += ' :'[x & 1] # same function as: s += ':' if x & 1 else ' ' 82 | s += str(x) 83 | screen.fill(0) 84 | screen.text(s, 0, 0, 1) 85 | screen.show() 86 | sleep_ms(200) 87 | # Show the brightness levels from 0 to 15 88 | for sb in range(16): 89 | screen.brightness(sb) 90 | screen.fill(0) 91 | screen.text('B' + hex(sb), 0, 0, 1) 92 | screen.show() 93 | sleep_ms(1000) 94 | 95 | # eof -------------------------------------------------------------------------------- /lcd16x2/demo/pico_i2c_lcd.py: -------------------------------------------------------------------------------- 1 | import utime 2 | import gc 3 | 4 | from lcd_api import LcdApi 5 | from machine import I2C 6 | 7 | # PCF8574 pin definitions 8 | MASK_RS = 0x01 # P0 9 | MASK_RW = 0x02 # P1 10 | MASK_E = 0x04 # P2 11 | 12 | SHIFT_BACKLIGHT = 3 # P3 13 | SHIFT_DATA = 4 # P4-P7 14 | 15 | class I2cLcd(LcdApi): 16 | 17 | #Implements a HD44780 character LCD connected via PCF8574 on I2C 18 | 19 | def __init__(self, i2c, i2c_addr, num_lines, num_columns): 20 | self.i2c = i2c 21 | self.i2c_addr = i2c_addr 22 | self.i2c.writeto(self.i2c_addr, bytes([0])) 23 | utime.sleep_ms(20) # Allow LCD time to powerup 24 | # Send reset 3 times 25 | self.hal_write_init_nibble(self.LCD_FUNCTION_RESET) 26 | utime.sleep_ms(5) # Need to delay at least 4.1 msec 27 | self.hal_write_init_nibble(self.LCD_FUNCTION_RESET) 28 | utime.sleep_ms(1) 29 | self.hal_write_init_nibble(self.LCD_FUNCTION_RESET) 30 | utime.sleep_ms(1) 31 | # Put LCD into 4-bit mode 32 | self.hal_write_init_nibble(self.LCD_FUNCTION) 33 | utime.sleep_ms(1) 34 | LcdApi.__init__(self, num_lines, num_columns) 35 | cmd = self.LCD_FUNCTION 36 | if num_lines > 1: 37 | cmd |= self.LCD_FUNCTION_2LINES 38 | self.hal_write_command(cmd) 39 | gc.collect() 40 | 41 | def hal_write_init_nibble(self, nibble): 42 | # Writes an initialization nibble to the LCD. 43 | # This particular function is only used during initialization. 44 | byte = ((nibble >> 4) & 0x0f) << SHIFT_DATA 45 | self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E])) 46 | self.i2c.writeto(self.i2c_addr, bytes([byte])) 47 | gc.collect() 48 | 49 | def hal_backlight_on(self): 50 | # Allows the hal layer to turn the backlight on 51 | self.i2c.writeto(self.i2c_addr, bytes([1 << SHIFT_BACKLIGHT])) 52 | gc.collect() 53 | 54 | def hal_backlight_off(self): 55 | #Allows the hal layer to turn the backlight off 56 | self.i2c.writeto(self.i2c_addr, bytes([0])) 57 | gc.collect() 58 | 59 | def hal_write_command(self, cmd): 60 | # Write a command to the LCD. Data is latched on the falling edge of E. 61 | byte = ((self.backlight << SHIFT_BACKLIGHT) | 62 | (((cmd >> 4) & 0x0f) << SHIFT_DATA)) 63 | self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E])) 64 | self.i2c.writeto(self.i2c_addr, bytes([byte])) 65 | byte = ((self.backlight << SHIFT_BACKLIGHT) | 66 | ((cmd & 0x0f) << SHIFT_DATA)) 67 | self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E])) 68 | self.i2c.writeto(self.i2c_addr, bytes([byte])) 69 | if cmd <= 3: 70 | # The home and clear commands require a worst case delay of 4.1 msec 71 | utime.sleep_ms(5) 72 | gc.collect() 73 | 74 | def hal_write_data(self, data): 75 | # Write data to the LCD. Data is latched on the falling edge of E. 76 | byte = (MASK_RS | 77 | (self.backlight << SHIFT_BACKLIGHT) | 78 | (((data >> 4) & 0x0f) << SHIFT_DATA)) 79 | self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E])) 80 | self.i2c.writeto(self.i2c_addr, bytes([byte])) 81 | byte = (MASK_RS | 82 | (self.backlight << SHIFT_BACKLIGHT) | 83 | ((data & 0x0f) << SHIFT_DATA)) 84 | self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E])) 85 | self.i2c.writeto(self.i2c_addr, bytes([byte])) 86 | gc.collect() 87 | -------------------------------------------------------------------------------- /max7219/max7219.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | from micropython import const 3 | import framebuf 4 | 5 | _DIGIT_0 = const(0x1) 6 | 7 | _DECODE_MODE = const(0x9) 8 | _NO_DECODE = const(0x0) 9 | 10 | _INTENSITY = const(0xA) 11 | _INTENSITY_MIN = const(0x0) 12 | 13 | _SCAN_LIMIT = const(0xB) 14 | _DISPLAY_ALL_DIGITS = const(0x7) 15 | 16 | _SHUTDOWN = const(0xC) 17 | _SHUTDOWN_MODE = const(0x0) 18 | _NORMAL_OPERATION = const(0x1) 19 | 20 | _DISPLAY_TEST = const(0xF) 21 | _DISPLAY_TEST_NORMAL_OPERATION = const(0x0) 22 | 23 | _MATRIX_SIZE = const(8) 24 | 25 | 26 | class Max7219(framebuf.FrameBuffer): 27 | """ 28 | Driver for MAX7219 8x8 LED matrices 29 | 30 | On some matrices, the display is inverted (rotated 180°), in this case 31 | you can use `rotate_180=True` in the class constructor. 32 | """ 33 | 34 | def __init__(self, width, height, spi, cs, rotate_180=False): 35 | # Pins setup 36 | self.spi = spi 37 | self.cs = cs 38 | self.cs.init(Pin.OUT, True) 39 | 40 | # Dimensions 41 | self.width = width 42 | self.height = height 43 | # Guess matrices disposition 44 | self.cols = width // _MATRIX_SIZE 45 | self.rows = height // _MATRIX_SIZE 46 | self.nb_matrices = self.cols * self.rows 47 | self.rotate_180 = rotate_180 48 | 49 | # 1 bit per pixel (on / off) -> 8 bytes per matrix 50 | self.buffer = bytearray(width * height // 8) 51 | format = framebuf.MONO_HLSB if not self.rotate_180 else framebuf.MONO_HMSB 52 | super().__init__(self.buffer, width, height, format) 53 | 54 | # Init display 55 | self.init_display() 56 | 57 | def _write_command(self, command, data): 58 | """Write command on SPI""" 59 | cmd = bytearray([command, data]) 60 | self.cs(0) 61 | for matrix in range(self.nb_matrices): 62 | self.spi.write(cmd) 63 | self.cs(1) 64 | 65 | def init_display(self): 66 | """Init hardware""" 67 | for command, data in ( 68 | (_SHUTDOWN, _SHUTDOWN_MODE), # Prevent flash during init 69 | (_DECODE_MODE, _NO_DECODE), 70 | (_DISPLAY_TEST, _DISPLAY_TEST_NORMAL_OPERATION), 71 | (_INTENSITY, _INTENSITY_MIN), 72 | (_SCAN_LIMIT, _DISPLAY_ALL_DIGITS), 73 | (_SHUTDOWN, _NORMAL_OPERATION), # Let's go 74 | ): 75 | self._write_command(command, data) 76 | 77 | self.fill(0) 78 | self.show() 79 | 80 | def brightness(self, value): 81 | """Set display brightness (0 to 15)""" 82 | if not 0 <= value < 16: 83 | raise ValueError("Brightness must be between 0 and 15") 84 | self._write_command(_INTENSITY, value) 85 | 86 | def show(self): 87 | """Update display""" 88 | # Write line per line on the matrices 89 | for line in range(8): 90 | self.cs(0) 91 | 92 | for matrix in range(self.nb_matrices): 93 | # Guess where the matrix is placed 94 | row, col = divmod(matrix, self.cols) 95 | # Compute where the data starts 96 | if self.rotate_180: 97 | offset = (self.rows - row) * self.cols * 8 - 1 98 | index = offset - self.cols * line - col 99 | else: 100 | offset = row * self.cols * 8 101 | index = offset + self.cols * line + col 102 | # Write data to the matrix display 103 | self.spi.write(bytearray([_DIGIT_0 + line, self.buffer[index]])) 104 | 105 | self.cs(1) 106 | -------------------------------------------------------------------------------- /max7219_32x8/max7219.py: -------------------------------------------------------------------------------- 1 | from machine import Pin 2 | from micropython import const 3 | import framebuf 4 | 5 | _DIGIT_0 = const(0x1) 6 | 7 | _DECODE_MODE = const(0x9) 8 | _NO_DECODE = const(0x0) 9 | 10 | _INTENSITY = const(0xA) 11 | _INTENSITY_MIN = const(0x0) 12 | 13 | _SCAN_LIMIT = const(0xB) 14 | _DISPLAY_ALL_DIGITS = const(0x7) 15 | 16 | _SHUTDOWN = const(0xC) 17 | _SHUTDOWN_MODE = const(0x0) 18 | _NORMAL_OPERATION = const(0x1) 19 | 20 | _DISPLAY_TEST = const(0xF) 21 | _DISPLAY_TEST_NORMAL_OPERATION = const(0x0) 22 | 23 | _MATRIX_SIZE = const(8) 24 | 25 | 26 | class Max7219(framebuf.FrameBuffer): 27 | """ 28 | Driver for MAX7219 8x8 LED matrices 29 | 30 | On some matrices, the display is inverted (rotated 180°), in this case 31 | you can use `rotate_180=True` in the class constructor. 32 | """ 33 | 34 | def __init__(self, width, height, spi, cs, rotate_180=False): 35 | # Pins setup 36 | self.spi = spi 37 | self.cs = cs 38 | self.cs.init(Pin.OUT, True) 39 | 40 | # Dimensions 41 | self.width = width 42 | self.height = height 43 | # Guess matrices disposition 44 | self.cols = width // _MATRIX_SIZE 45 | self.rows = height // _MATRIX_SIZE 46 | self.nb_matrices = self.cols * self.rows 47 | self.rotate_180 = rotate_180 48 | 49 | # 1 bit per pixel (on / off) -> 8 bytes per matrix 50 | self.buffer = bytearray(width * height // 8) 51 | format = framebuf.MONO_HLSB if not self.rotate_180 else framebuf.MONO_HMSB 52 | super().__init__(self.buffer, width, height, format) 53 | 54 | # Init display 55 | self.init_display() 56 | 57 | def _write_command(self, command, data): 58 | """Write command on SPI""" 59 | cmd = bytearray([command, data]) 60 | self.cs(0) 61 | for matrix in range(self.nb_matrices): 62 | self.spi.write(cmd) 63 | self.cs(1) 64 | 65 | def init_display(self): 66 | """Init hardware""" 67 | for command, data in ( 68 | (_SHUTDOWN, _SHUTDOWN_MODE), # Prevent flash during init 69 | (_DECODE_MODE, _NO_DECODE), 70 | (_DISPLAY_TEST, _DISPLAY_TEST_NORMAL_OPERATION), 71 | (_INTENSITY, _INTENSITY_MIN), 72 | (_SCAN_LIMIT, _DISPLAY_ALL_DIGITS), 73 | (_SHUTDOWN, _NORMAL_OPERATION), # Let's go 74 | ): 75 | self._write_command(command, data) 76 | 77 | self.fill(0) 78 | self.show() 79 | 80 | def brightness(self, value): 81 | """Set display brightness (0 to 15)""" 82 | if not 0 <= value < 16: 83 | raise ValueError("Brightness must be between 0 and 15") 84 | self._write_command(_INTENSITY, value) 85 | 86 | def show(self): 87 | """Update display""" 88 | # Write line per line on the matrices 89 | for line in range(8): 90 | self.cs(0) 91 | 92 | for matrix in range(self.nb_matrices): 93 | # Guess where the matrix is placed 94 | row, col = divmod(matrix, self.cols) 95 | # Compute where the data starts 96 | if self.rotate_180: 97 | offset = (self.rows - row) * self.cols * 8 - 1 98 | index = offset - self.cols * line - col 99 | else: 100 | offset = row * self.cols * 8 101 | index = offset + self.cols * line + col 102 | # Write data to the matrix display 103 | self.spi.write(bytearray([_DIGIT_0 + line, self.buffer[index]])) 104 | 105 | self.cs(1) 106 | -------------------------------------------------------------------------------- /lcd/demo/main.py: -------------------------------------------------------------------------------- 1 | import RGB1602 2 | import time 3 | 4 | """ 5 | From the LCD1602 RGB Module datasheet: 6 | Operating voltage: 3.3 ~ 5V, LCD controller: AiP31068 7 | Communication Interface: I2C, RGB driver: PCA9633 8 | Display Panel character LCD, Display size: 64.5 × 16.0mm 9 | Characters: 16 × 2, Dimensions: 87.0 × 32.0 × 13.0mm 10 | Backlight colors: 16M, Operating temperature: -20 ~ +70℃ 11 | """ 12 | 13 | 14 | def define_characters(lcd): 15 | heart = bytearray([0x00, 0x00, 0x1B, 0x1F, 0x1F, 0x0E, 0x04, 0x00]) # '@@[__ND@' 16 | face = bytearray([0x00, 0x00, 0x0A, 0x00, 0x11, 0x0E, 0x00, 0x00]) # '@@J@QN@@' 17 | lcd.command(0x40) # custom char 0 at (0x40 | (0 << 3)) 18 | lcd.printout(heart) 19 | lcd.command(0x48) # custom char 1 at (0x40 | (1 << 3)) 20 | lcd.printout(face) 21 | # Dirty trick: 22 | # Because the 5x7 matrix for display only uses bits 5,4,3,2,1 23 | # we can set bit 6 (0x40) and make the value a character 24 | # ASCII 0x40 = '@', 0x41 = 'A', ... , 0x5F = '_' 25 | lcd.command(0x50) # custom char 2 at (0x40 | (2 << 3)) 26 | lcd.printout('@@[__ND@') # heart, alternative definition 27 | lcd.command(0x58) # custom char 3 at (0x40 | (3 << 3)) 28 | lcd.printout('@@J@QN@@') # face, alternative definition 29 | 30 | 31 | def show_r_g_b(lcd): 32 | lcd.set_rgb(255, 127, 127) 33 | time.sleep(1) 34 | lcd.set_rgb(127, 255, 127) 35 | time.sleep(1) 36 | lcd.set_rgb(127, 127, 255) 37 | time.sleep(1) 38 | lcd.set_rgb(255, 0, 0) 39 | time.sleep(1) 40 | lcd.set_rgb(0, 255, 0) 41 | time.sleep(1) 42 | lcd.set_rgb(0, 0, 255) 43 | time.sleep(1) 44 | 45 | 46 | def discoloration(lcd): 47 | """ 48 | Soft color change. 49 | 50 | Source: https://www.waveshare.com/wiki/Raspberry_Pi_Pico#LCD1602_I2C_Example 51 | """ 52 | from math import pi, sin 53 | deg2rad = pi / 180 54 | t = 0 55 | while t < 360: 56 | r = int((abs(sin(deg2rad * t))) * 255) 57 | g = int((abs(sin(deg2rad * (t + 60)))) * 255) 58 | b = int((abs(sin(deg2rad * (t + 120)))) * 255) 59 | lcd.set_rgb(r, g, b) 60 | t = t + 3 61 | time.sleep(0.1) 62 | 63 | 64 | def animated_banner(lcd): 65 | # First line 66 | target_pos = 1 67 | for char in "Welkom student": 68 | for ani in range(16, target_pos - 1, -1): 69 | lcd.at(ani, 0).printout(char) 70 | if (ani < 15): 71 | lcd.at(ani + 1, 0).printout(' ') 72 | time.sleep(0.1) 73 | target_pos += 1 74 | # Second line 75 | lcd.at(2, 1) 76 | for char in "HBO-ICT 2022": 77 | lcd.printout(char) 78 | time.sleep(0.1) 79 | 80 | 81 | def fade(lcd, fade_in=True): 82 | for i in range(256): 83 | v = i if fade_in else 255 - i 84 | lcd.set_rgb(v, v, v) 85 | time.sleep(0.01) 86 | 87 | 88 | def demo(): 89 | """ 90 | RGB1602 demonstration 91 | 92 | Modified 2022-10-13 by Hagen Patzke, Hogeschool Utrecht HBO-ICT TI 93 | """ 94 | lcd = RGB1602.RGB1602(16, 2) 95 | 96 | define_characters(lcd) 97 | 98 | while True: 99 | lcd.clear() 100 | fade(lcd, fade_in=True) 101 | lcd.set_color_white() 102 | # The RGB1602 functions return 'self' -> we can chain commands (!) 103 | lcd.at(2, 0).printout(chr(0) + " WELCOME " + chr(1)) 104 | lcd.at(3, 1).printout(chr(1) + " STUDENT " + chr(2)) 105 | # "Discoloration" demo 106 | discoloration(lcd) 107 | # Display off for a moment 108 | lcd.display(False) 109 | time.sleep(1) 110 | lcd.set_color_white() 111 | lcd.display(True) 112 | # Show second banner 113 | lcd.clear() 114 | animated_banner(lcd) 115 | time.sleep(2) 116 | show_r_g_b(lcd) 117 | fade(lcd, fade_in=False) 118 | 119 | 120 | if __name__ == '__main__': 121 | demo() 122 | -------------------------------------------------------------------------------- /opdracht2/sub.py: -------------------------------------------------------------------------------- 1 | import network 2 | import time 3 | import ubinascii 4 | from umqtt.simple import MQTTClient 5 | import machine 6 | import ssd1306 7 | 8 | # Wi-Fi Configuration, add your Wi-Fi SSID and password here 9 | SSID = '' 10 | PASSWORD = '' 11 | 12 | # MQTT Configuration, add your MQTT broker address and port here 13 | MQTT_BROKER = 'broker.hivemq.com' 14 | MQTT_PORT = 1883 15 | CLIENT_ID = ubinascii.hexlify(machine.unique_id()) 16 | # Add your unique MQTT topic for temperature here (your name + your date of birth + 'TEMP') 17 | TOPIC_TEMP = '' 18 | # Add your unique MQTT topic for humidity here (your name + your date of birth + 'HUMID') 19 | TOPIC_HUMIDITY = '' 20 | 21 | 22 | # Set up I2C for OLED 23 | i2c = machine.I2C(0, sda=machine.Pin(4), scl=machine.Pin(5)) 24 | oled_width = 128 25 | oled_height = 64 26 | oled = ssd1306.SSD1306_I2C(oled_width, oled_height, i2c) 27 | 28 | # Function to update OLED display 29 | def update_oled(lines): 30 | # implement here your code: 31 | # 1) to clear the oled-display 32 | # 2) to read each element from lines 33 | # 3) to write each element to the oled-display 34 | # 4) update the display 35 | 36 | # Connect to Wi-Fi 37 | def connect_wifi(): 38 | wlan = network.WLAN(network.STA_IF) 39 | wlan.active(True) 40 | wlan.disconnect() # Disconnect in case it's already connected 41 | wlan.connect(SSID, PASSWORD) 42 | 43 | max_retries = 20 44 | retries = 0 45 | 46 | while not wlan.isconnected() and retries < max_retries: 47 | retries += 1 48 | time.sleep(1) 49 | # add an update_oled method to display 3 lines: "Connecting to"; "Wi-Fi"; "Retry x from 20". 50 | # add also a print statement with the same data (for debugging purpose) 51 | 52 | if wlan.isconnected(): 53 | # extract from the returnvalue of the wlan.ifconfig() method the IP-address 54 | ip = 55 | # add an update_oled method to display 3 lines: "Connected to Wi-Fi"; "IP:"; your.ip-address 56 | time.sleep(3) 57 | print('Connected to Wi-Fi:', wlan.ifconfig()) 58 | return True 59 | else: 60 | # add an update_oled method to display 4 lines: "Failed to"; "connect to"; "Wi-Fi"; your SSID 61 | print('Failed to connect to Wi-Fi') 62 | return False 63 | 64 | # Try to connect to Wi-Fi 65 | if not connect_wifi(): 66 | # If failed to connect, halt the program 67 | while True: 68 | time.sleep(1) 69 | 70 | # Global variables to store the last received values 71 | last_temp = "No Data" 72 | last_humidity = "No Data" 73 | 74 | # MQTT message callback 75 | def sub_callback(topic, msg): 76 | global last_temp, last_humidity 77 | 78 | print((topic, msg)) 79 | # add code here to test if the current topic is coming from your publisher and containind the TEMP-data, if so: store the decoded value in variable: last_temp 80 | # add code here to test if the current topic is coming from your publisher and containind the HUMIDITY-data, if so: store the decoded value in variable: last_humidity 81 | 82 | # Update OLED display with the last received values 83 | # add here an update_oled method to display 2 lines: "Temp: x C"; "Hum: y3 %" where x=last_temp and y=last_humidity 84 | oled.show() 85 | 86 | # Connect to MQTT Broker 87 | time.sleep(2) 88 | client = MQTTClient(CLIENT_ID, MQTT_BROKER, port=MQTT_PORT) 89 | client.set_callback(sub_callback) 90 | 91 | try: 92 | client.connect() 93 | # add here an update_oled method to display 3 lines: "Connected to MQTT"; "Broker"; MQTT_BROKER 94 | print('Connected to MQTT Broker:', MQTT_BROKER) 95 | 96 | # Subscribe to topics 97 | # add here an update_oled method to display 2 lines: "Subscribing to"; "topics..." 98 | client.subscribe(TOPIC_TEMP) 99 | client.subscribe(TOPIC_HUMIDITY) 100 | # add here an update_oled method to display 3 lines: "Subscribed to"; "topics"; "Waiting for data..." 101 | 102 | while True: 103 | client.check_msg() 104 | time.sleep(1) 105 | 106 | except Exception as e: 107 | # add here an update_oled method to display 3 lines: "Failed to"; "connect to the"; "MQTT broker" 108 | print('Failed to connect to MQTT Broker:', e) 109 | 110 | -------------------------------------------------------------------------------- /lcd/demo/RGB1602.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import time 3 | from machine import Pin, I2C 4 | 5 | RGB1602_SDA = Pin(4) 6 | RGB1602_SCL = Pin(5) 7 | 8 | # RGB1602_I2C = I2C(0, sda=RGB1602_SDA, scl=RGB1602_SCL, freq=400000) 9 | RGB1602_I2C = I2C(0, sda=RGB1602_SDA, scl=RGB1602_SCL, freq=125000) 10 | 11 | # Device I2C Address 12 | LCD_ADDRESS = (0x7C >> 1) 13 | RGB_ADDRESS = (0xC0 >> 1) 14 | # for LCD1602 RGB module, I2C.Scan() shows another (unknown) I2C device 15 | # UNK_ADDRESS = (0xE0 >> 1) 16 | 17 | # RGB color definitions 18 | REG_RED = 0x04 19 | REG_GREEN = 0x03 20 | REG_BLUE = 0x02 21 | REG_MODE1 = 0x00 22 | REG_MODE2 = 0x01 23 | REG_OUTPUT = 0x08 24 | 25 | # LCD commands 26 | LCD_CLEARDISPLAY = 0x01 27 | LCD_RETURNHOME = 0x02 28 | LCD_ENTRYMODESET = 0x04 29 | LCD_DISPLAYCONTROL = 0x08 30 | LCD_CURSORSHIFT = 0x10 31 | LCD_FUNCTIONSET = 0x20 32 | LCD_SETCGRAMADDR = 0x40 33 | LCD_SETDDRAMADDR = 0x80 34 | 35 | # Entry Mode flags 36 | LCD_ENTRYRTL = 0x00 # Right-to-Left 37 | LCD_ENTRYLTR = 0x02 # Left-to-Right 38 | LCD_ENTRYSHIFT = 0x01 39 | LCD_ENTRYNOSHIFT = 0x00 40 | 41 | # Display Control flags 42 | LCD_DISPLAYON = 0x04 43 | LCD_CURSORON = 0x02 44 | LCD_BLINKON = 0x01 45 | LCD_DISPLAYOFF = 0x00 46 | LCD_CURSOROFF = 0x00 47 | LCD_BLINKOFF = 0x00 48 | 49 | # Display/Cursor Shift flags 50 | LCD_DISPLAYMOVE = 0x08 51 | LCD_CURSORMOVE = 0x00 52 | LCD_MOVERIGHT = 0x04 53 | LCD_MOVELEFT = 0x00 54 | 55 | # Function Set flags 56 | LCD_8BITMODE = 0x10 57 | LCD_4BITMODE = 0x00 58 | LCD_2LINE = 0x08 59 | LCD_1LINE = 0x00 60 | LCD_5x8DOTS = 0x00 61 | 62 | 63 | class RGB1602: 64 | def __init__(self, columns=16, rows=2): 65 | self._cols = columns 66 | self._rows = rows 67 | self._showfunction = LCD_FUNCTIONSET | LCD_4BITMODE | LCD_5x8DOTS 68 | self._showfunction |= (LCD_1LINE if rows < 2 else LCD_2LINE) 69 | self._showcontrol = LCD_DISPLAYCONTROL | LCD_CURSOROFF | LCD_BLINKOFF 70 | self.begin() 71 | 72 | def command(self, cmd): 73 | RGB1602_I2C.writeto(LCD_ADDRESS, bytearray([0x80, cmd])) 74 | 75 | def write(self, data): 76 | RGB1602_I2C.writeto(LCD_ADDRESS, bytearray([0x40, data])) 77 | 78 | def printout(self, arg): 79 | if isinstance(arg, int): 80 | arg = str(arg) 81 | # bytearray(arg, 'utf-8') will make two characters from arg string/chr values 128..255 82 | # x=0..127: [x], x=128..191: [0xC2, x], 192..255: [0xC3, x - 64] 83 | # bytearray(arg, 'latin-1') preserves x for all chr(x) values from 0..255 84 | # x=0..255: [x] 85 | # RGB1602_I2C.writeto_mem(LCD_ADDRESS, 0x40, bytearray(arg, 'utf-8')) 86 | RGB1602_I2C.writeto_mem(LCD_ADDRESS, 0x40, bytearray(arg, 'latin-1')) 87 | return self # enable command chaining 88 | 89 | def set_reg(self, reg, data): 90 | RGB1602_I2C.writeto(RGB_ADDRESS, bytearray([reg, data])) 91 | 92 | def begin(self): 93 | # wait for more than 15 ms after VDD rises to 4.5V 94 | time.sleep(0.050) 95 | self.command(self._showfunction) 96 | time.sleep(0.005) 97 | self.command(self._showfunction) 98 | time.sleep(0.005) 99 | self.command(self._showfunction) 100 | # 4th try 101 | self.command(self._showfunction) 102 | # turn the display on with no cursor or blinking default 103 | self.display() 104 | # clear it 105 | self.clear() 106 | # Initialize to default text direction (for roman languages) 107 | self.command(LCD_ENTRYMODESET | LCD_ENTRYLTR | LCD_ENTRYNOSHIFT) 108 | # RGB backlight init 109 | self.set_reg(REG_MODE1, 0) 110 | # set LEDs controllable by both PWM and GRPPWM registers 111 | self.set_reg(REG_OUTPUT, 0xFF) 112 | # set MODE2 values 113 | # 0b0010_0000 -> 0x20 (DMBLNK to 1, ie blinky mode) 114 | self.set_reg(REG_MODE2, 0x20) 115 | self.set_color_white() 116 | return self # enable command chaining 117 | 118 | def at(self, col, row): 119 | col |= (0x80 if row < 1 else 0xC0) 120 | self.command(col) 121 | return self # enable command chaining 122 | 123 | def clear(self): 124 | self.command(LCD_CLEARDISPLAY) 125 | time.sleep(0.002) 126 | return self # enable command chaining 127 | 128 | def home(self): 129 | self.command(LCD_RETURNHOME) 130 | time.sleep(0.002) 131 | return self # enable command chaining 132 | 133 | def display(self, on=True): 134 | self.command(self._showcontrol | (LCD_DISPLAYON if on else LCD_DISPLAYOFF)) 135 | return self # enable command chaining 136 | 137 | def set_rgb(self, r, g, b): 138 | self.set_reg(REG_RED, r) 139 | self.set_reg(REG_GREEN, g) 140 | self.set_reg(REG_BLUE, b) 141 | return self # enable command chaining 142 | 143 | def set_color_white(self): 144 | self.set_rgb(255, 255, 255) 145 | return self # enable command chaining 146 | -------------------------------------------------------------------------------- /lcd16x2/demo/lcd_api.py: -------------------------------------------------------------------------------- 1 | """Provides an API for talking to HD44780 compatible character LCDs.""" 2 | 3 | import time 4 | 5 | class LcdApi: 6 | """Implements the API for talking with HD44780 compatible character LCDs. 7 | This class only knows what commands to send to the LCD, and not how to get 8 | them to the LCD. 9 | 10 | It is expected that a derived class will implement the hal_xxx functions. 11 | """ 12 | 13 | # The following constant names were lifted from the avrlib lcd.h 14 | # header file, however, I changed the definitions from bit numbers 15 | # to bit masks. 16 | # 17 | # HD44780 LCD controller command set 18 | 19 | LCD_CLR = 0x01 # DB0: clear display 20 | LCD_HOME = 0x02 # DB1: return to home position 21 | 22 | LCD_ENTRY_MODE = 0x04 # DB2: set entry mode 23 | LCD_ENTRY_INC = 0x02 # --DB1: increment 24 | LCD_ENTRY_SHIFT = 0x01 # --DB0: shift 25 | 26 | LCD_ON_CTRL = 0x08 # DB3: turn lcd/cursor on 27 | LCD_ON_DISPLAY = 0x04 # --DB2: turn display on 28 | LCD_ON_CURSOR = 0x02 # --DB1: turn cursor on 29 | LCD_ON_BLINK = 0x01 # --DB0: blinking cursor 30 | 31 | LCD_MOVE = 0x10 # DB4: move cursor/display 32 | LCD_MOVE_DISP = 0x08 # --DB3: move display (0-> move cursor) 33 | LCD_MOVE_RIGHT = 0x04 # --DB2: move right (0-> left) 34 | 35 | LCD_FUNCTION = 0x20 # DB5: function set 36 | LCD_FUNCTION_8BIT = 0x10 # --DB4: set 8BIT mode (0->4BIT mode) 37 | LCD_FUNCTION_2LINES = 0x08 # --DB3: two lines (0->one line) 38 | LCD_FUNCTION_10DOTS = 0x04 # --DB2: 5x10 font (0->5x7 font) 39 | LCD_FUNCTION_RESET = 0x30 # See "Initializing by Instruction" section 40 | 41 | LCD_CGRAM = 0x40 # DB6: set CG RAM address 42 | LCD_DDRAM = 0x80 # DB7: set DD RAM address 43 | 44 | LCD_RS_CMD = 0 45 | LCD_RS_DATA = 1 46 | 47 | LCD_RW_WRITE = 0 48 | LCD_RW_READ = 1 49 | 50 | def __init__(self, num_lines, num_columns): 51 | self.num_lines = num_lines 52 | if self.num_lines > 4: 53 | self.num_lines = 4 54 | self.num_columns = num_columns 55 | if self.num_columns > 40: 56 | self.num_columns = 40 57 | self.cursor_x = 0 58 | self.cursor_y = 0 59 | self.implied_newline = False 60 | self.backlight = True 61 | self.display_off() 62 | self.backlight_on() 63 | self.clear() 64 | self.hal_write_command(self.LCD_ENTRY_MODE | self.LCD_ENTRY_INC) 65 | self.hide_cursor() 66 | self.display_on() 67 | 68 | def clear(self): 69 | """Clears the LCD display and moves the cursor to the top left 70 | corner. 71 | """ 72 | self.hal_write_command(self.LCD_CLR) 73 | self.hal_write_command(self.LCD_HOME) 74 | self.cursor_x = 0 75 | self.cursor_y = 0 76 | 77 | def show_cursor(self): 78 | """Causes the cursor to be made visible.""" 79 | self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY | 80 | self.LCD_ON_CURSOR) 81 | 82 | def hide_cursor(self): 83 | """Causes the cursor to be hidden.""" 84 | self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY) 85 | 86 | def blink_cursor_on(self): 87 | """Turns on the cursor, and makes it blink.""" 88 | self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY | 89 | self.LCD_ON_CURSOR | self.LCD_ON_BLINK) 90 | 91 | def blink_cursor_off(self): 92 | """Turns on the cursor, and makes it no blink (i.e. be solid).""" 93 | self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY | 94 | self.LCD_ON_CURSOR) 95 | 96 | def display_on(self): 97 | """Turns on (i.e. unblanks) the LCD.""" 98 | self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY) 99 | 100 | def display_off(self): 101 | """Turns off (i.e. blanks) the LCD.""" 102 | self.hal_write_command(self.LCD_ON_CTRL) 103 | 104 | def backlight_on(self): 105 | """Turns the backlight on. 106 | 107 | This isn't really an LCD command, but some modules have backlight 108 | controls, so this allows the hal to pass through the command. 109 | """ 110 | self.backlight = True 111 | self.hal_backlight_on() 112 | 113 | def backlight_off(self): 114 | """Turns the backlight off. 115 | 116 | This isn't really an LCD command, but some modules have backlight 117 | controls, so this allows the hal to pass through the command. 118 | """ 119 | self.backlight = False 120 | self.hal_backlight_off() 121 | 122 | def move_to(self, cursor_x, cursor_y): 123 | """Moves the cursor position to the indicated position. The cursor 124 | position is zero based (i.e. cursor_x == 0 indicates first column). 125 | """ 126 | self.cursor_x = cursor_x 127 | self.cursor_y = cursor_y 128 | addr = cursor_x & 0x3f 129 | if cursor_y & 1: 130 | addr += 0x40 # Lines 1 & 3 add 0x40 131 | if cursor_y & 2: # Lines 2 & 3 add number of columns 132 | addr += self.num_columns 133 | self.hal_write_command(self.LCD_DDRAM | addr) 134 | 135 | def putchar(self, char): 136 | """Writes the indicated character to the LCD at the current cursor 137 | position, and advances the cursor by one position. 138 | """ 139 | if char == '\n': 140 | if self.implied_newline: 141 | # self.implied_newline means we advanced due to a wraparound, 142 | # so if we get a newline right after that we ignore it. 143 | self.implied_newline = False 144 | else: 145 | self.cursor_x = self.num_columns 146 | else: 147 | self.hal_write_data(ord(char)) 148 | self.cursor_x += 1 149 | if self.cursor_x >= self.num_columns: 150 | self.cursor_x = 0 151 | self.cursor_y += 1 152 | self.implied_newline = (char != '\n') 153 | if self.cursor_y >= self.num_lines: 154 | self.cursor_y = 0 155 | self.move_to(self.cursor_x, self.cursor_y) 156 | 157 | def putstr(self, string): 158 | """Write the indicated string to the LCD at the current cursor 159 | position and advances the cursor position appropriately. 160 | """ 161 | for char in string: 162 | self.putchar(char) 163 | 164 | def custom_char(self, location, charmap): 165 | """Write a character to one of the 8 CGRAM locations, available 166 | as chr(0) through chr(7). 167 | """ 168 | location &= 0x7 169 | self.hal_write_command(self.LCD_CGRAM | (location << 3)) 170 | self.hal_sleep_us(40) 171 | for i in range(8): 172 | self.hal_write_data(charmap[i]) 173 | self.hal_sleep_us(40) 174 | self.move_to(self.cursor_x, self.cursor_y) 175 | 176 | def hal_backlight_on(self): 177 | """Allows the hal layer to turn the backlight on. 178 | 179 | If desired, a derived HAL class will implement this function. 180 | """ 181 | pass 182 | 183 | def hal_backlight_off(self): 184 | """Allows the hal layer to turn the backlight off. 185 | 186 | If desired, a derived HAL class will implement this function. 187 | """ 188 | pass 189 | 190 | def hal_write_command(self, cmd): 191 | """Write a command to the LCD. 192 | 193 | It is expected that a derived HAL class will implement this 194 | function. 195 | """ 196 | raise NotImplementedError 197 | 198 | def hal_write_data(self, data): 199 | """Write data to the LCD. 200 | 201 | It is expected that a derived HAL class will implement this 202 | function. 203 | """ 204 | raise NotImplementedError 205 | 206 | # This is a default implementation of hal_sleep_us which is suitable 207 | # for most micropython implementations. For platforms which don't 208 | # support `time.sleep_us()` they should provide their own implementation 209 | # of hal_sleep_us in their hal layer and it will be used instead. 210 | def hal_sleep_us(self, usecs): 211 | """Sleep for some time (given in microseconds).""" 212 | time.sleep_us(usecs) # NOTE this is not part of Standard Python library, specific hal layers will need to override this 213 | -------------------------------------------------------------------------------- /rc522/read/rc522.py: -------------------------------------------------------------------------------- 1 | from machine import Pin, SPI 2 | from os import uname 3 | 4 | 5 | # 6 | # Library from https://github.com/danjperron/micropython-mfrc522 7 | # 8 | 9 | class MFRC522: 10 | DEBUG = False 11 | OK = 0 12 | NOTAGERR = 1 13 | ERR = 2 14 | 15 | REQIDL = 0x26 16 | REQALL = 0x52 17 | AUTHENT1A = 0x60 18 | AUTHENT1B = 0x61 19 | 20 | PICC_ANTICOLL1 = 0x93 21 | PICC_ANTICOLL2 = 0x95 22 | PICC_ANTICOLL3 = 0x97 23 | 24 | def __init__(self, sck, mosi, miso, rst, cs, baudrate=1000000, spi_id=0): 25 | 26 | self.sck = Pin(sck, Pin.OUT) 27 | self.mosi = Pin(mosi, Pin.OUT) 28 | self.miso = Pin(miso) 29 | self.rst = Pin(rst, Pin.OUT) 30 | self.cs = Pin(cs, Pin.OUT) 31 | 32 | self.rst.value(0) 33 | self.cs.value(1) 34 | 35 | board = uname()[0] 36 | 37 | self.spi = SPI(spi_id, baudrate=baudrate, sck=self.sck, mosi=self.mosi, miso=self.miso) 38 | 39 | self.rst.value(1) 40 | self.init() 41 | 42 | def _wreg(self, reg, val): 43 | 44 | self.cs.value(0) 45 | self.spi.write(b'%c' % int(0xff & ((reg << 1) & 0x7e))) 46 | self.spi.write(b'%c' % int(0xff & val)) 47 | self.cs.value(1) 48 | 49 | def _rreg(self, reg): 50 | 51 | self.cs.value(0) 52 | self.spi.write(b'%c' % int(0xff & (((reg << 1) & 0x7e) | 0x80))) 53 | val = self.spi.read(1) 54 | self.cs.value(1) 55 | 56 | return val[0] 57 | 58 | def _sflags(self, reg, mask): 59 | self._wreg(reg, self._rreg(reg) | mask) 60 | 61 | def _cflags(self, reg, mask): 62 | self._wreg(reg, self._rreg(reg) & (~mask)) 63 | 64 | def _tocard(self, cmd, send): 65 | 66 | recv = [] 67 | bits = irq_en = wait_irq = n = 0 68 | stat = self.ERR 69 | 70 | if cmd == 0x0E: 71 | irq_en = 0x12 72 | wait_irq = 0x10 73 | elif cmd == 0x0C: 74 | irq_en = 0x77 75 | wait_irq = 0x30 76 | 77 | self._wreg(0x02, irq_en | 0x80) 78 | self._cflags(0x04, 0x80) 79 | self._sflags(0x0A, 0x80) 80 | self._wreg(0x01, 0x00) 81 | 82 | for c in send: 83 | self._wreg(0x09, c) 84 | self._wreg(0x01, cmd) 85 | 86 | if cmd == 0x0C: 87 | self._sflags(0x0D, 0x80) 88 | 89 | i = 2000 90 | while True: 91 | n = self._rreg(0x04) 92 | i -= 1 93 | if ~((i != 0) and ~(n & 0x01) and ~(n & wait_irq)): 94 | break 95 | 96 | self._cflags(0x0D, 0x80) 97 | 98 | if i: 99 | if (self._rreg(0x06) & 0x1B) == 0x00: 100 | stat = self.OK 101 | 102 | if n & irq_en & 0x01: 103 | stat = self.NOTAGERR 104 | elif cmd == 0x0C: 105 | n = self._rreg(0x0A) 106 | lbits = self._rreg(0x0C) & 0x07 107 | if lbits != 0: 108 | bits = (n - 1) * 8 + lbits 109 | else: 110 | bits = n * 8 111 | 112 | if n == 0: 113 | n = 1 114 | elif n > 16: 115 | n = 16 116 | 117 | for _ in range(n): 118 | recv.append(self._rreg(0x09)) 119 | else: 120 | stat = self.ERR 121 | 122 | return stat, recv, bits 123 | 124 | def _crc(self, data): 125 | 126 | self._cflags(0x05, 0x04) 127 | self._sflags(0x0A, 0x80) 128 | 129 | for c in data: 130 | self._wreg(0x09, c) 131 | 132 | self._wreg(0x01, 0x03) 133 | 134 | i = 0xFF 135 | while True: 136 | n = self._rreg(0x05) 137 | i -= 1 138 | if not ((i != 0) and not (n & 0x04)): 139 | break 140 | 141 | return [self._rreg(0x22), self._rreg(0x21)] 142 | 143 | def init(self): 144 | 145 | self.reset() 146 | self._wreg(0x2A, 0x8D) 147 | self._wreg(0x2B, 0x3E) 148 | self._wreg(0x2D, 30) 149 | self._wreg(0x2C, 0) 150 | self._wreg(0x15, 0x40) 151 | self._wreg(0x11, 0x3D) 152 | self.antenna_on() 153 | 154 | def reset(self): 155 | self._wreg(0x01, 0x0F) 156 | 157 | def antenna_on(self, on=True): 158 | 159 | if on and ~(self._rreg(0x14) & 0x03): 160 | self._sflags(0x14, 0x03) 161 | else: 162 | self._cflags(0x14, 0x03) 163 | 164 | def request(self, mode): 165 | 166 | self._wreg(0x0D, 0x07) 167 | (stat, recv, bits) = self._tocard(0x0C, [mode]) 168 | 169 | if (stat != self.OK) | (bits != 0x10): 170 | stat = self.ERR 171 | 172 | return stat, bits 173 | 174 | def anticoll(self, anticolN): 175 | 176 | ser_chk = 0 177 | ser = [anticolN, 0x20] 178 | 179 | self._wreg(0x0D, 0x00) 180 | (stat, recv, bits) = self._tocard(0x0C, ser) 181 | 182 | if stat == self.OK: 183 | if len(recv) == 5: 184 | for i in range(4): 185 | ser_chk = ser_chk ^ recv[i] 186 | if ser_chk != recv[4]: 187 | stat = self.ERR 188 | else: 189 | stat = self.ERR 190 | 191 | return stat, recv 192 | 193 | def PcdSelect(self, serNum, anticolN): 194 | backData = [] 195 | buf = [] 196 | buf.append(anticolN) 197 | buf.append(0x70) 198 | # i = 0 199 | ###xorsum=0; 200 | for i in serNum: 201 | buf.append(i) 202 | # while i<5: 203 | # buf.append(serNum[i]) 204 | # i = i + 1 205 | pOut = self._crc(buf) 206 | buf.append(pOut[0]) 207 | buf.append(pOut[1]) 208 | (status, backData, backLen) = self._tocard(0x0C, buf) 209 | if (status == self.OK) and (backLen == 0x18): 210 | return 1 211 | else: 212 | return 0 213 | 214 | def SelectTag(self, uid): 215 | byte5 = 0 216 | 217 | # (status,puid)= self.anticoll(self.PICC_ANTICOLL1) 218 | # print("uid",uid,"puid",puid) 219 | for i in uid: 220 | byte5 = byte5 ^ i 221 | puid = uid + [byte5] 222 | 223 | if self.PcdSelect(puid, self.PICC_ANTICOLL1) == 0: 224 | return (self.ERR, []) 225 | return (self.OK, uid) 226 | 227 | def tohexstring(self, v): 228 | s = "[" 229 | for i in v: 230 | if i != v[0]: 231 | s = s + ", " 232 | s = s + "0x{:02X}".format(i) 233 | s = s + "]" 234 | return s 235 | 236 | def SelectTagSN(self): 237 | valid_uid = [] 238 | (status, uid) = self.anticoll(self.PICC_ANTICOLL1) 239 | # print("Select Tag 1:",self.tohexstring(uid)) 240 | if status != self.OK: 241 | return (self.ERR, []) 242 | 243 | if self.DEBUG: print("anticol(1) {}".format(uid)) 244 | if self.PcdSelect(uid, self.PICC_ANTICOLL1) == 0: 245 | return (self.ERR, []) 246 | if self.DEBUG: print("pcdSelect(1) {}".format(uid)) 247 | 248 | # check if first byte is 0x88 249 | if uid[0] == 0x88: 250 | # ok we have another type of card 251 | valid_uid.extend(uid[1:4]) 252 | (status, uid) = self.anticoll(self.PICC_ANTICOLL2) 253 | # print("Select Tag 2:",self.tohexstring(uid)) 254 | if status != self.OK: 255 | return (self.ERR, []) 256 | if self.DEBUG: print("Anticol(2) {}".format(uid)) 257 | rtn = self.PcdSelect(uid, self.PICC_ANTICOLL2) 258 | if self.DEBUG: print("pcdSelect(2) return={} uid={}".format(rtn, uid)) 259 | if rtn == 0: 260 | return (self.ERR, []) 261 | if self.DEBUG: print("PcdSelect2() {}".format(uid)) 262 | # now check again if uid[0] is 0x88 263 | if uid[0] == 0x88: 264 | valid_uid.extend(uid[1:4]) 265 | (status, uid) = self.anticoll(self.PICC_ANTICOLL3) 266 | # print("Select Tag 3:",self.tohexstring(uid)) 267 | if status != self.OK: 268 | return (self.ERR, []) 269 | if self.DEBUG: print("Anticol(3) {}".format(uid)) 270 | if self.MFRC522_PcdSelect(uid, self.PICC_ANTICOLL3) == 0: 271 | return (self.ERR, []) 272 | if self.DEBUG: print("PcdSelect(3) {}".format(uid)) 273 | valid_uid.extend(uid[0:5]) 274 | # if we are here than the uid is ok 275 | # let's remove the last BYTE whic is the XOR sum 276 | 277 | return (self.OK, valid_uid[:len(valid_uid) - 1]) 278 | # return (self.OK , valid_uid) 279 | 280 | def auth(self, mode, addr, sect, ser): 281 | return self._tocard(0x0E, [mode, addr] + sect + ser[:4])[0] 282 | 283 | def authKeys(self, uid, addr, keyA=None, keyB=None): 284 | status = self.ERR 285 | if keyA is not None: 286 | status = self.auth(self.AUTHENT1A, addr, keyA, uid) 287 | elif keyB is not None: 288 | status = self.auth(self.AUTHENT1B, addr, keyB, uid) 289 | return status 290 | 291 | def stop_crypto1(self): 292 | self._cflags(0x08, 0x08) 293 | 294 | def read(self, addr): 295 | 296 | data = [0x30, addr] 297 | data += self._crc(data) 298 | (stat, recv, _) = self._tocard(0x0C, data) 299 | return stat, recv 300 | 301 | def write(self, addr, data): 302 | 303 | buf = [0xA0, addr] 304 | buf += self._crc(buf) 305 | (stat, recv, bits) = self._tocard(0x0C, buf) 306 | 307 | if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): 308 | stat = self.ERR 309 | else: 310 | buf = [] 311 | for i in range(16): 312 | buf.append(data[i]) 313 | buf += self._crc(buf) 314 | (stat, recv, bits) = self._tocard(0x0C, buf) 315 | if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): 316 | stat = self.ERR 317 | return stat 318 | 319 | def writeSectorBlock(self, uid, sector, block, data, keyA=None, keyB=None): 320 | absoluteBlock = sector * 4 + (block % 4) 321 | if absoluteBlock > 63: 322 | return self.ERR 323 | if len(data) != 16: 324 | return self.ERR 325 | if self.authKeys(uid, absoluteBlock, keyA, keyB) != self.ERR: 326 | return self.write(absoluteBlock, data) 327 | return self.ERR 328 | 329 | def readSectorBlock(self, uid, sector, block, keyA=None, keyB=None): 330 | absoluteBlock = sector * 4 + (block % 4) 331 | if absoluteBlock > 63: 332 | return self.ERR, None 333 | if self.authKeys(uid, absoluteBlock, keyA, keyB) != self.ERR: 334 | return self.read(absoluteBlock) 335 | return self.ERR, None 336 | 337 | def MFRC522_DumpClassic1K(self, uid, Start=0, End=64, keyA=None, keyB=None): 338 | data = {} 339 | for absoluteBlock in range(Start, End): 340 | status = self.authKeys(uid, absoluteBlock, keyA, keyB) 341 | # Check if authenticated 342 | if status == self.OK: 343 | status, block = self.read(absoluteBlock) 344 | data[absoluteBlock] = block 345 | if status == self.ERR: 346 | break 347 | else: 348 | break 349 | for absoluteBlock, block in data.items(): 350 | print("{:02d} S{:02d} B{:1d}: ".format(absoluteBlock, absoluteBlock // 4, absoluteBlock % 4), end="") 351 | for value in block: 352 | print("{:02X} ".format(value), end="") 353 | print(" ", end="") 354 | for value in block: 355 | if (value > 0x20) and (value < 0x7f): 356 | print(chr(value), end="") 357 | else: 358 | print('.', end="") 359 | print("") 360 | if status == self.ERR: 361 | print("Authentication error") 362 | return self.ERR 363 | return self.OK 364 | 365 | 366 | 367 | -------------------------------------------------------------------------------- /rc522/write/rc522.py: -------------------------------------------------------------------------------- 1 | from machine import Pin, SPI 2 | from os import uname 3 | 4 | 5 | # 6 | # Library from https://github.com/danjperron/micropython-mfrc522 7 | # 8 | 9 | class MFRC522: 10 | DEBUG = False 11 | OK = 0 12 | NOTAGERR = 1 13 | ERR = 2 14 | 15 | REQIDL = 0x26 16 | REQALL = 0x52 17 | AUTHENT1A = 0x60 18 | AUTHENT1B = 0x61 19 | 20 | PICC_ANTICOLL1 = 0x93 21 | PICC_ANTICOLL2 = 0x95 22 | PICC_ANTICOLL3 = 0x97 23 | 24 | def __init__(self, sck, mosi, miso, rst, cs, baudrate=1000000, spi_id=0): 25 | 26 | self.sck = Pin(sck, Pin.OUT) 27 | self.mosi = Pin(mosi, Pin.OUT) 28 | self.miso = Pin(miso) 29 | self.rst = Pin(rst, Pin.OUT) 30 | self.cs = Pin(cs, Pin.OUT) 31 | 32 | self.rst.value(0) 33 | self.cs.value(1) 34 | 35 | board = uname()[0] 36 | 37 | self.spi = SPI(spi_id, baudrate=baudrate, sck=self.sck, mosi=self.mosi, miso=self.miso) 38 | 39 | self.rst.value(1) 40 | self.init() 41 | 42 | def _wreg(self, reg, val): 43 | 44 | self.cs.value(0) 45 | self.spi.write(b'%c' % int(0xff & ((reg << 1) & 0x7e))) 46 | self.spi.write(b'%c' % int(0xff & val)) 47 | self.cs.value(1) 48 | 49 | def _rreg(self, reg): 50 | 51 | self.cs.value(0) 52 | self.spi.write(b'%c' % int(0xff & (((reg << 1) & 0x7e) | 0x80))) 53 | val = self.spi.read(1) 54 | self.cs.value(1) 55 | 56 | return val[0] 57 | 58 | def _sflags(self, reg, mask): 59 | self._wreg(reg, self._rreg(reg) | mask) 60 | 61 | def _cflags(self, reg, mask): 62 | self._wreg(reg, self._rreg(reg) & (~mask)) 63 | 64 | def _tocard(self, cmd, send): 65 | 66 | recv = [] 67 | bits = irq_en = wait_irq = n = 0 68 | stat = self.ERR 69 | 70 | if cmd == 0x0E: 71 | irq_en = 0x12 72 | wait_irq = 0x10 73 | elif cmd == 0x0C: 74 | irq_en = 0x77 75 | wait_irq = 0x30 76 | 77 | self._wreg(0x02, irq_en | 0x80) 78 | self._cflags(0x04, 0x80) 79 | self._sflags(0x0A, 0x80) 80 | self._wreg(0x01, 0x00) 81 | 82 | for c in send: 83 | self._wreg(0x09, c) 84 | self._wreg(0x01, cmd) 85 | 86 | if cmd == 0x0C: 87 | self._sflags(0x0D, 0x80) 88 | 89 | i = 2000 90 | while True: 91 | n = self._rreg(0x04) 92 | i -= 1 93 | if ~((i != 0) and ~(n & 0x01) and ~(n & wait_irq)): 94 | break 95 | 96 | self._cflags(0x0D, 0x80) 97 | 98 | if i: 99 | if (self._rreg(0x06) & 0x1B) == 0x00: 100 | stat = self.OK 101 | 102 | if n & irq_en & 0x01: 103 | stat = self.NOTAGERR 104 | elif cmd == 0x0C: 105 | n = self._rreg(0x0A) 106 | lbits = self._rreg(0x0C) & 0x07 107 | if lbits != 0: 108 | bits = (n - 1) * 8 + lbits 109 | else: 110 | bits = n * 8 111 | 112 | if n == 0: 113 | n = 1 114 | elif n > 16: 115 | n = 16 116 | 117 | for _ in range(n): 118 | recv.append(self._rreg(0x09)) 119 | else: 120 | stat = self.ERR 121 | 122 | return stat, recv, bits 123 | 124 | def _crc(self, data): 125 | 126 | self._cflags(0x05, 0x04) 127 | self._sflags(0x0A, 0x80) 128 | 129 | for c in data: 130 | self._wreg(0x09, c) 131 | 132 | self._wreg(0x01, 0x03) 133 | 134 | i = 0xFF 135 | while True: 136 | n = self._rreg(0x05) 137 | i -= 1 138 | if not ((i != 0) and not (n & 0x04)): 139 | break 140 | 141 | return [self._rreg(0x22), self._rreg(0x21)] 142 | 143 | def init(self): 144 | 145 | self.reset() 146 | self._wreg(0x2A, 0x8D) 147 | self._wreg(0x2B, 0x3E) 148 | self._wreg(0x2D, 30) 149 | self._wreg(0x2C, 0) 150 | self._wreg(0x15, 0x40) 151 | self._wreg(0x11, 0x3D) 152 | self.antenna_on() 153 | 154 | def reset(self): 155 | self._wreg(0x01, 0x0F) 156 | 157 | def antenna_on(self, on=True): 158 | 159 | if on and ~(self._rreg(0x14) & 0x03): 160 | self._sflags(0x14, 0x03) 161 | else: 162 | self._cflags(0x14, 0x03) 163 | 164 | def request(self, mode): 165 | 166 | self._wreg(0x0D, 0x07) 167 | (stat, recv, bits) = self._tocard(0x0C, [mode]) 168 | 169 | if (stat != self.OK) | (bits != 0x10): 170 | stat = self.ERR 171 | 172 | return stat, bits 173 | 174 | def anticoll(self, anticolN): 175 | 176 | ser_chk = 0 177 | ser = [anticolN, 0x20] 178 | 179 | self._wreg(0x0D, 0x00) 180 | (stat, recv, bits) = self._tocard(0x0C, ser) 181 | 182 | if stat == self.OK: 183 | if len(recv) == 5: 184 | for i in range(4): 185 | ser_chk = ser_chk ^ recv[i] 186 | if ser_chk != recv[4]: 187 | stat = self.ERR 188 | else: 189 | stat = self.ERR 190 | 191 | return stat, recv 192 | 193 | def PcdSelect(self, serNum, anticolN): 194 | backData = [] 195 | buf = [] 196 | buf.append(anticolN) 197 | buf.append(0x70) 198 | # i = 0 199 | ###xorsum=0; 200 | for i in serNum: 201 | buf.append(i) 202 | # while i<5: 203 | # buf.append(serNum[i]) 204 | # i = i + 1 205 | pOut = self._crc(buf) 206 | buf.append(pOut[0]) 207 | buf.append(pOut[1]) 208 | (status, backData, backLen) = self._tocard(0x0C, buf) 209 | if (status == self.OK) and (backLen == 0x18): 210 | return 1 211 | else: 212 | return 0 213 | 214 | def SelectTag(self, uid): 215 | byte5 = 0 216 | 217 | # (status,puid)= self.anticoll(self.PICC_ANTICOLL1) 218 | # print("uid",uid,"puid",puid) 219 | for i in uid: 220 | byte5 = byte5 ^ i 221 | puid = uid + [byte5] 222 | 223 | if self.PcdSelect(puid, self.PICC_ANTICOLL1) == 0: 224 | return (self.ERR, []) 225 | return (self.OK, uid) 226 | 227 | def tohexstring(self, v): 228 | s = "[" 229 | for i in v: 230 | if i != v[0]: 231 | s = s + ", " 232 | s = s + "0x{:02X}".format(i) 233 | s = s + "]" 234 | return s 235 | 236 | def SelectTagSN(self): 237 | valid_uid = [] 238 | (status, uid) = self.anticoll(self.PICC_ANTICOLL1) 239 | # print("Select Tag 1:",self.tohexstring(uid)) 240 | if status != self.OK: 241 | return (self.ERR, []) 242 | 243 | if self.DEBUG: print("anticol(1) {}".format(uid)) 244 | if self.PcdSelect(uid, self.PICC_ANTICOLL1) == 0: 245 | return (self.ERR, []) 246 | if self.DEBUG: print("pcdSelect(1) {}".format(uid)) 247 | 248 | # check if first byte is 0x88 249 | if uid[0] == 0x88: 250 | # ok we have another type of card 251 | valid_uid.extend(uid[1:4]) 252 | (status, uid) = self.anticoll(self.PICC_ANTICOLL2) 253 | # print("Select Tag 2:",self.tohexstring(uid)) 254 | if status != self.OK: 255 | return (self.ERR, []) 256 | if self.DEBUG: print("Anticol(2) {}".format(uid)) 257 | rtn = self.PcdSelect(uid, self.PICC_ANTICOLL2) 258 | if self.DEBUG: print("pcdSelect(2) return={} uid={}".format(rtn, uid)) 259 | if rtn == 0: 260 | return (self.ERR, []) 261 | if self.DEBUG: print("PcdSelect2() {}".format(uid)) 262 | # now check again if uid[0] is 0x88 263 | if uid[0] == 0x88: 264 | valid_uid.extend(uid[1:4]) 265 | (status, uid) = self.anticoll(self.PICC_ANTICOLL3) 266 | # print("Select Tag 3:",self.tohexstring(uid)) 267 | if status != self.OK: 268 | return (self.ERR, []) 269 | if self.DEBUG: print("Anticol(3) {}".format(uid)) 270 | if self.MFRC522_PcdSelect(uid, self.PICC_ANTICOLL3) == 0: 271 | return (self.ERR, []) 272 | if self.DEBUG: print("PcdSelect(3) {}".format(uid)) 273 | valid_uid.extend(uid[0:5]) 274 | # if we are here than the uid is ok 275 | # let's remove the last BYTE whic is the XOR sum 276 | 277 | return (self.OK, valid_uid[:len(valid_uid) - 1]) 278 | # return (self.OK , valid_uid) 279 | 280 | def auth(self, mode, addr, sect, ser): 281 | return self._tocard(0x0E, [mode, addr] + sect + ser[:4])[0] 282 | 283 | def authKeys(self, uid, addr, keyA=None, keyB=None): 284 | status = self.ERR 285 | if keyA is not None: 286 | status = self.auth(self.AUTHENT1A, addr, keyA, uid) 287 | elif keyB is not None: 288 | status = self.auth(self.AUTHENT1B, addr, keyB, uid) 289 | return status 290 | 291 | def stop_crypto1(self): 292 | self._cflags(0x08, 0x08) 293 | 294 | def read(self, addr): 295 | 296 | data = [0x30, addr] 297 | data += self._crc(data) 298 | (stat, recv, _) = self._tocard(0x0C, data) 299 | return stat, recv 300 | 301 | def write(self, addr, data): 302 | 303 | buf = [0xA0, addr] 304 | buf += self._crc(buf) 305 | (stat, recv, bits) = self._tocard(0x0C, buf) 306 | 307 | if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): 308 | stat = self.ERR 309 | else: 310 | buf = [] 311 | for i in range(16): 312 | buf.append(data[i]) 313 | buf += self._crc(buf) 314 | (stat, recv, bits) = self._tocard(0x0C, buf) 315 | if not (stat == self.OK) or not (bits == 4) or not ((recv[0] & 0x0F) == 0x0A): 316 | stat = self.ERR 317 | return stat 318 | 319 | def writeSectorBlock(self, uid, sector, block, data, keyA=None, keyB=None): 320 | absoluteBlock = sector * 4 + (block % 4) 321 | if absoluteBlock > 63: 322 | return self.ERR 323 | if len(data) != 16: 324 | return self.ERR 325 | if self.authKeys(uid, absoluteBlock, keyA, keyB) != self.ERR: 326 | return self.write(absoluteBlock, data) 327 | return self.ERR 328 | 329 | def readSectorBlock(self, uid, sector, block, keyA=None, keyB=None): 330 | absoluteBlock = sector * 4 + (block % 4) 331 | if absoluteBlock > 63: 332 | return self.ERR, None 333 | if self.authKeys(uid, absoluteBlock, keyA, keyB) != self.ERR: 334 | return self.read(absoluteBlock) 335 | return self.ERR, None 336 | 337 | def MFRC522_DumpClassic1K(self, uid, Start=0, End=64, keyA=None, keyB=None): 338 | data = {} 339 | for absoluteBlock in range(Start, End): 340 | status = self.authKeys(uid, absoluteBlock, keyA, keyB) 341 | # Check if authenticated 342 | if status == self.OK: 343 | status, block = self.read(absoluteBlock) 344 | data[absoluteBlock] = block 345 | if status == self.ERR: 346 | break 347 | else: 348 | break 349 | for absoluteBlock, block in data.items(): 350 | print("{:02d} S{:02d} B{:1d}: ".format(absoluteBlock, absoluteBlock // 4, absoluteBlock % 4), end="") 351 | for value in block: 352 | print("{:02X} ".format(value), end="") 353 | print(" ", end="") 354 | for value in block: 355 | if (value > 0x20) and (value < 0x7f): 356 | print(chr(value), end="") 357 | else: 358 | print('.', end="") 359 | print("") 360 | if status == self.ERR: 361 | print("Authentication error") 362 | return self.ERR 363 | return self.OK 364 | 365 | 366 | 367 | --------------------------------------------------------------------------------