This is an old revision of the document!
Proiectul are ca scop crearea unui modul extern capabil sa transmita un flux video de la distante relativ mari, in dezavantajul calitatii imaginii si a numarului scazut de cadre pe secunda.
Laboratoare folosite: 1
(USART), 2
(Intreruperi), 3
(Timere) si 5
(SPI).
Schema bloc:
Modulul extern este format dintr-un:
Modulul local este format din:
Schema:
Cele doua transceivere LoRa functioneaza in mod half-duplex. In acest design, transceiver-ul de pe modulul local trebuie sa verifice CRC
-ul pachetului si sa transmita inapoi un tip de ACK
.
Pinul DIO0
de pe LoRa genereaza intreruperi. Cele trei care ne intereseaza sunt:
onReceive
. Un pachet nou este disponibil in bufferul LoRa.onTxDone
. Pachetul din buffer a fost trimis. Bufferul poate fi refolosit. Nu se garanteaza ca celalalt LoRa a primit pachetul.onCrcError
. A venit un pachet nou, insa CRC-ul nu este corect. Continutul pachetului nu este disponibil.
Exista un bug documentat, dar inca prezent in cea mai recenta versiune a bibliotecii: nu apare intreruperea lui onTxDone
, chiar daca bufferul a fost golit:
int LoRaClass::endPacket(bool async) { ... if (_onTxDone && (readRegister(REG_IRQ_FLAGS) & IRQ_TX_DONE_MASK) == IRQ_TX_DONE_MASK) { handleDio0Rise(); ... }
onCrcError
nu este implementat deloc. Tratamentul standard implica aruncarea silentioasa a pachetelor cu CRC-ul gresit. Am pus interrupt-ul in biblioteca (copiat comportamentul de la onTxDone
si adaugat un else
ca sa previn drop-ul):
void LoRaClass::handleDio0Rise() { ... if ((irqFlags & IRQ_PAYLOAD_CRC_ERROR_MASK) == 0) { ... } else if (_onCrcError) { _onCrcError(); } }
Design sumar al algortimului de compresie:
256 x 256
.v[0..255][0.255]
.d[i][j][l]
si D[i][j][L]
pentru anumiti i, j
din [0..255]
si l
putere a lui 2
.d[i][j][l]
reprezinta valoarea minima a unui pixel din careul [i..i+l-1] x [j..j+l-1]
.D[i][j][l]
reprezinta valoarea maxima a unui pixel din careul [i..i+l-1] x [j..j+l-1]
.scor
o functie care accepta parametrii l, minVal, maxVal
. Daca scor(l, d[i][j][l], D[i][j][l]) ⇐ thresh
(o constanta), nu mai sparg careul in patru cadrane si aproximez toti pixelii din careu cu media valorilor lor.(i, j, l)
in patru cadrane:(i, j, l/2)
,(i, j + l/2, l/2)
,(i + l/2, j, l/2)
,(i + l/2, j + l/2, l/2)
.
Matricele d[][][]
si D[][][]
se construiesc de la l
mic la mare (bottom-up), apoi urmeaza recursia top-down.
Pe ESP32-CAM
d
si D
sunt reprezentate liniar. Interactiunea fiu-tata este foarte similara cu cea de la reprezentarea unui heap in memorie (numarand de la 0
, daca tatal este la pozitia i
, fiii sunt la pozitiile 2i+1
si 2i+2
).
Diferenta este ca aici un nod are 4
fii, iar fiecare nod ocupa 3
pozitii consecutive, una pentru fiecare culoare.
int getChild(int r, int id) { return ((r / 3) * 4 + id) * 3; } int getFather(int r) { return ((r / 3) - 1) / 4 * 3; }
Functia scor are urmatoarea implementare:
dispThresh = 80 def corectorDisp(arie: int) -> float: #daca aria este prea mica, mai las din dispThresh. if arie > 1000: return 1.0 ex = math.exp(arie * 0.00390625) #coef pt 1024x768. cu cat e coef mai mic, cu atat compreseaza mai tare. return ex / (1 + ex) #normalizare pe [0, 1] cu sigmoid. def scor(l, minVal, maxVal): #minVal si maxVal in [0, 255]. return (maxVal - minVal) * corectorDisp(l * l) #spargere daca scor(l, d[i][j][l], D[i][j][l]) > dispThresh.
Pe ESP32-CAM
coeficientii de corectie sunt tinuti direct intr-o tabela de lookup. Normalizarea pe 0 - 1
in loc de 0.5 - 1
produce mult mai putini pixeli cu arii diferite.
<code c>
static float coef_corector_lookup[9] = {0.501f, 0.5039f, 0.5156f, 0.5622f, 0.7311f, 0.982f, 1.0f, 1.0f, 1.0f}; //0.00390625f
</code c>
Simularea locala a algortimului de compresie.
0.12%
din pixeli pastrati dupa compresie.
0.3%
din pixeli pastrati dupa compresie.
Schema protocolului pentru trimiterea unui cadru. Exista exemple pentru CRC fail si pentru pachet pierdut.
Mai jos sunt cateva poze obtinute in urma compresiei pe microcontroller:
Un zambet compresat. Paleta deplasata de culori poate fi cauzata de formatul RGB565.
808
pixeli compresati (1.2%
), 2.95KB
.
Unicul IDE si un portal catre cealalta lume (afara).
1174
pixeli compresati (1.8%
), 4.45KB
.
Biroul. Unele detalii sunt mult mai clare (marginile dintre doua culori indeajuns de diferite, fire de pe breadboard).
2107
pixeli compresati (3.2%
), 8.25KB
.
Daisychain ESP32-CAM –(serial)–> ESP32-WROOM –(serial)–> laptop
, 115200
bps. Link video (speedup 2x
)
Poza cu transmiterea prin LoRa functionala:
Test cu LoRa (speedup 4x
, ~4500
bps):