Demoboard ESP32: nuovi progetti dimostrativi con l’hardware di bordo (parte 2)

Sperimentiamo nuovi progetti dimostrativi con uno dei più utilizzati moduli WiFi: il SoC ESP32 Seconda puntata.

Abbiamo introdotto la demoboard per il SoC ESP32 ed accennato al fatto che per introdurvi nel mondo dello sviluppo con questo hardware, in ottica IoT, abbiamo scritto firmware e creato degli esempi che abbiamo iniziato a descrivere nella prima puntata. Adesso proseguiamo su questa strada proponendo applicazioni dimostrative che utilizzano l’hardware di bordo e i moduli collegabili esternamente tramite gli appositi connettori. Ricordiamo che alla demoboard possono essere applicati questi elementi:

  • sensore qualità aria cod. SGP30CO2;
  • sensore fulmini cod. FT1324M;
  • rilevatore di gesture cod. APDS9960BOUT;
  • sensore UVB cod. GYLM8511;
  • sensore pressione cod. BMP280;
  • lettore NFC/RFID cod. PN532;
  • sensore torbidità cod. TORBISENS;
  • sensore PIR cod. PIRMOD / cod. MINIPIRMOD;

I codici indicati sono quelli di www.futurashop.it, perché si tratta di prodotti commercializzati dalla Futura Elettronica.

Bene, ciò detto riprendiamo il discorso da dove lo avevamo lasciato e partiamo con la prima applicazione, nella quale utilizziamo il rilevatore di “gesture”.

Rilevamento dei gesti

Nel caso specifico, tramite un apposito firmware (OLED_Gesture.ino) da caricare in Arduino leggeremo i dati relativi ai gesti della mano rilevati dal detector APDS9960BOUT (prende posto in posizione U5 sulla demoboard) e ne permette la visualizzazione sul display delle quattro direzioni (UP-DOWN-LEFT-RIGHT) rilevabili, a seconda del gesto fatto con la mano.

Dopo avere installato il modulo U5, dovete copiare la cartella “libraries” sotto “/Documenti/Arduino” (se non avete cambiato la cartella predefinita), quindi aprire l’IDE di Arduino e dal menu “File” caricate il nostro codice d’esempio “Gesture/OLED_gesture.ino” che peraltro trovate al completo nel Listato 1.

La breakout board con cui rileviamo le gesture è proposta nella Fig. 1 ed è basata sul sensore RGB e Gesture APDS-9960; dotato di filtri anti-UV e IR integrati, quattro diodi separati sensibili a diverse direzioni e un’interfaccia compatibile I²C; questa piccola breakout permette di ottenere misurazioni della luce e del colore, rilevamento della prossimità e dei movimenti senza contatto, a una distanza compresa tra 10 e 20 cm.

Il sensore rileva i gesti attraverso radiazioni luminose. I pin della scheda utilizzati nella demoboard sono i seguenti: VL (alimentazione opzionale a LED IR), GND (Ground), VCC (alimentazione 3,3V), SDA (dati I²C) e SCL (clock I²C).

Fig. 1 La breakout board per rilevare i gesti

Listato 1

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#include <SparkFun_APDS9960.h>



// Pins

#define APDS9960_INT 27 // Needs to be an interrupt pin





#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED display height, in pixels



// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)

// The pins for I2C are defined by the Wire-library. 

// On an arduino UNO: A4(SDA), A5(SCL)

// On an arduino MEGA 2560: 20(SDA), 21(SCL)

// On an arduino LEONARDO: 2(SDA), 3(SCL), ...

#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)

#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);



#define NUMFLAKES 10 // Number of snowflakes in the animation example



#define LOGO_HEIGHT 16

#define LOGO_WIDTH 16





// Global Variables

SparkFun_APDS9960 apds = SparkFun_APDS9960();

int isr_flag = 0;





