Table of Contents

Închidere centralizată wireless pentru autoturisme

  • Nume: Popescu Ciprian-Mihail
  • Grupă: 332CD
  • Îndrumător: Răzvan Vîrtan

Introducere

În prezent, majoritatea autoturismelor noi vin cu dotări precum keyless entry și posibilitatea de a-ți conecta mașina la smartphone-ul personal prin intermediul unei aplicații dedicate.

Proiectul presupune implementarea unui sistem de keyless entry controlat din telefon, cât și montarea acestuia pe o mașină (mașina personală) care nu vine dotată cu sistemele menționate mai sus. Aplicația de pe smartphone va permite încuierea mașinii, cât și verificarea stării închiderii centralizate (încuiat/descuiat).

De asemenea, în traficul bucureștean și nu numai, ești lovit de situația în care, după ce ai ajuns la destinație, găsești un loc de parcare care nu-ți aparține, așa că îți lași numărul de telefon “în parbriz” astfel încât să poți fi contactat de proprietar în caz că ajunge acasă și nu își găsește locul liber.

Dar ce faci în cazul în care nu ai o hârtie sau pix ca să-ți treci numărul de telefon?

Ei bine, pe lângă sistemul de keyless entry, îți vei putea seta din aplicație datele de contact (prenume și număr de telefon), astfel încât acestea vor fi afișate pe un display.

Descriere generală

Schemă bloc

Mod de funcționare

Utilizatorul poate controla din aplicație:

Aplicația comunică cu placa de dezvoltare Arduino prin intermediul modulului HC-05, trimițând comenzile sus menționate.

Hardware Design

În realizarea proiectului voi folosi:

În diagrama circuitului, firele din ieșirile COM și NO ale modulului releu sunt lăsate “în aer”. Pentru vizualizarea conexiunii modulului releu cu modulul de închidere centralizată, vezi mai jos montajul pe mașină.

Pentru buna funcționare a circuitului de mai sus, designul este alcătuit din:

Am împărțit astfel, deoarece în circuitul buzzer-ului am folosit tranzistorul NPN 2N2222A pentru a amplifica curentul. Buzzerul pasiv este cunoscut pentru faptul că se aude încet, deci prin amplificarea curentului am reușit să măresc volumul buzzer-ului. Problema care apare aici este că amplificarea vine la pachet cu un consum mare de energie atât timp cât este pornit buzzer-ul (am fost lovit de situația în care LCD-ul “pâlpâia” pentru că nu avea suficient curent).

După cum se poate observa în setup, partea superioară a sursei de alimentare este setată pe OFF (nu avem nevoie de curent acolo, deoarece am conectat deja VCC-ul și GND-ul de la Arduino), iar partea inferioară am setat-o pe 5V.

Hei bună, am neastâmpărata asta pentru tine :)

Software Design

Arduino UNO R3

Software-ul pentru Arduino UNO R3 a fost realizat în Visual Studio Code, folosind extensia PlatformIO, unde am inclus bibliotecile LCD_I2C.h (îmi facilitează comunicarea cu display-ul) și SoftwareSerial.h (îmi permite să comunic serial cu modulul HC-05 folosind ceilalți pini digitali de pe Arduino).

În implementarea mea am definit două funcții auxiliare: commandParser() și serialFlush(). Modulul de Bluetooth HC-05 primește de la aplicația de pe telefon o comandă, îndeplinindu-se condiția BTSerial.available(), astfel se apelează funcția de parsare a comenzii, urmând să se execute rutina specifică. Comenzile implementate sunt:

Comanda setBtCred trece modulul HC-05 în modul AT (un fel de “sudo”), unde, în funcție de parametrii primiți, construiește comenzile AT specifice operațiunii dorite (AT+NAME=<1> setează numele modulului Bluetooth care o să apară în lista de pairing și AT+PSWD=<2> setează PIN-ul pe care utilizatorul va trebui să-l introducă în momentul în care realizează pairing-ul cu modulul). La finalul execuției fiecărei comenzi AT, modulul va returna pe serial stringul OK, așa că folosesc funcția serialFlush() pentru a goli buffer-ul.

