This is an old revision of the document!


Laboratorul 02. I2C - Haptics, Accelerometru

În laboratorul de astăzi veți învăța cum să interactionați cu diferite periferice prin I2C și cum datele de la hardware sunt transmise utilizatorului prin diferite niveluri de indirectare. Vom explora atât noțiuni low-level () cât și aspecte mai high-level (trimiterea datelor catre utilizator) construite peste.

Un modul de kernel (sau un device driver) este o bucată specializată de cod care este compilată și adăugată la kernel-ul sistemului de operare. În acest mod, sistemul de operare are posibilitatea de a interacționa cu diferite periferice - în absența driverelor, un kernel nu ar putea accesa lumea exterioară CPU-ului. De exemplu, dacă ne dorim ca sistemul nostru să poată transfera date prin controller-ul de I2C, avem nevoie de un driver pentru I2C care să programeze aceste tranzacții de transfer de date. Analog, dacă ne dorim să interacționăm cu un senzor, avem nevoie de un device driver care știe să programeze acel senzor.

Aproximativ 80% din codul unui sistem de operare este format din codul pentru drivere.

Din punct de vedere al user-ului, driverele pot să fie expuse în două moduri:

  • char device driver - în Linux sunt folosite pentru mouse și tastatură, de exemplu, iar în NuttX pentru senzori, printre altele. Pe scurt, dispozitive cu rată mică de transfer de date, care functionează la nivel de caracter (byte).
  • block device driver - folosite pentru hdd-uri, sdd-uri, device-uri care au nevoie să transfere date la nivel de blocuri (4KB de obicei).

I2C

I2C (Inter-Integrated Circuit) este un protocol de comunicație serială dezvoltat de Philips (acum NXP) în anii ’80, folosit pe scară largă pentru a conecta microcontrolere cu senzori, memorii, afișaje și alte periferice. Este foarte popular în proiecte embedded datorită simplității și numărului redus de pini necesari.

I2C este un protocol care functioneaza sub paradigma master-slave prin care un “master” (de obicei microcontroller-ul, in cazul nostru ESP32S3-ul) citeste sau scrie date de pe un device denumit “slave” (cele mai comune device-uri de acest fel in lumea embedded fiind senzorii).

Astfel, magistrala (bus-ul) este definita din doua linii de comunicatie:

  • SDA (Serial Data) - folosita pentru transmisia datelor.
  • SCL (Serial Clock) - folosita pentru propagarea ceasului dupa care se face esantionarea datelor.

Transmisia datelor se face in mod bidirectional (master → slave in cazul operatiei de write si slave → master in caz de read), insa nu este full-duplex - doar un singur device poate sa detina controlul SDA-ului in orice moment de timp. SCL-ul este intotdeauna generat de master-ul comunicatiei si este propagat catre toate dispozitivele de tip slave.

Fiecare dispozitiv slave este identificat printr-o adresa pe 7 biti la care se adauga un bit pentru R/W. Astfel:

  • pentru operatiile de write, master-ul pune pe magistrala si datele de transmis, iar slave-ul este in modul de “listening”.
  • pentru operatiile de read, dupa transmisia adresei si a bit-ului de R/W, slave-ul preia controlul SDA-ului, iar master-ul intra in modul de “listening” pentru a receptiona datele.

DRV2605L - senzor haptics

LSM6DSL - accelerometru si giroscop

Exerciții

Pentru a putea rula exercitiile, este nevoie să compilați NuttX folosind hacktorwatch:iot, la care va trebui sa activati manual cateva config-uri folosindu-va de sistemul de build (make menuconfig). Astfel, veti activa atat compilarea codului de driver si initializarea efectiva a hardware-ului, cat veti si incarca pe placa aplicatii de demo pe care le puteti rula.

Ca sa folositi senzorul de haptics, aveti nevoie de urmatoarele config-uri:

  • CONFIG_FF_DRV2605L
  • CONFIG_DRV2605L_TS2200_LIBRARY_A
  • CONFIG_EXAMPLES_DRV2605L

Atentie la dependintele lui CONFIG_FF_DRV2605L. In cadrul acestui exercitiu de set-up va trebui sa determinati care sunt acele dependinte si sa le activati mai intai pe acelea.

Pentru a valida ca ati configurat NuttX corect, este suficient un simplu restart de ceas. Codul de initializare din cadrul sistemului de operare realizeaza o calibrare a senzorului de haptics la boot time, iar ceasul va vibra.

Cele doua config-uri de mai jos va vor oferi access la accelerometru si giroscop:

  • CONFIG_SENSORS_LSM6DSL
  • CONFIG_EXAMPLES_LSM6DSL_READER

La fel ca in cazul device-ului de haptics, atentie la dependintele acestor config-uri.

1. Pentru a va acomoda cu API-ul pe care NuttX il ofera pentru a interactiona cu cele doua device-uri, in cadrul acestui exercitiu va trebui sa inspectati codul si sa rulati aplicatiile de demo disponibile in repository-ul nuttx-apps.

  1. nuttx-apps/examples/drv2605l/ initializeaza device-ul cu anumite efecte de vibrare (upload_rom_effect, upload_constant_effect). Apelarea acestora se face ulterior, “on demand”, prin play_effect.
  2. nuttx-apps/examples/lsm6dsl_reader afiseaza la consola o data la doua secunde datele obtinute de la accelerometru si giroscop. Observati modul de interactiune cu senzorul: acesta este expus printr-o intrare in /dev/ care va trebui folosita in cadrul apelului de sistem open, iar mai apoi folosim apeluri de ioctl pentru a interactiona cu hardware-ul.
  3. Cautati definitiile pentru structurile de date folosite in ambele aplicatii.

Toate fișierele de tip header le puteți găsi în nuttx/include/nuttx/. Puteți căuta recursiv din linia de comandă folosind grep -r <string>.

2. In cadrul acestui exercitiu, vrem ca ceasul sa ne ofere informatii (prin vibrare) atunci cand viram stanga, respectiv dreapta.

  1. Folosindu-ne de lsm6dsl_reader vom citi datele oferite de accelerometru si vom determina directia de mers.
  2. Daca ceasul este nemiscat sau merge inainte nu va oferi niciun fel de feedback utilizatorului.
  3. drv2605l are o biblioteca interna de efecte de vibrare pe care o puteti consulta aici, la pagina 63. Alegeti doua efecte din acest tabel si incarcati-le pe ceas.
  4. In functie de directia de mers, vom rula in mod constant unul dintre cele doua efecte pana cand ceasul va reveni in stare initiala (ceasul este nemiscat sau sau se misca doar inainte).

Hint: pentru a opri un efect, trebuie sa scrieti o functie care realizeaza inversul lui play_effect. Parametrul care ne intereseaza si trebuie modificat este play.value (trebuie sa fie setat pe 0 - disabled).

3. (Bonus) La exercitiul anterior, intensitatea de vibrare era absoluta (on/off). Ne dorim sa avem un mecanism mai complex prin care sa folosim vibrare graduala in functie de nivelul acceleratiei - cu cat acceleratia este mai mare, cu atat vibratia va fi mai puternica.

si/iot2025/lab02.1754756470.txt.gz · Last modified: 2025/08/09 19:21 by robert_ionut.alexa
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0