This shows you the differences between two versions of the page.
priot:laboratoare:04 [2024/10/15 11:06] vlad.radulescu2901 |
priot:laboratoare:04 [2024/11/05 15:26] (current) alexandru.bala [Bibliografie] |
||
---|---|---|---|
Line 4: | Line 4: | ||
Acest laborator ii va invata pe studenti sa: | Acest laborator ii va invata pe studenti sa: | ||
- | 1. Inteleaga ce este Raspberry Pi Pico si cum functioneaza. | + | * Inteleaga ce este Raspberry Pi Pico si cum functioneaza. |
- | 2. Invete despre senzorii BMP280 (temperatura si presiune) si LDR (lumina). | + | * Invete despre senzorii BMP280 (temperatura si presiune) si LDR (lumina). |
- | 3. Inteleaga ce este MicroPython, cum functioneaza si de ce este folosit. | + | * Inteleaga ce este MicroPython, cum functioneaza si de ce este folosit. |
- | 4. Configureze Raspberry Pi Pico in VS Code folosind extensia MicroPico. | + | * Configureze Raspberry Pi Pico in VS Code folosind extensia MicroPico. |
- | 5. Gaseasca adresa I2C a senzorului BMP280. | + | * Gaseasca adresa I2C a senzorului BMP280. |
- | 6. Conecteze si sa programeze senzorii pentru a citi date de la acestia. | + | * Conecteze si sa programeze senzorii pentru a citi date de la acestia. |
- | 7. Invete cum sa adune informatiile necesare pentru a scrie codul care citeste date de la senzori. | + | * Invete cum sa adune informatiile necesare pentru a scrie codul care citeste date de la senzori. |
====Partea I: Introducere teoretica==== | ====Partea I: Introducere teoretica==== | ||
+ | |||
+ | 1. Ce este Raspberry Pi Pico? | ||
+ | |||
+ | Raspberry Pi Pico este un microcontroler bazat pe cipul RP2040 dezvoltat de Raspberry Pi. Este ideal pentru proiecte de IoT, automatizari si roboti, fiind conceput pentru a interactiona cu senzori si alte componente electronice. | ||
+ | |||
+ | Caracteristici principale: | ||
+ | * Procesor dual-core ARM Cortex-M0+ la 133 MHz. | ||
+ | * 264 KB RAM. | ||
+ | * 26 pini GPIO care permit conectarea diverselor senzori si dispozitive externe. | ||
+ | * Suport pentru comunicatii I2C, SPI, UART, PWM si ADC. | ||
+ | |||
+ | |||
+ | 2. Ce este MicroPython? | ||
+ | |||
+ | MicroPython este o implementare usoara a Python, conceputa special pentru microcontrolere. Este eficienta si usor de utilizat, permitand dezvoltatorilor sa controleze senzori si alte componente hardware utilizand un limbaj de nivel inalt. | ||
+ | |||
+ | |||
+ | ====Partea II: Configurarea mediului de dezvoltare in VS Code==== | ||
+ | |||
+ | ==Instalarea si configurarea VS Code cu extensia MicroPico== | ||
+ | Pas 1: Descarca si instaleaza VS Code: | ||
+ | *Acceseaza https://code.visualstudio.com/ si descarca Visual Studio Code pentru sistemul tau de operare. | ||
+ | |||
+ | Pas 2: Instaleaza extensia MicroPico | ||
+ | |||
+ | * Deschide VS Code. | ||
+ | |||
+ | * Acceseaza Extensions (Ctrl+Shift+X) si cauta MicroPico. | ||
+ | |||
+ | * Instaleaza extensia si urmeaza instructiunile pentru configurarea mediului de dezvoltare pentru Raspberry Pi Pico. | ||
+ | |||
+ | Pas 3: Instalarea MicroPython pe Raspberry Pi Pico | ||
+ | |||
+ | * Conecteaza Pico la computer tinand apasat butonul BOOTSEL. | ||
+ | |||
+ | * Descarca fisierul MicroPython UF2 pentru Raspberry Pi Pico de pe https://micropython.org/download/rp2-pico/. | ||
+ | |||
+ | * Copiaza fisierul .uf2 in unitatea USB care apare in sistemul tau dupa conectarea Pico. | ||
+ | |||
+ | * Pico va reporni automat cu MicroPython instalat. | ||
+ | |||
+ | Pas 4: Testarea conexiunii in VS Code | ||
+ | |||
+ | * In VS Code, deschide un terminal nou (Ctrl + `) si apasa Ctrl + Shift + P pentru a deschide Command Palette. | ||
+ | |||
+ | * Selecteaza MicroPico: List Serial Ports si asigura-te ca portul corect pentru Pico este selectat. | ||
+ | |||
+ | * Daca totul este corect configurat, poti incepe sa rulezi cod pe Raspberry Pi Pico din VS Code. | ||
+ | |||
+ | |||
+ | ====Exercitii==== | ||
+ | |||
+ | ===Exercitiu 1: Utilizarea senzorilor BMP280 si LDR=== | ||
+ | |||
+ | 1. Conectarea senzorilor la Raspberry Pi Pico | ||
+ | |||
+ | * Senzorul BMP280 (I2C): | ||
+ | * SCL -> pin GP21. | ||
+ | * SDA -> pin GP20. | ||
+ | * VCC -> 3.3V. | ||
+ | * GND -> GND. | ||
+ | |||
+ | * Senzorul LDR: | ||
+ | * Un pin al LDR conectat la 3.3V si celalalt la pinul GP26 (ADC0). | ||
+ | {{:priot:laboratoare:conexiuni_raspberry_1.jpeg?600|}}{{:priot:laboratoare:conexiuni_raspberry_2.jpeg?600|}} | ||
+ | | ||
+ | |||
+ | ===Exercitiu 2: Citirea senzorului de lumina (LDR)=== | ||
+ | |||
+ | Pentru senzorul LDR, trebuie sa citesti o valoare analogica folosind ADC-ul de pe Raspberry Pi Pico. Urmatorii pasi te vor ajuta sa construiesti codul: | ||
+ | |||
+ | Ce trebuie sa stii: | ||
+ | * ADC (Analog to Digital Converter) este folosit pentru a converti semnalele analogice in valori numerice pe care Pico le poate procesa. | ||
+ | * In cazul unui LDR, poti citi intensitatea luminii prin intermediul unui pin ADC de pe Pico. | ||
+ | |||
+ | |||
+ | ===Exercitiu 3: Gasirea adresei senzorului I2C=== | ||
+ | |||
+ | Inainte de a putea citi date de la senzorul BMP280, trebuie sa afli adresa I2C a acestuia. Adresele I2C sunt unice pentru fiecare dispozitiv si pot varia. Procesul de a gasi adresa este esential pentru a comunica corect cu senzorul. | ||
+ | |||
+ | Pasul 1: Scrierea codului pentru scanarea dispozitivelor I2C | ||
+ | |||
+ | Pentru a gasi adresa senzorului, trebuie sa scrii un cod care sa scaneze dispozitivele I2C conectate la Raspberry Pi Pico. | ||
+ | |||
+ | Ce trebuie sa stii: | ||
+ | * I2C este un protocol de comunicatie utilizat pentru a conecta senzori si alte componente la un microcontroler. | ||
+ | * In Raspberry Pi Pico, poti utiliza biblioteca machine din MicroPython pentru a comunica cu dispozitivele I2C. | ||
+ | * Pinul SCL (Serial Clock) si pinul SDA (Serial Data) sunt necesare pentru comunicatia I2C. In acest laborator, vei folosi GP21 pentru SCL si GP20 pentru SDA. | ||
+ | |||
+ | Informatia necesara pentru a scrie codul: | ||
+ | * Foloseste functia scan() din obiectul I2C pentru a obtine o lista cu adresele dispozitivelor conectate. | ||
+ | |||
+ | ===Exercitiu 4: Citirea senzorului de temperatura=== | ||
+ | |||
+ | Acum ca ai gasit adresa senzorului BMP280, este timpul sa scrii codul care citeste datele de temperatura si presiune de la acesta. Pentru a face asta, trebuie sa intelegi urmatoarele concepte: | ||
+ | |||
+ | 1. Structura registrului BMP280 | ||
+ | * BMP280 comunica printr-un set de registre. Datele de temperatura si presiune sunt stocate in aceste registre si trebuie citite in format brut. | ||
+ | * Registrele importante pentru acest proiect sunt: | ||
+ | * 0xFA pana la 0xFC: Temperatura. | ||
+ | * 0xF7 pana la 0xF9: Presiune. | ||
+ | |||
+ | 2. Citirea coeficientilor de calibrare | ||
+ | * Senzorul BMP280 furnizeaza coeficienti de calibrare care sunt esentiali pentru a converti datele brute in valori corecte de temperatura si presiune. | ||
+ | * Acesti coeficienti se gasesc in registrele de calibrare care incep de la 0x88. | ||
+ | |||
+ | 3. Cum sa scrii functii pentru a citi datele | ||
+ | * Citeste datele brute din registre. | ||
+ | * Foloseste coeficientii de calibrare pentru a compensa valorile brute. | ||
+ | * Afiseaza rezultatele finale. | ||
+ | |||
+ | Etape: | ||
+ | * Initiaza senzorul: Scrie o functie pentru a seta senzorul in modul de operare normal. Acest lucru se face prin scrierea unei valori in registrul de control al senzorului. | ||
+ | * Citeste coeficientii de calibrare: Aceasta este o alta functie care citeste datele de calibrare de la senzor. Foloseste functia readfrom_mem() pentru a citi din registrele respective. | ||
+ | * Citeste valorile brute de temperatura si presiune: Scrie functii pentru a citi datele brute din registrele 0xF7-0xFC. | ||
+ | * Compenseaza datele: Foloseste formulele de calibrare specificate in documentatia BMP280 pentru a corecta valorile brute. | ||
+ | |||
+ | ==== Bibliografie ==== | ||
+ | |||
+ | - [[https://datasheets.raspberrypi.com/rp2040/rp2040-datasheet.pdf|Datasheet microcontroller RP2040]] | ||
+ | - [[https://datasheets.raspberrypi.com/pico/pico-datasheet.pdf|Datasheet Raspberry Pi Pico]] | ||
+ | - [[https://www.mouser.com/datasheet/2/783/BST-BME280-DS002-1509607.pdf?srsltid=AfmBOooMjmGwE224Ybw2eDvbuBsEsAHlDV7tL5KBk68xMOQx-3LOMppJ| Datasheet BME280]] | ||
+ | - [[https://www.raspberrypi.com/documentation/microcontrollers/c_sdk.html|Pico-SDK]] | ||
+ | - [[https://www.raspberrypi.com/documentation/pico-sdk/hardware.html#ga71d35b29e897b9bb4fc881b587b08cab|Documentatie Pico-SDK]] | ||
+ | - [[https://proto-pic.co.uk/content/RPI-PICO-R3-PUBLIC-SCHEMATIC.pdf|Schematic Raspberry Pi Pico]] | ||
+ | |||
+ | |||
+ | <hidden> | ||
+ | <code lang light.py> | ||
+ | from machine import ADC, Pin | ||
+ | import time | ||
+ | |||
+ | # Configurare pin pentru citirea senzorului de lumina (LDR) | ||
+ | light_sensor = ADC(0) # Pinul GP26 (A0) | ||
+ | |||
+ | while True: | ||
+ | # Citire valoare de la senzor (LDR) | ||
+ | light_value = light_sensor.read_u16() # Valorile sunt între 0 și 65535 | ||
+ | print("Valoare lumina:", light_value) | ||
+ | time.sleep(1) | ||
+ | |||
+ | </code> | ||
+ | <code lang adresa_senzor.py> | ||
+ | from machine import ADC, Pin | ||
+ | import time | ||
+ | |||
+ | # Configurare pin pentru citirea senzorului de lumina (LDR) | ||
+ | # Initializare I2C cu SDA pe GP20 și SCL pe GP21 | ||
+ | i2c = I2C(0, scl=Pin(21), sda=Pin(20), freq=100000) | ||
+ | |||
+ | # Scanare dispozitive I2C | ||
+ | devices = i2c.scan() | ||
+ | |||
+ | if devices: | ||
+ | print("Dispozitive I2C gasite:") | ||
+ | for device in devices: | ||
+ | print(hex(device)) # Afiseaza adresa în format hexazecimal | ||
+ | else: | ||
+ | print("Niciun dispozitiv I2C gasit") | ||
+ | </code> | ||
+ | |||
+ | <code lang temperature.py> | ||
+ | from machine import Pin, I2C | ||
+ | import time | ||
+ | |||
+ | # Initializare I2C cu SDA pe GP20 si SCL pe GP21 | ||
+ | i2c = I2C(0, scl=Pin(21), sda=Pin(20), freq=50000) | ||
+ | |||
+ | # Adresa senzorului BMP280/BME280 | ||
+ | address = 0x76 | ||
+ | |||
+ | # Registre pentru citirea temperaturii si presiunii brute | ||
+ | REG_TEMP_MSB = 0xFA | ||
+ | REG_TEMP_LSB = 0xFB | ||
+ | REG_TEMP_XLSB = 0xFC | ||
+ | REG_PRESS_MSB = 0xF7 | ||
+ | REG_PRESS_LSB = 0xF8 | ||
+ | REG_PRESS_XLSB = 0xF9 | ||
+ | REG_CONTROL = 0xF4 # Registrul de control | ||
+ | MODE_NORMAL = 0x27 # Mod normal, oversampling | ||
+ | |||
+ | # Registre de calibrare | ||
+ | REG_CALIB = 0x88 # De la adresa 0x88 incep coeficientii de calibrare | ||
+ | |||
+ | # Functie pentru initializarea senzorului | ||
+ | def init_sensor(): | ||
+ | # Setam senzorul in modul normal de operare (oversampling pentru temperatura si presiune) | ||
+ | i2c.writeto_mem(address, REG_CONTROL, bytes([MODE_NORMAL])) | ||
+ | time.sleep(0.5) # Pauza scurta pentru a permite initializarea | ||
+ | |||
+ | # Functie pentru citirea coeficientilor de calibrare | ||
+ | def read_calibration_data(): | ||
+ | calib = i2c.readfrom_mem(address, REG_CALIB, 24) | ||
+ | | ||
+ | dig_T1 = calib[0] | (calib[1] << 8) | ||
+ | dig_T2 = calib[2] | (calib[3] << 8) | ||
+ | dig_T3 = calib[4] | (calib[5] << 8) | ||
+ | | ||
+ | dig_P1 = calib[6] | (calib[7] << 8) | ||
+ | dig_P2 = calib[8] | (calib[9] << 8) | ||
+ | dig_P3 = calib[10] | (calib[11] << 8) | ||
+ | dig_P4 = calib[12] | (calib[13] << 8) | ||
+ | dig_P5 = calib[14] | (calib[15] << 8) | ||
+ | dig_P6 = calib[16] | (calib[17] << 8) | ||
+ | dig_P7 = calib[18] | (calib[19] << 8) | ||
+ | dig_P8 = calib[20] | (calib[21] << 8) | ||
+ | dig_P9 = calib[22] | (calib[23] << 8) | ||
+ | | ||
+ | return { | ||
+ | 'dig_T1': dig_T1, 'dig_T2': dig_T2, 'dig_T3': dig_T3, | ||
+ | 'dig_P1': dig_P1, 'dig_P2': dig_P2, 'dig_P3': dig_P3, | ||
+ | 'dig_P4': dig_P4, 'dig_P5': dig_P5, 'dig_P6': dig_P6, | ||
+ | 'dig_P7': dig_P7, 'dig_P8': dig_P8, 'dig_P9': dig_P9 | ||
+ | } | ||
+ | |||
+ | # Functie pentru citirea valorilor brute de temperatura | ||
+ | def read_raw_temp(): | ||
+ | msb = i2c.readfrom_mem(address, REG_TEMP_MSB, 1)[0] | ||
+ | lsb = i2c.readfrom_mem(address, REG_TEMP_LSB, 1)[0] | ||
+ | xlsb = i2c.readfrom_mem(address, REG_TEMP_XLSB, 1)[0] | ||
+ | raw_temp = (msb << 12) | (lsb << 4) | (xlsb >> 4) | ||
+ | return raw_temp | ||
+ | |||
+ | # Functie pentru citirea valorilor brute de presiune | ||
+ | def read_raw_press(): | ||
+ | msb = i2c.readfrom_mem(address, REG_PRESS_MSB, 1)[0] | ||
+ | lsb = i2c.readfrom_mem(address, REG_PRESS_LSB, 1)[0] | ||
+ | xlsb = i2c.readfrom_mem(address, REG_PRESS_XLSB, 1)[0] | ||
+ | raw_press = (msb << 12) | (lsb << 4) | (xlsb >> 4) | ||
+ | return raw_press | ||
+ | |||
+ | # Functie pentru compensarea temperaturii | ||
+ | def compensate_temperature(raw_temp, calib): | ||
+ | dig_T1 = calib['dig_T1'] | ||
+ | dig_T2 = calib['dig_T2'] | ||
+ | dig_T3 = calib['dig_T3'] | ||
+ | | ||
+ | var1 = (((raw_temp >> 3) - (dig_T1 << 1)) * dig_T2) >> 11 | ||
+ | var2 = (((((raw_temp >> 4) - dig_T1) * ((raw_temp >> 4) - dig_T1)) >> 12) * dig_T3) >> 14 | ||
+ | t_fine = var1 + var2 | ||
+ | temperature = (t_fine * 5 + 128) >> 8 | ||
+ | return temperature / 100.0, t_fine | ||
+ | |||
+ | # Functie pentru compensarea presiunii | ||
+ | def compensate_pressure(raw_press, calib, t_fine): | ||
+ | dig_P1 = calib['dig_P1'] | ||
+ | dig_P2 = calib['dig_P2'] | ||
+ | dig_P3 = calib['dig_P3'] | ||
+ | dig_P4 = calib['dig_P4'] | ||
+ | dig_P5 = calib['dig_P5'] | ||
+ | dig_P6 = calib['dig_P6'] | ||
+ | dig_P7 = calib['dig_P7'] | ||
+ | dig_P8 = calib['dig_P8'] | ||
+ | dig_P9 = calib['dig_P9'] | ||
+ | |||
+ | var1 = t_fine - 128000 | ||
+ | var2 = var1 * var1 * dig_P6 | ||
+ | var2 = var2 + ((var1 * dig_P5) << 17) | ||
+ | var2 = var2 + (dig_P4 << 35) | ||
+ | var1 = ((var1 * var1 * dig_P3) >> 8) + ((var1 * dig_P2) << 12) | ||
+ | var1 = (((1 << 47) + var1) * dig_P1) >> 33 | ||
+ | |||
+ | if var1 == 0: | ||
+ | return 0 # Pentru a evita diviziunea cu zero | ||
+ | |||
+ | pressure = 1048576 - raw_press | ||
+ | pressure = ((pressure << 31) - var2) * 3125 // var1 | ||
+ | var1 = (dig_P9 * (pressure >> 13) * (pressure >> 13)) >> 25 | ||
+ | var2 = (dig_P8 * pressure) >> 19 | ||
+ | |||
+ | pressure = ((pressure + var1 + var2) >> 8) + (dig_P7 << 4) | ||
+ | return pressure / 25600.0 # Conversie in hPa | ||
+ | |||
+ | # Initializam senzorul si citim coeficientii de calibrare | ||
+ | init_sensor() | ||
+ | calibration_data = read_calibration_data() | ||
+ | |||
+ | # Citire si afisare valori brute si compensate | ||
+ | try: | ||
+ | while True: | ||
+ | raw_temp = read_raw_temp() | ||
+ | raw_press = read_raw_press() | ||
+ | |||
+ | temp, t_fine = compensate_temperature(raw_temp, calibration_data) | ||
+ | press = compensate_pressure(raw_press, calibration_data, t_fine) | ||
+ | |||
+ | print("Valoare bruta temperatura:", raw_temp) | ||
+ | print("Valoare bruta presiune:", raw_press) | ||
+ | print("Temperatura compensata: {:.2f} C".format(temp)) | ||
+ | print("Presiunea compensata: {:.2f} hPa".format(press)) | ||
+ | time.sleep(2) | ||
+ | |||
+ | except OSError as e: | ||
+ | print("Eroare I2C:", e) | ||
+ | |||
+ | </code> | ||
+ | |||
+ | </hidden> | ||
+ | |||
+ | |||