Cuprins:

Media de rulare pentru proiectele dvs. de microcontroler: 6 pași
Media de rulare pentru proiectele dvs. de microcontroler: 6 pași

Video: Media de rulare pentru proiectele dvs. de microcontroler: 6 pași

Video: Media de rulare pentru proiectele dvs. de microcontroler: 6 pași
Video: Cum să controlați încărcarea cu 4 ca, folosind releul fără telecomandă KR1204 2024, Decembrie
Anonim
Medie de rulare pentru proiectele dvs. de microcontroler
Medie de rulare pentru proiectele dvs. de microcontroler

În acest instructiv, voi explica ce este o medie de rulare și de ce ar trebui să vă pese de ea, precum și să vă arăt cum trebuie implementată pentru o eficiență calculală maximă (nu vă faceți griji cu privire la complexitate, este foarte simplu de înțeles și voi oferiți o bibliotecă ușor de utilizat și pentru proiectele dvs. arduino:)

Media de funcționare, denumită în mod obișnuit și medie mobilă, medie mobilă sau medie de funcționare, este un termen folosit pentru a descrie valoarea medie a ultimelor N valori din seriile de date. Poate fi calculat la fel ca media normală sau puteți utiliza un truc pentru a avea un impact minim asupra performanței codului dvs.

Pasul 1: caz de utilizare: netezirea măsurătorilor ADC

Caz de utilizare: Netezirea măsurătorilor ADC
Caz de utilizare: Netezirea măsurătorilor ADC

Arduino are un ADC decent de 10 biți cu foarte puțin zgomot. Când măsurați valoarea unui senzor, cum ar fi potențiometrul, fotorezistorul sau alte componente cu zgomot ridicat, este greu să aveți încredere că măsurarea este corectă.

O soluție este să luați mai multe măsurători de fiecare dată când doriți să citiți senzorul și să le calculați în medie. În unele cazuri, aceasta este o soluție viabilă, dar nu întotdeauna. Dacă doriți să citiți ADC de 1000 de ori pe secundă, ar trebui să faceți 10 000 dacă ați lua în medie 10 măsurători. O mare pierdere de timp de calcul.

Soluția mea propusă este de a lua măsurători de 1000 de ori pe secundă, de a actualiza media de rulare de fiecare dată și de a o folosi ca valoare curentă. Această metodă introduce o anumită latență, dar reduce complexitatea de calcul a aplicației dvs., oferindu-vă mult mai mult timp pentru procesare suplimentară.

În imaginea de mai sus am folosit media de rulare a ultimelor 32 de măsurători. Veți vedea că această metodă nu este 100% rezistentă la erori, dar îmbunătățește semnificativ acuratețea (nu este mai rău decât media a 32 de eșantioane de fiecare dată). Dacă ați dori să calculați o medie de 32 de măsurători de fiecare dată, ar dura peste 0,25 ms pe Arduino UNO numai pentru măsurători!

Pasul 2: caz de utilizare: măsurarea componentei CC a semnalului microfonului

Caz de utilizare: măsurarea componentei CC a semnalului microfonului
Caz de utilizare: măsurarea componentei CC a semnalului microfonului
Utilizare: măsurarea componentei CC a semnalului microfonului
Utilizare: măsurarea componentei CC a semnalului microfonului
Utilizare: măsurarea componentei CC a semnalului microfonului
Utilizare: măsurarea componentei CC a semnalului microfonului

Arduino poate măsura tensiuni între 0 și Vcc (în mod normal 5 V). Semnalul audio este complet AC și dacă doriți să îl măsurați pe un microcontroler, trebuie să-l plasați în jur de 1/2 Vcc. Într-un proiect Arduino UNO care ar însemna aproximativ 2,5 V (DC) + semnal audio (AC). Când utilizați sursa de alimentare ADC de 10 biți și 5 V, distorsiunea de 2,5 V trebuie să fie egală cu o măsurare de 512. Deci, pentru a obține o valoare de curent alternativ a semnalului, 512 ar trebui scăzut din măsurarea ADC și asta este, nu?

