Community project · Arduino Uno R4 WiFi
First blink
By Lucero Celis V. Sistemas USAT (@lucero-celis-v-sistemas)
A circuit on the Arduino Uno R4 WiFi by Lucero Celis V. Sistemas USAT (@lucero-celis-v-sistemas), shared on Mokxi. Open it and press Run: it runs in your browser, free.
Runs in your browser. Free · 4 remixes · 1 heart.

The code
The sketch exactly as it was saved. Open it in the editor and press Run: it compiles in your browser.
sketch.ino · unor4wifi1
#include <Wire.h>
#include <EEPROM.h>
#include <DHT.h>
#include <LiquidCrystal_I2C.h>
#include <math.h>
#include <stdlib.h>
#define DHTTYPE DHT22
const bool MODO_DEMO = false;
const byte SENSOR=2, BOTON=3, VERDE=5;
const byte AMARILLO=6, ROJO=7, BUZZER=8;
DHT dht(SENSOR, DHTTYPE);
LiquidCrystal_I2C lcd(0x27,16,2);
float cache[5];
uint16_t cacheId[5]={0};
byte cacheN=0, cacheNext=0;
float ramT[20];
uint16_t ramId[20]={0};
byte ramN=0, ramNext=0;
float temperaturaActual=0, temperaturaMaxima=0;
uint32_t contadorAlarmas=0, hits=0, misses=0;
bool hayTemperatura=false, sensorOK=false;
bool alarmaAnterior=false;
uint16_t siguienteId=1, solicitado=1;
byte histNext=0, histN=0;
float limiteVerde=25, limiteAlarma=30;
unsigned long ultimaLectura=0, consultaInicio=0;
bool consultaVisible=false;
char linea[24]; byte lineaN=0;
bool lineaDesbordada=false;
void pantalla(const char *a, const char *b) {
lcd.clear(); lcd.setCursor(0,0); lcd.print(a);
lcd.setCursor(0,1); lcd.print(b);
}
void guardarControl() {
EEPROM.put(20,contadorAlarmas);
EEPROM.update(24,histNext);
EEPROM.update(25,histN);
EEPROM.put(26,siguienteId);
}
void prepararMemoria() {
uint16_t marca=0; EEPROM.get(0,marca);
if(marca!=0x4E52) {
for(int i=0;i<100;i++) EEPROM.update(i,0);
int16_t lv=250, la=300;
EEPROM.put(2,lv); EEPROM.put(4,la);
guardarControl();
marca=0x4E52; EEPROM.put(0,marca);
}
int16_t lv,la;
EEPROM.get(2,lv); EEPROM.get(4,la);
// Mantener exactamente los limites de la tabla.
if(lv!=250 || la!=300) {
lv=250; la=300;
EEPROM.put(2,lv); EEPROM.put(4,la);
}
limiteVerde=lv/10.0f; limiteAlarma=la/10.0f;
EEPROM.get(20,contadorAlarmas);
histNext=EEPROM.read(24); histN=EEPROM.read(25);
EEPROM.get(26,siguienteId);
if(histNext>9 || histN>10 || siguienteId==0) {
pantalla("Error memoria","Revisar datos");
Serial.println("Metadatos invalidos; revisar EEPROM.");
while(true) delay(100);
}
}
void salidas(float t, bool valido) {
digitalWrite(VERDE,valido && t<limiteVerde);
digitalWrite(AMARILLO,valido && t>=limiteVerde
&& t<limiteAlarma);
digitalWrite(ROJO,valido && t>=limiteAlarma);
if(valido && t>=limiteAlarma) tone(BUZZER,2000);
else noTone(BUZZER);
}
void mostrarEstado() {
lcd.clear(); lcd.setCursor(0,0);
if(!sensorOK) {
lcd.print(hayTemperatura ? "Error sensor" : "Sin lectura");
lcd.setCursor(0,1); lcd.print("Revisar sensor");
return;
}
lcd.print("T:"); lcd.print(temperaturaActual,1);
lcd.print(" C"); lcd.setCursor(0,1);
if(temperaturaActual<limiteVerde) lcd.print("NORMAL");
else if(temperaturaActual<limiteAlarma) lcd.print("ADVERTENCIA");
else lcd.print("ALARMA");
}
void mostrarCache() {
Serial.print("CACHE IDs antiguos a recientes: ");
for(byte j=0;j<cacheN;j++) {
byte k=(cacheNext+5-cacheN+j)%5;
Serial.print(cacheId[k]); Serial.print(' ');
}
Serial.println();
}
void guardarCritica(uint16_t id,float t) {
int a=50+5*histNext;
int16_t decimas=(int16_t)lroundf(t*10.0f);
EEPROM.update(a,0); // Invalidar antes de escribir.
EEPROM.put(a+1,id); EEPROM.put(a+3,decimas);
EEPROM.update(a,165); // Registro completo.
histNext=(histNext+1)%10;
if(histN<10) histN++;
guardarControl();
Serial.print("EEPROM ID="); Serial.print(id);
Serial.print(" T="); Serial.print(decimas/10.0f,1);
Serial.print(" direccion="); Serial.print(a);
Serial.print(" pagina="); Serial.println(a/10);
}
void procesar(float t) {
if(!isfinite(t) || t< -40 || t>80) {
sensorOK=false; salidas(0,false);
if(!consultaVisible) pantalla("Error sensor","Sin dato valido");
Serial.println("Lectura invalida; memoria sin cambios.");
return;
}
if(siguienteId>=65535) {
sensorOK=false; salidas(0,false);
pantalla("Limite de IDs","Revisar memoria");
return;
}
uint16_t id=siguienteId++;
// Evitar repetir identificadores despues de reiniciar.
EEPROM.put(26,siguienteId);
temperaturaActual=t;
if(!hayTemperatura || t>temperaturaMaxima)
temperaturaMaxima=t;
hayTemperatura=true; sensorOK=true;
cache[cacheNext]=t; cacheId[cacheNext]=id;
cacheNext=(cacheNext+1)%5;
if(cacheN<5) cacheN++;
ramT[ramNext]=t; ramId[ramNext]=id;
ramNext=(ramNext+1)%20;
if(ramN<20) ramN++;
bool alarmaAhora=t>=limiteAlarma;
if(alarmaAhora && !alarmaAnterior) {
contadorAlarmas++;
EEPROM.put(20,contadorAlarmas);
}
alarmaAnterior=alarmaAhora;
salidas(t,true);
if(t>limiteAlarma) guardarCritica(id,t);
Serial.print("LECTURA ID="); Serial.print(id);
Serial.print(" T="); Serial.print(t,1);
Serial.print(" MAX="); Serial.print(temperaturaMaxima,1);
Serial.print(" ALARMAS="); Serial.println(contadorAlarmas);
mostrarCache();
if(!consultaVisible) mostrarEstado();
}
bool buscarEEPROM(uint16_t id,float &t) {
for(byte j=0;j<histN;j++) {
byte k=(histNext+10-1-j)%10;
int a=50+5*k;
if(EEPROM.read(a)!=165) continue;
uint16_t leido; int16_t decimas;
EEPROM.get(a+1,leido);
if(leido==id) {
EEPROM.get(a+3,decimas); t=decimas/10.0f;
return true;
}
}
return false;
}
void consultar() {
float t=0; bool encontrado=false, hit=false;
const char *origen="NO DISPONIBLE";
for(byte i=0;i<cacheN;i++) {
if(cacheId[i]==solicitado) {
t=cache[i]; encontrado=true; hit=true;
origen="CACHE"; break;
}
}
if(hit) hits++;
else {
misses++;
for(byte i=0;i<ramN;i++) {
if(ramId[i]==solicitado) {
t=ramT[i]; encontrado=true; origen="SRAM"; break;
}
}
if(!encontrado && buscarEEPROM(solicitado,t)) {
encontrado=true; origen="EEPROM";
}
}
lcd.clear(); lcd.setCursor(0,0);
lcd.print(hit ? "HIT ID:" : "MISS ID:");
lcd.print(solicitado); lcd.setCursor(0,1);
if(encontrado) {
lcd.print(t,1); lcd.print("C "); lcd.print(origen);
} else lcd.print("No disponible");
Serial.print("CONSULTA ID="); Serial.print(solicitado);
Serial.print(hit ? " HIT " : " MISS ");
Serial.print(origen);
if(encontrado) { Serial.print(" T="); Serial.print(t,1); }
Serial.print(" H="); Serial.print(hits);
Serial.print(" M="); Serial.println(misses);
consultaVisible=true; consultaInicio=millis();
}
void comando() {
linea[lineaN]='\0';
char *fin;
if(MODO_DEMO && linea[0]=='T') {
float t=strtof(linea+1,&fin);
if(fin!=linea+1 && *fin=='\0') procesar(t);
else Serial.println("Temperatura no valida.");
} else {
long id=strtol(linea,&fin,10);
if(fin!=linea && *fin=='\0' && id>0 && id<65535) {
solicitado=(uint16_t)id;
Serial.print("Seleccionado ID="); Serial.println(solicitado);
} else Serial.println("Enviar ID valido o Tvalor en DEMO.");
}
}
void leerSerial() {
while(Serial.available()) {
char c=Serial.read();
if(c=='\r') continue;
if(c=='\n') {
if(!lineaDesbordada && lineaN>0) comando();
else if(lineaDesbordada) Serial.println("Comando muy largo.");
lineaN=0; lineaDesbordada=false;
} else if(lineaN<sizeof(linea)-1) linea[lineaN++]=c;
else lineaDesbordada=true;
}
}
void atenderBoton() {
static bool anterior=HIGH, estable=HIGH;
static unsigned long cambio=0;
bool leido=digitalRead(BOTON);
if(leido!=anterior) { cambio=millis(); anterior=leido; }
if(millis()-cambio>=40 && leido!=estable) {
estable=leido;
if(estable==LOW) consultar();
}
}
void setup() {
Serial.begin(115200);
pinMode(BOTON,INPUT_PULLUP);
pinMode(VERDE,OUTPUT); pinMode(AMARILLO,OUTPUT);
pinMode(ROJO,OUTPUT); pinMode(BUZZER,OUTPUT);
lcd.init(); lcd.backlight(); dht.begin();
if(EEPROM.length()<100) {
pantalla("Sin memoria","EEPROM < 100");
while(true) delay(100);
}
prepararMemoria(); salidas(0,false);
pantalla("Monitor listo",MODO_DEMO ? "DEMO: Tvalor" : "Esperar sensor");
Serial.print("Contador recuperado="); Serial.println(contadorAlarmas);
Serial.println("Seleccionar ID y pulsar boton para consultar.");
}
void loop() {
leerSerial();
if(!MODO_DEMO && millis()-ultimaLectura>=2000) {
ultimaLectura=millis(); procesar(dht.readTemperature());
}
atenderBoton();
if(consultaVisible && millis()-consultaInicio>=3000) {
consultaVisible=false; mostrarEstado();
}
}
sketch.ino
// Mokxi.
// This circuit has no board, so Run simulates the parts only.
// Add a board and pick a program in its Firmware panel: the editor then shows
// that program's source, and Run builds what you type here for that board.
void setup() {
pinMode(13, OUTPUT);
Serial.begin(115200);
}
void loop() {
digitalWrite(13, HIGH);
delay(500);
digitalWrite(13, LOW);
delay(500);
}
Parts list
16 parts, plus the jumper wires. Every one is in the editor's parts bin.
- 1 × Arduino Uno R4 WiFi
- 1 × Buzzer
- 1 × Character LCD with I2C backpack
- 1 × Diode
- 1 × Full-size breadboard
- 3 × LED
- 1 × Pushbutton
- 5 × Resistor
- 1 × Temperature and humidity, DHT22
- 1 × Transistor (NPN or PNP)