void setup() {

Serial.begin(9600);



// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally

if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {

Serial.println(F(“SSD1306 allocation failed”));

for(;;); // Don’t proceed, loop forever

}





display.display();

delay(2000); // Pause for 2 seconds



// Clear the buffer

display.clearDisplay();

display.setTextSize(2); // Draw 2X-scale text

display.setTextColor(SSD1306_WHITE);

display.setCursor(5, 0);

display.print(“** Test **”);

display.setCursor(20, 30);

display.print(“Gesture”);



// Show the display buffer on the screen. You MUST call display() after

// drawing commands to make them visible on screen!

display.display();

delay(2000);

// display.display() is NOT necessary after every single drawing command,

// unless that’s what you want...rather, you can batch up a bunch of

// drawing operations and then update the screen all at once by calling

// display.display(). These examples demonstrate both approaches...





/*

// Invert and restore display, pausing in-between

display.invertDisplay(true);

delay(1000);

display.invertDisplay(false);

delay(1000);

*/



// Set interrupt pin as input

pinMode(APDS9960_INT, INPUT);



// Initialize Serial port

Serial.begin(9600);

Serial.println();

Serial.println(F(“--------------------------------”));

Serial.println(F(“ OLED + APDS-9960 - GestureTest “));

Serial.println(F(“--------------------------------”));



// Initialize interrupt service routine

attachInterrupt(APDS9960_INT, interruptRoutine, FALLING);



// Initialize APDS-9960 (configure I2C and initial values)

if ( apds.init() ) {

Serial.println(F(“APDS-9960 initialization complete”));

} else {

Serial.println(F(“Something went wrong during APDS-9960 init!”));

}



// Start running the APDS-9960 gesture sensor engine

if ( apds.enableGestureSensor(true) ) {

Serial.println(F(“Gesture sensor is now running”));

} else {

Serial.println(F(“Something went wrong during gesture sensor init!”));

}

}



void loop() 

{

if( isr_flag == 1 ) 

{

detachInterrupt(0);

handleGesture();

isr_flag = 0;

attachInterrupt(0, interruptRoutine, FALLING);

}

}



void interruptRoutine() 

{

isr_flag = 1;

}



void handleGesture() 

