Internet de les coses amb ESP32 i ESP8266

Exemples Referència Plaques   Recursos CITCEA
Projectes Programació Perifèrics   Inici

Sonòmetre

Programa del grup 3

En aquest cas s'ha dissenyat un sonòmetre per a sales interiors. El microcontrolador treballa com a client i envia periòdicament el valor de so mesurat a un full de càlcul de Google i, a més, canvia el color del LED. Es fa servir un script per enviar, si el nivell de so és elevat, un correu electrònic a la persona responsable. Addicionalment, hi ha una aplicació per a mòbils que permet consultar la informació. El programa del microcontrolador és el següent:

#include <SPI.h>	// Carreguem la biblioteca SPI
#include <WiFiNINA.h>	// Carreguem la biblioteca WiFiNINA
#include <Adafruit_NeoPixel.h>	// biblioteca per als NeoPixels
#define LED 1	// pota on hem connectat el LED
#define MICpin A6
#define numMost 500
WiFiSSLClient client;
Adafruit_NeoPixel cadena = Adafruit_NeoPixel(1, LED, NEO_GRB + NEO_KHZ800);
const char idXarxa[] = "xarxa";	// Nom del punt d'accés 
const char contrasenya[] = "contrasenya";	// Contrasenya de connexió 
const char formulari[] = "1PKLQIW4EEKrIHUUUgCmqn7fxyZ5FnPTj-rvpt1tYKL0/edit#gid=1237915684";
const char adrePost[] = "/forms/u/0/d/e/1FAMpQLSdWJmRvnpm0zFrYqgMZPyqhwpSbvkdrDouvRHRacovY8CGr-g/formResponse";
char server_script[] = "script.google.com";
char id_script[]= "/macros/s/AKfycbybIYvW1WTHcCzSbwmeIOtj_FPNcXYaSbpqPvAGfdjd9LL4u-0/exec?accio=darrer";
String camp = "entry.286343721";
char server_full_calcul[] = "docs.google.com";
String data;
int status = WL_IDLE_STATUS;
int lectures[numMost];
int lectura, maxim, minim, suma;
float rms, lecCorr, mitjana;
int R, G, B;	// Aquí guardarem els colors
void setup() {	// Inicialització
	Serial.begin(9600);	// Monitor sèrie
	cadena.begin();	// Inicialitza els NeoPixels		
	cadena.show();
	while (!Serial) {
		;	// Esperem que l'usuari obri el monitor sèrie
	}
	if (WiFi.status() == WL_NO_MODULE) {
		Serial.println("No s'ha trobat el dispositiu Wi-Fi");
		while (true);	// Bloquegem el programa
	}
	String versio = WiFi.firmwareVersion();
	if (versio < "1.0.0") {
		Serial.println("Convindria actualitzar el firmware");
	}
	while (status != WL_CONNECTED) {
		Serial.print("Connectant a la xarxa ");
		Serial.println(idXarxa);
		status = WiFi.begin(idXarxa, contrasenya);
		delay(10000);	// Ho tornarem a intentar passats 10 s
	}
	Serial.print("Connectat a "); 
	Serial.println(WiFi.SSID());
	Serial.print("Estat de la connexió: ");
	Serial.println(WiFi.status()); 
	Serial.print("Adreça IP del dispositiu: ");
	Serial.println(WiFi.localIP()); 
	Serial.print("Intensitat del senyal: ");
	Serial.print(WiFi.RSSI()); 
	Serial.println(" dBm");
	Serial.println(); 
	Serial.println("Anem a connectar al servidor");
}
void loop() {
	// Primer escrivim els valors en un full de càlcul
	if (status != WiFi.status()) {	// Mirem si ha canviat l'estat de la connexió
		status = WiFi.status();
		if (status == WL_AP_CONNECTED) {
			Serial.println("Dispositiu connectat al punt d'accés");
		} else {
			Serial.println("El dispositiu s'ha desconnectat del punt d'accés");
		}
	}
	maxim = 0;
	minim = 1024;
	suma = 0;
	for (int i = 0; i < numMost; i++){
		lectura = analogRead(MICpin);
		suma = suma + lectura;
		if(lectura > maxim){
			maxim = lectura;
		}
		if(lectura < minim){
			minim = lectura;
		}
		lectures[i] = lectura;
	}
	mitjana = float(suma) / numMost;
	rms = 0;
	for (int i = 0; i < numMost; i++){
		lecCorr = float(lectures[i]) - mitjana;
		rms = rms + lecCorr * lecCorr;
	}
	rms = sqrt(rms / numMost);
	data = "";
	data += camp;
	data += "=";
	data += rms;
	data += "&submit=Submit";
	if (client.connect(server_full_calcul, 443)) {
		Serial.println("Connectat");
		client.print("POST ");
		client.print(adrePost);
		client.print("?formkey=");
		client.print(formulari);
		client.println("&ifq HTTP/1.1");
		client.print("Host: ");
		client.println(server_full_calcul);
		client.println("Content-Type: application/x-www-form-urlencoded");
		client.println("Connection: close");
		client.print("Content-Length: ");
		client.println(data.length());
		client.println();
		client.print(data);
		client.println();
		Serial.print("Enviat	So = ");
		Serial.print(rms);
	}
	delay(1000);
	if (!client.connected()) {
		Serial.println();
		Serial.println("Desconnectant");
		client.stop();
	}
	delay(10000);
	// Ara llegim aquests valors i encenem el LED
	if (rms <= 5) {	// El LED s'encén de color verd perquè hi ha poc soroll
		R= 0; 
		G= 255;
		B= 0;
	} else if ((rms> 5)&& (rms<= 10)){	// El LED s'encén de color taronja
		R= 255; 
		G= 128;
		B= 0;	
	}
	else if (rms > 10){	// El LED s'encén de color vermell perquè hi ha molt soroll
		R= 255; 
		G= 0;
		B= 0; 
		if (client.connect(server_script, 443)) {
			Serial.println("Connectat");
			client.println(server_script);
			client.print(id_script);
		}		
	}
	cadena.setPixelColor(0, R, G, B);
	cadena.show();
}

