Questa è una vecchia versione del documento!
Ratcam v1
Ratcam ti permette di controllare la fotocamera del RaspberryPi da un bot di Telegram, e ti allerta in caso di movimento inviando video e foto.
L'idea è nata quando ho trovato tracce di topi in casa, e volevo scoprire da dove entravano pittosto che adottare misure più drastiche (e dovermi occupare dei resti).
Ho sviluppato una versione iniziale, ma vorrei includere dei miglioramenti.
Stato del progetto
- OK Circuito stampato controllato in PWM per l'illuminazione notturna
- OK Kicad script support per placement e routing circolare
- OK Selezione dei componenti e realizzazione del PCB
- OK Test hardware PWM
- OK Installazione sensore di luminosità
- IN CORSO Modularizzazione del codice per attivare/disattivare features
- DA FARE Supporto per LED RGB che indica lo stato della telecamera
- OK Case stampato in 3D
— Pietro Saccardi 2018/07/26 00:04
Funzionalità
- PCB con 10 LED IR per illuminare la scena
- Controllo PWM dell'illuminazione basato sulla funzionalità flash o sull'esposizione
- LED RGB per segnalare lo stato della telecamera
- Modularizzazione delle funzionalità: LED e illuminatore opzionali
- Case stampato in 3D
- Collo snodabile per la telecamera
Sviluppo del circuito
Ho realizzato il pcb usanto il sapiente aiuto di g5pw, wifasoi e ziongate con Kicad . Il circuito deve semplicemente alimentare dei LED infrarossi dal pin a 5V del Raspberry Pi. In più, vorrei poterli pilotare da uno dei pin a 3v3 del Raspberry; in questa maniera posso regolare la luminosità usando PWM.
Tutti i file del progetto sono reperibili su Gitlab.
I componenti che ho trovato nella miriade dei semiconduttori disponibili online sono:
VSMY2850G
, LED 850 nm, adatto per operare in PWM, quantità: 12.RK73H-5715
, resistenza da 15 Ohm, quantità: 6.DMG1012UW
, n-channel MOSFET, quantità: 1.VEML7700-TR
, sensore di luce ambientale nello spettro visibile, quantità: 1.M20-8750342
, connettore a 3 pin, quantità: 1.C0805C104Z3VACTU
, condensatore da 0.1 uF, quantità: 2.RK73H2ATTDD4701F
, resistenza da 4.7 KOhm, quantità: 2.
Note sulla selezione dei componenti
Un lavoro (noioso) di lettura dei datasheet su vari siti di elettronica finché non ho trovato i componenti che andavano bene insieme.
Ho identificato prima i LED infrarossi, confrontando le specifiche su quanta luce emettono rispetto alle specifiche di alcuni LED in mio possesso. 10 LED sembrava la giusta quantità per avere (almeno) il doppio dell'illuminazione (emessa) della versione 1. Con i dati dei LED, ho calcolato quanti ne posso mettere al massimo in serie (2 al massimo) con i 5V del Raspberry Pi. A quel punto ho selezionato in base ai componenti fissati il MOSFET per controllare i LED dal pin 3v3.
Nello scegliere i componenti ho tenuto conto che non fossero eccessivamente piccoli, dato che non ho esperienza di saldatura SMT.
Progettazione del PCB
Volevo disporre i LED in maniera circolare, ma Kicad non ha strumenti adatti; non è possibile disegnare curve con le tracce o con i fill. Per cui ho preso spunto da qui per disegnare degli elementi circolari con Kicad.
All'inizio avevo scritto il codice minimo indispensabile per generare tracce circolari, ma mi sono reso conto che per allineare correttamente i componenti e calcolare i fill c'era bisogno di un supporto più estensivo per lavorare in coordinate polari, per cui ho scritto qualche classe per manipolare corde e settori circolari, ed un layer di interfaccia a Kicad più “pythonico” di quello offerto da Kicad. Il set di script è su Gitlab, consta di
cad.py
data model e astrazione degli oggetti di Kicad (limitata solo a quello che serviva per questo progetto)pcb.py
conversione da e a Kicadpolar.py
primitivi geometriciradial_illuminator.py
placer e router per un circuito tipo Ratcam, configurabile.
Kicad si può controllare via python, ma la documentazione è scarsa e spesso bisogna ricorrere ad ispezionare il codice sorgente di Kicad per capire cosa una certa funzione fa. Gli oggetti sono trasportati via Swig direttamente da C(++) a Python, per cui sono relativamente scomodi da utilizzare. Alcuni link utili per chi tentasse di seguire la stessa strada:
- Kicad scripting blog: probabilmente il posto migliore sul web per imparare a scrivere script per Kicad, anche meglio della documentazione di Kicad.
- Studio clock , progetto analogo a Ratcam
- generatore di QR code footprint in Kicad.
- Bug report nella beta di Kicad non è possibile leggere l'outline di un fill
Placement e routing
Segue l'outline dell'algoritmo di placement e routing usato.
Componenti frontali:
- Calcola l'angolo sotteso ai pad di ciascuno dei componenti frontali (resistenze e led).
- Disponi i componenti frontali lungo un cerchio di raggio fissato, in maniera che il baricentro dei pad giaccia sulla circonferenza, e l'angolo sotteso a due pad adiacenti di componenti differenti sia costante (sono equidistanziati nel senso dell'angolo piuttosto che della distanza).
- Completa le reti inserendo delle tracce lungo la circonferenza data.
- Identifica le reti che vanno ai 5V e al drain del mosfet (chiamata “ground” nel codice, perché se non fosse per il mosfet sarebbe a massa).
- Traccia un arco in più da ciascuno dei pad che collegano ad una delle due reti, 5v e ground, e traccia un raggio in maniera da collegarli a due circonferenze concentriche a quella data.
- Aggiungi i copper pour a ciascun pad dei led e della resistenze, tracciando un fill che corrisponde ad un settore circolare di angolo fissato. Per pad collegati, il settore circolare ricopre l'intera traccia, per i pad adiacenti che vanno a 5v o ground, lascia uno spazio pari alla dimensione fissata della traccia.
Componenti posteriori (il codice è attivo ma non usato perché ho fatto il routing manuale per alloggiare anche il sensore di luminosità):
- Posizione i mosfet e il connettore diametralmente opposti.
- Riorienta mosfet e connettore in maniera tale che i pad che sono collegati tra loro guardino nella stessa direzione (in maniera da collegarli con un solo arco).
- Calcola la posizione ottimale lungo il diametro perché i componenti non escano dall'outline dalle tracce frontali. Questo viene fatto tenendo conto di non causare sovrapposizioni e corti, e aggiungendo la quantità minima di tracce per agganciarsi alle reti a 5v e ground.
- Collega con due archi i pin del connettore e del mosfet.
- Collega con un tratto orizzontale e una via il mosfet e il connettore alle reti ground e 5v rispettivamente.
- Aggiungi i copper pour intorno al mosfet come per i componenti frontali.
Successivamente ho aggiunto il QR code e le scritte.
Outline e manifattura
Nella documentazione del modulo videocamera del Raspberry Pi ho trovato le misure della videocamera. Ho disegnato gli stessi elementi in Kicad, in maniera che la videocamera fosse al centro della circonferenza. Ho aggiunto delle footprint per i fori e ho fatto realizzare il PCB da Elecrow; aggiungo qui le impostazioni di esportazioni che wifasoi ha suggerito dato che ho trovato opinioni discordanti online.
Montaggio e limitazioni
Nel corso del montaggio mi sono reso conto di alcune limitazioni del design corrente.
- C'è poco spazio per consentire al flex di flettersi.
- L'uso di un pin header ortogonale alla scheda aumenta l'ingombro.
Controllo dei LED in PWM
A quanto pare il mosfet che sto usando sembra operare bene in PWM. Ho fatto alcuni test con la libreria WiringPi. A quanto pare, RPi.GPIO
usa software PWM, il che usa alcune risorse della CPU, ma wiringPi e il tool gpio
possono sfruttare il pin fisico 12 che ha accesso ad hardware PWM. Ho scritto un breve programma in C++ (C sarebbe bastato) che fa oscillare linearmente il duty cycle del PWM hardware del Raspberry Pi, e registrato il risultato.
PWM richiede sudo
Una nota importante: usare il PWM richiede permessi di root. Il tool gpio
è SUID, per cui non ci sono di questi problemi, ma il programma che segue dev'essere eseguito come sudo
.
Per compilare è richiesta la libreria wiringpi:
- setup.sh
sudo apt-get install wiringpi build-essential g++ -lwiringPi oscillate.cpp -o oscillate sudo ./oscillate
- oscillate.cpp
#include <wiringPi.h> #include <iostream> int main() { wiringPiSetupPhys(); pinMode(12, PWM_OUTPUT); std::div_t div; for (int i = 0; ; i = (i + 1) % 2048, div = std::div(i, 1024), delay(1)) { const int duty_cycle = div.rem * (1 - 2 * div.quot) + 1024 * div.quot; pwmWrite(12, duty_cycle); if (i % 64 == 0) { std::cout << int(100.f * duty_cycle / 1024.f) << std::endl; } } return 0; }
Il risultato segue qui sotto. Da notare anche come l'illuminazione sia più che sufficiente per registrare foto e video con Ratcam.
Sensore di luminosità
Idealmente, i LED dovrebbero attivarsi e disattivarsi autonomamente in base alla luminosità ambientale. Tuttavia non è possibile identificare l'intensità della luce ambientale solo a partire dall'esposizione della telecamera: una volta che i LED IR sono accesi, l'immagine è ben illuminata, e resta tale anche quando sorge il sole. Per cui non c'è maniera di “vedere se è buio fuori”, dato che “buio” significa “nello spettro visibile”, ma nello spettro visibile + IR, c'è invece luce.
Per cui dal momento che dovevo modificare il circuito per cambiare il pin header, ho aggiunto un sensore di luminosità. Ho scelto questo VEML7700
perché ha una risposta nel visibile, è digitale via I2C, e taglia gli infrarossi in maniera netta (in realtà non ce n'erano molti che potessi saldare a mano :D).
Dal momento che lo userò in Python, ho scritto un controller in Python per il sensore. È disponibile qui. Ho implementato tutte le funzionalità offerte dal sensore, un apprezzamento alla Vishay che ha rilasciato una guida pratica su come usarlo.