ESP32lights

by luca
30 comments

Il progetto che vi presento oggi, ESP32lights, è una centralina di controllo luci smart, basata sul chip esp32.

esp32lights-004 esp32lights-005

Tramite ESP32lights è possibile accendere/spegnere un carico (io lo utilizzo per le luci natalizie…)

[checklist]

  • manualmente
  • secondo una schedulazione oraria
  • in base alla luminosità

[/checklist]

ESP32lights si collega alla rete wifi di casa, è gestito interamente via browser ed è ottimizzato per dispositivi mobile (interfaccia responsive basata su jQuery Mobile).

Componenti

Cuore della centralina ESP32lights è la scheda di sviluppo Lolin32 Lite di Wemos. Uno dei pin digitali della scheda è collegato ad un modulo relay, il quale controlla il carico. Due pin digitali, assegnati al primo controller i2c del chip esp32, sono invece connessi al sensore luminosità BH1750. L’alimentazione a tutti i dispositivi della centralina è infine fornita dal modulo HLK-PM01 di Hi-Link che converte i 220V AC della rete in 5V DC senza necessità di componenti esterni:

esp32l-001

Tutti i componenti sono inseriti in un contenitore a tenuta stagna, in modo da poter collocare la centralina anche all’esterno:

esp32lights-006 esp32lights-007

Programmazione

Il programma in esecuzione sulla devboard esp32 è disponibile nel mio repository Github.

In uno dei successivi paragrafi vi illustrerò il suo funzionamento. Se volete semplicemente realizzare la vostra centralina, potete effettuare la programmazione del firmware come segue:

1) effettuare il clone del mio repository in una cartella locale del vostro PC (dovete avere installato l’ambiente di sviluppo esp-idf):

2) configurare i parametri della vostra rete wifi e del fuso orario tramite menuconfig:

esp32lights-003

3) compilare e programmare il firmware:

make flash

4) memorizzare nella flash la partizione SPIFFS (utilizzate la vostra porta COM e il path dove avete salvato il file img):

python $IDF_PATH/components/esptool_py/esptool/esptool.py --chip esp32 --port COM15
 --baud 115200 write_flash --flash_size detect 0x180000 /home/esp32lights.img

Se tutto è stato eseguito correttamente, collegandosi in seriale (make monitor) alla scheda di sviluppo dovrebbe apparire il seguente output:

esp32lights-025

Utilizzo

ESP32light mette a disposizione una interfaccia HTTP attraverso la quale è possibile inserire la programmazione (oraria o basata su una soglia di intensità luminosa) o controllare manualmente l’accensione e lo spegnimento del carico collegato alla centralina.

E’ possibile visualizzare l’interfaccia collegandosi (da PC o smartphone) all’indirizzo http://<esp_ip> (l’indirizzo IP della scheda è visibile dall’output seriale come mostrato nel paragrafo precedente).

L’interfaccia è divisa in 3 tab, uno per ogni modalità di funzionamento:

esp32lights-001

La barra di stato visualizza la modalità di funzionamento attuale:

esp32lights-002

Nel breve video che segue, potete vedere l’utilizzo della centralina (sottotitoli in italiano disponibili):

[youtube id=”56xeacghJrc” width=”600″ height=”350″]

Software

Il firmware di ESP32lights è stato realizzato sfruttando quando appreso nei miei precedenti tutorial. Se infatti seguite il mio blog, avrete sicuramente capito che prediligo il metodo divide et impera, ovvero suddividere un progetto complesso in task più semplici.

Tutti i parametri di configurazione di ESP32lights (modalità di funzionamento, programmazione oraria…) sono memorizzati nella partizione NVS come vi ho spiegato in questo tutorial; in questo modo è possibile conservarli anche in caso di riavvio del chip esp32:

nvs_handle my_handle;
int working_mode;
[...]
esp_err_t err = nvs_flash_init();
err = nvs_open("storage", NVS_READWRITE, &my_handle);
err = nvs_get_i32(my_handle, "mode", &working_mode);

I diversi elementi della interfaccia web (pagine html, fogli di stile css…) sono memorizzati all’interno di una partizione SPIFFS. In un precedente tutorial vi ho mostrato come preparare l’immagine ed accedere al suo contenuto:

esp32l-002

Anche il collegamento ad una rete wifi e l’utilizzo dei pin digitali del chip esp32 per il controllo del relay sono stati oggetto di tutorial dedicati.