Fiecare comandă executată va întoarce pe serial success sau fail, fiind mai ușoară gestionarea erorilor în aplicația de pe telefon.

În final, în funcția loop() am realizat blink-ul pentru martorul de încuiere/descuiere, folosind millis() în loc de delay(), deoarece nu întrerup execuția instrucțiunilor.

Aplicația Android

Această aplicație a fost realizată în Android Studio, folosind limbajul de programare Kotlin. Template-ul ales pentru proiect este “Bottom Navigation Views Activity”, după care am setat SDK-ul pe nivelul API 31 (Android 12 Snow Cone), adică versiunea minimă de Android care suportă aplicația.

Partea de UI a aplicației este compusă dintr-un MainActivity, care conține un indicator de progres (este ascuns utilizatorului – afișat la nevoie, de exemplu când se realizează un task), bara de navigație care conține trei butoane spre fiecare meniu și host fragment-ul (un fel de “iframe” din HTML). Toate iconițele pentru butoane și TextInput-uri sunt importate din Vector Asset.

Toate componentele folosite în aplicație folosesc Material 3, ultima versiune de design system creată de Google.

În HomeFragment se regăsesc două MaterialCardView-uri (pe care le-am făcut clickable, deci sunt butoane) și un FloatingActionButton:

La prima rulare a aplicației de după instalare, se va solicita acordarea permisiunii Nearby devices. După acordarea permisiunilor, utilizatorul poate continua spre selectarea dispozitivului dorit. Dacă se refuză prima dată acordarea permisiunii, utilizatorului i se va afișa un MaterialAlertDialog (numit și “permission rationale”) în care este explicat faptul că aplicația are nevoie de permisiunea respectivă pentru funcționarea corectă. Dacă după acest mesaj se mai refuză o dată acordarea permisiunii, utilizatorul este informat că aplicația va rula cu funcționalități limitate. Dacă acesta se răzgândește, este redirecționat spre pagina de setări a aplicației, de unde poate acorda manual permisiunea necesară.

Toată logica pentru prompt-urile de runtime permissions se află în HomeFragment.kt.

În DisplayFragment am folosit un MaterialCardView în care am adăugat două TextInput-uri (unde utilizatorul își va completa datele de contact), un SwitchMaterial (poți alege dacă vrei să afișezi datele de contact sau nu) și un MaterialButton căruia i-am setat un onClickListener (după apăsarea butonului, aplicația generează comenzile specifice fiecărui câmp completat și le adaugă în coada de execuție a task-urilor).

  1. În prima imagine comenzile generate vor fi setInfo:Ciprian,1234567890123456 și hideInfo:0
  2. În a doua imagine comenzile generate vor fi setInfo:Ciprian,* și hideInfo:0
  3. În a treia imagine comenzile generate vor fi setInfo:*,1234567890123456 și hideInfo:0
  4. În ultima imagine comenzile generate vor fi setInfo:*,* și hideInfo:1

Pentru punctul 4 comanda setInfo:*,* este generată onClick, însă pentru că nu face nimic, aceasta nu va fi adăugată în coada de execuție.

Dak nu era Bujie pă intervenție, nu a-r fii arătat așa șukar fragmentu

SettingsFragment are un layout și un comportament similar: în loc să genereze comenzile setInfo și hideInfo, va genera comanda setBtCred în funcție de câmpurile completate. Însă, după ce se înregistrează un onClickEvent, utilizatorul este informat că dispozitivul va reporni, iar reconectarea va fi necesară.

Dacă nu exista maneaua asta nu știu cum rezistam să scriu atâta

Pentru a facilita accesul la thread-ul de conexiune, cât și comunicarea cu MainActivity, am creat o interfață cu două metode abstracte: connectTo() și getBtConnection(). Metoda connectTo() este apelată din SelectBtDeviceFragment.kt pentru a putea trimite mai departe spre prelucrare către MainActivity dispozitivul selectat de utilizator, deoarece ciclul de viață al unui fragment se limitează la perioada în care conținutul acestuia este afișat pe ecran (după ce acesta este scos de pe back stack, ajunge în starea DESTROYED, iar toate datele din acel fragment vor fi pierdute).