{

if ( apds.isGestureAvailable() ) 

{

display.clearDisplay();

display.setTextSize(2); // Draw 2X-scale text

display.setTextColor(SSD1306_WHITE);

display.setCursor(5, 30);



switch ( apds.readGesture() ) 

{

case DIR_UP:

display.print(“ UP “);

break;

case DIR_DOWN:

display.print(“ DOWN “);

break;

case DIR_LEFT:

display.print(“ LEFT “);

break;

case DIR_RIGHT:

display.print(“ RIGHT “);

break;

case DIR_NEAR:

display.print(“ NEAR “);

break;

case DIR_FAR:

display.print(“ FAR “);

break;

default:

display.print(“ NONE “);

}

display.display(); // Show initial text

delay(100);

}

Rilevamento dei fulmini

Passiamo adesso alla seconda applicazione di questo articolo, che vede la demoboard ESP32 impiegata con a bordo la breakout board basata sul chip AMS AS3935, un componente in grado di captare i disturbi radioelettrici causati dallo scoccare di archi elettrici e in particolare scariche atmosferiche (i fulmini insomma…) e, tramite un’opportuna elaborazione, fornire un segnale che corrisponde al rilevamento di un fulmine e della sua intensità. Tutti i segnali necessari alla gestione dell’integrato sono riportati su una fila di piazzole a passo 2,54 mm poste su un lato. La connessione dati con l’esterno avviene tramite I²C Bus o SPI.

La Breakout board rilevatore di fulmini (Fig. 2) nasce per essere abbinata a un microcontrollore e per utilizzarla con hardware Arduino, il cui compito è analizzare il segnale fornito dal sensore ed elaborarlo per poi mostrare sul display OLED della demoboard, il numero di scariche elettriche rilevate e la distanza stimata, sono previste delle librerie dedicate, una delle quali viene utilizzata in questa applicazione e inclusa nel codice che abbiamo sviluppato allo scopo. La tensione di alimentazione è 5 Vcc, corrente assorbita 50 mA, distanza di rilevamento massima 40 km.

Per effetto del collegamento, sulla seriale viene mostrata l’indicazione di eventuali fulmini captati, o disturbi temporaleschi.

Per poter implementare questo esempio applicativo dovete copiare la cartella “libraries” sotto “/Documenti/Arduino”, quindi aprire l’IDE di Arduino e caricare l’esempio nella cartella “Sens_Fulmini”; questo codice permette di inviare sulla seriale l’indicazione circa eventuali fulmini captati o disturbi dovuti a fenomeni elettrici temporaleschi. Se volete anche la visualizzazione sul display della demoboard, vi serve caricare l’esempio OLED_Sens_Fulmini (Listato 2), il cui codice fa in modo che sia sul display che sulla seriale venga inviata l’indicazione di eventuali fulmini captati o disturbi temporaleschi.

Fig. 2 Breakout board per rilevare i fulmini

Listato 2

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>



//for lightning

#include <SPI.h>

#include <Wire.h>

#include “SparkFun_AS3935.h”



// Adjust the address jumpers on the underside of the product. 

#define AS3935_ADDR 0x03 

#define INDOOR 0x12 

#define OUTDOOR 0xE

#define LIGHTNING_INT 0x08

#define DISTURBER_INT 0x04

#define NOISE_INT 0x01









#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED displdfsfdfsfdsfdsfdsfdsay height, in pixels



// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)

// The pins for I2C are defined by the Wire-library. 

// On an arduino UNO: A4(SDA), A5(SCL)

// On an arduino MEGA 2560: 20(SDA), 21(SCL)

// On an arduino LEONARDO: 2(SDA), 3(SCL), ...

#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)

#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);



#define NUMFLAKES 10 // Number of snowflakes in the animation example



#define LOGO_HEIGHT 16

#define LOGO_WIDTH 16



//for lightning

SparkFun_AS3935 lightning(AS3935_ADDR);



// Interrupt pin for lightning detection 

const int lightningInt = 35; 

const int threshVal = 10; //a higher number means better disturber rejection.



// This variable holds the number representing the lightning or non-lightning

// event issued by the lightning detector. 

int intVal = 0;

int noise = 2; // Value between 1-7 

int disturber = 2; // Value between 1-10





void setup() 

{

Serial.begin(9600);



// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally

if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) 

{

Serial.println(F(“SSD1306 allocation failed”));

for(;;); // Don’t proceed, loop forever

}



// Show initial display buffer contents on the screen --

// the library initializes this with an Adafruit splash screen.

display.display();

delay(2000); // Pause for 2 seconds



// Clear the buffer

display.clearDisplay();

display.setTextSize(2); // Draw 2X-scale text

display.setTextColor(SSD1306_WHITE);

display.setCursor(5, 0);

display.print(“** Test **”);

display.setCursor(10, 30);

display.print(“Lightning”);



// Show the display buffer on the screen. You MUST call display() after

// drawing commands to make them visible on screen!

display.display();

delay(2000);

// display.display() is NOT necessary after every single drawing command,

// unless that’s what you want...rather, you can batch up a bunch of

// drawing operations and then update the screen all at once by calling

// display.display(). These examples demonstrate both approaches...





/*

// Invert and restore display, pausing in-between

display.invertDisplay(true);

delay(1000);

display.invertDisplay(false);

delay(1000);

*/

while (!Serial); 

// When lightning is detected the interrupt pin goes HIGH.

pinMode(lightningInt, INPUT); 

Serial.println(“AS3935 Franklin Lightning Detector”); 

Wire.begin(); // Begin Wire before lightning sensor. 

if( !lightning.begin() ) 

{ // Initialize the sensor. 

Serial.println (“Lightning Detector did not start up!”); 

OLED_Message(“Lightning Detector”,”did not start up!”);

while(1); 

}

else

{

Serial.println(“Lightning Detector Ready!”);

OLED_Message(“Lightning Detector”,”Ready!”);

delay(1500);

}





// The lightning detector defaults to an indoor setting at 

// the cost of less sensitivity, if you plan on using this outdoors 

// uncomment the following line:

//lightning.setIndoorOutdoor(OUTDOOR); 

}