Într-o lume ideală, asta ar fi adevărat. Din păcate, viața reală este mai complicată, iar tendința noastră de semnal tinde să derive. Foarte frecvent este zgomotul de 50 Hz (60 Hz dacă locuiți în SUA) din rețeaua electrică. De obicei, nu este prea problematic, dar este bine să știm că există. Mai problematică este derivarea liniară de la încălzirea componentelor. Setați cu atenție corecția offset DC la pornire și se îndepărtează încet pe măsură ce aplicația dvs. rulează.

Voi ilustra această problemă cu un detector de ritm (muzical). Vă configurați eliminarea prejudecății și bătăile sunt clare (imaginea 2). După ceva timp, polarizarea DC se mișcă și bătăile sunt abia vizibile pentru microcontroler (imaginea 3). Algoritmul de detectare a bătăilor va fi explorat în profunzime într-un viitor instructiv, deoarece depășește domeniul de aplicare al acestui articol.

Din fericire, există o modalitate de a continua să calculăm în mod constant offset-ul audio DC. Nu va fi o surpriză faptul că media de rulare, subiectul acestui instructable, oferă o soluție.

Știm că valoarea medie a oricărui semnal de curent alternativ este 0. Folosind aceste cunoștințe putem deduce că valoarea medie a semnalului de curent alternativ + curent continuu este că este o polarizare continuă. Pentru a-l elimina, putem lua o medie de funcționare a ultimelor câteva valori și o putem scădea din citirea ADC curentă. Rețineți că trebuie să utilizați o medie de rulare suficient de lungă. Pentru sunet, o zecime de secundă (numărul de eșantioane depinde de rata de eșantionare) ar trebui să fie suficientă, dar să știți că mediile mai lungi funcționează mai bine. În prima imagine puteți vedea un exemplu de calcul al polarizării DC reale cu media de rulare cu 64 de elemente la o rată de eșantionare de 1 kHz (mai puțin decât am recomandat, dar funcționează în continuare).

Pasul 3: Calcul

Calcul
Calcul

Vă puteți imagina media de rulare ca o medie a greutății persoanelor din sala de așteptare a medicului. Doctorul termină examinarea unui pacient și simultan unul nou intră în sala de așteptare.

Pentru a afla greutatea medie a tuturor pacienților care așteaptă în sala de așteptare, asistenta ar putea apoi să întrebe fiecare pacient despre greutatea lor, să adune aceste numere și să împartă la numărul de pacienți. De fiecare dată când medicul acceptă un nou pacient, asistenta ar repeta întregul proces.

S-ar putea să vă gândiți: „Acest lucru nu sună prea eficient … Trebuie să existe o modalitate mai bună de a face acest lucru.” Și ai fi corect.

Pentru a optimiza acest proces, asistenta ar putea ține o evidență a greutății totale a grupului actual de pacienți. Odată ce medicul sună pacientul nou, asistenta îl întreabă despre greutatea sa și îl scade din totalul grupului și îl lasă să plece. Asistenta ar întreba apoi pacientul care tocmai a intrat în sala de așteptare despre greutatea sa și a adăugat-o la total. Greutatea medie a pacienților după fiecare schimbare ar fi suma greutăților împărțite la numărul de pacienți (da, la fel ca înainte, dar acum asistenta a întrebat doar două persoane despre greutatea lor în loc de toți). Îmi dau seama că acest paragraf ar fi putut fi puțin confuz, așa că vă rugăm să consultați ilustrația de mai sus pentru mai multă claritate (sau puneți întrebări în comentarii).

Dar, chiar dacă nu ați găsit confuz ultimul paragraf, s-ar putea să aveți întrebări precum ce ar trebui să fie în acumulator la început, cum pot pune ceea ce tocmai am citit într-un cod C real? Acest lucru va fi abordat în pasul următor, unde veți obține și codul meu sursă.

Pasul 4: Codul

Codul
Codul

Pentru a calcula media de rulare, mai întâi aveți nevoie de o modalitate de a stoca ultimele N valori. ați putea avea o matrice cu N elemente și puteți muta întregul conținut la un loc de fiecare dată când adăugați un element (vă rugăm să nu faceți acest lucru), sau puteți suprascrie un element vechi și reglați indicatorul la următorul element pentru a fi aruncat (vă rugăm să faceți acest lucru:)

Acumulatorul ar trebui să înceapă inițializat la 0, același lucru este valabil pentru toate elementele din linia de întârziere. În alt caz, media de rulare va fi întotdeauna greșită. Veți vedea că delayLine_init se ocupă de inițializarea liniei de întârziere, ar trebui să vă ocupați singur de acumulator.

