En aquest cas el sistema detecta si l'aparell està engegat o aturat. Quan està en marxa, es recullen els corrents consumits en mitjana i el seu màxim.
El programa del microcontrolador és el següent:
#include <SPI.h> // Carreguem la biblioteca SPI #include <WiFiNINA.h> // Carreguem la biblioteca WiFiNINA #define server_len 50 #define pag_len 400 #define SensLec A5 // Pota de lectura del sensor #define SensRef A6 // Pota de referència del sensor #define numEsp 2 // Nombre d'espires en el primari #define numCicles 100 // Nombre de cicles que es mesuraran
const char idXarxa[] = "xarxa-wifi"; // Nom del punt d'accés const char contrasenya[] = "contrasenya-wifi"; // Contrasenya de connexió const String server0 = "script.google.com"; String pagina0 = ""; const String pagina_base = "/macros/s/^^fycbxwccmJp3XLOEMnnACsHzxgVieOIecHB8iq6137FHRI-goBy-Hfl8t4_iEI_iTcegO_/exec"; char server[server_len]; char pagina[pag_len]; unsigned long darreraConnexio = 0; const unsigned long periodeConnexio = 10000UL; unsigned long tempsAnt; float maxI = 0; // Valor màxim calculat float minI = 0; // Valor mínim calculat float sumaquad = 0; // Suma per al càlcul del valor eficaç float suma = 0; // Suma per al càlcul de la mitjana int n = 0; // Nombre de valors llegits, per fer la mitjana bool pendent, completa, redir; bool ara = false; bool llest = false; bool ences = false; float Intensity; float medI; float Irms; String data; String peticio = ""; // Aquí guardarem una línia de la petició del client String peticioAux = ""; // i la petició anterior (també ho farem servir de reserva) int status = WL_IDLE_STATUS; WiFiSSLClient client;
void setup() { // Inicialització
tempsAnt = millis();
Serial.begin(9600); // Monitor sèrie
while (!Serial) {
; // Esperem que l'usuari obri el monitor sèrie
}
pinMode(LED_BUILTIN, OUTPUT); // Configura el pin como salida
digitalWrite(LED_BUILTIN, LOW); // Asegura que el LED empiece apagado
Serial.println(Irms > 1 ? "LED ENCÈS (Intensitat > 1A)" : "LED APAGAT (Intensitat = 1A)");
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();
redir = false;
}
void loop() { // Programa que es repeteix indefinidament
// El bucle principal té tres parts:
// 1. Gestió dels caràcters que arriben
// 2. Tractament de les dades rebudes
// 3. Nova petició quan ha passat el temps
while (client.available()) {
// Gestió dels caràcters que arriben
// Aquest bucle va guardant els caràcters rebuts
// i espera al moment en que arriba un salt de línia
char c = client.read(); // Rebem caràcters del servidor
if (c == '\n') { // Mirem si és un salt de línia
peticioAux = peticio; // Guardem la petició anterior
peticio = ""; // Ens preparem per a la línia següent
completa = true; // Preparat per escriure-ho
} else {
peticio += c; // Afegim el caràcter rebut
}
// Quan ha arribat un salt de línia, hem de mirar què ha arribat
if (completa){ // Ha arribat una línia completa
if (peticioAux.startsWith("HTTP/1.1 200")){ // Resposta bona
pendent = true;
}
if (peticioAux.startsWith("HTTP/1.1 302")){ // Redireccionament
redir = true;
}
if (redir && (peticioAux.startsWith("Location:"))){
// Si hi ha redireccionament, hem de buscar l'adreça
// i extreure'n el servidor i la pàgina
String adre = peticioAux.substring(peticioAux.indexOf("//") +2);
String server1 = adre.substring(0, adre.indexOf(".com") +4);
String pagina1 = adre.substring(adre.indexOf(".com") +4);
server1.toCharArray(server, 50);
pagina1.toCharArray(pagina, 400);
ara = true;
}
completa = false;
}
}
// Hi ha una resposta per processar
// Però ignorarem les dades que ens envia l'script
if (pendent) {
pendent = false;
}
int lec_sensor = analogRead(SensLec);
int ref_sensor = analogRead(SensRef);
// Calculem el valor instantani del corrent
float Iinst = 30 * 3.3 * (lec_sensor - ref_sensor) / 1023 / numEsp;
sumaquad = sumaquad + (Iinst * Iinst); // Suma de quadrats
suma = suma + abs(Iinst); // Suma de valors absoluts
n++;
if((millis() - tempsAnt) > (20 * numCicles)){
llest = true;
tempsAnt = millis();
medI = 1.1107 * suma / n; // Valor eficaç
// calculat a partir de la mitjana
// pi/2/sqrt(2) = 1.1107
Irms = sqrt(sumaquad / n);
if (Irms > 1) {
digitalWrite(LED_BUILTIN, HIGH); // Enciende el LED
ences = true;
} else {
digitalWrite(LED_BUILTIN, LOW); // Apaga el LED
}
if(Irms > maxI){
maxI = Irms;
}
if(Irms < minI){
minI = Irms;
}
data = "?";
data += "i=";
data += Irms;
data += "&max=";
data += maxI;
data += "&min=";
data += minI;
data += "&ences=";
data += ences;
}
// Quan toca, tornem a fer una petició
if (ara || ((millis() - darreraConnexio > periodeConnexio))) {
if(!ara) {
;
}
if (redir){
redir = false;
} else {
pagina0 = pagina_base + data;
server0.toCharArray(server, server_len);
pagina0.toCharArray(pagina, pag_len);
}
client.stop();
if(llest){
if (client.connect(server, 443)) {
Serial.println("S'ha fet la connexió al servidor");
client.print("GET ");
client.print(pagina);
client.println(" HTTP/1.1");
client.print("Host: ");
client.println(server);
client.println("Connection: close");
client.println();
Serial.print("n = ");
Serial.print(n);
Serial.print(" Max = ");
Serial.print(maxI);
Serial.print(" Min = ");
Serial.print(minI);
Serial.print(" RMSap = ");
Serial.print(medI);
Serial.print(" A");
Serial.print(" RMS = ");
Serial.print(Irms);
Serial.println(" A");
maxI = 0;
minI = 0;
sumaquad = 0;
suma = 0;
// Guardem quan hem fet la connexió
darreraConnexio = millis();
Serial.print("Enviat: ");
Serial.println(data);
} else {
Serial.println("connection failed");
}
llest = false;
}
ara = false;
ences = false;
}
}
El programa de l'script és el següent:
var IdFull = "^^YTvG6jkGDEbN88ozLI-39nq76l1lnQFcrdMIWeffjI"; // ID del full de càlcul
function doGet(e) {
var resultat = '';
var camps = new Array(8);
var camps2 = new Array(5);
var Intensity = e.parameter.i;
var Maxim = e.parameter.max;
var Ences = parseInt(e.parameter.ences);
var EstatAnterior;
var now = new Date();
var data = Utilities.formatDate(now, Session.getScriptTimeZone(), "yyyy-MM-dd");
var hora = Utilities.formatDate(now, Session.getScriptTimeZone(), "HH:mm:ss");
var sh = SpreadsheetApp.openById(IdFull);
var fullSheet = sh.getSheetByName("Hoja 1");
var resumSheet = sh.getSheetByName("Hoja 2");
var full = fullSheet.getDataRange().getValues();
var lastrow = fullSheet.getLastRow();
if (lastrow > 1) {
var filera = full[lastrow - 1];
EstatAnterior = filera[0];
var horaApagatAnterior = filera[5];
}
if (Ences == 1) {
if (EstatAnterior == 'Encès') {
// Continuació del cicle
camps[0] = "Encès";
camps[1] = Intensity;
camps[2] = Maxim;
camps[3] = data;
camps[4] = hora;
} else {
// Nou cicle d'encès
camps[0] = "Encès";
camps[6] = hora;
camps[3] = data;
}
fullSheet.appendRow(camps);
resultat = 'Valors guardats';
} else {
// Ara està apagat
if (EstatAnterior == 'Encès') {
// S'ha apagat, cal calcular cicle i escriure'l
camps[0] = "Apagat";
camps[3] = data;
camps[5] = hora;
// ======= CÀLCUL DE MITJANA I MÀXIM DEL CICLE =========
const LLINDAR = 0.5;
var dades = full;
var ultimCicle = [];
var enCicle = false;
var dataInici = "";
var horaInici = "";
for (var i = dades.length - 1; i >= 0; i--) {
var fila = dades[i];
var estat = fila[0];
var intensitat = parseFloat(fila[1]);
var maxim = parseFloat(fila[2]);
var dataFila = fila[3];
var horaFila = fila[4];
if (estat === "Encès" && intensitat > LLINDAR) {
ultimCicle.unshift({ intensitat, maxim });
enCicle = true;
dataInici = dataFila;
horaInici = horaFila;
} else if (enCicle && estat === "Apagat") {
break;
}
}
if (ultimCicle.length > 0) {
var suma = ultimCicle.reduce((acc, obj) => acc + obj.intensitat, 0);
var mitjana = suma / ultimCicle.length;
var maximCicle = Math.max(...ultimCicle.map(obj => obj.maxim));
camps2[1] = mitjana;
camps2[2] = maximCicle;
camps2[3] = hora;
resumSheet.appendRow(camps2);
}
// ======================================================
fullSheet.appendRow(camps);
resultat = 'Valors guardats';
}
}
return ContentService.createTextOutput(resultat);
}

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