void loop() 

{

String text_msg = “”;

if(digitalRead(lightningInt) == HIGH)

{

// Hardware has alerted us to an event, now we read the interrupt register

// to see exactly what it is. 

intVal = lightning.readInterruptReg();

if(intVal == NOISE_INT)

{

OLED_Message(“Noise detected”,””);

Serial.println(“Noise.”); 

// Too much noise? Uncomment the code below, a higher number means better

// noise rejection.

//lightning.setNoiseLevel(setNoiseLevel); 

delay(1500);

}

else if(intVal == DISTURBER_INT)

{

OLED_Message(“Disturber detected”,””); 

Serial.println(“Disturber.”); 

// Too many disturbers? Uncomment the code below, a higher number means better

// disturber rejection.

lightning.watchdogThreshold(threshVal); 

delay(1500);

}

else if(intVal == LIGHTNING_INT)

{

// Lightning! Now how far away is it? Distance estimation takes into

// account any previously seen events in the last 15 seconds. 

byte distance = lightning.distanceToStorm(); 

//text_msg = String(distance) + “km away!”;

text_msg = “km away!”;

OLED_Message(“Lightning detected”,text_msg); 

Serial.println(text_msg); 

delay(1500);

}

}

OLED_Message(“No disturb detected”,””);

delay(500); // Slow it down.

}



void OLED_Message(String text_display1, String text_display2)