Din punct de vedere al modului de funcționare, aplicația funcționează pe 2 thread-uri: primul thread (main) se ocupă de UI/UX, iar al doilea thread se ocupă atât de stabilirea conexiunii Bluetooth cu modulul HC-05, cât și de executarea task-urilor din coada de execuție. Pe măsură ce utilizatorul blochează/deblochează mașina, setează datele de contact, etc., thread-ul main (dispatcher-ul) va genera comenzile implementate în Arduino, pe care le va adăuga în coada de execuție a thread-ului de conexiune (ConnectionThread cum l-am denumit în implementare).

enqueue_example.kt
val btConnection = activityPipe!!.getBtConnection()
if (contactCommand != "setInfo:*,*") {
    btConnection!!.enqueueJob(this@DisplayFragment, contactCommand)
}
btConnection!!.enqueueJob(this@DisplayFragment, displayCommand)

Am ales să folosesc multithreading, deoarece execuția comenzilor din coadă necesită trimiterea acestora pe serial, așteptarea unui răspuns al Arduino-ului (success sau fail, plus starea curentă a închiderii centralizate – în cazul comenzii sync), ceea ce presupune folosirea unui while (în care am setat un timp maxim de așteptare de 5 secunde, după care inițiez un timeout, care va opri imediat thread-ul și va închide socket-ul de Bluetooth). Această așteptare după un răspuns blochează complet aplicația, deoarece singurul thread disponibil care se ocupa de animații, onClickEvent-uri, etc. este ocupat să execute bucla, fiind un comportament nedorit și de evitat.

Montare

Pentru montarea efectivă a sistemului wireless pe autoturism, am parcurs următoarele etape:

Rezultate Obţinute

În final, circuitul pentru acest proiect și partea software funcționează exact cum am vrut: absolut toată interacțiunea cu sistemul wireless de închidere centralizată se realizează prin intermediul aplicației Android, nemaifiind necesară intervenția utilizatorului asupra componentelor după instalare, de exemplu dacă se dorește schimbarea credențialelor modulului Bluetooth, software-ul se va ocupa atât de modificarea setărilor (includem schimbarea în modul AT fără apăsarea butonului fizic de către utilizator), cât și de repornirea modulului pentru ca acestea să fie aplicate imediat.

După atâta muncă, ar merge acum un test drive

Concluzii

Proiectul a fost unul foarte interesant, dar și challenging. Am avut ocazia să învăț multe lucruri de la zero, în special partea de Android a software-ului, cu care nu mai lucrasem până acum. Mi-a plăcut să lucrez la acest proiect și am învățat multe aspecte noi care îmi vor fi utile pe viitor. Am dobândit cunoștințe valoroase în dezvoltarea de aplicații Android și cred cu tărie că această experiență m-a ajutat să îmi dezvolt abilitățile și să capăt mai multă încredere în lucrul cu tehnologii noi.

De asemenea, mi-a plăcut să îmi “creez” un upgrade (sau dotare) pentru mașina personală și să stau să meșteresc pe sub volan (însă a rămas o adevărată harababură, deci va trebui să găsesc o zi liberă ca să montez la loc ornamentele și plasticele de sub volan LOL).

Pentru că ai ajuns până aici, am ceva pentru tine

Download

Link repository GitHub

Bibliografie/Resurse

Hardware

Plusivo Wireless Super Starter Kit with ESP8266 Guide, pagina 72

MB102 Datasheet

KEETEC TS-10 Datasheet

Block Diagram Tool

Hardware Design Tool

Software

Arduino

HC-05 Datasheet

Biblioteca SoftwareSerial

Biblioteca LCD_I2C

Android

Material Theme Builder

Material 3 UI Components

Bluetooth Setup

Find Bluetooth devices

Connect Bluetooth devices

Request runtime permissions

Comunicare de la Fragment la Activity