La fase di setup iniziale si conclude con la configurazione del sensore di luminosità BH1750. Tale sensore offre una interfaccia i2c e può essere quindi collegato ad uno dei due controller i2c del chip come spiegato in questo tutorial. Nel mio programma ho utilizzato un driver preparato da pcbreflux.

Il programma principale è composto da tue task distinti:

xTaskCreate(&http_server, "http_server", 20000, NULL, 5, NULL);
xTaskCreate(&monitoring_task, "monitoring_task", 2048, NULL, 5, NULL);

esp32l-003

Il primo pubblica l’interfaccia web, mentre il secondo si occupa di verificare – ogni secondo – se esistono le condizioni (orario o intensità luminosa) per accendere o spegnere il carico:

if(working_mode == MODE_LIGHT && lux_valid) {
  int actual_light_value = get_light_value();
  if(actual_light_value < lux) {
    if(relay_status == false) {
      gpio_set_level(CONFIG_RELAY_PIN, 1);
      relay_status = true;
    }

Ecco nel dettaglio come funziona il server http quando viene richiesta una risorsa statica, memorizzata nella partizione SPIFFS.

Per prima cosa al path della risorsa deve essere aggiunta la root della partizione SPIFFS (/spiffs):

sprintf(full_path, "/spiffs%s", resource);

quindi il programma verifica se la risorsa esiste nella partizione:

if (stat(full_path, &st) == 0) {

in caso affermativo, apre il file in lettura:

FILE* f = fopen(full_path, "r");

e ne invia il contenuto al client, leggendo blocchi di 500 bytes:

char buffer[500];
while(fgets(buffer, 500, f)) {
  netconn_write(conn, buffer, strlen(buffer), NETCONN_NOCOPY);
}

Vediamo infine il funzionamento dell’interfaccia web. Questa è composta da una pagina html (index.html) che utilizza jQuery per effettuare chiamate AJAX al server e aggiornare l’interfaccia responsive (basata su jQuery Mobile). Non è necessario inserire il nome della pagina nel browser perché il server http effettua una redirect automatica se viene richiesta la pagina di default:

if(strstr(request_line, "GET / "))
  spiffs_serve("/index.html", conn);

Gli endpoints pubblicati dal server e invocati dalla pagina con chiamate AJAX sono 3:

[checklist]

  • setConfig, per inviare una nuova configurazione
  • getConfig, per leggere la configurazione attuale
  • getLight, per leggere il valore attuale di luminosità

[/checklist]

Al primo caricamento della pagina, questa chiama la getConfig per visualizzare la configurazione attuale; inoltre schedula ogni cinque secondi la chiamata a getLight per tenere aggiornato il valore visualizzato:

refreshConfig();
setInterval("refreshLightLevel()", 5000);

Alla pressione del pulsante SET, viene invece invocata la setConfig per inviare al server la nuova configurazione:

esp32l-004

Lo scambio di informazioni avviene utilizzando il formato JSON. Il framework esp-idf include la libreria cJSON che semplifica sia il parsing che la costruzione di un nuovo messaggio json:

cJSON *root = cJSON_Parse(body);
cJSON *mode_item = cJSON_GetObjectItemCaseSensitive(root, "mode");
[...]
cJSON *root = cJSON_CreateObject();
cJSON_AddNumberToObject(root, "lux", light_value);
char *rendered = cJSON_Print(root);

Making of

Ho iniziato la costruzione della centralina tagliando un pezzo di breadboard delle dimensioni del contenitore:

esp32lights-008 esp32lights-009

La breadboard è collegata al contenitore tramite due distanziali e due fori:

esp32lights-010 esp32lights-011

Ho praticato due fori in un lato del contenitore per ospitare l’interruttore principale e un led di stato:

esp32lights-012 esp32lights-013

Ho saldato i vari componenti sulla breadboard e realizzato – tramite filo – i vari collegamenti:

esp32lights-014 esp32lights-015

Per rendere più facile l’installazione, tutti i componenti esterni (led, modulo relay…) sono collegati tramite jumpers:

esp32lights-016 esp32lights-017

Primo test di funzionamento:

esp32lights-018

Ho fissato il sensore di luminosità al coperchio del contenitore, dopo aver praticato un foro per consentirgli di “vedere” la luce esterna:

esp32lights-019 esp32lights-020

Ho infine realizzato i collegamenti elettrici, installando un interruttore generale:

esp32lights-021 esp32lights-022

e collegando l’uscita del modulo relay ad cavo che termina con una presa universale:

esp32lights-023 esp32lights-024

Related Posts

30 comments

Georgian 8 gennaio 2018 - 20:51

Hello, I see that you use a lot that AC/DC convertor. Are you satisfied with it. I just started using one for an ESP8266 project and so far no smoke and everything seems to work fine. Did you have any issues with them?
Thank you.

Reply
luca 8 gennaio 2018 - 21:32

Hi, so far the AC/DC modules I used in my projects worked great! No issues at all!

Reply
Georgian 9 gennaio 2018 - 21:08

Thank you, I hope that mine will do just fine too. Great work.

Reply
tom 9 gennaio 2018 - 08:19

hi, Luca, i am in China and we want develop a device using ESP32 as the WIFI module. we have a device needs to be controlled remotelly with mobile phone. do you know any company or ppl who is good at this ESP32 based development?

Thanks.

Reply
luca 9 gennaio 2018 - 09:28

Hi Tom, try asking on esp32.com, it’s the “official” forum and there are freelancers who regularly write on it

Reply
tom 9 gennaio 2018 - 16:03

thanks, i will go for it.

Reply
Daren 12 gennaio 2018 - 08:49

Economics of scale kicking in. A 1A USB charger is much cheaper than the Hi-Link module, and is about the same size.
The build quality is questionable and you have to pot them yourself then of course, but I have had good luck with them in similar applications.

If you really wanted to get cheap since your design can be entirely isolated: Switch your relay out for a logic level triac and you can then drive this directly from mains with just two capacitors, a switching diode, and a zener. This comes with the warning that one leg of the ESP32 will be at mains level then so no human contact allowed once in circuit, and triac failure will likely fry the ESP32.

Reply
luca 12 gennaio 2018 - 09:43

Hi Daren, thanks for your suggestions! To be honest I had some Hi-Link modules laying around and I this was a good project to test them.

Reply
Lachlan 14 gennaio 2018 - 12:15

Hi Luca, great project, is there anywhere that describes how the data in the webapp is accessed by the esp32 ?
js and web development is not my strongpoint by any stretch
thanks ! keep up the good work

Reply
Lachlan 14 gennaio 2018 - 12:17

ah sorry, ignore my question i hadn’t got that far down the article 🙂

Reply
Ted 14 gennaio 2018 - 18:06

Your Hi-Link is dead!

Reply
luca 15 gennaio 2018 - 08:23

Thanks Ted, now fixed

Reply
mauro 22 gennaio 2018 - 17:41

Ciao Luca, chiaro come sempre: avrei una domanda sul relay.. I 5 v per la bobina sono presi dalla esp32 board ma il pin per azionare il relay è a 3.3 v (uscita della scheda) : non hai paura che bruci la scheda (oppure hai tolto il jumper vcc che si trova sul relay e alimentazione e controllo sono su 2 linee separate?)
Per farla breve si può connettere in maniera così semplice un relay 5 v dc alla scheda esp32?
Grazie in anticipo della risposta
Mauro

Reply
luca 23 gennaio 2018 - 09:57

Ciao Mauro! In effetti il relay è dichiarato a 5v (avevo solo quello) ma “scatta” anche se lo controlli a 3.3V… non c’è rischio di bruciare la scheda, al massimo se la tensione non è sufficiente il relay non si aziona.

Reply
Herman 28 gennaio 2018 - 17:41

Hi Luca,

Great project, it is almost exactly what I was looking for.
I had a timer for years that turns the lights on when it gets dark, and turns it off at given time so it won’t be on until the morning. Since I am not a programmer, I want to ask you if your program can be modified to do that. It would be of great help to me since the timer I used is EOL and there are no replacements for a usable price.

Thanks.

Reply
luca 26 febbraio 2018 - 14:53

Hi Herman, you should be able to modify the program… to keep it simple you could use one of the time fields already present in the GUI to set the “off” time instead of designing a dedicated GUI (more complex)

Reply
Felice 12 marzo 2018 - 19:36

Ciao Luca, grazie per la condivisione del progetto.
Ho un dubbio sui collegamenti elettrici.
l’uscita massa e +5 volt del convertitore su quali pin della scheda lolin32 li collego?
A me sembra che questa scheda si alimenti solo dalla presa usb.
Tu come li hai collegati?
Infine confermami per cortesia gli altri pin di collegamento che sono pin 0=comando relè, il 4=SCL il 16=SDA del sensore BH1750.
Grazie mille in anticipo.
Felice.

Reply
luca 16 marzo 2018 - 10:42

Ciao Felice, ho utilizzato il connettore batteria (vedi questa immagine). Il pin del relay lo configuri da menuconfig, mentre quelli del sensore sono i pin 18 e 19 (ma li puoi cambiare editando bh1750.c

Reply
Massimo 29 marzo 2018 - 13:12

Ciao Luca, ieri ho inserito una richiesta, vorrei solo sapere se è stata ricevuta, grazie.
Massimo

Reply
luca 29 marzo 2018 - 13:58

ciao massimo, no non ho ricevuto nulla… mi hai scritto tramite form?

Reply
Iulian Ilie 9 febbraio 2019 - 11:08

Ciao Luca. Sei grande.Bravo. Un rumeno chi aprezza tuo lavoro.

Reply
luca 9 febbraio 2019 - 15:57

grazie mille!

Reply
Roberto 9 febbraio 2019 - 17:18

Ciao Luca,
grazie per le spiegazioni molto chiare!
Ho un problema con il file .img della partizione SPIFFS relativa ai files css e html.
Se utilizzo quello incluso nel progetto tutto funziona correttamente, mentre semplicemente rigenerando il file .img con i comandi da te indicati nel tutorial, ottengo un file binariamente differente rispetto all’originale con l’effetto di non riuscire ad avviare la pagina web dal browser

Hai qualche consiglio sulla origine delle differenze?

Grazie

Roberto

Reply
luca 10 febbraio 2019 - 20:48

ciao Roberto, a partire da una certa versione in avanti, espressif ha “rotto” la compatibilità con l’utility mkspiffs… quale versione stai usando?

Reply
Roberto 11 febbraio 2019 - 18:02

Ciao Luca,
ho scaricato e compilato la versione dal link
https://github.com/loboris/ESP32_spiffs_example
per generare il file di creazione dei file immagine .img
Per quanto riguarda i files da allegare al progetto ho lasciato quelli da te inclusi nel progetto (cartella firmware\components\spiffs\).

Reply
luca 16 febbraio 2019 - 11:23

ciao Roberto, prova ad aggiornare anche la libreria spiffs che sta nella sottocartella components, probabilmente se usi la versione più recente di mkspiff devi usare anche la libreria relativa

Reply
Roberto 22 febbraio 2019 - 17:33

Ciao Luca,
problema risolto.
L’origine del problema era il disallineamento tra i files spiffs_config.h: il primo necessario per generare il file mkspiffs.exe di creazione della immagine .img , il secondo quello per accedere tramite applicazione scaricata su esp32 ai files contenuti nell’immagine stessa.
Roberto

Reply
nicola 5 aprile 2019 - 15:46

Ciao Roberto volevo chiederti un chiarimento: come capitato a te provando a creare una nuovo file .img non visualizzo i contenuti sul web browser.
Hai accennato a un problema di disallineamento dei file spiffs_config.h.
Puoi spiegarmi in dettaglio quale operazione hai effettuato ?

Reply
Roberto 5 maggio 2019 - 20:44

Ciao Nicola,
io avevo trovato una differente definizione dei parametri
SPIFFS_OBJ_META_LEN
SPIFFS_USE_MAGIC_LENGTH
SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
tra il progetto di Luca e quanto scaricato da internet, necessario per generare il file mkspiffs.exe.
Ti consiglio di mettere alcune std::cout nel main per stampare dette defines, ricompilare ed eseguire mkspiffs.exe: in questo modo potrai vedere con quali parametri sta creando l’immagine il software mkspiffs.exe e confrontarli con quelli del tuo progetto. io me ne sono accorto in questo modo.

Luigi Augello 20 maggio 2019 - 14:05

Ciao Luca
Sto sviluppando un progetto simile al tuo che in pratica prevede che dei relè siano comandati da un’app e ho già sviluppato tutto. La mia domanda è la seguente: dato che usi in questo progetto un relè uguale al mio per comandare la 220. Dovrei pilotare un carico di circa 10A sulla 220AC, secondo te va bene o esplode? Ho anche preso, sempre made in cina, un relè più grosso, che indica 30A o 1/2 HP su 240VAC. In pratica dovrei comandare due motori elettrici, uno da 0,6HP e uno da 1 HP credo che neanche il relè più grosso vada bene o sbaglio?

Aspettavo anche una tua risposta sul progetto al link
http://www.lucadentella.it/2015/09/12/collegare-arduino-a-dispositivi-a-3-3v/

Reply

Rispondi a Massimo Cancel Reply