{

int lunghezza = 0;

display.clearDisplay();

display.setTextSize(1); // Draw 2X-scale text

display.setTextColor(SSD1306_WHITE);

display.setCursor(0, 20);

lunghezza = text_display1.length();

lunghezza=21-lunghezza;

lunghezza=lunghezza/2;

for (int i=0;i<lunghezza;i=i+1)

{

display.print(“ “); 

}

display.print(text_display1);

display.setCursor(0, 40);

lunghezza = text_display2.length();

lunghezza=21-lunghezza;

lunghezza=lunghezza/2;

for (int i=0;i<lunghezza;i=i+1)

{

display.print(“ “); 

}

display.print(text_display2);

display.display(); 

delay(1500);

Lettura di tag NFC

Passiamo adesso alla terza applicazione di questo articolo, che ci permetterà di sperimentare la tecnologia NFC di comunicazione wireless a corto raggio attraverso l’utilizzo di una breakout board dedicata, da montare a bordo. La scheda in questione è la PN532 e consiste in un lettore/scrittore NFC/RFID dotato di 1 LED di stato, antenna integrata sul PCB, interfaccia di comunicazione I²C, SPI e HSU (High Speed UART).

Può funzionare come lettore/scrittore di RFID card, come lettore NFC con smartphone Android e in modalità wireless con due dispositivi identici.

Può essere utilizzato con Arduino per realizzare dispositivi di controllo accessi, ecc. e applicazioni demo come quella qui descritta.

La breakout board NFC può implementare la comunicazione dati su interfaccia I²C, SPI e HSU (High Speed UART), selezionabili una alla volta tramite dip-switch. Supporta la lettura/scrittura RFID, comunicazione P2P tra due moduli uguali, NFC con smartphone Android e per quanto riguarda la lettura/scrittura RFID è compatibile con i seguenti standard:

  • Mifare 1k, 4k, Ultralight, DesFire cards;
  • ISO/IEC 14443-4 card come la CD97BX, CD light, Desfire, P5CN072 (SMX);
  • Innovision Jewel card come la IRT5001;
  • FeliCa card come ad esempio le RCS_860 e RCS_854.

La massima distanza alla quale è possibile la lettura dei tag è compresa tra 50 e 70 mm.

Il lettore/scrittore di tag e card NFC PN532 è proposto nella Fig. 3 e va introdotto nello strip femmina localizzato nella posizione U8 della demoboard.

Per implementare le applicazioni rendiamo disponibili, al solito, due codici d’esempio: uno per la gestione della breakout board allo scopo di farle leggere un tag e l’altro, più completo, per visualizzare sul display OLED di bordo i dati acquisiti dal tag o card NFC.

Come anche per gli altri esempi, per prima cosa, dovete copiare la cartella delle librerie, quindi aprire l’IDE di Arduino e dal menu “File” aprite la cartella “NFC” e tra i codici di esempio che vi trovate all’interno caricate l’esempio NFC.ino, grazie al quale sulla seriale viene inviato il codice della card NFC letta; lo vedete proposto nel Listato 3.

Il secondo sketch che trovate è l’OLED_NFC.ino, eseguendo il quale, sia sul display che sulla seriale viene mostrato il codice del tag o della card NFC.

Fig. 3 Breakout board NFC

Listato 3

#include <Wire.h>

#include <PN532_I2C.h>

#include <PN532.h>

#include <NfcAdapter.h>



PN532_I2C pn532i2c(Wire);

PN532 nfc(pn532i2c);





void setup(void) {

Serial.begin(115200);

Serial.println(“Hello!”);



nfc.begin();



uint32_t versiondata = nfc.getFirmwareVersion();

if (! versiondata) {

Serial.print(“Didn’t find PN53x board”);

while (1); // halt

}



// Got ok data, print it out!

Serial.print(“Found chip PN5”); Serial.println((versiondata>>24) & 0xFF, HEX); 

Serial.print(“Firmware ver. “); Serial.print((versiondata>>16) & 0xFF, DEC); 

Serial.print(‘.’); Serial.println((versiondata>>8) & 0xFF, DEC);



// Set the max number of retry attempts to read from a card

// This prevents us from waiting forever for a card, which is

// the default behaviour of the PN532.

nfc.setPassiveActivationRetries(0xFF);



// configure board to read RFID tags

nfc.SAMConfig();



Serial.println(“Waiting for an ISO14443A card”);

}



void loop(void) {

boolean success;

uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID

uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)



// Wait for an ISO14443A type cards (Mifare, etc.). When one is found

// ‘uid’ will be populated with the UID, and uidLength will indicate

// if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)

success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);



if (success) {

Serial.println(“Found a card!”);

Serial.print(“UID Length: “);Serial.print(uidLength, DEC);Serial.println(“ bytes”);

Serial.print(“UID Value: “);

for (uint8_t i=0; i < uidLength; i++) 

{

Serial.print(“ 0x”);Serial.print(uid[i], HEX); 

}

Serial.println(“”);

// Wait 1 second before continuing

delay(1000);

}

else

{

// PN532 probably timed out waiting for a card

Serial.println(“Timed out waiting for a card”);

}

}

Misuriamo la pressione atmosferica

Proseguiamo con una quarta applicazione, nella quale andiamo a rilevare la pressione atmosferica mediante l’abbinamento alla nostra demoboard di un sensore di pressione: il BMP280 della Bosch.

Si tratta di un trasduttore di pressione barometrica assoluta di tipo piezoresistivo, con campo di misura 300÷1100 hPa, montato su breakout board.

Le peculiarità di questo sensore oltre che nella linearità e stabilità, sono evidenziate anche nella sua accuratezza relativa, che il costruttore dichiara in ±0,12 hPa, pari a ±1 m di colonna d’aria.

In Fig. 4 vedete il sensore montato sulla relativa breakout board, la quale, dopo essere stata dotata del relativo pin-strip da saldare nelle rispettive piazzole, andrà introdotta nella posizione U7 della demoboard ESP32.

Anche per questa applicazione è previsto un apposito sketch da caricare in Arduino utilizzando l’IDE e la connessione USB; il file dell’applicazione è quello chiamato OLED_Pressure.ino e fa in modo che sul display venga mostrata la temperatura ambiente, la pressione atmosferica e l’umidità rilevata.