adăugarea unui element la linia de întârziere este la fel de ușoară ca descreșterea indexului celui mai nou element cu 1, asigurându-ne că nu indică partea matricei de linie de întârziere. după decrementarea indexului atunci când este 0, va rula în jurul valorii de 255 (deoarece este un număr întreg de 8 biți nesemnat). Operatorul Modulo (%) cu dimensiunea liniei de întârziere se va asigura că indexul va indica un element valid.

Calculul unei medii curente ar trebui să fie ușor de înțeles dacă mi-ați urmat analogia în pasul anterior. Scoateți cel mai vechi element din acumulator, adăugați cea mai nouă valoare acumulatorului, împingeți cea mai nouă valoare pe linia de întârziere, întoarceți acumulatorul împărțit la numărul de elemente.

Ușor, nu?

Nu ezitați să experimentați utilizarea codului atașat pentru a înțelege mai bine cum funcționează toate acestea. În prezent, arduino citește valoarea analogică pe pinul analogic A0 și tipărește „[valoare ADC], [medie de rulare]” pe portul serial la o rată de 115200 baud. Dacă deschideți plotterul serial arduino la rata de transmisie corectă, veți vedea două linii: valoarea ADC (albastru) și valoarea netezită (roșu).

Pasul 5: Extra

In plus
In plus

Există câteva lucruri pe care nu trebuie neapărat să le cunoașteți pentru a utiliza media de rulare în proiectul dvs. ut nu va strica să știți.

întârziere: voi începe cu a vorbi despre ilustrarea acestui pas. Veți observa că media de rulare a mai multor elemente introduce o întârziere mai mare. Dacă timpul dvs. de răspuns la schimbarea valorii este critic, vă recomandăm să utilizați o medie de rulare mai scurtă sau să măriți rata de eșantionare (măsurați mai des).

Trecând peste.

inițializare: Când am vorbit despre inițializarea acumulatorului și a elementelor de întârziere, am spus că ar trebui să le inițializăm pe toate la 0. Alternativ, puteți inițializa linia de întârziere la orice doriți, dar acumulatorul ar trebui să înceapă ca o sumă de cele mai noi N elemente din linia de întârziere (unde N este numărul de elemente din media dvs. de rulare). Dacă acumulatorul pornește ca orice altă valoare, media calculată va fi greșită - fie prea mică, fie prea mare, întotdeauna cu aceeași cantitate (presupunând aceleași condiții inițiale). Vă sugerez să încercați să aflați de ce este așa utilizând o „simulare stilou și hârtie”.

dimensiunea acumulatorului: ar trebui să rețineți, de asemenea, că acumulatorul ar trebui să fie suficient de mare pentru a stoca suma tuturor elementelor în linia de întârziere dacă toate sunt maxime pozitive sau negative. Practic, acest lucru înseamnă că acumulatorul ar trebui să fie cu un tip de date mai mare decât elementele de linie de întârziere și semnat, dacă elementele de linie de întârziere sunt semnate.

truc: Liniile cu întârziere lungă ocupă multă memorie. Acest lucru poate deveni rapid o problemă. Dacă sunteți foarte limitat de memorie și nu vă pasă prea mult de acuratețe, puteți aproxima media de rulare omițând întârzierea complet și făcând acest lucru în schimb: scădeți acumulatorul 1 / N * din acumulator și adăugați o valoare nouă (de exemplu, media medie de funcționare 8: acumulator = acumulator * 7/8 + newValue). Această metodă dă rezultate greșite, dar este o metodă decentă de calcul al mediei de rulare atunci când nu aveți suficientă memorie.

lingvistică: „media de rulare / medie” este de obicei utilizată atunci când se referă la media în timp real, în timp ce „media mobilă / medie” înseamnă, de obicei, că algoritmul rulează pe un set de date statice, cum ar fi foaia de calcul Excel.

Pasul 6: Concluzie

Sper că acest instructiv a fost suficient de ușor de înțeles și că vă va ajuta în proiectele viitoare. Vă rugăm să nu ezitați să postați întrebări în comentariile de mai jos dacă există ceva neclar.

Recomandat: