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.

  1. OK Circuito stampato controllato in PWM per l'illuminazione notturna
    1. OK Kicad script support per placement e routing circolare
    2. OK Selezione dei componenti e realizzazione del PCB
    3. OK Test hardware PWM
    4. OK Installazione sensore di luminosità
  2. IN CORSO Modularizzazione del codice per attivare/disattivare features
  3. DA FARE Supporto per LED RGB che indica lo stato della telecamera
  4. OK Case stampato in 3D

Pietro Saccardi 2018/07/26 00:04

Ratcam

  • Data inizio: 13 ott. 2017
  • Data fine: in corso
  • Stato: modularizzazione codice

Progetto PCB

Codice

Controller sensore ambientale

Versione 0

  • 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

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à: 1.
  • 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 Kicad
  • polar.py primitivi geometrici
  • radial_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:

Placement e routing

Segue l'outline dell'algoritmo di placement e routing usato.

Componenti frontali:

  1. Calcola l'angolo sotteso ai pad di ciascuno dei componenti frontali (resistenze e led).
  2. 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).
  3. Completa le reti inserendo delle tracce lungo la circonferenza data.
  4. 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).
  5. 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.
  6. 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à):

  1. Posizione i mosfet e il connettore diametralmente opposti.
  2. 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).
  3. 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.
  4. Collega con due archi i pin del connettore e del mosfet.
  5. Collega con un tratto orizzontale e una via il mosfet e il connettore alle reti ground e 5v rispettivamente.
  6. 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.

Impostazioni per Elecrow.
PCB (fronte)
PBC (retro)

Montaggio e limitazioni

Nel corso del montaggio mi sono reso conto di alcune limitazioni del design corrente.

  1. C'è poco spazio per consentire al flex di flettersi.
  2. L'uso di un pin header ortogonale alla scheda aumenta l'ingombro.
Allineamento non corretto dei cavi con il flex nei primi test.
Primo test LED lampeggianti
Montaggio con viti M2 e terzo braccio
PCB con componenti saldati (fronte)
PCB con componenti saldati (retro)

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.

Anche ad occhio nudo promette bene
Test del PWM da Ratcam
Illuminazione sufficiente

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.

Lo sviluppo del case è stato un processo più semplice del PCB, ma ha richiesto diverse rifiniture. L'idea principale è di avere un case per il Raspberry collegato con uno snodo vincolato cavo per far scorrere i cavi e il flex. I dettagli sullo snodo vincolato sono nella voce dedicata. Qui alcuni dettagli tecnici:

  • L'assemblaggio richiede 12 viti M2 da 1cm.
  • Il gap per tutti gli incastri è di 0.2mm in ogni direzione, che ho visto mi permette di stampare con risoluzione da 0.12 a 0.24 e comunque avere un incastro funzionante
  • Il gap dello snodo è di 0.3mm perché sia possibile stamparlo in un unico blocco
  • Stampato il roof support: in questa maniera crea un blocco di materiale che supporta meglio i punti cavi, come ad esempio gli alloggiamenti per i dadi
  • Per stampare il nido d'ape del logo Mittelab e il logo del Raspberry Pi ho dovuto rallentare la velocità di stampa perché aderisse bene al piatto. È sufficiente ridurre i primi layer.
  • Supporti ovunque purché partano dal piatto e non dal materiale
  • La mia Creality3D CR-10 stampa molto meglio a multipli di 0.4mm.
  • Raft per stampare lo snodo.

Ho sviluppato prima lo snodo, poi il case dell'illuminatore, poi del Raspberry. Il render è fatto con Blender e il progetto è sviluppato in Rhino.

Blender render
Wireframe

Limitazioni e problemi noti

  • Lo spazio è poco e i pin header verticali ne consumano molto. Questo introduce una struttura ingombrante per far spazio ai jumper nello snodo.
  • Il flex… non è affatto flex. E passa a malapena, ma il volume dello snodo cresce notevolmente se aumento il diametro. Per cui, dal momento che comunque non flette affatto, è stato inciso lungo il senso della lunghezza (ma va?). :-P
  • L'illuminatore occupa più spazio in verticale che il case del Raspberry, per cui non appoggia sulla base. Questo comunque non è un problema perché volevo appoggiarlo su una batteria portatile per farlo funzionare senza cavo.

Istruzioni di assemblaggio

Incidi il flex a metà usando uno scalpello e un righello metallico come guida. Io ho fissato tutto al piano di lavoro con nastro adesivo per essere sicuro che nulla si muovesse. Assembla il resto come segue:

  • progetti/5p4k/ratcam_v1.txt
  • Ultima modifica: 2018/07/25 23:11
  • da 5p4k