L'script és el següent:

var IdFull = "1PKLQIW4EEErIHUUUbCmqn7gxyZ5FnPTj-rvpt1tSRL0"; // Identificador del full de càlcul 
							// S'aconsegueix picant a Comparteix i triant Opcions avançades
var numCols = 2;	// Nombre de columnes de treball que tenim al full de càlcul
var range1;
var range2;
// Script per interactuar amb el full de càlcul
// Funció que s'executa quan hi ha una ordre get
// La nostra funció tindrà un paràmetre: so
function doGet(e) {
	// Assignem els paràmetres a variables
	var RMS= e.parameter.so;
	// Obrim el full de càlcul
	var sh = SpreadsheetApp.openById(IdFull);
	var sheet = sh.getSheets();
	// Llegim les dades del full 1 per obtenir el valor RMS
	var full1 = sheet[1].getDataRange().getValues();
	range1 = sheet[1].getLastRow();
	if (range1 > 1){		// Si és 0 només hi ha els títols
		var darreraConnexio = full1[range1 -1][0];
	}
	// Llegim les dades del full 2 per obtenir el correu i el lloc
	var full2 = sheet[2].getDataRange().getValues();
	range2 = sheet[2].getLastRow();
	if (range2 > 1){		// Si és 0 només hi ha els títols
		var destinatari = full2[range2 -1][0];
		var lloc= full2[range2 -1][1];
	}	
	var ara = new Date();
	var Hora = ara.getHours();
	var Minut = ara.getMinutes();
	var horaActual = Hora + ":" + Minut + " h";
	var Dia= ara.getDate();
	var Mes= ara.getMonth()+1;
	var Any= ara.getFullYear();
	var diaActual= Dia + "-" + Mes + "-" + Any;
	var titol = "Avís: so elevat";
	var text = "Avui, dia " + diaActual + ", a les " + horaActual + ", s'ha produït un esdeveniment que ha provocat l'enviament d'aquest correu electrònic. ";
	text= text + "\n \n";
	text= text + " A la sala " + lloc +" hi ha actualment un soroll molt elevat. "
	text= text + "\n \n";
	text = text + "Concretament, de " + RMS + " unitats. Aquest valor es troba per sobre del límit establert. ";
	text= text + "\n \n";
	text = text + "Si us plau, convindria reduir el volum per no molestar els veïns i companys.";
	text = text + "\n\n";	// Dos salts de línia
	text = text + "Gràcies!";
	var interval_millis= 10*60*1000; // Correspon a 10 min
	if (ara.getTime() - darreraConnexio.getTime() >= interval_millis){
		MailApp.sendEmail(destinatari, titol, text);
		sheet[1].appendRow ([ara, RMS]);
	}
	return ContentService.createTextOutput(RMS);
}

L'aplicació feta amb App Inventor té dues pantalles. La disposició d'elements a la primera pantalla és:

Pantalla

El programa és el següent:

Programa

La disposició d'elements a la segona pantalla és:

Pantalla

El programa és el següent:

Programa

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.