Table of Contents

Long-distance Lossy Livestream - Ulmeanu Vlad-Adrian 335CA

Introducere

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).

Descriere generală

Schema bloc:

Hardware Design

Modulul extern este format dintr-un:

Modulul local este format din:

Schema:

pmproj_uva_schematic.pdf

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:

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();
    }
}

Receiver-ul si sender-ul trecute pe placi de prototipare:

Software Design

Design sumar al algortimului de compresie:

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.

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

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.

(Concluzie ulterioara) schema protocolului a ajutat la rezolvarea bugului legat de primirea de pachete eronate daca distanta fata de laptop era putin mai mare (peste cativa metri): ACK-ul trebuia trimis imediat inapoi de catre Receiver. Lasam seriala catre laptop sa transmita octetii primiti inainte de a face asta. Cumva cuanta de timp alocata pentru asta era prea mare.

Rezultate Obţinute

Git repo.

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):

Acum ca stream-ul merge la o distanta mai mare de laptop, pot sa arat poze precum cea de mai jos (luna, 2+ pereti distanta):

Concluzii

Download

Jurnal

Bibliografie/Resurse

Export to PDF