Los timbres inteligentes son un gadget increíble pero aún costosos (~ $200),pero gracias Naran Inc disfrutamos de un sencillo tutorial, para ayudarnos a crear nuestro propio timbre hogar inteligente para menos de $40.
Lo guiará a través de los pasos del núcleo básico para crear el timbre con componentes simples y sin necesidad de codificación o habilidad manual. Si eres apasionado de la artesanía en madera o impresión 3D, por supuesto puede ir más allá y dar el timbre de la puerta un hermoso caso (si lo haces por favor comparta con nosotros!). Por simplicidad, vamos a mantener nuestras explicaciones a la versión «raw» de la puerta.
CARACTERÍSTICAS
Con este proyecto, podrás crear un timbre que puede:
Cuando alguien suena (¡duh!) en tu smartphone
Usar las luces de la oficina de la casa como una herramienta de notificación visual
Enviarle una foto de tus invitados en tu smartphone
Que pueda abrir la puerta remotamente
Y todo esto sin ningún conocimiento técnico especial y ningún equipo costoso.
Que? Este proyecto puede ser ideal para usted si usted es:
Un entusiasta de la tecnología con ganas de aprender más sobre el planeta natal de IoT/smart
Un fabricante experimentado de automatización del hogar quién quiere agregar funciones nuevas y diversión a su casa y hacerla aún más automatizado
Una persona con discapacidad o un pariente : IoT dispositivos son ideales para personas con movilidad reducida. Recibimos retroalimentación de cada día de los usuarios de nuestros productos que son capaces remotamente accionar el equipo de salud, automatizar las tareas domésticas o iniciar aplicaciones inalcanzables y estamos inmensamente orgullosos de que nuestro trabajo puede mejorar un poco su vida diaria.
Alguien apasionado por los proyectos de bricolaje quién no conoce mucho de tecnología pero
O simplemente un persona perezosa !
Componentes necesarios
Frambuesa Pi 2, 3 ($20 ~ $35) / 2 de RPi, usted necesitará dongles de Bluetooth y WiFi
Primero debes construir el cubo inteligente que conectan todos los dispositivos y controlar la automatización de su campana anillo. OS prota para Raspberry Pi es nuestro hub inteligente libre sistema operativo que es muy fácil de instalar. En ningún momento a su vez su frambuesa Pi en un centro de automatización del hogar inteligente!
Descargar aplicación de telegrama en el teléfono inteligente y crear una cuenta
Descargar aplicación de telegrama en su Pi del Prota (en las bibliotecas de la aplicación)
Abra la aplicación telegrama de Prota y haga clic en «Solicitar autorización»
Configurar un nombre y nombre de usuario para tu bot, a continuación, haga clic en «Crear»
¡Ahora se crea tu bot! Una vez que la automatización es la configuración (siguiente paso), el bot le enviará una notificación + una foto de la persona que sonó el timbre de la puerta inteligente. Si usted tiene un empuje de MicroBot, también será capaz de abrir la puerta mediante el envío de un mensaje a tu bot!
Ahora vamos a configurar rápidamente su webcam viejo para convertirlo en una cámara inteligente!
Plug-in cable USB de la cámara a su frambuesa Pi
Descargar la aplicación de la Webcam en su Pi del Prota (en las bibliotecas de la aplicación)
Abra la aplicación para comprobar que la cámara está trabajando ahora (debe comenzar a tomar automáticamente imágenes en caso de cualquier movimiento)
Ahora que se instalan el bot y la webcam, tenemos que crear el flujo de trabajo de automatización
Paso 5: Escribir la historia de la automatización
Aplicación de historias es lo que le permite configurar los flujos de trabajo de automatización escrito en lenguaje natural.
Necesitamos automatizar dos cosas:
Qué sucede después de que el cliente Presione la queda (notificaciones varias)
La apertura remota de la puerta (si tienes un empuje de MicroBot)
Vamos a establecer primero la historia de notificación:
Abrir aplicación de historias, haga clic en + y luego en «cuando»
Haga clic en «set sensor» y selecciona GPIO. El evento debe «detecta una interrupción creciente pin GPIO18». Esto significa que «cuando se presiona su bell ring».
Ahora estableceremos las acciones que siguen este disparador. Seleccionar Webcam, el evento de acción debe ser «webcam toma una instantánea».
Haga clic en el botón de «entonces» en la esquina superior derecha. Seleccione el telegrama para la siguiente acción, seleccione tu bot, seleccione «enviar? a»y para las instrucciones de agregar un texto de notificación como» alguien en la puerta! «
Haga clic en «entonces». Seleccione «enviar una foto a» y añadir las instrucciones para «a» del campo y seleccione «archivo de instantáneas» para ser enviado.
Opcionalmente, si tienes una bombilla Philips Hue, añadir esta parte «Luego Philips Hue alarmas rápidamente» para que también tenga una advertencia visual en tu escritorio.
Ahora vamos a configurar los comandos para abrir la puerta. Si tienes una puerta en el hogar o en la oficina que puede abrir con un botón, MicroBot puede automatizar! En primer lugar, instalar el pulsador del MicroBot en el botón de bloqueo de puerta como lo hicimos en nuestra oficina.
A continuación, sincronizarlo con aplicación de MicroBot empuje de su Prota. Una vez hecho esto, escribir el siguiente argumento: «Cuando Bot telegrama recibe un mensaje» y añadir la condición «Texto igual a ‘Abrir’» «Y empuje la puerta Presione el botón» ahora, una vez notificado de la llegada de su huésped, un simple texto «Abrir» enviado a tu Bot de telegrama abrirá la puerta.
Hecho ¡ ! Ahora puede probarlo antes de instalarlo todo junto a su puerta (ver gif en la parte superior)
Paso 6: Instalar y utilizar!
<
En el video siguiente podemos ver el proyecto funcionando:
Los Fire TV Stick son de las pocas alternativas que tenemos de disfrutar del ecosistema que Amazon pone en nuestra mano para convertir en inteligente un viejo TV ( o no tanto) . Como puede deducirse, el Fire Stick TV es uno de los productos más vendidos en Amazon ,ya que por sus prestaciones y precio ( entre 30€ en la versión lite, 40€ la versión standard y hasta llegar a los 60€ en su versión 4k) puede ser de gran utilidad en casa.
En efecto, como sabemos, el Fire TV Stick convierte su televisor en una Smart TV, por lo que básicamente es un reproductor de contenido multimedia en streaming con capacidad de resolución 4K (según versión), el cual además sólo se puede conectar mediante HDMI a su TV. Para ello debemos conectar el Amazon Fire TV Stick a su televisor HD por algun puerto hdmi libre sin olvidar de alimentarlo con 5v DC con el cargador incorporado (aunque podemos usar también un puerto USB del TV si este permite también un consumo de unos 100mA) y empiece a ver contenido en streamingen cuestión de minutos ( tras la configuración inicial donde básicamente ajustamos el idioma, la wifi a la que nos conectaremos, las credenciales de Amazon y se actualizará el firmware).
Este dispositivo es muy interesante poque con el asistente por voz Alexa solo tenemos que pulsar un botón y pedirle que busque películas y episodios de series favoritas, así como deportes y noticias en directo usando las principales plataformas del mercado, como Netflix, DAZN, Movistar+, Disney+, Apple TV y Amazon Prime Video, todo en un solo dispositivo. Asimismo podemos reproducir en streaming millones de canciones y usar el nuevo mando por voz Alexa para pedir una canción, artista o lista de reproducción, o para controlar la reproducción en servicios como Amazon Music, Spotify o TuneIn.
Amazon Fire TV Stick funciona con cualquier televisor HD, así que puede usarlo en casa de sus amigos o llevarlo de viaje pero para conectarlo y usarlo en cualquier lugar, necesitaremos una conexión Wi-Fi ( puede ser suficiente la zona wifi que activemos en nuestro dispositivo móvil).
Aunque no es un aparato que falle demasiado, de vez en cuando se pueden producir errores graves mientras usamos el Fire TV Stick. Por ejemplo, que el mando no nos responda y que sea imposible revivirlo. Una primera medida que podemos hacer es la de apagar la llave HDMI a ver si vuelve en sí, pero si persiste, entonces tenemos que hacer algo mucho más agresivo. Esos dos grandes incidentes pueden ser, o bien que el mando a distancia se ha desemparejado, es decir, ha perdido su vínculo con el Fire TV Stick que compramos, o bien el cuelgue solo afecta al mando, de tal forma que sea necesario reiniciarlo para devolverlo a un estado de completa actividad.
Los botones del mando
De todos los botones que podemos ver en el mando de control remoto de vuestro Fire TV Stick, vamos a quedarnos con solo cuatro, que son los que tenemos señalados justo aquí debajo con números que van del 1 al 4:
Home (o Inicio): es el que podéis ver en la parte central y que tiene un iconito de una casa.
Cursor izquierdo: de la rueda que contiene los botones de las cuatro direcciones posibles, solo nos interesa la que apunta a la izquierda.
Volver: a los que tenéis un móvil con Android os sonará, porque es la flechita que parece volver por dónde venía. Atentos a ella.
Opciones: con varias líneas blancas horizontales, ese botón será esencial para realizar cieras acciones.
Cómo resetear el mando del Fire TV Stick
Antes de que nos decidamos por tomar medidas especiales más expeditivas como es el realizar un nuevo emparejamiento del mando a distancia con el Fire TV Stick, lo mejor es intentar antes algo más rápido y que afecta solo al propio mando así que lo interesante es empezar con un reset para intentar arreglar ese cuelgue transitorio en el que está sumido. Para llevarlo a cabo, solo tenéis que hacer lo siguiente en el mando del Fire TV Stick con Alexa integrado:
Desconecte el Fire TV Stick de tu televisor y espere un minuto. Esto lo haremos para no encenderlo al tocar el mando.
A continuación, mantenga pulsado el cursor izquierdo, el de Menú y Atrás todos a la vez. Es importante que no los pulsé escalonadamente, o que alguno se suelte durante el proceso de reset. Así que antes de hacerlo, pruebe a ver de qué forma segura puede colocar los dedos para que no haya errores.
En el caso del modelo 4K de ese mismo Fire TV Stick, el procedimiento es sensiblemente distinto:
Repetimos el mismo proceso que antes solo que los tres botones los mantenemos pulsados a la vez durante 12 segundos.
Los soltamos y esperamos otros cinco segundos.
Ahora quitamos las pilas del mando a distancia.
Encendemos el Fire TV Stick 4K y esperamos un minuto más.
Colocamos de nuevo las pilas al mando y pulsamos sobre el botón Home. El indicador LED que trae debería parpadear en color azul para confirmarnos que todo el proceso ha funcionado y el control se está comunicando con la llave HDMI.
Es importante decir que el modelo con Alexa Voice Remote Lite no tiene esa luz LED, por lo que identificar que todo funciona será cuestión de ver que ya podemos navegar correctamente por los menús.
Vuelva a emparejar el mando con su Fire TV Stick
Ahora bien, el otro problema que puede asaltarnos es que, por razones desconocidas, el mando parece funcionar al pulsar los botones (se ilumina el LED) pero los menús del Fire TV Stick no responden. En ese caso, es posible que el remote haya perdido la vinculación con la llave HDMI, así que toca volver a realizar el proceso de emparejado de los dos dispositivos. Para conseguirlo debe seguir los siguintes pasos:
Enciende la televisión con la entrada HDMI del Fire TV Stick seleccionada.
Colócate a menos de tres metros del dongle para poder conectar de nuevo el mando.
Pulsa el botón de Inicio del mando durante 10 segundos ininterrumpidamente.
A partir de ese momento la luz LED del remote tendría que parpadear, lo que provocará un mensaje en la pantalla del televisor de que todo el proceso ha funcionado sin problemas.
El mando a distancia vuelve a estar emparejado con su Fire TV Stick original.
Un truco: si la versión del mando no tiene testigo led podemos ver si está emitiendo ráfagas infrarojos al fire-stick, con una cámara digital enfocando a la parte delantera deberíamos ver un puntito de luz blanca al pulsar cualquier tecla.
Averias del mando mas comunes
Llegados a este punto, tu mando debería estar conectado a tu Fire TV Stick y funcionando de nuevo de forma correcta. ¿No es el caso? Entonces, toca comprobar estos puntos:
Pilas: el mando del Fire TV Stick funciona con 2 pilas AAA. Y puede darse el caso de que se estén agotando y no tengan energía para mantener las funciones mínimas del control remoto. También puede ocurrir que alguna de las pilas ( o las dos ) se haya sulfatado y esté impidiendo que la corriente pase al mando, independientemente de que hayamos conectado una pila nueva en buenas condiciones. Simplemente, retire la tapa del compartimento de pilas y compruebe que no hay óxido ni corrosión. Aproveche también para probar con otras pilas nuevas, por si las moscas.
Mando estropeado: los mandos a distancia suelen caerse al suelo con frecuencia, y esto puede acabar pasando factura. Si después de hacer todo este proceso, no ha conseguido volver a conectar tu mando al Fire TV Stick, puede que se haya estropeado. En este casos en el siguiente epígrafe veremos cómo podemos repararlo o en el peor de los casos conseguir un sustituto al mando a distancia del Fire TV Stick.
Las pilas del mando
Tan improbable como parece, pero a veces las baterías del mando se desalinean y por supuesto se agotan ( lo cual deberíamos probar con un comprobador de pilas o un multímetro). Saque las pilas y manténgalas fuera durante 10-20 segundos. A continuación, vuelva a colocar las pilas correctamente y conéctelas en el orden correcto en el mando como está indicado en la carcasa (compruebe que de verdad estan en su posición correcta ambas pilas).
Una de las razones más comunes por las que el mando a distancia Fire TV Stick no se acopla antes o después del restablecimiento de fábrica es que la batería está agotada o agotada, así que recomendamos que introduzca un par de pilas nuevas en el control remoto en caso de duda.
Muchas veces, la corrosión o la suciedad en el interior del compartimento de la batería impide que se active el mando a distancia correctamente. En el caso de qeu se hayan quedado pilas agotadas y se hayan sulfatado, debe retirar estas a la mayor brevedad posible y limpiar los dos conectores metálicos con un pañuelo de papel o un paño limpio. A continuación, inserte las pilas y reinicie el Fire TV Stick desenchufándolo. Entonces intente emparejarlo con el mando nuevamente.
Reparación en caso de sulfatación de las pilas
A todos nos ha pasado que hemos encontrado alguna vez un aparato que teníamos olvidado por casa y al comprobar si tenía pilas, estas se encontraban en el interior oxidadas o sulfatadas . Aunque pueda ser desagradable a primera vista, hay ocasiones en que los dispositivos sucios por las pilas todavía funcionan. En nuestro caso, si tras la limpieza en profundidad del porta pilas accesible desde el exterior, sigue sin responder, deberemos intentar abrir el mando para limpiar el interior.
Se abre el mando por el lateral con un utensilio de plástico.
Vemos dos tornillos philips que fijan la placa madre a la carcasa.
Desatornillamos los tornillos para poder limpiar la parte más expuesta.
Guardamos o apartamos las carcasas con cuidado.
En nuestro caso, vemos como la sulfatación ha afectado a gran parte de la placa por lo que debemos limpiar con profundidad esta parte con un bastoncillo o un cepillo y alcohol ( hay personas que también da buenos resultados el zumo de un limón disuelto en agua).
Tras frotar, comprobará cómo se irá desprendiendo lo sucio y las partes metálicas y muelles del aparato volverán a estar como nuevos. En el caso de que tras limpiarlo y secarlo siga igual, lamentamos decirle que tendrá que valorar el estado interno del aparato o ir a un servicio técnico, aunque lo habitual es que vuelvan a funcionar tras esta limpieza.
También en el peor de los casos si tras la limpieza no ha funcionado el mando podemos intentar con una pistola de calor incidir en las zonas donde estaba la suciedad para intentar reactivar las soldaduras que podrían haberse dañado con la sulfatación de las pilas.
¿Y si pierdo el mando o está roto?
Si pierde el mando de su Fire TV Stick, o si simplemente, deja de funcionar ( y no ha funcionado nada de lo que hemos visto hasta aquí), puede controlar el dispositivo directamente desde la aplicación Fire TV, disponible tanto para Android como para el iPhone. Por supuesto, también va poder utilizar comandos de Alexa para controlar el televisor, aunque, si ya lo ha hecho con anterioridad, sabrá que esto no es lo óptimo.
Y bien, aunque existen las alternativas de software, seguro que no tiene ganas de comprar otro Fire TV únicamente por recuperar el mando. Puede que una mala caída haya dejado tu mando totalmente fuera de combate, que simplemente haya dejado de funcionar de un día para otro o que sencillamente, el dispositivo haya desaparecido de casa —o que se lo haya tragado el sofá, cosa que descubrirás dentro de unos meses.
Para estos casos, existen mandos genéricos que pueden hacerte el apaño. No obstante, en Amazon también va a poder encontrar el mando original del Fire TV Stick en caso de que lo necesites. Antes de hacerse con un sustituto, confirme que el modelo que va a comprar sea compatible con su dispositivo, luego, simplemente tendrá que emparejar el nuevo mando con tu Fire TV tal y como te hemos explicado en las líneas anteriores.
Recambio original de mando para Fire TV
Este mando solo le merecerá la pena en el caso de que tenga un Fire TV 4K, debido a que su precio es bastante alto pues por prácticamente su precio, puede comprarse otro Fire TV Lite o estándar. No obstante, es el modelo que le va a garantizar el máximo de compatibilidad con tu dispositivo de Amazon. A pesar del precio, si no quiere complicarte la vida, esta es la mejor opción que va a encontrar.
Mandos genéricos
Existen también mandos genéricos compatibles con los Fire TV. En estos casos, puede ocurrir que se asocien con el dongle de una forma distinta al modelo original. Por lo general, es interesante un mano con micrófono para no perder así la posibilidad de dictar texto y hacer comandos de Alexa. Un modelo muy interesante es el L5B83H, que tiene un buen precio y va a permitir recuperar el control de su Fire TV. Por lo general, este modelo merece más la pena si tiene un Fire TV Stick de los básicos. No obstante, en algunos casos le merecerá más la pena comprar un dongle completo simplemente por precio.
Eso sí, con los mandos genéricos hay que tener algo más de cuidado. Le recomendamos que mire bien las especificaciones para garantizar que el mando genérico es compatible con su Fire TV. Si no recuerda bien qué modelo tienes conectado a tu televisor, puedes mirarlo desde ajustes utilizando la aplicación de Fire TV para el móvil. No obstante, también puede consultar en el historial de compras de Amazon para ver exactamente qué unidad tiene.
Una de las mejores cosas de ESP32 es que su firmware se puede actualizar de forma inalámbrica. Este tipo de programación se llama «Over-The-Air» (OTA) permitiendo actualizar/cargar un nuevo programa al ESP32 a través de Wi-Fi sin tener que conectar el ESP32 a un ordenador a través de USB.
La funcionalidad OTA es útil cuando no hay acceso físico al módulo ESP pero además, reduce el tiempo necesario para actualizar cada módulo ESP durante el mantenimiento.
Una ventaja clave de OTA es que una única ubicación central puede enviar una actualización a varios ESP en la misma red.
La única desventaja es que debe incluir un código OTA con cada boceto que cargue para poder usar OTA en la próxima actualización.
Hay dos formas de implementar la funcionalidad OTA en el ESP32:
OTA básico : las actualizaciones se envían mediante el IDE de Arduino.
Web Updater OTA : las actualizaciones se entregan a través de un navegador web.
Cada uno tiene sus propios beneficios, por lo que puede usar el que funcione mejor para su proyecto.
OTA Básico
En este primer apartado veremos el proceso de implementación de OTA básico. En resumen son 3 pasos simples para usar OTA básico con el ESP32
Instalación de la serie Python 2.7.x: el primer paso es instalar la serie Python 2.7.x en su computadora.
Carga de firmware OTA básico en serie: cargue el boceto que contiene el firmware OTA en serie. Este es un paso necesario para realizar las actualizaciones posteriores de forma inalámbrica.
Carga de nuevos bocetos por aire: ahora puede cargar nuevos bocetos al ESP32 desde Arduino IDE por aire.
1: Instalación de Python 2.7.x
Para usar la funcionalidad OTA, primero debe instalar Python 2.7.x, si aún no está instalado en su máquina. Descargue Python 2.7.x para Windows (instalador MSI) desde el sitio web oficial de Python .
Inicie el instalador y continúe con el asistente de instalación
Asegúrese de que la opción «Agregar python.exe a la ruta» esté habilitada en la sección Personalizar Python 2.7.X.
2: Carga del firmware OTA básico en serie
Debido a que la imagen de fábrica del ESP32 carece de la capacidad de actualización OTA, primero debe cargar el firmware OTA en el ESP32 a través de la interfaz serial.
Es necesario actualizar primero el firmware para poder realizar actualizaciones inalámbricas posteriores.
El complemento ESP32 para Arduino IDE incluye una biblioteca OTA, así como un ejemplo de BasicOTA. Simplemente navegue a Archivo > Ejemplos > ArduinoOTA > BasicOTA .
Antes de comenzar a cargar el boceto, debe modificar las siguientes dos variables con sus credenciales de red para que el ESP32 pueda conectarse a una red existente.
Cuando haya terminado, siga adelante y cargue el boceto.
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
const char* ssid = "..........";
const char* password = "..........";
void setup() {
Serial.begin(115200);
Serial.println("Booting");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
// Port defaults to 3232
// ArduinoOTA.setPort(3232);
// Hostname defaults to esp3232-[MAC]
// ArduinoOTA.setHostname("myesp32");
// No authentication by default
// ArduinoOTA.setPassword("admin");
// Password can be set with it's md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
ArduinoOTA.handle();
}
Ahora, abra el Serial Monitor a 115200 baudios y presione el botón EN en el ESP32. Si todo está bien, debería ver la dirección IP dinámica asignada por su enrutador. Tome nota de ello.
Paso 3: Carga del nuevo boceto por aire
Ahora, subamos un nuevo boceto por aire. Recuerde que debes incluir el código OTA en cada sketch que subas. De lo contrario, perderá la capacidad OTA y no podrá realizar la próxima carga inalámbrica. Por lo tanto, se recomienda que modifique el código anterior para incluir su nuevo código.
Como ejemplo, incluiremos un boceto Blink simple en el código OTA básico. Recuerda modificar las variables SSID y contraseña con sus credenciales de red.
Los cambios en el programa Basic OTA están resaltados con comentarios //******.
#include <WiFi.h>
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
const char* ssid = "..........";
const char* password = "..........";
//******codigo programa*******
//variabls for blinking an LED with Millis
const int led = 2; // ESP32 Pin to which onboard LED is connected
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 1000; // interval at which to blink (milliseconds)
int ledState = LOW; // ledState used to set the LED
//******fin codigo programa*******
void setup() {
//******codigo programa*******
pinMode(led, OUTPUT);
//******fin codigo programa*******
Serial.begin(115200);
Serial.println("Booting");
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.waitForConnectResult() != WL_CONNECTED) {
Serial.println("Connection Failed! Rebooting...");
delay(5000);
ESP.restart();
}
// Port defaults to 3232
// ArduinoOTA.setPort(3232);
// Hostname defaults to esp3232-[MAC]
// ArduinoOTA.setHostname("myesp32");
// No authentication by default
// ArduinoOTA.setPassword("admin");
// Password can be set with it's md5 value as well
// MD5(admin) = 21232f297a57a5a743894a0e4a801fc3
// ArduinoOTA.setPasswordHash("21232f297a57a5a743894a0e4a801fc3");
ArduinoOTA
.onStart([]() {
String type;
if (ArduinoOTA.getCommand() == U_FLASH)
type = "sketch";
else // U_SPIFFS
type = "filesystem";
// NOTE: if updating SPIFFS this would be the place to unmount SPIFFS using SPIFFS.end()
Serial.println("Start updating " + type);
})
.onEnd([]() {
Serial.println("\nEnd");
})
.onProgress([](unsigned int progress, unsigned int total) {
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
})
.onError([](ota_error_t error) {
Serial.printf("Error[%u]: ", error);
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
else if (error == OTA_END_ERROR) Serial.println("End Failed");
});
ArduinoOTA.begin();
Serial.println("Ready");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
ArduinoOTA.handle();
//******codigo programa*******
//loop to blink without delay
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
ledState = not(ledState);
// set the LED with the ledState of the variable:
digitalWrite(led, ledState);
//******fin codigo programa*******
}
}
Tenga en cuenta que no hemos utilizado la delay()función para hacer que el LED parpadee. Esto se debe a que la delay()función pausa el programa. Si se genera la siguiente solicitud OTA mientras el ESP32 está en pausa esperando a delay()que se complete, su programa perderá esa solicitud.
Después de copiar el boceto anterior en su IDE de Arduino, navegue hasta la opción Herramientas > Puerto . Busque algo como: esp32-xxxxxx en your_esp_ip_address . Si no puede localizarlo, es posible que deba reiniciar su IDE.
Elija el puerto y presione el botón Cargar. El nuevo boceto se cargará en cuestión de segundos. El LED integrado debería comenzar a parpadear.
Actualizador OTA via web
La programación OTA es útil cuando necesita actualizar el código de las placas ESP32 a las que no se puede acceder fácilmente. El ejemplo que mostraremos aquí funciona cuando el ESP32 y su navegador están en su red local.
La única desventaja de OTA Web Updater es que debe agregar el código para OTA en cada boceto que cargue, para que pueda usar OTA en el futuro.
¿Cómo funciona el Actualizador web OTA?
El primer boceto debe cargarse a través del puerto serie. Este boceto debe contener el código para crear el actualizador web OTA, de modo que pueda cargar el código más tarde con su navegador.
El boceto de OTA Web Updater crea un servidor web al que puede acceder para cargar un nuevo boceto a través del navegador web.
Luego, debe implementar rutinas OTA en cada boceto que cargue, de modo que pueda realizar las próximas actualizaciones/cargas por aire.
Si carga un código sin una rutina OTA, ya no podrá acceder al servidor web y cargar un nuevo boceto por aire.
Antes de continuar , debe tener instalado el complemento ESP32 en su IDE de Arduino. Veamos los pasos a seguir
1-Carga de OTAWebUpdater
Cuando instala el complemento ESP32 para Arduino IDE, instalará automáticamente la biblioteca ArduinoOTA. Vaya a Archivo > Ejemplos > ArduinoOTA > OTAWebUpdater .
Debería cargarse el siguiente código.
/*
* OTAWebUpdater.ino Example from ArduinoOTA Library
* Rui Santos
* Complete Project Details https://randomnerdtutorials.com
*/
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>
const char* host = "esp32";
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
WebServer server(80);
/*
* Login page
*/
const char* loginIndex =
"<form name='loginForm'>"
"<table width='20%' bgcolor='A09F9F' align='center'>"
"<tr>"
"<td colspan=2>"
"<center><font size=4><b>ESP32 Login Page</b></font></center>"
"<br>"
"</td>"
"<br>"
"<br>"
"</tr>"
"<td>Username:</td>"
"<td><input type='text' size=25 name='userid'><br></td>"
"</tr>"
"<br>"
"<br>"
"<tr>"
"<td>Password:</td>"
"<td><input type='Password' size=25 name='pwd'><br></td>"
"<br>"
"<br>"
"</tr>"
"<tr>"
"<td><input type='submit' onclick='check(this.form)' value='Login'></td>"
"</tr>"
"</table>"
"</form>"
"<script>"
"function check(form)"
"{"
"if(form.userid.value=='admin' && form.pwd.value=='admin')"
"{"
"window.open('/serverIndex')"
"}"
"else"
"{"
" alert('Error Password or Username')/*displays error message*/"
"}"
"}"
"</script>";
/*
* Server Index Page
*/
const char* serverIndex =
"https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
"<input type='file' name='update'>"
"<input type='submit' value='Update'>"
"</form>"
"<div id='prg'>progress: 0%</div>"
"<script>"
"$('form').submit(function(e){"
"e.preventDefault();"
"var form = $('#upload_form')[0];"
"var data = new FormData(form);"
" $.ajax({"
"url: '/update',"
"type: 'POST',"
"data: data,"
"contentType: false,"
"processData:false,"
"xhr: function() {"
"var xhr = new window.XMLHttpRequest();"
"xhr.upload.addEventListener('progress', function(evt) {"
"if (evt.lengthComputable) {"
"var per = evt.loaded / evt.total;"
"$('#prg').html('progress: ' + Math.round(per*100) + '%');"
"}"
"}, false);"
"return xhr;"
"},"
"success:function(d, s) {"
"console.log('success!')"
"},"
"error: function (a, b, c) {"
"}"
"});"
"});"
"</script>";
/*
* setup function
*/
void setup(void) {
Serial.begin(115200);
// Connect to WiFi network
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
/*use mdns for host name resolution*/
if (!MDNS.begin(host)) { //http://esp32.local
Serial.println("Error setting up MDNS responder!");
while (1) {
delay(1000);
}
}
Serial.println("mDNS responder started");
/*return index page which is stored in serverIndex */
server.on("/", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", loginIndex);
});
server.on("/serverIndex", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", serverIndex);
});
/*handling uploading firmware file */
server.on("/update", HTTP_POST, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []() {
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
Serial.printf("Update: %s\n", upload.filename.c_str());
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
/* flashing firmware to ESP*/
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
Update.printError(Serial);
}
}
});
server.begin();
}
void loop(void) {
server.handleClient();
delay(1);
}
Debe cambiar las siguientes líneas en el código para incluir sus propias credenciales de red:
El ejemplo de OTAWebUpdater para ESP32 crea un servidor web asíncrono donde puede cargar código nuevo en su placa sin necesidad de una conexión en serie.Suba el código anterior a tu placa ESP32. No olvide ingresar sus credenciales de red y seleccionar la placa y el puerto serial correctos.
Después de cargar el código, abra el monitor serie a una velocidad de transmisión de 115200, presione el botón de activación de ESP32 y obtendrá la dirección IP de ESP32:
Ahora, puede cargar el código a su ESP32 por aire usando un navegador en su red local.
Para probar el Actualizador web OTA, puede desconectar el ESP32 de su computadora y encenderlo con un banco de energía, por ejemplo (esto es opcional, lo sugerimos para imitar una situación en la que el ESP32 no está conectado a su computadora).
2-Actualización del nuevo código usando el actualizador web OTA
Abra un navegador en su red e ingrese la dirección IP ESP32. Deberías obtener lo siguiente:
Introduzca el nombre de usuario y la contraseña:
Nombre de usuario : admin
contraseña : admin
Puede cambiar el nombre de usuario y la contraseña en el código.
Nota: Después de ingresar el nombre de usuario y la contraseña, será redirigido a la URL /serverIndex . No necesita ingresar el nombre de usuario y la contraseña para acceder a la URL /serverIndex . Por lo tanto, si alguien conoce la URL para cargar el nuevo código, el nombre de usuario y la contraseña no protegen la página web para que otros no puedan acceder a ella.
Debería abrirse una nueva pestaña en la URL /serverIndex . Esta página le permite cargar un nuevo código a su ESP32. Debería cargar archivos .bin (veremos cómo hacerlo en un momento).
3-Preparación del nuevo sketch
Al cargar un nuevo boceto por aire, debe tener en cuenta que debe agregar código para OTA en su nuevo boceto, de modo que siempre pueda sobrescribir cualquier boceto con uno nuevo en el futuro. Por lo tanto, le recomendamos que modifique el boceto de OTAWebUpdater para incluir su propio código.
Con fines de aprendizaje, subamos un nuevo código que parpadee un LED (sin demora). Copie el siguiente código en su IDE de Arduino.
/*
* Rui Santos
* Complete Project Details https://randomnerdtutorials.com
*/
#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>
#include <Update.h>
const char* host = "esp32";
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
//variabls to blink without delay:
const int led = 2;
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 1000; // interval at which to blink (milliseconds)
int ledState = LOW; // ledState used to set the LED
WebServer server(80);
/*
* Login page
*/
const char* loginIndex =
"<form name='loginForm'>"
"<table width='20%' bgcolor='A09F9F' align='center'>"
"<tr>"
"<td colspan=2>"
"<center><font size=4><b>ESP32 Login Page</b></font></center>"
"<br>"
"</td>"
"<br>"
"<br>"
"</tr>"
"<td>Username:</td>"
"<td><input type='text' size=25 name='userid'><br></td>"
"</tr>"
"<br>"
"<br>"
"<tr>"
"<td>Password:</td>"
"<td><input type='Password' size=25 name='pwd'><br></td>"
"<br>"
"<br>"
"</tr>"
"<tr>"
"<td><input type='submit' onclick='check(this.form)' value='Login'></td>"
"</tr>"
"</table>"
"</form>"
"<script>"
"function check(form)"
"{"
"if(form.userid.value=='admin' && form.pwd.value=='admin')"
"{"
"window.open('/serverIndex')"
"}"
"else"
"{"
" alert('Error Password or Username')/*displays error message*/"
"}"
"}"
"</script>";
/*
* Server Index Page
*/
const char* serverIndex =
"https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
"<input type='file' name='update'>"
"<input type='submit' value='Update'>"
"</form>"
"<div id='prg'>progress: 0%</div>"
"<script>"
"$('form').submit(function(e){"
"e.preventDefault();"
"var form = $('#upload_form')[0];"
"var data = new FormData(form);"
" $.ajax({"
"url: '/update',"
"type: 'POST',"
"data: data,"
"contentType: false,"
"processData:false,"
"xhr: function() {"
"var xhr = new window.XMLHttpRequest();"
"xhr.upload.addEventListener('progress', function(evt) {"
"if (evt.lengthComputable) {"
"var per = evt.loaded / evt.total;"
"$('#prg').html('progress: ' + Math.round(per*100) + '%');"
"}"
"}, false);"
"return xhr;"
"},"
"success:function(d, s) {"
"console.log('success!')"
"},"
"error: function (a, b, c) {"
"}"
"});"
"});"
"</script>";
/*
* setup function
*/
void setup(void) {
pinMode(led, OUTPUT);
Serial.begin(115200);
// Connect to WiFi network
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
/*use mdns for host name resolution*/
if (!MDNS.begin(host)) { //http://esp32.local
Serial.println("Error setting up MDNS responder!");
while (1) {
delay(1000);
}
}
Serial.println("mDNS responder started");
/*return index page which is stored in serverIndex */
server.on("/", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", loginIndex);
});
server.on("/serverIndex", HTTP_GET, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/html", serverIndex);
});
/*handling uploading firmware file */
server.on("/update", HTTP_POST, []() {
server.sendHeader("Connection", "close");
server.send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
ESP.restart();
}, []() {
HTTPUpload& upload = server.upload();
if (upload.status == UPLOAD_FILE_START) {
Serial.printf("Update: %s\n", upload.filename.c_str());
if (!Update.begin(UPDATE_SIZE_UNKNOWN)) { //start with max available size
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_WRITE) {
/* flashing firmware to ESP*/
if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
Update.printError(Serial);
}
} else if (upload.status == UPLOAD_FILE_END) {
if (Update.end(true)) { //true to set the size to the current progress
Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
} else {
Update.printError(Serial);
}
}
});
server.begin();
}
void loop(void) {
server.handleClient();
delay(1);
//loop to blink without delay
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
ledState = not(ledState);
// set the LED with the ledState of the variable:
digitalWrite(led, ledState);
}
}
Como puede ver, hemos agregado el código «parpadeo sin demora» al código OTAWebUpdater, para que podamos realizar actualizaciones más adelante.
Después de copiar el código en su IDE de Arduino, debe generar un archivo .bin .
4-Generación del archivo .bin en Arduino IDE
Guarde su boceto como LED_Web_Updater .
Para generar un archivo .bin a partir de su boceto, vaya a Boceto > Exportar binario compilado
Se debe crear un nuevo archivo en el boceto de la carpeta. Vaya a Bosquejo > Mostrar carpeta de bosquejo . Debe tener dos archivos en su carpeta Sketch: el archivo .ino y el archivo .bin . Debe cargar el archivo .bin mediante el actualizador web de OTA.
5-Carga del nuevo sketch por aire al ESP32
En su navegador, en la página ESP32 OTA Web Updater, haga clic en el botón Elegir archivo . Seleccione el archivo .bin generado anteriormente y luego haga clic en Actualizar .
Después de unos segundos, el código debería cargarse correctamente.
El LED incorporado ESP32 debe estar parpadeando.¡Felicidades! Ha subido un nuevo código a tu ESP32 por aire.
Las actualizaciones inalámbricas hemos visto que son útiles para cargar un nuevo código en su placa ESP32 cuando no es fácilmente accesible. En este segundo caso hemos visto el código OTA Web Updater como crea un servidor web al que puede acceder para cargar un nuevo código en su placa ESP32 utilizando un navegador web en su red local.
El objetivo de esta post es en primer lugar comprender como se puede ejecutar la multitarea en el ESP32 para después ver como se implementa un algoritmo de cálculo de potencia simple en el ESP32 y probar la aceleración ejecutándolo en los dos núcleos del microcontrolador.
El ESP32 viene con 2 microprocesadores Xtensa LX6 de 32 bits: core 0 y core 1. Entonces, es dual core. Cuando ejecutamos código en Arduino IDE, de forma predeterminada, se ejecuta en el núcleo 1. En esta publicación, le mostraremos cómo ejecutar código en el segundo núcleo ESP32 mediante la creación de tareas. Puede ejecutar piezas de código simultáneamente en ambos núcleos y hacer que su ESP32 sea multitarea. Como nota imporante no necesariamente necesita ejecutar doble núcleo para lograr la multitarea.
El ESP32 por tanto tiene dos núcleos Tensilica LX6 [1] que podemos usar para ejecutar código. Al momento de escribir, la forma más fácil de controlar la ejecución de código en los diferentes núcleos del ESP32 es usando FreeRTOS y asignar una tarea a cada CPU
Aunque de forma genérica son muchos los beneficios de tener más de un núcleo disponible para ejecutar código, uno de los más importantes es aumentar el rendimiento de nuestros programas. Entonces, aunque veremos en este post cómo ejecutar código en los dos núcleos del ESP32, también comprobaremos el aumento de rendimiento que podemos obtener de eso mediante una aplicación simple que sea capaz de calcular una potencia de los números de una matriz. Lo ejecutaremos en un solo núcleo y luego dividiremos el procesamiento por los dos núcleos y verificaremos si hay una ganancia en el tiempo de ejecución. Finalmente, solo para comparar, también dividiremos la ejecución entre cuatro tareas (dos asignadas a cada núcleo) solo para verificar si hay alguna aceleración para generar más tareas que núcleos.
Introducción
El ESP32 viene con 2 microprocesadores Xtensa LX6 de 32 bits, por lo que es de doble núcleo:
Núcleo 0
Núcleo 1
Cuando subimos el código al ESP32 usando el IDE de Arduino, simplemente se ejecuta; no tenemos que preocuparnos de qué núcleo ejecuta el código.
Hay una función que puede usar para identificar en qué núcleo se está ejecutando el código:
xPortGetCoreID()
Si usa esa función en un boceto de Arduino, verá que tanto setup() para la configuración() como el loopo()se ejecutan en el núcleo 1. Pruébelo usted mismo cargando el siguiente boceto en su ESP32.
Abra el Serial Monitor a una velocidad de transmisión de 115200 y verifique el núcleo en el que se ejecuta el boceto de Arduino.
Crear tareas
Arduino IDE es compatible con FreeRTOS para ESP32, que es un sistema operativo en tiempo real. Esto nos permite manejar varias tareas en paralelo que se ejecutan de forma independiente. Las tareas son fragmentos de código que ejecutan algo. Por ejemplo, puede hacer parpadear un LED, realizar una solicitud de red, medir lecturas de sensores, publicar lecturas de sensores, etc.
Para asignar partes específicas de código a un núcleo específico, debe crear tareas. Al crear una tarea, puede elegir en qué núcleo se ejecutará, así como su prioridad. Los valores de prioridad comienzan en 0, en el que 0 es la prioridad más baja. El procesador ejecutará primero las tareas con mayor prioridad.
Para crear tareas necesita seguir los siguientes pasos:
1. Crear un identificador de tarea. Un ejemplo para Task1:
TaskHandle_t Task1;
2. En la configuración()crear una tarea asignada a un núcleo específico usando elxTaskCreatePinnedToCorefunción. Esa función toma varios argumentos, incluida la prioridad y el núcleo donde se debe ejecutar la tarea (el último parámetro).
xTaskCreatePinnedToCore(
Task1code, /* Function to implement the task */
"Task1", /* Name of the task */
10000, /* Stack size in words */
NULL, /* Task input parameter */
0, /* Priority of the task */
&Task1, /* Task handle. */
0); /* Core where the task should run */
3. Después de crear la tarea, debe crear una función que contenga el código para la tarea creada. En este ejemplo, debe crear la tarea e1código()función. Así es como se ve la función de tarea:
los for(;;)crean un bucle infinito. Por lo tanto, esta función se ejecuta de manera similar a la función loop(). Puede usarlo como un segundo ciclo en su código, por ejemplo.
Si durante la ejecución de su código desea eliminar la tarea creada, puede utilizar la función vTareaEliminar(), que acepta el identificador de tareas (Tarea 1) como argumento:
vTaskDelete(Task1);
Veamos cómo funcionan estos conceptos con un ejemplo sencillo.
Crear tareas en diferentes núcleos: ejemplo
Para seguir este ejemplo usaremos las siguientes partes:
Para crear diferentes tareas que se ejecuten en diferentes núcleos, crearemos dos tareas que parpadeen los LED con diferentes tiempos de retraso . Conectaremos mediante dos resistencias en serie de 330 ohmios el cátodo de un led rojo al puerto 4 (GPIO4) y el otro cátodo del led verde al GPIO2 uniendo ambas masas y conectando estas al ping GND del ESP32 .
El plano resultante seria similar al siguiente diagrama:
Crearemos dos tareas ejecutándose en diferentes núcleos:
Task1 se ejecuta en el núcleo 0;
Task2 se ejecuta en el núcleo 1;
Cargue el siguiente boceto en su ESP32 para hacer parpadear cada LED en un núcleo diferente:
TaskHandle_t Task1;
TaskHandle_t Task2;
// LED pins
const int led1 = 2;
const int led2 = 4;
void setup() {
Serial.begin(115200);
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
//create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
//create a task that will be executed in the Task2code() function, with priority 1 and executed on core 1
xTaskCreatePinnedToCore(
Task2code, /* Task function. */
"Task2", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task2, /* Task handle to keep track of created task */
1); /* pin task to core 1 */
delay(500);
}
//Task1code: blinks an LED every 1000 ms
void Task1code( void * pvParameters ){
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
for(;;){
digitalWrite(led1, HIGH);
delay(1000);
digitalWrite(led1, LOW);
delay(1000);
}
}
//Task2code: blinks an LED every 700 ms
void Task2code( void * pvParameters ){
Serial.print("Task2 running on core ");
Serial.println(xPortGetCoreID());
for(;;){
digitalWrite(led2, HIGH);
delay(700);
digitalWrite(led2, LOW);
delay(700);
}
}
void loop() {
}
Cómo funciona el código
Nota: en el código creamos dos tareas y asignamos una tarea al núcleo 0 y otra al núcleo 1. Los bocetos de Arduino se ejecutan en el núcleo 1 de forma predeterminada. Por lo tanto, podría escribir el código para Task2 en el loop()(no hubo necesidad de crear otra tarea). En este caso, creamos dos tareas diferentes con fines de aprendizaje.
Sin embargo, según los requisitos de su proyecto, puede ser más práctico organizar su código en tareas como se muestra en este ejemplo.
El código comienza creando un identificador de tarea para Task1 y Task2 llamadoTarea 1yTarea 2.
TaskHandle_t Task1;
TaskHandle_t Task2;
Asigne GPIO 2 y GPIO 4 a los LED:
const int led1 = 2;
const int led2 = 4;
En la configuración(), inicialice el monitor serie a una velocidad en baudios de 115200:
Serial.begin(115200);
Declare los LED como salidas:
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
Luego, cree Task1 usando la función xTaskCreatePinnedToCore() :
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
Task1 se implementará con eltarea1código()función. Entonces, necesitamos crear esa función más adelante en el código. Le damos a la tarea la prioridad 1 y la anclamos al núcleo 0.
Creamos Task2 usando el mismo método:
xTaskCreatePinnedToCore(
Task2code, /* Task function. */
"Task2", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task2, /* Task handle to keep track of created task */
1); /* pin task to core 0 */
Después de crear las tareas, necesitamos crear las funciones que ejecutarán esas tareas.
La función para Task1 se llamatarea1código()(Puedes llamarlo como quieras). Para fines de depuración, primero imprimimos el núcleo en el que se ejecuta la tarea:
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
Entonces, tenemos un ciclo infinito similar alcírculo()en el boceto de Arduino. En ese ciclo, parpadeamos el LED1 cada segundo.
Lo mismo sucede con Task2, pero parpadeamos el LED con un tiempo de retraso diferente.
Finalmente, el bucle loop tiene ()la función está vacía:
void loop() { }
Nota: como se mencionó anteriormente, el bucle loop ()se ejecuta en el núcleo 1. Entonces, en lugar de crear una tarea para ejecutar en el núcleo 1, simplemente puede escribir su código dentro del loop().
Demostración
Suba el código a su ESP32. Asegúrese de tener la placa y el puerto COM correctos seleccionados.
Abra el monitor serie a una velocidad en baudios de 115200. Debería recibir los siguientes mensajes:
Como era de esperar, Task1 se ejecuta en el núcleo 0, mientras que Task2 se ejecuta en el núcleo 1.
En su circuito, un LED debe parpadear cada 1 segundo y el otro debe parpadear cada 700 milisegundos.
Los bocetos de Arduino se ejecutan en el núcleo 1 de forma predeterminada;
Para usar core 0 necesitas crear tareas;
Puede usar la función TaskCreatePinnedToCore() para fijar una tarea específica a un núcleo específico;
Con este método, puede ejecutar dos tareas diferentes de forma independiente y simultánea utilizando los dos núcleos.
Hemos visto un ejemplo simple con LED. La idea es utilizar este método con proyectos más avanzados con aplicaciones del mundo real. Por ejemplo, puede ser útil usar un núcleo para tomar lecturas de sensores y otro para publicar esas lecturas en un sistema de automatización del hogar. Ahora a continuación usando la multitarea vamos a calcular como aumenta la aceleración usando ambos núcleos
Cálculo de aceleración
Básicamente, lo que queremos comprobar es cuánto aumenta la velocidad de ejecución de nuestro programa cuando pasamos de una ejecución de un solo núcleo a una ejecución de doble núcleo. Entonces, una de las formas más fáciles de hacerlo es calcular la relación entre el tiempo de ejecución del programa que se ejecuta en un solo núcleo y el que se ejecuta en los dos núcleos del ESP32 [2].
Mediremos el tiempo de ejecución para cada enfoque utilizando la función Arduino micros , que devuelve la cantidad de microsegundos desde que la placa comenzó a ejecutar el programa [3].
Entonces, para medir un bloque de ejecución de código, haremos algo similar a lo que se indica a continuación.
start = micros();
//Run code
end = micros();
execTime = end - start;
Podríamos haber usado la función FreeRTOS xTaskGetTickCount para una mayor precisión, pero la función micros será suficiente para lo que queremos mostrar y es una función muy conocida de Arduino.
Variables globales
Comenzaremos nuestro código declarando algunas variables globales auxiliares. No vamos a necesitar ningún include.
Como vamos a comparar aceleraciones en diferentes situaciones, vamos a especificar una matriz con múltiples exponentes para probar. Además, vamos a tener una variable con el tamaño de la matriz, para que podamos iterarla. Primero vamos a probar valores pequeños para el exponente y luego comenzaremos a aumentarlos mucho.
int n[10] = {2, 3, 4, 5, 10, 50, 100, 1000, 2000, 10000 };
int nArraySize = 10;
También vamos a tener algunas variables para almacenar el tiempo de ejecución del código en los diferentes casos de uso. Reutilizaremos las variables de inicio y finalización de la ejecución , pero usaremos una variable diferente para cada caso de uso: ejecución de una tarea, ejecución de dos tareas y ejecución de cuatro tareas. De esta forma, almacenaremos los valores para una última comparación.
unsigned long start;
unsigned long end;
unsigned long execTimeOneTask, execTimeTwoTask, execTimeFourTask ;
Luego, declararemos un semáforo de conteo para poder sincronizar la función de configuración (que se ejecuta en una tarea de FreeRTOS) con las tareas que vamos a ejecutar. Consulte esta publicación para obtener una explicación detallada sobre cómo lograr este tipo de sincronización.
Tenga en cuenta que la función xSemaphoreCreateCounting recibe como entrada el recuento máximo y el recuento inicial del semáforo. Como tendremos como máximo 4 tareas para sincronizar, su valor máximo será 4.
Finalmente, declararemos dos arreglos: uno con los valores iniciales (llamado bigArray ) y otro para almacenar los resultados (llamado resultArray ). Haremos sus tallas grandes.
int bigArray[10000], resultArray[10000];
La tarea de FreeRTOS
Definiremos la función que implementará nuestro algoritmo de cálculo de potencia, para ser lanzada como tarea. Si necesita ayuda con los detalles sobre cómo definir una tarea de FreeRTOS, consulte este tutorial anterior.
Lo primero que debemos tener en cuenta es que nuestra función recibirá algunos parámetros de configuración. Dado que en algunos de los casos de uso vamos a dividir la ejecución del algoritmo en varias tareas, necesitamos controlar la parte de la matriz que cubrirá cada tarea.
Para crear solo una tarea genérica que pueda responder a todos nuestros casos de uso, pasaremos como parámetro los índices de la matriz de la que será responsable la tarea. Además, vamos a pasar el exponente, así que ahora sabemos cuántas multiplicaciones necesitamos realizar. Puede consultar con más detalle cómo pasar un argumento a una tarea de FreeRTOS en este tutorial anterior.
Entonces, primero definiremos una estructura con estos 3 parámetros, para poder pasarla a nuestra función. Puedes leer más sobre estructuras aquí . Tenga en cuenta que esta estructura se declara fuera de cualquier función. Entonces, el código se puede colocar cerca de la declaración de variables globales.
struct argsStruct {
int arrayStart;
int arrayEnd;
int n;
};
Como ya tenemos declarada nuestra estructura, dentro de la función declararemos una variable del tipo de esta estructura. Luego, asignaremos el parámetro de entrada de la función a esta variable. Recuerde que los parámetros se pasan a las funciones de FreeRTOS como un puntero a nulo ( void * ) y es nuestra responsabilidad devolverlo al tipo original.
Tenga en cuenta también que le pasamos a la función un puntero a la variable original y no a la variable real, por lo que necesitamos usar el puntero para acceder al valor.
argsStruct myArgs = *((argsStruct*)parameters);
Ahora, implementaremos la función de cálculo de potencia. Tenga en cuenta que podríamos haber usado la función Arduino pow , pero luego explicaré por qué no lo hicimos. Entonces, implementaremos la función con un ciclo donde multiplicaremos un valor por sí mismo n veces.
Comenzamos declarando una variable para contener el producto parcial. Luego, haremos un ciclo for para iterar todos los elementos de la matriz asignada a la tarea. Recuerda que este era nuestro objetivo inicial. Luego, para cada elemento, calcularemos su potencia y al final le asignaremos el valor a la matriz de resultados. Esto asegura que usaremos los mismos datos en todas nuestras pruebas y no cambiaremos la matriz original.
Para un código más limpio, podríamos haber implementado el algoritmo pow en una función dedicada, pero se intenta minimizar las llamadas a funciones auxiliares para un código más compacto.
Verifique el código a continuación. Dejo ahí comentada una línea de código para calcular la potencia usando la función pow , así que puedes probarlo si quieres. Tenga en cuenta que los resultados de aceleración serán considerablemente diferentes. Además, para acceder a un elemento de una variable de estructura, usamos el nombre de la variable punto («.») el nombre del elemento.
int product;
for (int i = myArgs.arrayStart; i < myArgs.arrayEnd; i++) {
product = 1;
for (int j = 0; j < myArgs.n; j++) {
product = product * bigArray[i];
}
resultArray[i]=product;
//resultArray [i] = pow(bigArray[i], myArgs.n);
}
Compruebe el código de función completo a continuación. Tenga en cuenta que al final del código estamos aumentando el semáforo de conteo global en una unidad. Esto se hace para asegurar la sincronización con la función de configuración, ya que contaremos el tiempo de ejecución a partir de ahí. Además, al final, estamos eliminando la tarea.
Vamos a hacer todo el código restante en la función de configuración, por lo que nuestro ciclo principal estará vacío. Comenzaremos abriendo una conexión en serie para generar los resultados de nuestras pruebas.
Serial.begin(115200);
Serial.println();
Ahora, inicializaremos nuestra matriz con algunos valores para aplicar el cálculo. Tenga en cuenta que no nos preocupa el contenido de la matriz ni el resultao real, sino los tiempos de ejecución. Entonces, vamos a inicializar la matriz con valores aleatorios solo para mostrar esas funciones, ya que no vamos a imprimir la matriz que contendrá los resultados.
Primero vamos a llamar a la función randomSeed , por lo que los valores aleatorios generados diferirán en diferentes ejecuciones del programa [4]. Si el pin analógico está desconectado, devolverá un valor correspondiente a ruido aleatorio, lo cual es ideal para pasar como entrada de la función randomSeed .
Después de eso, podemos simplemente llamar a la función aleatoria , pasando como argumentos los valores mínimo y máximo que se pueden devolver [4]. Nuevamente, estamos haciendo esto solo con fines ilustrativos, ya que no vamos a imprimir el contenido de las matrices.
randomSeed(analogRead(0));
for (int i = 0; i < 10000; i++) {
bigArray[i] = random(1, 10);
}
Ahora, vamos a definir las variables que se utilizarán como argumentos para nuestras tareas. Recuerda la estructura declarada anteriormente, que contendrá los índices del arreglo que procesará cada tarea y el exponente.
Entonces, el primer elemento de la estructura es el índice inicial, el segundo es el índice final y el tercero es el exponente. Declararemos estructuras para cada caso de uso (una tarea, dos tareas y cuatro tareas) como se puede ver en el código a continuación. Tenga en cuenta que en el último elemento de la estructura estamos pasando un elemento de la matriz global que declaramos con los exponentes. Entonces, como veremos en el código final, iteraremos toda la matriz, pero por ahora mantengamos las cosas simples.
Ahora, vamos a hacer la prueba usando una sola tarea. Empezamos por obtener el tiempo de ejecución con la función micros. Luego, usaremos la función xTaskCreatePinnedToCore para crear una tarea de FreeRTOS anclada a uno de los núcleos. Elegiremos el núcleo 1.
Vamos a pasar como parámetro la dirección de la variable de estructura oneTask , que contiene los argumentos necesarios para que se ejecute la función. No olvides el yeso al vacío* .
Una cosa muy importante a tener en cuenta es que aún no hemos analizado qué tareas pueden haber sido lanzadas por el núcleo de Arduino y que pueden influir en el tiempo de ejecución. Entonces, para garantizar que nuestra tarea se ejecutará con mayor prioridad, le asignaremos un valor de 20. Recuerde, los números más altos significan una mayor prioridad de ejecución para el programador de FreeRTOS.
Después de iniciar la tarea, solicitaremos una unidad del semáforo, asegurándonos de que la función de configuración se mantendrá hasta que la nueva tarea termine de ejecutarse. Finalmente, imprimiremos el tiempo de ejecución.
Serial.println("");
Serial.println("------One task-------");
start = micros();
xTaskCreatePinnedToCore(
powerTask, /* Function to implement the task */
"powerTask", /* Name of the task */
10000, /* Stack size in words */
(void*)&oneTask, /* Task input parameter */
20, /* Priority of the task */
NULL, /* Task handle. */
1); /* Core where the task should run */
xSemaphoreTake(barrierSemaphore, portMAX_DELAY);
end = micros();
execTimeOneTask = end - start;
Serial.print("Exec time: ");
Serial.println(execTimeOneTask);
Serial.print("Start: ");
Serial.println(start);
Serial.print("end: ");
Serial.println(end);
Esto es más o menos lo que vamos a hacer para el resto de los casos de uso. La única diferencia es que vamos a lanzar más tareas y vamos a intentar sacar más unidades del semáforo (tantas como tareas lanzadas para ese caso de uso).
Consulte el código fuente completo a continuación, que ya incluye los casos de uso para ejecutar el código con dos tareas (una por núcleo ESP32) y cuatro tareas (dos por núcleo ESP32). Además, al final de la función de configuración, incluye la impresión de los resultados de aceleración para cada iteración.
Tenga en cuenta que el parámetro extra de la función Serial.println indica el número de lugares decimales para el número de punto flotante.
int n[10] = {2, 3, 4, 5, 10, 50, 100, 1000, 2000, 10000 };
int nArraySize = 10;
struct argsStruct {
int arrayStart;
int arrayEnd;
int n;
};
unsigned long start;
unsigned long end;
unsigned long execTimeOneTask, execTimeTwoTask, execTimeFourTask ;
SemaphoreHandle_t barrierSemaphore = xSemaphoreCreateCounting( 4, 0 );
int bigArray[10000], resultArray[10000];
void setup() {
Serial.begin(115200);
Serial.println();
randomSeed(analogRead(0));
for (int i = 0; i < 10000; i++) {
bigArray[i] = random(1, 10);
}
for (int i = 0; i < nArraySize; i++) {
Serial.println("#############################");
Serial.print("Starting test for n= ");
Serial.println(n[i]);
argsStruct oneTask = { 0 , 1000 , n[i] };
argsStruct twoTasks1 = { 0 , 1000 / 2 , n[i] };
argsStruct twoTasks2 = { 1000 / 2 , 1000 , n[i] };
argsStruct fourTasks1 = { 0 , 1000 / 4 , n[i] };
argsStruct fourTasks2 = { 1000 / 4 , 1000 / 4 * 2, n[i]};
argsStruct fourTasks3 = { 1000 / 4 * 2, 1000 / 4 * 3, n[i]};
argsStruct fourTasks4 = { 1000 / 4 * 3 , 1000, n[i]};
Serial.println("");
Serial.println("------One task-------");
start = micros();
xTaskCreatePinnedToCore(
powerTask, /* Function to implement the task */
"powerTask", /* Name of the task */
10000, /* Stack size in words */
(void*)&oneTask, /* Task input parameter */
20, /* Priority of the task */
NULL, /* Task handle. */
1); /* Core where the task should run */
xSemaphoreTake(barrierSemaphore, portMAX_DELAY);
end = micros();
execTimeOneTask = end - start;
Serial.print("Exec time: ");
Serial.println(execTimeOneTask);
Serial.print("Start: ");
Serial.println(start);
Serial.print("end: ");
Serial.println(end);
Serial.println("");
Serial.println("------Two tasks-------");
start = micros();
xTaskCreatePinnedToCore(
powerTask, /* Function to implement the task */
"powerTask", /* Name of the task */
10000, /* Stack size in words */
(void*)&twoTasks1, /* Task input parameter */
20, /* Priority of the task */
NULL, /* Task handle. */
0); /* Core where the task should run */
xTaskCreatePinnedToCore(
powerTask, /* Function to implement the task */
"coreTask", /* Name of the task */
10000, /* Stack size in words */
(void*)&twoTasks2, /* Task input parameter */
20, /* Priority of the task */
NULL, /* Task handle. */
1); /* Core where the task should run */
for (int i = 0; i < 2; i++) {
xSemaphoreTake(barrierSemaphore, portMAX_DELAY);
}
end = micros();
execTimeTwoTask = end - start;
Serial.print("Exec time: ");
Serial.println(execTimeTwoTask);
Serial.print("Start: ");
Serial.println(start);
Serial.print("end: ");
Serial.println(end);
Serial.println("");
Serial.println("------Four tasks-------");
start = micros();
xTaskCreatePinnedToCore(
powerTask, /* Function to implement the task */
"powerTask", /* Name of the task */
10000, /* Stack size in words */
(void*)&fourTasks1, /* Task input parameter */
20, /* Priority of the task */
NULL, /* Task handle. */
0); /* Core where the task should run */
xTaskCreatePinnedToCore(
powerTask, /* Function to implement the task */
"powerTask", /* Name of the task */
10000, /* Stack size in words */
(void*)&fourTasks2, /* Task input parameter */
20, /* Priority of the task */
NULL, /* Task handle. */
0); /* Core where the task should run */
xTaskCreatePinnedToCore(
powerTask, /* Function to implement the task */
"powerTask", /* Name of the task */
10000, /* Stack size in words */
(void*)&fourTasks3, /* Task input parameter */
20, /* Priority of the task */
NULL, /* Task handle. */
1); /* Core where the task should run */
xTaskCreatePinnedToCore(
powerTask, /* Function to implement the task */
"powerTask", /* Name of the task */
10000, /* Stack size in words */
(void*)&fourTasks4, /* Task input parameter */
20, /* Priority of the task */
NULL, /* Task handle. */
1); /* Core where the task should run */
for (int i = 0; i < 4; i++) {
xSemaphoreTake(barrierSemaphore, portMAX_DELAY);
}
end = micros();
execTimeFourTask = end - start;
Serial.print("Exec time: ");
Serial.println(execTimeFourTask);
Serial.print("Start: ");
Serial.println(start);
Serial.print("end: ");
Serial.println(end);
Serial.println();
Serial.println("------Results-------");
Serial.print("Speedup two tasks: ");
Serial.println((float) execTimeOneTask / execTimeTwoTask, 4 );
Serial.print("Speedup four tasks: ");
Serial.println((float)execTimeOneTask / execTimeFourTask, 4 );
Serial.print("Speedup four tasks vs two tasks: ");
Serial.println((float)execTimeTwoTask / execTimeFourTask, 4 );
Serial.println("#############################");
Serial.println();
}
}
void loop() {
}
void powerTask( void * parameters ) {
argsStruct myArgs = *((argsStruct*)parameters);
int product;
for (int i = myArgs.arrayStart; i < myArgs.arrayEnd; i++) {
product = 1;
for (int j = 0; j < myArgs.n; j++) {
product = product * bigArray[i];
}
resultArray[i]=product;
//resultArray [i] = pow(bigArray[i], myArgs.n);
}
xSemaphoreGive(barrierSemaphore);
vTaskDelete(NULL);
}
Probando el código
Para probar el código, simplemente cárguelo con el IDE de Arduino y abra el monitor serie. Debería obtener un resultado similar a la figura 1. Naturalmente, los tiempos de ejecución pueden variar.
Figura 1 : Salida del programa de prueba de aceleración.
Los resultados para cada exponente se muestran en la siguiente tabla, en la tabla 1.
Exponente
1 tarea [µs]
2 tareas [µs]
4 tareas [µs]
Acelerar 1 tarea frente a 2 tareas
Acelerar 1 tarea frente a 4 tareas
Acelerar 2 tareas vs 4 tareas
2
229
183
296
1.2514
0.7736
0.6182
3
271
207
325
1.3092
0.8338
0.6369
4
312
224
340
1.3929
0.9176
0.6588
5
354
249
367
1.4217
0.9646
0.6785
10
556
347
451
1.6023
1.2328
0.7694
50
2235
1188
1305
1.8813
1.7126
0.9103
100
4331
2234
2343
1.9387
1.8485
0.9535
1000
42072
21108
21212
1.9932
1.9834
0.9951
2000
83992
42138
42190
1.9933
1.9908
0.9988
10000
419400
210283
210310
1.9945
1.9942
0.9999
Tabla 1 – Resultados de aceleración para los exponentes definidos en el código.
Analizando los resultados
Para comprender los resultados, primero debemos tener en cuenta que no se puede paralelizar completamente todo el programa. Entonces, siempre habrá partes del código que se ejecuten en un solo núcleo, como el lanzamiento de las tareas o los mecanismos de sincronización.
Aunque no teníamos este caso de uso, muchos algoritmos de paralelización también tienen una parte en la que cada resultado parcial se agrega secuencialmente (por ejemplo, si tenemos varias tareas calculando el valor máximo de su parte de la matriz y luego la tarea principal calcula el valor máximo entre todos los resultados parciales).
Entonces, hagamos lo que hagamos, teóricamente no podemos lograr una aceleración igual a la cantidad de núcleos (hay algunas excepciones en, por ejemplo, algoritmos que buscan un valor específico y salen cuando lo encuentran, pero no nos compliquemos).
Entonces, mientras más cómputos ejecutemos en paralelo versus la porción que ejecutamos en secuencia, más aceleración tendremos. Y eso es precisamente lo que vemos en nuestros resultados. Si comenzamos con un exponente de 2 , nuestra aceleración de la ejecución de una tarea a dos tareas es solo de 1.2514 .
Pero a medida que aumentamos el valor del exponente, hacemos más iteraciones del ciclo más interno y, por lo tanto, más cálculos podemos realizar en paralelo. Así, a medida que aumentamos el exponente, vemos un aumento de la aceleración. Por ejemplo, con un exponente de 1000 , nuestra aceleración es 1.9933 . Lo cual es un valor muy alto en comparación con el anterior.
Entonces, esto significa que la parte secuencial se diluye y para grandes exponentes la paralelización compensa. Tenga en cuenta que podemos lograr este tipo de valores altos porque el algoritmo es muy simple y fácil de paralelizar. Además, debido a la forma en que FreeRTOS maneja las prioridades y los cambios de contexto de ejecución de tareas, no hay mucha sobrecarga después de que se ejecutan las tareas. Una computadora normal tiende a tener más cambios de contexto entre subprocesos y, por lo tanto, la sobrecarga secuencial es mayor.
Tenga en cuenta que no usamos la función pow para mostrar esta progresión en los valores de aceleración. La función pow usa flotantes, lo que significa que su implementación es más intensiva en computación. Entonces, obtendríamos aceleraciones mucho mejores en exponentes más bajos porque la parte paralela sería mucho más relevante que la secuencial. Puede comentar nuestro algoritmo implementado y usar la función pow para comparar los resultados.
Además, es importante tener en cuenta que lanzar más tareas que la cantidad de núcleos no aumenta la velocidad. De hecho, tiene el efecto contrario. Como podemos ver en los resultados, la aceleración de ejecutar con 4 tareas siempre es menor que la de ejecutar con 2 tareas. De hecho, para exponentes bajos, en realidad es más lento ejecutar el código con 4 tareas (aunque estén divididas entre los dos núcleos del ESP32) que ejecutar con una tarea en un solo núcleo.
Esto es normal porque cada CPU solo puede ejecutar una tarea en un momento dado y, por lo tanto, lanzar más tareas que CPU significa más tiempo secuencial para manejarlas y más sobrecarga en los puntos de sincronización.
Sin embargo, tenga en cuenta que esto no siempre es blanco y negro. Si las tareas tuvieran algún tipo de punto de rendimiento en el que dejarían de esperar algo, entonces tener más tareas que núcleos podría ser beneficioso para usar los ciclos de CPU libres. Sin embargo, en nuestro caso, las CPU nunca rinden y siempre se están ejecutando, por lo que no hay ningún beneficio en lanzar más de 2 tareas, en cuanto a la aceleración.
La ley de Amdhal
Para complementar los resultados, veremos la ley de Amdahl . Entonces, vamos a aplicar algunas transformaciones a la fórmula de aceleración que estábamos usando. La fórmula inicial era que la aceleración es igual al tiempo de ejecución secuencial (lo llamaremos T ) dividido por el tiempo de ejecución en paralelo (lo llamaremos T Paralelo ).
Pero, como vimos, hay una parte del tiempo de ejecución que siempre es secuencial y otra que puede ser paralelizada. Llamemos p a la fracción del programa que podemos ejecutar en paralelo. Como es una fracción, su valor estará entre 0 y 1.
Entonces, podemos representar el tiempo de ejecución secuencial T como la porción que puede ejecutarse en paralelo ( p*T ) más la porción que no puede (1-p)*T .
Como solo podemos dividir la parte paralela entre los núcleos de nuestra máquina, el tiempo T Parallel es similar a la fórmula anterior, excepto que la parte paralela aparece dividida por la cantidad de núcleos que tenemos disponibles.
Entonces, nuestra fórmula de aceleración se convierte en:
Ahora tenemos la aceleración escrita en función de T , el tiempo de ejecución original sin mejoras. Entonces, podemos dividir cada término por T :
Entonces, ahora tenemos la aceleración escrita en función de la parte que puede ejecutarse en paralelo y la cantidad de núcleos. Para terminar, supongamos que tenemos una cantidad infinita de núcleos disponibles para ejecutar (el caso de uso real sería un número muy grande, pero analizaremos matemáticamente la fórmula).
Como una constante dividida por infinito es igual a 0, terminamos con:
Así que, aunque la aceleración aumenta con la cantidad de recursos disponibles para la paralelización (la cantidad de núcleos, en nuestro caso), lo cierto es que la máxima aceleración teórica posible está limitada por la parte no paralela, que no podemos optimizar.
Esta es una conclusión interesante para que decidamos si vamos o no a la paralelización. Algunas veces, los algoritmos pueden paralelizarse fácilmente y tenemos una tremenda aceleración, otras el esfuerzo necesario no justifica la ganancia.
Además, otra cosa importante a tener en cuenta es que el mejor algoritmo secuencial no siempre es el mejor después de la paralelización. Entonces, a veces, es mejor usar un algoritmo que tiene menos rendimiento en la ejecución secuencial, pero termina siendo mucho mejor que el mejor secuencial en la paralelización.
Resumen
Con este post, confirmamos que las funciones disponibles para la ejecución multinúcleo funcionan bien y podemos aprovecharlas para obtener beneficios de rendimiento.
La última parte más teórica tenía el objetivo de mostrar que la paralelización no es un tema trivial, y uno no puede saltar directamente a un enfoque paralelo sin un análisis previo y esperar una aceleración igual a la cantidad de núcleos disponibles. Este razonamiento se extiende más allá del alcance del ESP32 y se aplica a la computación paralela en general.
Entonces, para aquellos que van a comenzar con la computación paralela utilizando el ESP32 para mejorar el rendimiento, es un buen comienzo para aprender primero algunos de los conceptos más teóricos.
Finalmente, tenga en cuenta que el código está orientado a mostrar los resultados, por lo que se podrían haber hecho muchas optimizaciones, como lanzar las tareas en un ciclo en lugar de repetir el código o condensar el algoritmo en una función.
Además, no buscábamos los resultados de la ejecución para confirmar que la matriz de salida era la misma porque ese no era nuestro enfoque principal. Naturalmente, pasar de secuencial a paralelo requiere una implementación cuidadosa del código y la ejecución de muchas pruebas para garantizar que el resultado sea el mismo.
Este módulo AZ-Delivery , desarrollado por la empresa Espressif tiene el potente Microcontrolador ESP32 instalado siendo por tanto ideal para prototipos rápidos ya que esta placa de desarrollo ESP32 permite la dinámica creación de prototipos con una sencilla programación a través de un script Lua o en la construcción compatible con Arduino-IDE y Breadboard. Integra funciones Wi-Fi y Bluetooth.
Destaca además el consumo ultra bajo de energía ideal para poderlo alimentarlo con baterías. Asimismo cuenta con chips Bluetooth Wi-Fi de modo dual de 2,4 GHz y TSMC, así como tecnología de bajo consumo de 40 nm.
Esta versión tiene 38 pines y ofrece más funciones que un módulo de 30 pines y es más pequeño y más conveniente de usar.
De igual manera que en el modelo predecesor ESP8266, la funcionalidad WLAN está implementada directamente en el SoC, pero con funcionalidad Bluetooth adicional (incl. BLE).
El procesador ESP32 es mucho más potente que el ESP8266 pues combina una CPU con 2 núcleos Tensilica LX6, con una frecuencia de hasta 240 MHz, y 512 Kilobytes de SRAM en un único chip microcontrolador. Además, integra una unidad de radio para WLAN (según 802.11bgn) y Bluetooth (Classic y LE) , esta conectividad que por cierto no posee el ESP8266.
La función WLAN soporta todos los métodos de encriptación habituales, como WPA2. También puede actuar en la WLAN como punto de acceso o Sniffer en modo pasivo.
A través de los 32 pines están disponibles, entre otros, UART, I2C, SPI, DAC, ADC (12 bits) y todos los pines GPIO pueden utilizarse como entrada o salida.
Información Técnica
Voltaje de alimentación
5V
Voltaje de entrada / salida
3.3V
Corriente de Funcionamiento
min. 500mA
SoC
ESP32-WROOM 32
Frecuencia de Reloj
80MHz / 240MHz
RAM
512kB
Memoria Flash externa
4MB
Pines I / O
34
Interfaces
SPI, I2C, I2S, CAN, UART
Protocolos Wi-Fi
802.11 b/g/n (802.11n hasta 150 Mbps)
Frecuencia Wi-Fi
2.4 GHz – 2.5 GHz
Bluetooth
V4.2 – BLE y Bluetooth clásico
Antena inalámbrica
PCB
Dimensiones
56x28x13mm
Hay un complemento para el IDE de Arduino que le permite programar el ESP32 utilizando el IDE de Arduino y su lenguaje de programación. En este post, le mostraremos cómo instalar la placa ESP32 en Arduino IDE, ya sea que esté usando Windows, Mac OS X o Linux..
Antes de comenzar este procedimiento de instalación, asegúrese de tener instalada la última versión del IDE de Arduino en su computadora. Si no lo hace, desinstálelo e instálelo de nuevo. De lo contrario, es posible que no funcione.
Abra el Administrador de tableros. Vaya a Herramientas > Tablero > Administrador de tableros…
Busque ESP32 y presione el botón de instalación para » ESP32 by Espressif Systems «:
Eso es todo. Debe instalarse después de unos segundos.
Prueba de la instalación
Conecte la placa ESP32 a su ordenador mediante un cable USB. Lo más sencillo seria probar a hacer parpadear el led interno , pero realmente si queremos probar la conectividad wifi es mejor probar esto con un codigo mas elaborado. Afortunadamente no tenemos que buscar mucho porque el propio IDE de Arduino incluye los ejemplos .
Con su Arduino IDE abierto, siga estos pasos:
1. Seleccione su placa en el menú Herramientas > Placa (en el ejemplo es un DOIT ESP32 DEVKIT V1 pero si compra el AZDelivery ESP32 ESP-WROOM-32 NodeMCU Modulo WiFi + Bluetooth Dev Kit C Placa de Desarrollo 2.4 GHz Dual Core con Chip CP2102 deberemos poner ESP32Dev Module )
3. Abra el siguiente ejemplo en Archivo > Ejemplos > WiFi (ESP32) > WiFiScan
4. Se abre un nuevo boceto en su IDE de Arduino:
5. Presione el botón Cargar en el IDE de Arduino. Espere unos segundos mientras el código se compila y carga en su placa.
6. Si todo salió como se esperaba, debería ver un mensaje » Terminó de cargar». » mensaje.
7. Abra el monitor serie Arduino IDE a una velocidad de transmisión de 115200:
8. Presione el botón Habilitar integrado de ESP32 y debería ver las redes disponibles cerca de su ESP32:
Solución de problemas más comunes
Si intenta cargar un nuevo boceto a su ESP32 y recibe este mensaje de error » Se produjo un error fatal: no se pudo conectar a ESP32: se agotó el tiempo de espera… Conectando… «. Significa que su ESP32 no está en modo de carga/parpadeo.
Con el nombre de la placa y el puerto COM seleccionados, siga estos pasos:
Mantenga presionado el botón » BOOT » en su tablero ESP32
Presione el botón » Cargar » en el IDE de Arduino para cargar su boceto:
Después de ver el mensaje “ Conectando…. ” en su IDE de Arduino, suelte el dedo del botón “ BOOT ”:
Después de eso, debería ver el mensaje » Terminó de cargar «.
Eso es todo. Su ESP32 debería tener el nuevo boceto ejecutándose. Presione el botón » HABILITAR » para reiniciar el ESP32 y ejecutar el nuevo boceto cargado.
Solución de otros problemas
Los problemas de parpadeo pueden ser complicados de solucionar. Pruebe las sugerencias aquí si tiene problemas:
El gestor de arranque no responde
Si ve errores como «Error al conectar», es probable que su chip no esté ingresando correctamente al gestor de arranque:
Compruebe que está pasando el puerto serie correcto en la línea de comandos.
Verifique que tenga permisos para acceder al puerto serie y que otro software (como el administrador de módem en Linux) no esté tratando de interactuar con él. Un error común es dejar un terminal serial accediendo a este puerto abierto en otra ventana y olvidarse de él.
Compruebe que el chip esté recibiendo 3,3 V de una fuente de alimentación estable (consulte Alimentación insuficiente para obtener más detalles).
Verifique que todos los pines estén conectados como se describe en Selección del modo de inicio . Verifique los voltajes en cada pin con un multímetro, los pines «altos» deben estar cerca de 3.3V y los pines «bajos» deben estar cerca de 0V.
Si ha conectado otros dispositivos a los pines GPIO, intente eliminarlos y vea si esptool comienza a funcionar.
Intente usar una tasa de baudios más lenta ( es un valor muy lento que puede usar para verificar que no es un problema de tasa de baudios).-b 9600
Escribir en Flash falla a mitad de camino
Si el parpadeo falla con errores aleatorios en la mitad, vuelva a intentarlo con una velocidad en baudios más baja.
Los problemas de estabilidad de energía también pueden causar esto (consulte Energía insuficiente ).
La escritura en Flash se realiza correctamente, pero el programa no se ejecuta
Si esptool puede actualizar su módulo write_flashpero su programa no se ejecuta, verifique lo siguiente:
Modo de flash incorrecto
Algunos dispositivos solo admiten el diomodo flash. Escribir en flash con qioel modo tendrá éxito, pero el chip no puede volver a leer el flash para ejecutarlo, por lo que no sucede nada en el arranque. Prueba a pasar la opción a .-fm diowrite_flash
Consulte la página Modos de flash SPI para obtener una descripción completa de los modos de flash y cómo determinar cuáles son compatibles con su dispositivo.
Poder insuficiente
La fuente de alimentación de 3,3 V para el chip ESP tiene que suministrar grandes cantidades de corriente (hasta 70 mA continuos, pico de 200-300 mA, puede ser un poco más alto). También necesita suficiente capacitancia en el circuito de alimentación para satisfacer grandes picos de demanda de energía.
Capacitancia insuficiente
Si está utilizando una placa o módulo de desarrollo prefabricado, el regulador de potencia y los condensadores incorporados suelen ser lo suficientemente buenos, siempre que la fuente de alimentación de entrada sea adecuada.
Nota
Esto no es cierto para algunos módulos de ruptura de pines muy simples, similar a este . Estos desgloses no integran suficiente capacitancia para funcionar de manera confiable sin componentes adicionales. Los módulos OEM de montaje en superficie como ESP-WROOM02 y ESP-WROOM32 requieren un condensador volumétrico externo en la PCB para ser confiables, consulte la hoja de datos del módulo.
Clasificación de la fuente de alimentación
Es posible tener una fuente de alimentación que suministre suficiente corriente para la etapa del cargador de arranque en serie con esptool, pero no lo suficiente para el funcionamiento normal del firmware. Es posible que vea que el voltaje VCC de 3,3 V cae si lo mide con un multímetro, pero puede tener problemas incluso si esto no sucede.
Intente cambiar un suministro de 3,3 V con una clasificación de corriente más alta, agregue condensadores a la línea de alimentación y/o acorte los cables de alimentación de 3,3 V.
La salida de 3,3 V de los chips/adaptadores FTDI FT232R o las placas Arduino no suministran suficiente corriente para alimentar un chip ESP (a veces puede parecer que funciona, pero no funcionará de manera confiable). Otros adaptadores USB TTL/serie también pueden ser marginales.
Falta el cargador de arranque
ESP-IDF y utiliza un pequeño programa cargador de arranque de firmware. El cargador de arranque de hardware en ROM carga este cargador de arranque de firmware desde flash y luego ejecuta el programa. En ESP32, la imagen del cargador de arranque debe ser flasheada por ESP-IDF en el desplazamiento 0x1000.
Consulte la documentación de ESP-IDF para obtener detalles sobre qué binarios deben actualizarse en qué compensaciones.
Pines SPI que deben desconectarse
En comparación con el cargador de arranque ROM con el que habla esptool, un firmware en ejecución usa más pines del chip para acceder al flash SPI.
Si configura el modo «Quad I/O» ( , el valor predeterminado de esptool), los GPIO 7, 8, 9 y 10 se utilizan para leer el flash SPI y, de lo contrario, deben desconectarse.-fm qio
Si configura el modo «Dual I/O» ( ), los GPIO 7 y 8 se utilizan para leer el flash SPI y, de lo contrario, deben desconectarse.-fm dio
Intente desconectar cualquier cosa de esos pines (y/o cambie al modo de E/S dual si anteriormente estaba usando el modo de E/S cuádruple pero desea conectar cosas a los GPIO 9 y 10). Tenga en cuenta que si los GPIO 9 y 10 también están conectados a los pines de entrada en el chip flash SPI, aún pueden no ser adecuados para su uso como E/S de propósito general.
Además de estos pines, los GPIO 6 y 11 también se utilizan para acceder al flash SPI (en todos los modos). Sin embargo, el parpadeo generalmente fallará por completo si estos pines están conectados incorrectamente.
Accidente de etapa temprana
Utilice cualquiera de los programas de terminal serie para ver el registro de arranque. (La tasa de baudios ESP32 es 115200bps). Vea si el programa se bloquea durante el inicio temprano o si muestra un mensaje de error.
Programas de terminal serie
Hay muchos programas de terminal en serie adecuados para la depuración y la interacción en serie. El módulo pySerial (que se requiere para esptool) incluye uno de esos programas de terminal de línea de comandos: miniterm.py. Para obtener más detalles, consulte la documentación relacionada con pySerial o ejecute . Para conocer los valores exactos de configuración del puerto serie, consulte Configuración del puerto serie .miniterm -h
Seguimiento de las interacciones de Esptool
La ejecución volcará todas las interacciones en serie a la salida estándar (esto es una gran cantidad de salida). Esto puede ser útil al depurar problemas con la conexión en serie o al proporcionar información para informes de errores.esptool.py --trace
Errores comunes
Esta es una lista no exhaustiva de los errores de esptool más comunes junto con explicaciones de posibles causas y soluciones. Antes de leer cualquier consejo específico de error, se recomienda encarecidamente que revise primero toda la sección de Solución de problemas.
No se recibieron datos seriales.
Esptool no recibió ningún byte de datos o un paquete de deslizamiento exitoso . Este error generalmente implica algún tipo de problema de hardware. Esto puede deberse a que el hardware no funciona correctamente, las líneas seriales RX/TX no están conectadas o porque hay algún problema al restablecer el modo de descarga .
¡Modo de arranque incorrecto detectado (0xXX)! El chip debe estar en modo de descarga.
La comunicación con el chip funciona (se detecta el registro de arranque de la ROM), pero no se restablece automáticamente al modo de descarga.
Para resolver esto, verifique el circuito de restablecimiento automático (si su placa lo tiene), o intente restablecer el modo de descarga manualmente. Consulte Cargador de arranque manual para obtener instrucciones.
El modo de descarga se detectó correctamente, pero no se obtuvo respuesta de sincronización: la ruta de transmisión en serie parece estar inactiva.
El chip se restablece con éxito en el modo de descarga y envía datos a la computadora host, pero no recibe ninguna respuesta enviada por correo electrónico esptool. Esto implica un problema con la línea TX que se ejecuta desde el host hasta el dispositivo ESP. Verifique dos veces su placa o circuito de placa de prueba para ver si hay algún problema.
Encabezado de paquete no válido (0xXX): posible corrupción o ruido en serie.
Este error suele ser causado por una de las siguientes razones:
Usando un cable USB de mala calidad.
A veces, las placas de prueba pueden acortar los pines flash SPI en la placa y causar este tipo de problema. Intente quitar su placa de desarrollo de la placa de pruebas.
El chip podría estar oscureciéndose durante el flasheo. El regulador interno de 3,3 V de los chips FTDI no es suficiente para alimentar un ESP, consulte Alimentación insuficiente .
Otras cosas para probar:
Intente sincronizar y comunicarse a una velocidad en baudios mucho más baja, p .esptool.py --baud 9600 ...
Intente rastrear las interacciones en curso y vea si se recibe algo.esptool.py --trace ...
Intente omitir la detección automática de chips especificando el tipo de chip, ejecute .esptool.py --chip ESP32 ...
Si ninguna de las soluciones mencionadas anteriormente ayuda y su problema persiste, abra un nuevo problema .
Se produjo un error de excepción en serie
esptool.pyutiliza el módulo pySerial Python para acceder al puerto serie. Si pySerial no puede funcionar normalmente, genera un error y finaliza. Algunas de las causas de error de pySerial más comunes son:
No tienes permiso para acceder al puerto.
El puerto ya está siendo utilizado por otro software.
El puerto no existe.
El dispositivo se desconecta inesperadamente.
Los controladores de puerto serie necesarios no están instalados o están defectuosos.
Un ejemplo de un error pySerial:
A serial exception error occurred: read failed: [Errno 6] Device not configured
Los errores que se originan en pySerial, por lo tanto, no son un problema con esptool.py, pero generalmente son causados por un problema con el hardware o los controladores.
Por cierto, una forma rapida de conseguir el ESP32 es Amazon porque por unos 10€ podemos tenerlo en casa y empezar a experimentar porque además regalan un ebook
Debido al aumento de los costos de energía, las personas están encontrando formas de monitorear su consumo de energía para tomar medidas de ahorro de energía para su hogar. El objetivo de este proyecto es hacer un medidor de energía de bricolaje usando el PZEM-004T v3 para monitorear su consumo de energía, y dado que IoT es la nueva norma para el monitoreo remoto, también podemos conectar el medidor de energía con un tablero de IoT a través de Wi-Fi.
Esta conexión la haremos usando el mini microcontrolador ESP8266 para visualizar las lecturas del medidor en línea donde puede acceder usando su ordenador o teléfono inteligente a traves de la app de Cayenne.
Componentes de hardware y software:
Hardware:
Medidor de energía PZEM-004T-100A v3
ESP8266 con cable ( también nos sirve cualquier controlador de la família ESP8266 como Wemos D1 Mini)
Cables de puente macho – hembra
Tablero de circuitos
Software:
IDE de Arduino
Plataforma en línea:
Cayenne IoT
El medidor de energía PZEM-004T-100A v3
Rango de medida de 100A utilizando un transformador externo
Se utiliza principalmente para medir voltaje CA, corriente, potencia, energía, frecuencia y factor de potencia
Sin función de visualización
La capa física utiliza la interfaz de comunicación UART a RS485
La capa de aplicación utiliza el protocolo Modbus-RTU para comunicarse
Los datos se leen a través de la interfaz TTL que se puede conectar directamente con microcontroladores basados en Arduino o ESP sin necesidad de ningún convertidor adicional
CARASTERICTICAS FUNDAMENTALES:
Tipo de producto:Módulo de comunicación AC
Modelo de producto:PZEM-004T
Función del producto:
Este documento describe la especificación del módulo de comunicación de CA PZEM-004T, el módulo se utiliza principalmente para medir la tensión de CA, la corriente, la potencia activa, la frecuencia, el factor de potencia y la energía activa, el módulo es sin función de visualización, los datos se leen a través de la interfaz TTL.
PZEM-004T-10A: Rango de medición 10A (Shunt incorporado)
PZEM-004T-100A: Rango de medición 100A (transformador externo)
Rango de medición:
Tensión Rango de medición:80~260V Resolución: 0.1V Precisión de medición: 0,5%. Corriente Rango de medición: 0~10A(PZEM-004T-10A); 0~100A(PZEM-004T-100A) Corriente de medición inicial: 0,01A(PZEM-004T-10A); 0,02A(PZEM-004T-100A) Resolución: 0.001A Precisión de medición: 0,5%. Potencia activa Rango de medición: 0~2.3kW(PZEM-004T-10A); 0~23kW(PZEM-004T-100A) Potencia de medición inicial: 0,4W Resolución: 0.1W Formato de visualización: <1000W, muestra un decimal, como: 999.9W
≥1000W, muestra sólo números enteros, como: 1000W
Precisión de medición: 0,5%. Factor de potencia Rango de medición: 0.00~1.00 Resolución: 0.01 Precisión de medición: 1%. Frecuencia Rango de medición: 45Hz~65Hz Resolución: 0,1Hz Precisión de medición: 0,5%. Energía activa Rango de medición: 0~9999.99kWh Resolución: 1Wh Precisión de medición: 0,5%. Formato de visualización: <10kWh, la unidad de visualización es Wh(1kWh=1000Wh), como: 9999Wh
≥10kWh, la unidad de visualización es kWh, como por ejemplo 9999.99kWh
Restablecimiento de la energía: utilice el software para restablecer. Alarma de sobre potencia El umbral de potencia activa se puede establecer, cuando la potencia activa medida supera el umbral, puede alarmar
Interfaz de comunicación Interfaz TTL。
Protocolo de la capa física La capa física utiliza la interfaz de comunicación UART a TTL
La velocidad de transmisión es de 9600, 8 bits de datos, 1 bit de parada, sin paridad
¿Cómo mide?
El medidor utiliza un transformador de corriente para medir la corriente. Está diseñado para producir una corriente alterna en su devanado secundario que es proporcional a la corriente que se mide en su primario. Reduce las corrientes de alto voltaje a un valor mucho más bajo y proporciona una forma conveniente de monitorear de manera segura la corriente eléctrica real que fluye en una línea de transmisión de CA.
INSTALAR ESP8266 EN IDE ARDUINO
Actualmente configurar el entorno de Arduino para funcionar con las placas de desarrollo de ESP8266 es muy sencillo,gracias al soporte que ha recibido de la comunidad, que hace que lo tengamos disponible como un paquete que podemos descargar y añadir al gestor de placas.
Para poder programar las placas de desarrollo basadas en el ESP8266 simplemente tendremos que configurar la URL del paquete para que podamos agregarlas al gestor de placas del IDE de Arduino.
Para ello accedemos al menú de configuración y en “Gestor de URLs adicionales de tarjeta” hacemos click en el pequeño botón de la derecha.
En la ventana que aparece, añadimos esta la siguiente URL.
Si teníamos otras direcciones, dejamos cada una de ellas en una línea.
Ahora entramos en el gestor de tarjetas del IDE de Arduino.
Buscamos el paquete de placas de desarrollo basadas en el ESP8266 y lo instalamos.
Ya tenemos disponibles las placas de desarrollo basadas en el ESP8266 para programarlas con el IDE de Arduino. ¡Así de fácil!
En la próxima entrada profundizaremos en cómo programar ESP8266 con el IDE de Arduino, y veremos las similitudes y diferencias entre programar un Arduino convencional y una placa basada en el ESP8266.
Plataforma en línea:
Cayenne IoT
Cayenne es el primer generador de proyectos de IoT de arrastrar y soltar del mundo que permite a los desarrolladores, diseñadores e ingenieros crear rápidamente prototipos y compartir sus proyectos de dispositivos conectados.
Cayenne se diseñó para ayudar a los usuarios a crear prototipos de Internet de las cosas y luego llevarlos a producción
Cayenne es un producto de myDevices que le permite no solo mostrar datos, sino también configurar disparadores, monitorear dispositivos, controlar dispositivos, etc.
La API de Cayenne MQTT se utiliza para conectar cualquier dispositivo que tenga con Cayenne Cloud
¿Qué es MQTT?MQTT significa
transporte de telemetría de Message Queue Server. Es un protocolo de mensajería extremadamente simple y liviano (suscripción y publicación) diseñado para dispositivos limitados y redes con alta latencia, bajo ancho de banda o redes poco confiables. Con MQTT, los dispositivos IoT con recursos limitados pueden enviar o publicar información sobre un tema específico a un servidor que actúa como
intermediario de mensajes MQTT. Luego, el corredor transmite la información a aquellos clientes que se han suscrito previamente al tema del cliente. Para este proyecto,
Cayenne Dashboard actúa como intermediario de mensajes MQTT.
Configuración de hardware:
Diagrama esquemático:
Conexiones:
PZEM-004T-100A v3
Conexión de carga
Transformador de corriente (CT) Cable VCC conectado a PZEM-004T v3 Live (+) Terminal
Transformador de corriente (CT) Cable GND conectado al terminal neutro (-) PZEM-004T v3
Cable de carga viva (+) conectado al terminal de carga viva (+) PZEM-004T v3
Cable de carga neutra (-) conectado a la terminal de carga neutra (-) PZEM-004T v3
Conexión ESP8266
Cable VCC conectado al pin 3.3v
Cable GND conectado al pin GND
El cable TX (transmisión) está conectado al pin D7
El cable RX (recepción) está conectado al pin D8
ESP8266
Pin VCC conectado al cable PZEM-004T v3 VCC
Pin GND conectado al cable PZEM-004T v3 GND
Pin D7 (RX) conectado al cable PZEM-004T v3 TX
Pin D8 (TX) conectado al cable PZEM-004T v3 RX
Configuración del programa:
Antes de configurar el código Arduino, debemos instalar la placa ESP8266 en el IDE de Arduino.
Capaz de escribir bocetos, usar funciones y bibliotecas de Arduino
Ejecute bocetos sin necesidad de un microcontrolador externo
Biblioteca integrada en el IDE
Más información sobre la biblioteca, junto con la configuración de ESP8266 Arduino en Github
PZEM004Tv30.h
Biblioteca de medidores de energía Peacefair (PZEM-004T v3)
Versión actualizada de la biblioteca PZEM-004T anterior para admitir versiones más nuevas
Proporciona funciones completas del monitor de energía PZEM-004T v3
Más información sobre la biblioteca y enlace de descarga en Github
También se puede descargar en Arduino Library Manager
Variables:
PZEM004Tv30 pzem(D7,D8)
El constructor de objetos para el medidor de energía junto con las conexiones de pin
Voltaje
Valor del sensor de tensión en voltios (V)
Actual
Valor del sensor de corriente en amperios (A)
Energía
Valor del sensor de potencia en vatios
Energía
Valor del sensor de energía en kilovatios hora (kWh)
Frecuencia
Valor del sensor de frecuencia en hercios (Hz)
Factor de potencia
Resultado calculado basado en los valores del sensor
Funciones:
pzem.voltaje()
obtener valor de voltaje
pzem.actual()
obtener el valor actual
pzem.power()
obtener valor de potencia
pzem.energy()
obtener valor de energía
pzem.frecuencia()
recuperar valor de frecuencia
pzem.pf()
obtener el valor del factor de potencia
Después de probar el sensor SIN CONEXION , ahora podemos conectarlo con el tablero de Cayenne para cargar lecturas de energía en línea.
Con el siguiente código que subiremos al ESP8266 si lo personalizamos con nuestras propias claves (estan marcadas tachadas) podemos probar
Code (PZEM-004T V3 with Cayenne Dashboard):
//Libraries
#include <Arduino.h>
#include <CayenneMQTTESP8266.h>
#include <PZEM004Tv30.h>
//Debug Cayenne Connection
#define CAYENNE_DEBUG
//Enable Serial Print
#define CAYYENE_PRINT Serial
//Canales de Cayenne para mostrar los datos
#define VOLTAGE_CHANNEL 1 //voltage
#define CURRENT_CHANNEL 2 //current
#define POWER_CHANNEL 3 //power
#define ENERGY_CHANNEL 4 //energy
#define FREQUENCY_CHANNEL 5 //frequency
#define POWERFACTOR_CHANNEL 6 //power factor
//RX pin = D7 connected to the TX pin of PZEM-004T v3
//TX pin = D8 connected to the RX pin of PZEM-004T v3
//Constructor del dispositivo Peacefair
PZEM004Tv30 pzem(D7,D8);
//Credencial de la WiFi a la que se conectara para el envio.
char ssid[] = "HOTSPOTniKOYA";
char wifiPassword[] = "09771665851";
//ESP8266 Información para la autenticacion de Cayenne obtenida de Cayenne Dashboard.
char username[] = "439049b0-0660-11ed-8df2-dd50487e509b";
char password[] = "1f5cf9c47e9fc2b28eaa1ffb054b62003a71127a";
char clientID[] = "349a2920-1bf1-11ed-baf6-35fab7fd0ac8";
//Meter values
float Voltage;
float Current;
float Power;
float Energy;
float Frequency;
float PowerFactor;
void setup() {
Serial.begin(115200);
//Esperar a que Serial Monitor se abra antes de proceder
while(!Serial);
delay(100);
//Start Cayenne connection
Cayenne.begin(username, password, clientID, ssid, wifiPassword);
Serial.println("PZEM-004T-100A Energy Meter Cayenne Interface using ESP8266 ( o un Wemos D1 Mini)");
Serial.println("");
}
void loop() {
//get meter values
Voltage = pzem.voltage();
Current = pzem.current();
Power = pzem.power();
Energy = pzem.energy();
Frequency = pzem.frequency();
PowerFactor = pzem.pf();
Cayenne.loop();
}
//Display Voltage Value
CAYENNE_OUT(VOLTAGE_CHANNEL)
{
Serial.println("Resultados de las medidas: ");
Cayenne.virtualWrite(VOLTAGE_CHANNEL, Voltage);
Serial.print("Voltaje: "); Serial.print(Voltage,3); Serial.println("V");
}
//Display Current Value
CAYENNE_OUT(CURRENT_CHANNEL)
{
Cayenne.virtualWrite(CURRENT_CHANNEL, Current);
Serial.print("Corriente: "); Serial.print(Current,3); Serial.println("A");
}
//Display Power Value
CAYENNE_OUT(POWER_CHANNEL)
{
Cayenne.virtualWrite(POWER_CHANNEL, Power);
Serial.print("Potencia: "); Serial.print(Power,3); Serial.println("W");
}
//Display Energy Value
CAYENNE_OUT(ENERGY_CHANNEL)
{
Cayenne.virtualWrite(ENERGY_CHANNEL, Energy);
Serial.print("Energia: "); Serial.print(Energy,3); Serial.println("kWh");
}
//Display Frequency Value
CAYENNE_OUT(FREQUENCY_CHANNEL)
{
Cayenne.virtualWrite(FREQUENCY_CHANNEL, Frequency);
Serial.print("Frequencia: "); Serial.print(Frequency,2); Serial.println("Hz");
}
//Display Power Factor Value
CAYENNE_OUT(POWERFACTOR_CHANNEL)
{
Cayenne.virtualWrite(POWERFACTOR_CHANNEL, PowerFactor);
Serial.print("Factor de Potencia: "); Serial.println(PowerFactor,3);
Serial.println("");
}
Desglose del código:
Bibliotecas:
Arduino.h
El soporte ESP8266 para Arduino
Capaz de escribir bocetos, usar funciones y bibliotecas de Arduino
Ejecute bocetos sin necesidad de un microcontrolador externo
Biblioteca integrada en el IDE
Más información sobre la biblioteca, junto con la configuración de ESP8266 Arduino en Github
CayenneMQTTESP8266.h
Biblioteca Cayenne MQTT ESP para la conexión del generador de proyectos Cayenne IoT
Admite módulos Wi-Fi ESP8266 y ESP32
Leer y enviar datos a Cayenne Dashboard
Más información sobre la biblioteca y enlace de descarga en Github
PZEM004Tv30.h
Biblioteca de medidores de energía Peacefair (PZEM-004T v3)
Versión actualizada de la biblioteca PZEM-004T anterior para admitir versiones más nuevas
Proporciona funciones completas del monitor de energía PZEM-004T v3
Más información sobre la biblioteca y enlace de descarga en Github
También se puede descargar en Arduino Library Manager
Variables: @PZEM-004T v3
PZEM004Tv30 pzem(D7,D8)
El constructor de objetos para el medidor de energía junto con las conexiones de pin
Voltaje
Valor del sensor de tensión en voltios (V)
Actual
Valor del sensor de corriente en amperios (A)
Energía
Valor del sensor de potencia en vatios
Energía
Valor del sensor de energía en kilovatios hora (kWh)
Frecuencia
Valor del sensor de frecuencia en hercios (Hz)
Factor de potencia
Resultado calculado basado en los valores del sensor
@Cayenne
CAYENNE_DEBUG
Habilita la impresión en serie de Cayenne
Serie CAYENNE_PRINT
Habilita el monitor serie para imprimir datos
VOLTAJE_CANAL 1
El canal Cayenne asignado para proyectar lecturas de voltaje del medidor
CANAL_ACTUAL 2
El canal Cayenne asignado para proyectar lecturas actuales del medidor
POTENCIA_CANAL 3
El canal Cayenne asignado para proyectar lecturas de energía del medidor
ENERGÍA_CANAL 4
El canal Cayenne asignado para proyectar lecturas de energía del medidor
FRECUENCIA_CANAL 5
El canal Cayenne asignado para proyectar lecturas de frecuencia del medidor
FACTOR DE POTENCIA_CANAL 6
El canal Cayenne asignado para proyectar lecturas de factor de potencia del medidor
sid[]
El nombre de la conexión Wi-Fi para conectar el Wemos D1 mini
Contraseña de wifi[]
La contraseña de conexión Wi-Fi para conectar el Wemos D1 mini
nombre de usuario char[]
Nombre de usuario de Cayenne del dispositivo (proporcionado en el código de enlace de Cayenne)
contraseña de char[]
Contraseña de Cayenne del dispositivo (proporcionada en el código de enlace de Cayenne)
ID de cliente char[]
ID de cliente de Cayenne del dispositivo (proporcionado en el código de enlace de Cayenne)
Funciones: @PZEM-004T V3
pzem.voltaje()
obtener valor de voltaje
pzem.actual()
obtener el valor actual
pzem.power()
obtener valor de potencia
pzem.energy()
obtener valor de energía
pzem.frecuencia()
recuperar valor de frecuencia
pzem.pf()
obtener el valor del factor de potencia
@Cayenne
Cayenne.begin(nombre de usuario, contraseña, ID de cliente)
Inicia la conexión de cayena
Muestra el estado de la conexión en el monitor serie
Cayenne.loop()
Llama a la clase CAYENNE_OUT(VIRTUAL_CHANNEL)
Cayenne.virtualWrite(Canal, Salida)
Mostrar los valores del medidor en el monitor serial
Sube los valores de salida al canal virtual del tablero
Y una vez que llevamos un rato con el montaje funcionando este es el resultado
NOTAS IMPORTANTES:
Si conectamos el PZEM004 a un ESP8266, la tension de alimentación para la sincronizacion del canal de comunicaciones es 3,3V (en caso de un Wemos seria de 5v)
Para que las medidas sean correctas los leds TX y RX del PZEM004 deben parpadear rápido y con luz tenue. Si alguno de los leds TX o RX se queda fijo esto significa que o bien alguna conexión es incorrecta o no se ha actualizado el firmware del controlador , de modo que si consultamos la consola serie veremos que las medidas no son correctas ( el IDE de Arduino las pinta como nan). Ver la imagen de abajo donde se aprecia este error.
En caso de que no se pueda programar el controlador ESP8266 desde el IDE de Arduino un truco consiste en desconectar la línea de 3.3V hacia la salida RS425 antes de compilar el código.
A veces es necesario reiniciar tanto el PZEM004 como el ESP8266 si no hay resultados correctos .
Si no tenemos la consola serie para saber si está sacando datos correctos ( es decir que no saca los valores nan) una buena referencia son los dos leds (tX y RX) del PZEM004 qeu deben lucir a la vez a intervalos regulares ( según el delay definido en el bucle principal)
Debemos programar el controlador antes de conectar la salida RS425 del PZEM004 para evitar problemas
Se ha usado un ESP8266 ( aunque se puede usar cualquiera similar que pertenezca a esta familia) para que no de problemas el api de Cayenne . Para usar un ESP32 se debe seleccionar en el interfaz el Esp826 pues funciona también con la familia del ESP32 , si bien la llibreria es CayenneMQTTESP32.h
El objetivo de este post es ver un ejemplo der cómo medir el voltaje, la corriente y la potencia con dos sensores PZEM 004T de una Raspberry Pi .
En el ejemplo los sensores no están conectados directamente a la Raspberry, pero están conectados a un microcontrolador Arduino (Mega 2560) y este se conecta a la Raspberry a través de un cable USB.
Primero obtenemos todos estos valores usando el microcontrolador Arduino con capacidad de dos puertos serie como podria ser también un ESP32 (NodeMCU) o por supuesto un Arduino Mega, y luego los enviamos a la Raspberry Pi.
Es interesante observar cómo al proporcionar los módulos PZEM004 una salida serie necesitamos usar ese protocolo para recepcionar los datos motivo por el cual precisamente utilizamos dos puertos serie del microcontrolador ( y no sería posible por tanto añadir más módulos PZEM004)
Gracias a la biblioteca PZEM-004T v3.0 para el monitor de energía Peacefair PZEM-004T-10A yPZEM-004T-100A v3.0 utilizando la interfaz ModBUS y un microcontrolador, podemos monitorizar el consumo eléctrico junto a otras variables eléctricas como la tensión , la frecuencia , el factor de potencia, etc.
Es interesante destacar que debemos usar la ultima version del modulo, pues la versión 3.0 PZEM es una versión mejorada del antiguo PZEM-004T
Respecto a las conexiones eléctricas debemos tener especialmente cuidado en el conexionado de las clemas de BT , las cuales viene claramente especificadas en la hoja de característica del modulo PZEM que usemos, pues una parte es para la medida del voltaje ( la medición se hace en paralelo ) y la parte contigua es la parte de la medida de la Intensidad (la medida se toma en serie en versiones de menos intensidad maxima admisible, pero para la version de 100A se suele tomar con una bobina toroidal o con un pinza amperimétrica)
¡Asegúrese de que el dispositivo esté conectado a la alimentación de CA! Los 5V solo alimentan los optoacopladores, no el chip real. Además, tenga cuidado, ¡la corriente alterna es peligrosa! ¡Si no sabe lo que estás haciendo, puede morir ! Es usted responsable de su propia estupidez. Así que no sea estúpido
Peor tanto ,debemos extremar el cuidado especialmente en estas conexiones (las que van con tornillo).
Observe por ejemplo las conexiones del módulo de 100 Amp. usado para escribir este post:
Esta versión PZEM tiene una UART Serial que funciona a 5V, por lo que se debe realizar una simple modificación soldando una resistencia de 1K a 1/4W para permitir que la comunicación funcione a 3.3v en los casos de placas como Raspberry Pi, ESP32 y esp8266, con esta modificación la UART funcionará a 5v o 3.3v.
Nota: Esta es la manera más sencilla y económica si no tienen al alcance un convertidor TTL de 5 a 3.3v, pero no se garantiza que funcione en todos los casos y con todos los medidores (en el prototipo probado funciona sin problemas).
El circuito final para el montaje de los dos PZEM quedaría como se puede ver en la imagen donde vemos como los alimentamos a +5V DC desde el microcontrolador, usamos las lineas tx/rx de forma inversa hacia el microcontrolador y finalmente el microcontrolador lo comunicamos con la Raspberry pi mediante un cable USB
Como se indicó anteriormente, el primer paso es recopilar todos los valores del microcontrolador Arduino, por lo que para hacerlo debemos usar la biblioteca . Esta biblioteca se puede descargar desde la página web: https://github.com/olehs/PZEM004T como un paquete zip, luego se debe agregar dentro del IDE de Arduino
El siguiente paso es conectar los sensores al microcontrolador arduino. Usaremos la librería SoftwareSerial para permitir la comunicación serial en otros pines digitales del Arduino y poder leer más de un dispositivo serial. Entonces, los terminales RX y TX del primer sensor están conectados a los pines 11 y 10 del microcontrolador y los terminales RX y TX del segundo sensor están conectados a los pines 13 y 12 respectivamente.
Ahora es el momento de desarrollar el código en Arduino IDE de la siguiente manera:
///////////////////////////////////////////////////////// ///////////////////////////////////////////////// // /////////////////////////////////////////
//* Código para obtener el voltaje, corriente y potencia de dos sensores AC PZEM conectados al microcontrolador Arduino Mega, luego todos los valores *//
// se concatenan en una variable char para poder enviarla a través de comunicación serie //
///////////////////////////////////////////////////////// ///////////////////////////////////////////////// // ///////////////////////////////////////
#include
#include
IPAddress ip(192,168,1,11);
IPAddress ip1(192,168,1,10);
charix[10];
char iy[10];
char iz[10];
charconc[360];
charix1[10];
char iy1[10];
char iz1[10];
flotante V, V1;
flotar i, i1;
flotante p, p1;
void setup () {
Serial.begin(9600);
}
void loop () {
PZEM004T pzem(10,11); //(RX TX)
pzem.setAddress(ip);
V=pzem.voltage(ip); //voltaje obtenido de la biblioteca pzem
i = pzem.current(ip); // actual obtenido de la biblioteca pzem
p = pzem.power(ip);//potencia obtenida de la biblioteca pzem
dtostrf(V,7,3,ix); //función utilizada para almacenar el valor actual en la variable char ix, especificando 3 como el número de dígitos después del punto
dtostrf(i,7,3,iy); //función utilizada para almacenar el valor actual en la variable char iy, especificando 3 como el número de dígitos después del punto
dtostrf(p,7,3,iz); //función utilizada para almacenar el valor de potencia en la variable char iz, especificando 3 como el número de dígitos después del punto
retraso (1000);
PZEM004T pzem1(12,13); //(RX TX)
pzem1.setAddress(ip1);
V1=pzem1.voltage(ip1); //voltaje obtenido de la biblioteca pzem
i1 = pzem1.current(ip1); // actual obtenido de la biblioteca pzem
p1 = pzem1.power(ip1);//potencia obtenida de la biblioteca pzem
dtostrf(V1,7,3,ix1);//función utilizada para almacenar el valor actual en la variable char ix1, especificando 3 como el número de dígitos después del punto
dtostrf(i1,7,3,iy1); //función utilizada para almacenar el valor actual en la variable char iy1, especificando 3 como el número de dígitos después del punto
dtostrf(p1,7,3,iz1); // función utilizada para almacenar el valor de potencia en la variable char iz1, especificando 3 como el número de dígitos después del punto
retraso (1000);
sprintf(conc,":%s,:%s,:%s,:%s,:%s,:%s,\n", ix,iy,iz,ix1,iy1,iz1); // función utilizada para concatenar todos los valores en una sola variable char
Serial.write(conc);
} /////////////////////////
Observaciones:
Los sensores no se leen al mismo tiempo.
El tipo de los valores dados por el sensor es flotante.
Después de obtener todos los valores, estos se convierten de tipo flotante a char utilizando la función «dtostrf» en la que los lugares decimales se limitan a tres.
Los 6 valores se concatenan mediante la función «sprintf», en una única matriz de caracteres y luego se envían como datos en serie.
Además de poner todos los valores juntos en la matriz char, también ponemos los caracteres ‘:’ y ‘,’. Al final, la matriz de caracteres se ve así: “:val1,:val2,:val3,:val4,:val5,:val6,:”. Se hace con el fin de analizar y sacar los valores fácilmente en python.
Después de cargar y probar el código en el microcontrolador, es hora de lidiar con el script de python. El microcontrolador Arduino debe conectarse a la Raspberry mediante un cable USB.
Antes de comenzar con el código, podría ser bueno saber cómo crear un archivo python desde la terminal de Linux. Se hace escribiendo la siguiente línea de comando:
toque PZEM_Sensors.py
Luego para abrir el archivo ya creado, debemos teclear la siguiente línea de comando:
nano PZEM_Sensores.py
import serial
import time
import re
port = "/dev/ttyACM0"
s1 = serial.Serial(port,9600)
while True:
if s1.inWaiting()>0:
inputValue = s1.readline().decode()
m = re.search('.*:(.*),.*:(.*),.*:(.*),.*:(.*),.*:(.*),.*:(.*),',inputValue) # command used to read the information and split it between the charcaters ':' and ','
v1 = m.group(1).replace(" ","") ## command used to saved the information splitted before in a the variable
i1 = m.group(2).replace(" ","")
p1 = m.group(3).replace(" ","")
v2 = m.group(4).replace(" ","")
i2 = m.group(5).replace(" ","")
p2 = m.group(6).replace(" ","")
a = float(v1)
b = float(i1)
c = float(p1)
d = float(v2)
e = float(i2)
f = float(p2)
print("Voltage1:",+a)
print("Current1:",+b)
print("Power1:",+c)
print("Voltage2:",+d)
print("Current2:",+e)
print("Power2:",+f)
Observaciones:
Deberíamos especificar el puerto de la Raspberry donde está conectado el sensor. Para saberlo, solo debemos escribir el siguiente comando desde la ventana de la Terminal LX: ls /dev –> Los nombres de los dispositivos USB conectados comienzan con: “ttyUSBX”. Donde X indica el número de cada dispositivo USB conectado.
El puerto serie se lee y decodifica para asegurarse de que tenemos una cadena de caracteres. Se hace con la función readline() y decode() respectivamente.
Los seis valores se obtienen mediante el uso de expresiones regulares. Usando ‘.*:(.*),’, tomamos todos los caracteres que están entre ‘:’ y ‘,’ y luego los almacenamos en grupos.
Al final los valores se convierten de tipo char a tipo float.
Después de escribir todo el código y presionar las teclas Ctrl + X, se le pedirá que lo guarde o no. Debe presionar la tecla y o n y luego Enter.
Para ejecutar el código, debemos escribir la siguiente línea de comando:
python PZEM_Sensores.py
Luego, todos los resultados y mensajes aparecerán en las ventanas de la Terminal o aparecerá un mensaje de error si hay algo incorrecto dentro del código.
La siguiente figura muestra todos los resultados obtenidos de los dos sensores PZEM. La corriente 1 es 0 debido a que no hay ningún sensor de corriente conectado y por eso la potencia 1 también es 0. Si hay algún problema de comunicación el valor que obtendremos es -1.
En este post vamos a ver una interesante idea que busca optimizar uno de los electrodomésticos que porcentualmente más consume en una vivienda: la nevera. Es un espectacular proyecto desarrollado en conjunto por G4lile0, programarfacil y Germán Martín que se presentaron como candidatos al Intel Hacks 2017.
La idea surgió de uno de los miembros del equipo, cuando un día descubrió que su factura eléctrica era demasiado alta lo cual lelo llevó a investigar para encontrar alguna forma de medir el consumo eléctrico de su casa. Encontro el sitio web de Open Energy Monitor , un sistema que permite medir el consumo eléctrico mediante Arduino . Esto cambió todo porque no dependía de terceros para hacer un análisis de sus electrodomésticos. De repente miró el refrigerador, ¿qué estaba pasando? Este electrodoméstico era el que más consumía por día en toda la casa con diferencia. Investigando más a fondo descubrió varias cuestiones interesantes sobre los frigoríficos. Pero quizás, lo más importante fue que debido al calor que se concentra detrás de estos dispositivos, su consumo eléctrico aumenta entre un 15% y un 25%.Esta fue la semilla de este proyecto.
Funcionamiento de una nevera
Hay más de 7 mil millones de personas en el mundo. Uno de cada cinco tiene un refrigerador en su casa. Eso es más de 1.500 millones de refrigeradores .
Este electrodoméstico es uno de los pocos que está encendido las 24 horas del día y los 365 días del año. Esto significa que cada frigorífico consume una media de 450 KWh al año. Si multiplicamos el número de frigoríficos en todo el mundo (1.500 millones) y el consumo anual de cada uno, el total deja 649 millones de MWh de consumo anual.
Si lo miramos desde otra perspectiva, podemos afirmar que todos los frigoríficos domésticos del mundo consumen más que un país como Alemania.
Por tanto, suponiendo que pudiéramos reducir un 10% el consumo de todos los frigoríficos del mundo, estaríamos ahorrando un total de 64,9 millones de MWh al año. Si un KWh equivale a 0,62 kg de CO2 , evitaríamos verter a la atmósfera 42.185.000.000 kg de CO2.
El mero hecho de disponer de los datos de consumo de los electrodomésticos, hace que tu factura eléctrica se reduzca un 10%. Como veremos a lo largo de este proyecto, este dispositivo se puede utilizar para otros electrodomésticos. Esto implica que podremos tener un ahorro considerable en la factura eléctrica.
El funcionamiento de un frigorífico consiste en trasladar el calor del interior al exterior, lo cual permite que la temperatura dentro de la nevera sea mucho más baja que la temperatura ambiente de la habitación enfriando por tanto los alimentos y bebidas que hay en su interior.
Si no hay suficiente lugar para ser expulsado, el aire caliente que expulsa el propio aparato se condensa en la parte posterior, lo que afecta la eficiencia del compresor. Esto provoca que se necesite más tiempo para enfriar y como consecuencia, un aumento en el consumo eléctrico.
Una posible solución es ventilar la parte trasera a través de un flujo de aire fresco. Esto se puede lograr de varias formas, dando más espacio en la parte trasera o moviendo el aire con ventiladores.
Pero claro, todo esto no tiene sentido si no tenemos datos de consumo y temperaturas. Aquí es donde entra en juego Arduino, donde conectaremos los sensores de temperatura y consumo de energía para transmitirlos a una base de datos en la nube.
Planteado el problema y una posible solución, ya podemos intuir de lo que va el proyecto.
Cómo lo construimos
El eje central de este proyecto es el Arduino 101 . Esta placa lleva el microcontrolador Intel Curie . Es un chip pequeño pero completo. Entre sus características tiene incorporada una IMU o Unidad de Medida Inercial que cuenta con acelerómetro y giroscopio y conectividad Bluetooth a través de la tecnología BLE o Bluetooth Low Energy.
Una cosa importante a tener en cuenta con esta placa prototipo es que debe tener el firmware más actualizado posible. Esto se debe a que lo que en realidad estás haciendo es emular un Arduino.
Volviendo al planteamiento inicial del proyecto, debemos hacer varias cosas con el Arduino 101. Medir varias temperaturas, consumo de energía y controlar los ventiladores para generar ese flujo de aire fresco en la parte trasera del refrigerador.
En particular, tomamos la decisión de medir la temperatura de la parte trasera, la temperatura frontal, el congelador y el refrigerador. Esto nos da 4 sensores de temperatura y un sensor para medir el consumo eléctrico.
Para la toma de datos se utilizó el sensor de temperatura DS18B20 y el sensor SCT-013 que mide el consumo eléctrico.
No es obligatorio utilizar estos modelos, se puede utilizar cualquier otro sensor similar para obtener la información de temperatura y consumo.
Sensor de temperatura DS18B20
El sensor de temperatura Maxim Integrated DS18B20 ofrece un rango de temperatura entre -55 °C y 155 °C, con una precisión de ± 0,5 °C.
El modelo que utilizamos es el comercializado como sonda estanca evitando cualquier problema en el interior del frigorífico o congelador. Este sensor utiliza el protocolo de comunicación de 1 cable de Maxim Integrated que permite la conexión simultánea de más de 100 sensores a través de un solo pin.
Sensor de consumo eléctrico SCT-013
Para medir el consumo, utilizamos un sensor de corriente no invasivo. Así que no nos preocupamos por tener que alterar demasiado el cable de alimentación del frigorífico. Lo único que tenemos que hacer es pelar el cable y abrazar solo uno de los dos cables de alimentación, vivo o tierra.
Este tipo de sensores se conocen como Transformadores de Corriente y uno de los más comunes es el SCT-013. Operan bajo el principio de inducción electromagnética. La salida de estos sensores es una intensidad proporcional a la que pasa por un cable o circuito eléctrico.
Hay dos tipos de sensores, que proporcionan una corriente o un voltaje. Lo mismo que usas, pero el más sencillo es el que nos ofrece un voltaje.
Aficionados
Finalmente conectaron ventiladores. Teniendo en cuenta el consumo, las dimensiones y el ruido que pueden generar. Podemos usar cualquier modelo, pero debemos estar muy atentos a estos componentes ya que hay diferentes modelos para diferentes usos y no todos valen. La idea es poder adaptar el proyecto para utilizar los típicos ventiladores de los ordenadores ya que consumen muy poco y son muy económicos. Los que están probando a José Manuel y Germán son tipo Boxer Fan.
Conexión de Arduino 101 a Internet
Aunque, como decía, es una placa muy robusta y muy útil, el gran inconveniente es que no tiene conexión a Internet. Esto nos obligó a buscar soluciones para enviar toda la información adquirida a una plataforma en la nube .
Hay diferentes opciones como usar Bluetooth para conectarse a otro dispositivo que tenga conexión a Internet. Pero quizás lo más sencillo y económico que encontramos fue utilizar un NodeMCU .
Este kit de desarrollo está basado en el ESP8266 y es muy fácil de usar (es compatible con el IDE de Arduino) y tiene un precio muy económico y tiene una librería para configurar WiFi como WiFiManager
Toda la lógica del proyecto reside en el Arduino 101 y NodeMCU solo hace de puente entre la placa e Internet.
Envía información a la plataforma en la nube
Los datos deben ser visibles en tiempo real en todo momento. Solo así comprobaremos si el proyecto es viable y podemos tomar las decisiones adecuadas.
Como plataforma en la nube los creadores de este proyecto eligieron Firebase , pues una de sus ventajas es que es muy fácil de usar gracias a la API REST que incorpora. Con solo una llamada HTTP podemos almacenar los datos obtenidos de temperatura, consumo y uso de los ventiladores. Todo esto se envía en formato JSON. Por lo tanto, la integración entre Firebase y NodeMCU es instantánea.
La base de datos de Firebase
Las características que buscaban sus creadores para integrar un servicio en la nube en este proyecto son la facilidad y el costo. En la actualidad son muchos los servicios que podemos llegar a utilizar como Thingspeak, ThingerIO o el propio Arduino Cloud. Todo puede ser una buena elección.
Firebase tiene a su favor de que dispone de APIs para muchos lenguajes de programación entre los que se encuentra JavaScript.
La base de datos tiene limitaciones ya que es una cuenta gratuita.
No permite más de 100 conexiones simultáneas.
Tienes un límite de 1 GB de almacenamiento.
Tienes un límite de 10GB de descarga.
Con todo esto, el proyecto tras un mes de recogida de datos cada minuto de dos frigoríficos, tenemos un consumo de almacenamiento de 3,9 MB y 158,4 MB de descarga.
Aplicación web para visualización de datos
Con todo previamente montado, ya no queda nada para ver la información de manera amigable en cualquier dispositivo.
Si queremos monitorizar los datos en tiempo real, desde cualquier parte del mundo y cualquier dispositivo, una de las opciones más rápidas es crear una aplicación web.
Firebase tiene una API de Javascript que hace que sea muy fácil integrar una base de datos de esta plataforma en una página web.
Además, se puede agregar el marco Bootstrap para que responda utilizado una plantilla abierta para este marco, SB Admin 2 .
Todo esto ha dado como resultado un sitio web que se puede ver en www.iotfridgesaver.com . Consta de dos pantallas.
La pantalla inicial muestra un mapa de Google donde iremos ubicando los diferentes frigoríficos que se utilizan.
Una vez que encuentres el que deseas consultar, solo dale al icono y hacemos clic en info. Desde aquí se puede acceder al histórico de temperatura, consumo y uso de ventilador.
Desafíos
Han sido muchos los retos a los que nos hemos enfrentado en este proyecto. Primero la integración de una placa sin conexión a Internet que resolvieron usando una placa basada en ESP8266 como NodeMCU. Quizás haya una solución mucho mejor, pero la más simple y rápida fue esta.
A la hora de realizar la ventilación trasera, el problema es principalmente cómo hacer que fluya aire fresco para bajar la temperatura.Han seguido diferentes fases para decidir cuándo encender los ventiladores.En una primera fase han hecho una recogida de datos para analizar la información. Luego se activan manualmente para verificar qué sucede en ciertas situaciones. Esto les llevó a pensar que la diferencia de temperatura entre la parte trasera y la delantera era un buen indicador de un alto consumo.
.
Sin embargo, mientras recopilában datos, se dieron cuenta de que el mejor momento es cuando se activa el compresor y al mismo tiempo aumenta la temperatura trasera lo cual es mucho más fácil en términos de programación controlar esta situación pues sin duda, la temperatura trasera está íntimamente ligada a la actividad del compresor.
Las primeras pruebas muestran que puede haber una mejora de la eficiencia energética de alrededor del 20 % al activar el flujo de aire lo cual verificaron que, cuando el soplador mueve el aire detrás del refrigerador, la actividad del compresor y la velocidad de reducción de la temperatura interna se reducen significativamente.
Logros de este proyecto
En el equipo está muy orgullosos de haber logrado un sistema que es capaz de dos tareas. Por un lado controlar parámetros ocultos de los frigoríficos a los usuarios. Por otro lado se han podido minimizar el consumo eléctrico en determinadas condiciones.
En una primera etapa, fue difícil asignar sensores de temperatura a cada punto de medición. Tuvieron que verificar sus direcciones de hardware para identificarlos y escribirlo en el código fuente. Ahora, usan diferencias de temperatura para identificar sensores automáticamente. Esto facilita la configuración del sistema. No cabe duda de que aún queda mucho camino por recorrer en este proyecto, pero con el solo hecho de tener toda esta información pueden ayudar a las personas a reducir el consumo de sus electrodomésticos.
Con solo aplicar algunas modificaciones a la instalación, podemos reducir su consumo. Pero todo esto no es posible si no disponemos de datos analíticos que lo corroboren. Aquí es donde entran en juego las tecnologías abiertas. Nos dan la posibilidad de crear dispositivos que se adapten a nuestros requerimientos. Sin estas tecnologías nada de esto sería posible.
También han encontrado que puede haber grandes diferencias en el consumo de diferentes refrigeradores de modo que este este proyecto puede ayudar a identificar los modelos más eficientes.
Solo si conocemos el mundo que nos rodea, podemos cambiarlo .
Finalmente han creado un video explicando el funcionamiento de su proyecto
En primer lugar, hay que sincronizar el mando a distancia con el repetidor de señal y, a continuación, con el propio estor. Es importante que ambas partes estén muy cerca para que no haya problemas en la sincronización.
Además si tiene otros dispositivos que usen el protocolo ZigBee si puede desconéctelos porque podria dar problemas a la hora de registrar el nuevo estore
Muy resumidamente estos son los pasos a seguir:
Desmontar la tapa del mando a distancia con un destornillador philips
En la parte trasera descubierta del mando hay un pulsador oculto de sincronización cerca de la pila
Mantén el mando a distancia cerca del repetidor de señal.
Pulse el botón de sincronización del mando durante al menos 10 segundos.
Las luces LED rojas parpadearán mientras se efectúa la sincronización, y luego volverán a parpadear cuando esta se haya completado.
IMPORTANTE: Si no luce el led interno del mando con toda probabilidad la pila CRC25 se habrá gastado , por lo que se recomienda reemplazarla por una nueva . Obviamente si tiene un polímetro pude comprobar el voltaje de esta debiendo superar los 3V ( si está por debajo de este valor no es seguro de que pueda funcionar)
En el siguiente video podemos ver el proceso completo
Sincronización del mando a distancia y el estor
Una vez sincronizado el mando con la base no ponga la tapa a este porque necesitara volver a sincronizar este pero esta vez con el estor.
Muy resumidamente estos son los pasos a seguir:
Mantenga cargado la bateria del store antes de empezar la sincronización ( una bateria descargada suele tardar unas 24 horas en cargarse).
Antes de proceder también deferia haber sincronizado el mando con la base de control
Pulse brevemente ahora los dos botones simultáneamente de la estructura para activar el estor ( estan a la izda y son los qeu sirven parta activar el store manualmente hacia arriba o hacia abajo) . Una luz LED blanca confirmará una vez que está activo. La luz esta vez lucirá fija y si no se actua terminar apagándose
Acerca el mando a distancia al icono de sincronización situado en la estructura del estor.
Pulse el botón de sincronización del mando durante al menos 20 segundos. Las luces LED rojas parpadearán mientras se efectúa la sincronización, y luego volverán a parpadear cuando esta se haya completado.
El estor bajará y subirá ligeramente cuando se complete la sincronización.
Ahora ya puede utilizar el mando a distancia para controlar el estor.
Ya puede montar la tapa del mando
Posibles problemas : Si se ha sincronizado el mando ok con las base , el store funciona manualmente pero no se logra sincronizar a veces quitar la bateria de la base del store y volverla a insertar resuelve el problema
En el siguiente video podemos ver el proceso completo:
Es importante destacar que siempre que se agote la bateria del mando o la del store, deberemos repetir ambas operaciones ya comentadas.
Después de enchufar el repetidor de señal por primera vez, pueden pasar unos minutos hasta que empiece a comunicarse con el mando a distancia y el estor. Esto también puede ocurrir después de un apagón o si se desenchufa el repetidor.
Utiliza el mando a distancia para subir o bajar el estor. Si el estor no se mueve o el mando no responde, prueba estos cuatro pasos:
Instalar las baterías
Desatornille la parte trasera del mando e introduce la pila en la ranura.
Deje la parte trasera abierta por ahora; retomaremos este tema cuando reiniciemos y sincronicemos.
Asegúrese de que la batería del estor esté colocada y de que tanto el estor como el repetidor de señal estén encendidos. Utilize el mando a distancia para subir o bajar el estor
Pulse el botón de bajada del mando para bajar el estor. Si no se mueve, prueba el siguiente paso: Cargar la batería. Bajar la persiana tal cual
Carga de las baterías
Si el estor sigue sin responder, es posible que la batería se haya quedado sin carga.
Abra la pestaña que hay en la estructura del estor y extrae la batería.
La batería de un estor inteligente se carga sobre una mesa
Conecte la batería al repetidor de señal mediante un cable USB y deja que se cargue.
Una vez que se haya cargado por completo, la luz se apagará y la batería estará lista para su uso.
Desconecte la batería y vuelve a colocarla en su posición dentro de la estructura. El estor se enrollará hasta la parte superior una vez completado el proceso de carga.
Utilice el mando a distancia para subir o bajar el estor. Si no se mueve, prueba el siguiente paso: Reiniciar
Reinicio
El mando a distancia, el repetidor de señal y el estor necesitan reiniciarse. Sigue las instrucciones que aparecen a continuación para comenzar el reinicio.
Pulse el botón de sincronización 4 veces en 5 segundos.Las luces LED rojas parpadearán cuando se haya completado el reinicio.
Reinicie el repetidor de señal.Introduzca un objeto puntiagudo en el orificio del repetidor de señal. Mantengalo pulsado durante 5 segundos y después suéltelo. Una vez que deje de pulsar, una luz LED blanca parpadeará 4 veces para indicar que el reinicio se ha completado.Si la luz no parpadea, vuelva a pulsar a través del orificio para probar a reiniciar de nuevo. Reinicia el estor
Mantenga pulsados los dos botones de la estructura durante al menos 5 segundos.Una luz LED blanca parpadeará cuando se haya completado el reinicio. Cuando esté listo, avanza al siguiente paso: Sincronizar ( ya comentado al principio de este post)
En efecto gracias a la extensión de Jupyter para Visual Studio Code podemos ejecutar nuestros cuadernos en python de Jupyter Notebook desde el interfaz de Visual Studio Code, editor que como probablemente amigo lector sabrà es gratuito y uno de los más potentes IDEs hasta la fecha.
Jupyter Notebook es una herramienta increíblemente poderosa para desarrollar y presentar proyectos de ciencia de datos de forma interactiva. Este post intentara guiarle de cómo usar Jupyter Notebooks para proyectos de ciencia de datos y cómo configurarlo en su máquina local pero en vez de usar un navegador lo cual nos genera ciertos problemas ( versionado, restauración de código , etc.) lo usaremos desde el potente IDE de Visual Studio Code.
Pero primero: ¿qué es un “cuaderno”?
Un cuaderno integra código y su salida en un solo documento que combina visualizaciones, texto narrativo, ecuaciones matemáticas y otros medios enriquecidos. En otras palabras: es un documento único en el que puede ejecutar código, mostrar el resultado y también agregar explicaciones, fórmulas, gráficos y hacer que su trabajo sea más transparente, comprensible, repetible y compartible.
El uso de Notebooks es ahora una parte importante del flujo de trabajo de la ciencia de datos en empresas de todo el mundo. Si su objetivo es trabajar con datos, el uso de una computadora portátil acelerará su flujo de trabajo y facilitará la comunicación y el intercambio de resultados.
Aunque es posible utilizar muchos lenguajes de programación diferentes en Jupyter Notebooks, nos centraremosen Python, ya que es el caso de uso más común. (Entre los usuarios de R, R Studio tiende a ser una opción más popular).Jupyter Notebooks también puede actuar como una plataforma flexible para familiarizarse con los pandas e incluso con Python, como se verá en este tutorial.
Las extensiones de Visual Studio Code proporcionan soporte básico de cuaderno para los kernels de lenguaje que son compatibles con los cuadernos Jupyter hoy en día. Muchos kernels de lenguaje funcionarán sin ninguna modificación. Para habilitar las características avanzadas, pueden ser necesarias modificaciones en las extensiones de lenguaje de VS Code.
La extensión Jupyter incluye por defecto las extensiones Jupyter Keymaps y Jupyter Notebook Renderers. La extensión Jupyter Keymaps proporciona mapas de teclado consistentes con Jupyter y la extensión Jupyter Notebook Renderers proporciona renderizadores para tipos MIME como latex, plotly, vega, y similares. Ambas extensiones pueden deshabilitarse o desinstalarse. Y por cierto, la extensión está disponible en varios idiomas: de, en, es, fa, fr, it, ja, ko-kr, nl, pl, pt-br, ru, tr, zh-cn, zh-tw
La Extensión Jupyter utiliza el soporte de cuadernos incorporado de VS Code. Esta interfaz de usuario ofrece una serie de ventajas a los usuarios de cuadernos:
Soporte inmediato de la amplia gama de funciones básicas de edición de código de VS Code, como la salida en caliente, la búsqueda y el reemplazo, y el plegado de código.
Extensiones del editor como VIM, coloración de corchetes, linters y muchas más están disponibles mientras se edita una celda.
Profunda integración con el banco de trabajo general y con las funciones basadas en archivos de VS Code, como la vista de esquema (tabla de contenidos), las migas de pan y otras operaciones.
Tiempos de carga rápidos para los archivos Jupyter notebook (.ipynb). Cualquier archivo de cuaderno se carga y renderiza lo más rápidamente posible, mientras que las operaciones relacionadas con la ejecución se inicializan entre bastidores.
Incluye una herramienta de diferencias para cuadernos, que facilita la comparación y la visualización de las diferencias entre las celdas de código, los resultados y los metadatos.
Extensibilidad más allá de lo que proporciona la extensión Jupyter. Las extensiones ahora pueden añadir su propio lenguaje o tiempo de ejecución específico a los cuadernos, como los cuadernos interactivos de .NET y Gather
Aunque la extensión de Jupyter viene con un amplio conjunto de los renderizadores más utilizados para la salida, el mercado admite renderizadores personalizados instalables para que el trabajo con tus cuadernos sea aún más productivo. Para empezar a escribir los tuyos propios, consulta la documentación de la api de renderizadores de VS Code.
Trabajar con Python
Si quiere trabajar con Python sólo tiene que asegurarte de que utiliza la última versión de la Extensión Python para disfrutar de la asociación conjunta de las Extensiones Python y Juypter.
Por favor, siga las instrucciones de Léame de la Extensión Python para empezar y visite la Documentación de Python para aprender más sobre cómo la Extensión Python y Jupyter trabajan juntas para proporcionar una experiencia óptima de cuadernos Python.
Ejecutar por línea
Para iniciar una sesión de depuración ligera y ejecutar celdas de código línea por línea en cuadernos de Python, pulse F10 mientras selecciona una celda o haga clic en el botón Ejecutar por línea de la barra de herramientas de la celda. También admite núcleos remotos.
Una vez que inicies una sesión de Ejecutar por Línea, aparecerá el Explorador de Variables y los valores de las variables se actualizarán a medida que itera a través de su código.
Para recorrer el resto de la celda durante una sesión Run by Line pulse Ctrl+Enter. Para parar, puede hacer clic en el botón de interrupción en el lado izquierdo de la celda.
Por cierto como ya se ha comentado ,la Extensión Jupyter soporta otros lenguajes además de Python como Julia, R y C#.
Estsos serian los pasos a seguir para un Inicio rápido
Paso 4. Abra o cree un archivo de cuaderno y comience a codificar.
Para crear un nuevo cuaderno, abra la paleta de comandos (Windows: Ctrl + Shift + P, macOS: Command + Shift + P) y seleccione el comando «Crear: Nuevo cuaderno Jupyter».
Selecciona su kernel haciendo clic en el selector de kernel en la parte superior derecha del cuaderno o invocando el comando «Notebook: Seleccionar núcleo de cuaderno».(Notebook: Select Notebook Kernel)
Cambie el idioma de la celda haciendo clic en el selector de idioma o invocando el comando «Cuaderno: Cambiar idioma de la celda». (Notebook: Change Cell Language)
Comandos útiles
Abre la paleta de comandos (Comando+Mayúsculas+P en macOS y Ctrl+Mayúsculas+P en Windows/Linux) y escribe uno de los siguientes comandos:
Command
Description
Create: New Jupyter Notebook
Create: New Jupyter Notebook
Notebook: Select Notebook Kernel
Select or switch kernels within your notebook
Notebook: Change Cell Language
Change the language of the cell currently in focus
Jupyter: Export to HTML Jupyter: Export to PDF
Create a presentation-friendly version of your notebook in HTML or PDF
Para ver todos los comandos disponibles de Jupyter Notebook, abra la paleta de comandos y escriba Jupyter o Notebook.
Teclas de contexto para los enlaces de teclas
Puede utilizar las teclas de contexto de la extensión en cláusulas «cuando». He aquí un ejemplo:
Cuadernos Jupyter: Cree y edite cuadernos Jupyter, añada y ejecute celdas de código/marcadas, haga trazados, cree versiones de su cuaderno aptas para la presentación exportándolas a HTML o PDF y mucho más. (mas info en https://code.visualstudio.com/docs/python/jupyter-support)
Con la crisis actual energètica se hace imprescindible optimizar nuestro consumo de la forma más precisa posible, porque se puede llegar a reducir desde un 15% en adelante nuestro consumo global. Para hacer esto posible quizás lo más económico sea poner un pequeño HAT a la Raspberry del fabricante LeChacal del que ya hemos hablado eneste blog, pues cuenta con diferentes escudos con a posibilidad de apilar estos de modo que si queremos meter más de 8 sensores no intrusivos, montamos tantas placas como necesitemos una sobre otra!
La serie RPICT es una gama de escudo para la Raspberrypi como sensor de corriente CA (CT) y de temperatura. Todas las placas RPICT se conectan al conector GPIO y proporcionan datos a través del puerto serie . Un microcontrolador programable Arduino ( Atmega328 en el caso de la placa con 8 entradas) opera la placa. Es interesante destacar que el código fuente del microcontrolador está disponible gratuitamente.
Como hemos visto en este blogs hay varias opciones para registrar y ver los datos siendo los más utilizados Emoncms e Influxdb con Grafana aunque también es posible usar su propio script de Python. En este post vamos a ver un complemento RPICT7V1 que le permite recuperar las medidas de su tarjeta de la serie RPICT instalada como HAT en su Raspberry PI y mostrarlas en Jeedom.
Para recuperar la información de su tarjeta de la serie RPICT, primero debe conectar esta placa la a su Raspberry PI:
LOS CT DE SALIDA DE VOLTAJE NO SON COMPATIBLES CON ESTA TARJETA.
Apilamiento de tarjetas RPICT en HAT en Raspberry PI
Las placas RPICT7V1 versión 2 se pueden apilar con otras placas RPICT7V1 o RPICT4V3 o RPICT8 para ampliar la cantidad de sensores admitidos. Atención, en el sitio web del fabricante, todas las unidades vendidas están preconfiguradas como MASTER. Consulte la wiki del fabricante para ver cómo configurarlos como esclavos. ApilamientoDocumentación
Configurando la tarjeta RPICT en su Raspberry
Su Raspberry se comunica con la tarjeta RPICT a través del puerto serie. Entonces, debe configurar Rapsberry para que funcione este puerto serie.Ver documentación completa del fabricante AQUÍ
Habilitar puerto serie
Ejecute la herramienta raspi-config,$ sudo raspi-config
Luego deshabilite el inicio de sesión de uart:5 Interfacing Options / P6 Serial
Seleccione No a la pregunta del shell de inicio de sesión.
Seleccione Sí a la pregunta de hardware del puerto serie que se habilitará.
Seleccione Ok en el resumen.
De vuelta en el menú, seleccione Finalizar.
Seleccione No a la pregunta de reinicio (lo haremos más adelante).
Configuración general de Raspberry
Edite el archivo /boot/config.txt$ sudo nano /boot/config.txt
Al final del archivo, agreguedtoverlay=pi3-disable-bt
Desactivar hciuartsudo systemctl disable hciuart
(!) OPCIONAL, Los dos comandos siguientes desactivan el bluetooth del RPI. Si se usa BT, omita este paso y use ttyS0 en lugar de ttyAMA0 en los siguientes pasos.
Reinicie la Raspberry Pi sudo reboot
Prueba de funcionalidad
Una vez que se inserta la tarjeta RPICT y se reinicia la Rpi, se puede hacer una prueba en la línea de comando para verificar que todo esté bien. Tienes que configurar el puerto y empezar a escuchar.
Después de activar el complemento, debe elegir el puerto del módem:
Dependiendo de si ha dejado el Bluetooth activado o no (ver arriba), el puerto a utilizar puede ser uno de los dos siguientes:
/dev/ttyS0
/dev/ttyAMA0
Finalmente recuerda guardar.
Un nuevo protocolo está disponible en Complementos => Protocolo domótico => RPICT7V1
Configuración
El complemento ofrece la posibilidad de crear automáticamente pedidos recibidos. Para hacer esto, inicie el demonio, espere a que lleguen los primeros marcos, luego vaya a Complemento / Protocolos domóticos / RPICTV7.
Debes crear el objeto, darle un nombre y llegas a la página de configuración de la tarjeta RPICT.
Debe introducir el ID de nodo de la tarjeta RPICT (previamente programada al valor 11 al salir de fábrica). Seleccione «Creación automática de pedidos» en la parte superior derecha, finalmente guarde.
A partir de este momento se añadirán automáticamente todos los pedidos recibidos y no reconocidos.
También puede crear pedidos manualmente:
Cree su nuevo dispositivo haciendo clic en Agregar
Añade los pedidos que quieras recuperar haciendo clic en el botón verde “Pedir”
Complete el nombre que se muestra en Jeedom, el Subtipo de acuerdo con la información que se recuperará, el canal en cuestión de la tarjeta y, finalmente, los parámetros asociados.
Clic en Guardar.
Las órdenes
Los comandos (Add data) corresponden a los datos enviados por la tarjeta RPICT.
El número de canales depende de la tarjeta de la serie RPICT que tenga.
El plugin gestiona un máximo de 15 canales.
Salud
Es posible verificar la recepción de los datos antes de su procesamiento.
Para hacer esto, vaya al objeto RPICT y luego haga clic en Salud
La ventana que se abre le permite verificar la correcta recepción de datos por NodeID para cada canal:
API
El complemento RPICT proporciona una API para actualizar datos de otros sistemas. Esta es una URL de llamada de tipo GET. Para acceder a esta información se requiere:
#IP_JEEDOM# corresponde a la dirección IP de su Jeedom #PORT_JEEDOM# corresponde al puerto de acceso a su Jeedom #YOUR_API_JEEDOM# es la clave API disponible en el menú General / Administración / Configuración
#NODE_ID_RPICT# corresponde al NodeID de la tarjeta RPICT. Esta información es necesariamente transmitida por la tarjeta RPICT cuando recibe una trama.
Tenga en cuenta que /jeedom puede ser diferente si está en una instalación de bricolaje u OEM. Por lo general, tienes que agregarlo.
A esta url de llamada se le pueden agregar los diferentes valores según el formato: &#NAME_DE_LA_VALEUR#=#VALEUR#
Por ejemplo para el canal 1 equivalente a 123456789:
&ch1=123456789
Por lo tanto, la URL se sobrecargará con toda la información útil.
A la hora de medir con un controlador la intensidad de un circuito de ca, existen shunts , modernamente sensores hall, pero ambos adolecen de ser intrusivos porque requieren interrumpir el circuito para conectar estos. Modernamente han aparecido sensores no intrusivos basados en un núcleo partido que se puede abrir para intercalar el fase del circuito a medir. En este ámbito destacan los sensores de corriente alterna SCT-013 , los cuales podríamos clasificarlos en dos grupos: los que proporcionan una corriente o los que proporcionan un voltaje siendo la gran diferencia entre ellos que en los primeros no viene incluida una resistencia de carga y en los segundos sí (el nombre resistencia de carga o resistencia «burden» se refiere a la función que hace, no a como están fabricadas siendo su función convertir la corriente en un voltaje limitado que podamos medir, por ejemplo, con un microcontrolador).
El sensor SCT-013-000 es el único que nos proporciona una corriente y por tanto no tiene resistencia de carga. Puede medir una corriente de entre 50 mA y 100 A. El resto de la familia de sensores SCT-013 sí que tienen incluida la resistencia de carga. Podemos encontrar varios modelos pero todos tienen un voltaje de salida entre 0V y 1V.
Esta tabla nos describe las principales características de la familia de sensores SCT disponible :
Elegir uno u otro sensor SCT-013 dependerá de las necesidades reales. Como vemos en la tabla anterior, deberá elegir la intensidad de corriente que mejor se acople a sus necesidades o bien seleccionar el modelo «personalizado» SCT-013-000.
En post por tanto vamos a trabajar con el SCT-013-000 debido a que no tiene resistencia de carga lo cual nos va a permitir seleccionar la resistencia de carga más adecuada para medir con masa precisión el consumo eléctrico de un electrodoméstico en concreto como por ejemplo podria ser un frigorífico.
Para conectar un sensor CT a un Arduino, la señal de salida del sensor CT debe acondicionarse para que cumpla con los requisitos de entrada de las entradas analógicas Arduino, es decir, un voltaje positivo entre 0 V y el voltaje de referencia ADC.
Este ejemplo vemos una placa Arduino que funciona a 5 V y el EmonTx que funciona a 3,3 V. Asegúrese de utilizar el voltaje de suministro y el voltaje de polarización correctos en sus cálculos que correspondan a su configuración.
Esto se puede lograr con el siguiente circuito que consta de dos partes principales:
El sensor CT y la resistencia de carga
El divisor de voltaje de polarización ( R1 y R2 )
Basta con sumar 2,5V y estaría resuelto. Esto lo haremos a través de un circuito conocido como circuito offset en DC,lo cual básicamente consiste en poner un divisor de tensión y un condensador (el condensador tiene que ser de 10μF y unos pocos cientos de voltios lo cual hace que la reactancia sea baja y la corriente alterna evite la resistencia).
El valor de las resistencias del divisor de tensión puede ser 10kΩ siempre y cuando lo alimentemos a través de la red eléctrica, pero si su dispositivo va a funcionar con baterías utilice unas resistencias de 470kΩ para que el consumo sea mínimo.
Cálculo de un tamaño de resistencia de carga adecuado
Si el sensor CT es del tipo de «salida de corriente» como el YHDC SCT-013-000 , la señal de corriente debe convertirse en una señal de voltaje con una resistencia de carga. Si se trata de un CT de salida de voltaje, puede omitir este paso y omitir la resistencia de carga, ya que la resistencia de carga está integrada en el CT.
Este es el cálculo de la citada resistencia:
1) Elija el rango actual que desea medir
El YHDC SCT-013-000 CT tiene un rango de corriente de 0 a 100 A. Para este ejemplo, elijamos 100 A como nuestra corriente máxima.
2) Convierta la corriente RMS máxima en corriente pico multiplicando por √2.
Corriente máxima primaria = corriente RMS × √2 = 100 A × 1,414 = 141,4 A
Resultado =141,4 Amp
3) Divida el pico de corriente por el número de vueltas en el TC para obtener el pico de corriente en la bobina secundaria.
El TC YHDC SCT-013-000 tiene 2000 vueltas, por lo que la corriente pico del secundario será:
Pico de corriente secundario = Pico de corriente primario / no. de vueltas = 141.4 A / 2000 = 0.0707A
Resultado 2= 0.07Amp
4) Para maximizar la resolución de la medición, el voltaje a través de la resistencia de carga en el pico de corriente debe ser igual a la mitad del voltaje de referencia analógico de Arduino. (AREF / 2)
Si está utilizando un Arduino que funciona a 5V: AREF / 2 será de 2,5 voltios.
Entonces la resistencia de carga ideal será:
Resistencia de carga ideal = (AREF/2) / Pico de corriente secundario = 2,5 V / 0,0707 A = 35,4 Ω
Resultado 3= 35,4 ohmios
Es fácil adivinar que 35 Ω no es un valor de resistencia común. Los valores más cercanos a ambos lados de 35 Ω son 39 y 33 Ω. Elija siempre el valor más pequeño, o la corriente de carga máxima creará un voltaje más alto que AREF. Recomendamos una carga de 33 Ω ±1%. En algunos casos, el uso de 2 resistencias en serie estará más cerca del valor de carga ideal. Cuanto más lejos del ideal esté el valor, menor será la precisión.
Aquí están los mismos cálculos que arriba en una forma más compacta:
Si está utilizando un emonTx V2 alimentado por batería, AREF comenzará a 3,3 V y disminuirá lentamente a medida que el voltaje de la batería caiga a 2,7 V. Por lo tanto, la resistencia de carga ideal para el voltaje mínimo sería:
Resistencia de carga ideal = (AREF/2) / Pico de corriente secundario = 1,35 V / 0,0707 A = 19,1 Ω
19 Ω no es un valor común. Tenemos una opción de 18 o 22 Ω. Recomendamos utilizar una carga de 18 Ω ±1%.
emonTx V3
El emonTx V3 usa un regulador de 3.3V, por lo que es V CC y por lo tanto AREF, siempre será de 3.3V independientemente del voltaje de la batería. El emonTx V3 estándar usa resistencias de carga de 22 Ω para CT 1, 2 y 3, y una resistencia de 120 Ω para CT4, el canal de alta sensibilidad.
2) Agregar un sesgo de CC
Si tuviera que conectar uno de los cables del TC a tierra y medir el voltaje del segundo cable, con respecto a tierra, el voltaje variaría de positivo a negativo con respecto a tierra. Sin embargo, las entradas analógicas de Arduino requieren un voltaje positivo. Al conectar el cable de CT que conectamos a tierra, a una fuente a la mitad del voltaje de suministro, el voltaje de salida de CT ahora oscilará por encima y por debajo de 2,5 V, por lo que permanecerá positivo.
Las resistencias R1 y R2 en el diagrama de circuito anterior son un divisor de voltaje que proporciona la fuente de 2,5 V (1,65 V para el emonTx). El condensador electrolítico C1 tiene una reactancia baja de unos pocos cientos de ohmios, y proporciona un camino para que la corriente alterna evite la resistencia. Un valor de 10 μF es adecuado por ejemplo de 100v.
Elegir un valor adecuado para las resistencias R1 y R2:
Una mayor resistencia reduce el consumo de energía en reposo por lo que podemos usar resistencias de 10 kΩ para monitores alimentados por la red. El emonTx utiliza resistencias de 470 kΩ para mantener el consumo de energía al mínimo, ya que está diseñado para funcionar con baterías durante varios meses.
Boceto de Arduino
Para usar el circuito descrito para medir la corriente RMS, con un voltaje RMS fijo asumido (por ejemplo, 240 V) para indicar la potencia aparente aproximada, podemos usar el siguiente código en Arduino:
// Include Emon Library
#include "EmonLib.h"
// Crear una instancia EnergyMonitor
EnergyMonitor energyMonitor;
// Voltaje de nuestra red eléctrica
float voltajeRed = 220.0;
void setup()
{
Serial.begin(9600);
// Iniciamos la clase indicando
// Número de pin: donde tenemos conectado el SCT-013
// Valor de calibración: valor obtenido de la calibración teórica
energyMonitor.current(0, 2.6);
}
void loop()
{
// Obtenemos el valor de la corriente eficaz
// Pasamos el número de muestras que queremos tomar
double Irms = energyMonitor.calcIrms(1484);
// Calculamos la potencia aparente
double potencia = Irms * voltajeRed;
// Mostramos la información por el monitor serie
Serial.print("Potencia = ");
Serial.print(potencia);
Serial.print(" Irms = ");
Serial.println(Irms);
}
Debe estar conectado para enviar un comentario.