Per eseguire l’applicazione dovete copiare la cartella “libraries” sotto il percorso “/Documenti/Arduino”; si carica così la libreria di gestione del sensore di pressione. Per poter utilizzare proficuamente lo sketch di esempio da noi fornito, è necessario che l’indirizzo I²C-Bus della breakout board sia configurato a 0x76.

Il codice dell’applicazione di misura della pressione atmosferica è quello riportato nel Listato 4 e implementa l’acquisizione delle letture del sensore dall’I²C-Bus e la sua visualizzazione sul display OLED di bordo.

Fig. 4 Il sensore Bosch BMP280

Listato 4

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#include <Adafruit_BMP280.h>



#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED display height, in pixels



// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)

// The pins for I2C are defined by the Wire-library. 

// On an arduino UNO: A4(SDA), A5(SCL)

// On an arduino MEGA 2560: 20(SDA), 21(SCL)

// On an arduino LEONARDO: 2(SDA), 3(SCL), ...

#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)

#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);



#define NUMFLAKES 10 // Number of snowflakes in the animation example



#define LOGO_HEIGHT 16

#define LOGO_WIDTH 16



Adafruit_BMP280 bmp; // I2C



void setup() {

Serial.begin(9600);

// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally

if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {

Serial.println(F(“SSD1306 allocation failed”));

for(;;); // Don’t proceed, loop forever

}



// Show initial display buffer contents on the screen --

// the library initializes this with an Adafruit splash screen.

display.display();

delay(2000); // Pause for 2 seconds



// Clear the buffer

display.clearDisplay();

display.setTextSize(2); // Draw 2X-scale text

display.setTextColor(SSD1306_WHITE);

display.setCursor(5, 0);

display.print(“** Test **”);

display.setCursor(15, 30);

display.print(“Pressure”);



// Show the display buffer on the screen. You MUST call display() after

// drawing commands to make them visible on screen!

display.display();

delay(2000);

// display.display() is NOT necessary after every single drawing command,

// unless that’s what you want...rather, you can batch up a bunch of

// drawing operations and then update the screen all at once by calling

// display.display(). These examples demonstrate both approaches...



/*

// Invert and restore display, pausing in-between

display.invertDisplay(true);

delay(1000);

display.invertDisplay(false);

delay(1000);

*/



Serial.begin(9600);

Serial.println(F(“BMP280 test”));



if (!bmp.begin(0x76)) {

Serial.println(F(“Could not find a valid BMP280 sensor, check wiring!”));

while (1);

}



/* Default settings from datasheet. */

bmp.setSampling(Adafruit_BMP280::MODE_NORMAL, /* Operating Mode. */

Adafruit_BMP280::SAMPLING_X2, /* Temp. oversampling */

Adafruit_BMP280::SAMPLING_X16, /* Pressure oversampling */

Adafruit_BMP280::FILTER_X16, /* Filtering. */

Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */



}



void loop() 

{

display.clearDisplay();

display.setTextSize(1); // Draw 2X-scale text

display.setTextColor(SSD1306_WHITE);



display.setCursor(5, 0);

display.print(“Temp:”);

display.setCursor(60, 0);

display.print(bmp.readTemperature());

display.print(“ C”);



display.setCursor(5, 20);

display.print(“Pressure:”);

display.setCursor(60, 20);

display.print(bmp.readPressure());

display.print(“ Pa”);

display.setCursor(5, 40);

display.print(“Altitude:”);

display.setCursor(60, 40);

display.print(bmp.readAltitude(1013.25));

display.print(“ m”);

display.display();

delay(2000);

}

Rilevamento di presenza con PIR

Concludiamo questa puntata con un’applicazione nella quale andiamo a rilevare il movimento di persone e cose nel raggio di azione di un radar a infrarossi passivi, meglio noto come rivelatore PIR; allo scopo utilizeremo uno sketch specifico.

L’applicazione consiste in questo: quando il sensore PIR rileva un movimento (mediante connettore CNU10) l’uscita a relè si attiva e a display viene mostrato un avviso. Il PIR va collegato con i suoi tre contatti (positivo e negativo di alimentazione, uscita) al connettore PU10 dedicato al collegamento di dispositivi all’esterno della demoboard. Ogniqualvolta il radar a infrarossi passivi rileva il movimento nel proprio campo d’azione, il relé a bordo scheda (RL1) rimane attivato per il tempo in cui l’uscita PIR è in allarme. Ad esempio il modello PIRMOD tiene attivata l’uscita per 10 secondi al termine del rilevamento. Il firmware da caricare nell’ESP32 per implementare questa applicazione di test è OLED_PIR.ino e lo trovate nel Listato 5; va caricato, al solito, tramite l’IDE e la connessione USB.

Listato 5

#include <SPI.h>

#include <Wire.h>

#include <Adafruit_GFX.h>

#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels

#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)

// The pins for I2C are defined by the Wire-library. 

// On an arduino UNO: A4(SDA), A5(SCL)

// On an arduino MEGA 2560: 20(SDA), 21(SCL)

// On an arduino LEONARDO: 2(SDA), 3(SCL), ...

#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)

#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);



#define NUMFLAKES 10 // Number of snowflakes in the animation example

#define LOGO_HEIGHT 16

#define LOGO_WIDTH 16



const int PIR = 19;

const int RELAY = 32;

const int LEDR = 25;

int stato=0;



void setup() {

Serial.begin(9600);



// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally

if(!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {

Serial.println(F(“SSD1306 allocation failed”));

for(;;); // Don’t proceed, loop forever

}



// Show initial display buffer contents on the screen --

// the library initializes this with an Adafruit splash screen.

display.display();

delay(2000); // Pause for 2 seconds



// Clear the buffer

display.clearDisplay();

display.setTextSize(2); // Draw 2X-scale text

display.setTextColor(SSD1306_WHITE);

display.setCursor(5, 0);

display.print(“** Test **”);

display.setCursor(25, 30);

display.print(“ PIR “);



// Show the display buffer on the screen. You MUST call display() after

// drawing commands to make them visible on screen!

display.display();

delay(2000);

// display.display() is NOT necessary after every single drawing command,

// unless that’s what you want...rather, you can batch up a bunch of

// drawing operations and then update the screen all at once by calling

// display.display(). These examples demonstrate both approaches...





/*

// Invert and restore display, pausing in-between

display.invertDisplay(true);

delay(1000);

display.invertDisplay(false);

delay(1000);

*/



pinMode(PIR, INPUT);

pinMode(RELAY, OUTPUT);

pinMode(LEDR, OUTPUT);

}



void loop() 

{

display.clearDisplay();

display.setTextSize(2); // Draw 2X-scale text

display.setTextColor(SSD1306_WHITE);



Ctrl_Pir();

switch(stato) 

{

case 0:

display.setCursor(10, 10);

display.print(“PIR:ALARM”);

display.setCursor(10, 40);

display.print(“OUT:ON”);

digitalWrite(RELAY,HIGH); 

digitalWrite(LEDR,HIGH);

break;

case 1:

display.setCursor(10, 10);

display.print(“PIR:-----”);

display.setCursor(10, 40);

display.print(“OUT:OFF”);

digitalWrite(RELAY,LOW); 

digitalWrite(LEDR,LOW);

break;

default:

break; 

}



display.display();

delay(500);

}



void Ctrl_Pir()

{ 

if (digitalRead(PIR)==LOW) stato=1;

else stato=0;

}

Conclusioni

Bene, termina qui questa seconda puntata, nella quale vi abbiamo mostrato ulteriori potenzialità offerte dalla nostra demoboard ESP32 e dalle sue periferiche on-board ed esterne. Concluderemo la carrellata sui dispositivi e sulle applicazioni dimostrative nella prossima e conclusiva puntata.

Buon proseguimento!

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Menu