Alimentador USB - Jusaba/Domo-Serverpic GitHub Wiki
Se va a describir en este apartado uno de los módulos más sencillos que nos ayudará a consolidar lo expuesto en el apartado de Dispositivos
Este dispositivo se trata de un conmutador controlado desde Serverpcic que intercalado entre un alimentador USB convencional ( con conector tipo A ) y su carga, permite la conexión/desconexión de la misma desde el entorno Serverpic, un ejemplo, podría ser una cámara que se alimente con un alimentados USB, podríamos apagarla y encenderla desde Serverpic.
El código de este dispositivo se puede descargar desde en este repositorio. En el repositorio se ha incluido los ficheros de Proteus con el hardware así como los Skectchup correspondientes al diseño 3D de la caja que se ha empleado.
En las siguientes fotografías se puede ver el módulo montado y preparado para funcionar
En el siguiente gráfico se puede ver el esqema del circuito, se ha excluido el tema de alimentación y conectores, el hardware real está incluido en el repositorio.
El circuito no tienen ningún secreto, se ha seleccioneado el módelo ESP-01 de la familia ESP8266 por que es el más sencillo y dispone de suficientes Pin`s de Entrada/salida, para este circuito tan solo se utiliza el pin GPIO2 como salida ( IO1 en el esquema ), ese pin controla un MOSFET como conmutador de carga. Como que GPIO2 en el arranque se pone por defecto a 1, para que no se conecte la carga del MOSFET será necesario invertir la loógica de control del MOSFET y para ello, intercalamos el transistor bipolar entre ESP-01 y MOSFET, ahora, deberemos tener en cuenta que para controlar la carga utilizaremos lógica negativa.
Cuando en el pin GPIO2 haya un uno, la carga conectada al dispositivo USB estará alimentada y por el contrario, cuando en GPIO2 haya un 0, la carga se desconectará
Por utilizar las librerías de Serverpcic el módulo tiene habilitadas todas las ordenes de servicio y, además, tiene las siguientes ordenes específicas de dispositivo
Comando | Descripcion |
---|---|
On | Conecta el dispositivo |
Off | Desconecta el dispositivo |
Change | Provoca un cambio de estado en el dispositivo |
ChangeGet | Provoca un cambio de estado en el dispositivo y manda mensaje a remitente con el nuevo estado |
Get | Manda mensaje a remitente con el estado actual del dispositivo |
Antes de que este dispositivo formara parte de la familia Outlet tenía un software específico y seguia fielmente la estructura del Módulo Básico, tan solo deberiamos incorporar el GPIO2 como pin de control, diseñar las fucniones de On y Off y desarrollar el bloque Interactua con Serverpic
Al incluirlo en la familia Outlet el software, si bien sigue la estructura del Módulo Básico, tiene varios condicionales para poder compatibilizar el resto de dispositivos de la familia-
De todas formas, a titulo ilustrativo, a continuación se detallan los distintos bloques de código del software especifico que ya no está en los repositorios.
Se hace una exposición detallada de ese software, se incluyen comentarios para complementar la explicación de la entrada anterior, en los próximos módulos, la descripción no será tan extensa, se expondrá unicamente las particularidades del dispositivo.
IO.h
#ifndef IO_H
#define IO_H
#ifdef ESP01
#define Modelo "ESP01"
int PinReset = 0;
int PinSalida = 2;
#endif
#ifdef ESP11
#define Modelo "ESP11"
int PinReset = 0;
int PinSalida = 2;
#endif
#ifdef ESP12
#define Modelo "ESP12"
int PinReset = 0;
int PinSalida = 12;
#endif
#endif
Este fichero establece los pin a utilizar, aunque puede utilizar otros modelos de ESP, en el diseño hemos utilizado el ESP01 y, como se puede ver, como pin de salida utilizadmos GPIO2
Serverpic.h
#ifndef SERVERPIC_H
#define SERVERPIC_H
//----------------------------------------------
//Includes
//----------------------------------------------
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include "Global.h"
#include "Configuracion.h"
#include "Eprom.h"
#include "ModoAP.h"
#include "ModoSTA.h"
#include "Servidor.h"
//----------------------------
//Declaracion de variables UNIVERSALES
//----------------------------
ESP8266WebServer server(80);
WiFiClient Cliente;
Telegrama oMensaje;
String cSalida;
String cDispositivo = String(' ');
boolean lEstado = 0;
boolean lConexionPerdida = 0;
boolean lHomeKit;
boolean lWebSocket ;
boolean lEstadisticas;
long nMiliSegundosTest = 0;
//----------------------------
//Declaracion de variables PARTICULARES
//----------------------------
//----------------------------
//CARACTERISTICAS DISPOSITIVO
//----------------------------
#define ESP01
#define Ino "AlimentadorUSB"
#define VIno "1.1"
#define Placa "ESP-01 POWER USB 1.0"
#define VBuild "6"
//---------------------------------
//CARACTERISTICAS DE LA COMPILACION
//---------------------------------
#define Compiler "Stino"; //Compilador
#define VCore "2.5.2"; //Versión del Core Arduino
#include "IO.h";
//----------------------------------------------
//DEBUG
//----------------------------------------------
//#define Debug
//----------------------------------------------
//HOME KIT
//----------------------------------------------
#define HomeKit
//----------------------------------------------
//Web Socket
//----------------------------------------------
#define WebSocket
//----------------------------------------------
//Teimpo de Test de conexion
//----------------------------------------------
#define TiempoTest 14000
//--------------------------------------------------------------------------
//Variables donde se almacenan los datos definidos anteriormente para
//pasarlos a Serverpic.h para mandar la información del Hardware
//y Software utilizados.
//En la libreria ServerPic.h estan definidos como datos externos y se
//utilizan en la funcion Mensaje () para responder al comando generico #Info.
//Con ese comando, el dispositivo mandara toda esta información al cliente
//que se lo pida
//ESTOS DATOS NO SON PARA MODIFICAR POR USUARIO
//--------------------------------------------------------------------------
//----------------------------
//Datos del programa principal
//----------------------------
String VMain = VIno;
String Main = Ino;
String VModulo = VBuild;
//----------------------------
//Datos de compilación
//----------------------------
String Compilador = Compiler;
String VersionCore = VCore;
//----------------------------
//Datos de Hardware
//----------------------------
String ModeloESP = Modelo;
String Board = Placa;
//----------------------------
//Funciones particulares
//----------------------------
/**
******************************************************
* @brief Devuelve el estado en el que se encuentra el dispositivo
*
* @param Devuelve 1 si el dispositivo esta en On, 0 en caso contrario
*/
boolean GetDispositivo (void)
{
boolean lEstadoDispositivo;
if ( digitalRead(PinSalida) == 0 )
{
lEstadoDispositivo = 1;
}else{
lEstadoDispositivo = 0;
}
return ( lEstadoDispositivo );
}
/**
******************************************************
* @brief Pone el dispositivo en On
*
*/
void DispositivoOn (void)
{
digitalWrite(PinSalida, LOW);
}
/**
******************************************************
* @brief Pone el dispositivo en OPff
*
*/
void DispositivoOff (void)
{
digitalWrite(PinSalida, HIGH);
}
#endif
Este fichero es muy similar al expuesto en el Módulo Básico.
No utiliza VARIABLES PARTICULARES, Las características del dispositivo son las propias de este dispositivo y por últinmo las funciones particulares, utiliza tres funciones muy sencillas, DispositivoOn, DispositivoOff y GetDispositivo que por su sencillez no se van a comentar, tan solo, observar el empleo de lógica negativa para encender/apagar la carga.
AlimentadorUSB.ino
El programa principal, a diferencia del Módulo Básico desarrolla los bloques encargados del análisis de mensaje recibido para la conexión/desconexión de la carga, empezamos por el bloque setup()
void setup() {
#ifdef Debug
Serial.begin(9600);
Serial.println("Iniciando........");
#endif
EEPROM.begin(128);
pinMode(PinReset, INPUT_PULLUP);
pinMode(PinSalida, OUTPUT); //Configuramos el pin del transistor como salida salida
DispositivoOff (); //Apagamos el dispositivo cuando arranca
if ( LeeByteEprom ( FlagConfiguracion ) == 0 )
{
ModoAP();
}else{
if ( ClienteSTA() )
{
if ( ClienteServerPic () )
{
CheckFirmware();
#ifdef Debug
Serial.println(" ");
Serial.println("Conectado al servidor");
#endif
DataConfig aCfg = EpromToConfiguracion ();
char USUARIO[1+aCfg.Usuario.length()];
(aCfg.Usuario).toCharArray(USUARIO, 1+1+aCfg.Usuario.length());
cDispositivo = USUARIO;
lHomeKit = aCfg.lHomeKit;
lWebSocket = aCfg.lWebSocket;
lEstadisticas = aCfg.lEstadisticas;
if ( lEstadisticas )
{
delay(200);
GrabaVariable ("inicios",1 + LeeVariable("inicios") );
delay(200);
}
cSalida = LeeValor();
if ( cSalida == "ERROR") //Si no tiene registrado ultimo valor
{ //por que es nuevo o por cualquier
DispositivoOn(); //otra causa, conectamos la carga
}else{ //Si si que se registro ultimo valor
if (cSalida == "On") //ponemos la carga tal como quedó
{ //cuando se desconecto el dispositivo
DispositivoOn();
}
if (cSalida == "Off")
{
DispositivoOff();
}
}
}
}
}
}
Se han comentado los bloques que se han añadido respecto al Módulo Básico
loop()
void loop() {
/*----------------
Comprobacion Reset
------------------*/
TestBtnReset (PinReset);
/*----------------
Comprobacion Conexion
------------------*/
if ( TiempoTest > 0 )
{
if ( millis() > ( nMiliSegundosTest + TiempoTest ) ) //Comprobamos si existe conexion
{
nMiliSegundosTest = millis();
if ( !TestConexion(lEstadisticas) ) //Si se ha perdido la conexion
{
lConexionPerdida = 1; //Flag de perdida conexion a 1
if ( GetDispositivo() ) //Si el dispositivo estaba a On
{
lEstado = 1; //Guardamos ese estado para
//recuperarlo en la reconexion
DispositivoOff(); //Ponemos a Off el dispositivo
}
}else{
if ( lConexionPerdida ) //Comprobamos si una reconexion
//( por perdida anterior )
{ //Si lo es
lConexionPerdida = 0; //Reseteamos flag de reconexion
digitalWrite(PinSalida, !lEstado); //Ponemos el dispositivo en el
//estado anterior a la perdida
//de conexion
lEstado = 0; //Reseteamos el Flag lEstado
}
}
}
}
/*----------------
Analisis comandos
------------------*/
oMensaje = Mensaje ();
if ( oMensaje.lRxMensaje) //Si se ha recibido ( oMensaje.lRsMensaje = 1)
{
#ifdef Debug
Serial.println(oMensaje.Remitente);
Serial.println(oMensaje.Mensaje);
#endif
//En este punto empieza el bloque de programa particular del dispositivo
if (oMensaje.Mensaje == "On") //Si se recibe "On", se pone PinSalida a '1'
{
DispositivoOn();
cSalida = "On"; //Preparamos el mensaje para enviar a HomeKit
//Y/o WebSocket
}
if (oMensaje.Mensaje == "Off") //Si se recibe "Off", se pone PinSalida a '0'
{
DispositivoOff();
cSalida = "Off"; //Preparamos el mensaje para enviar a HomeKit
//Y/o WebSocket
}
if (oMensaje.Mensaje == "Change") //Si se recibe 'Change',
{ //cambia el estado de PinSalida
if ( GetDispositivo() ) //Para ello, miramos el estado
{ //actual
DispositivoOff(); //y lo cambiamos
cSalida = "Off"; //Preparamos cSalida para
}else{ //para informar a HomeKit
DispositivoOn(); //y/o WebSocket
cSalida = "On";
}
}
if (oMensaje.Mensaje == "ChangeGet") //Si se recibe 'ChangeGet', cambia
//el estado de PinSalida y devuelve
//el nuevo estado al remitente
{
if ( GetDispositivo() )
{
DispositivoOff();
cSalida = "Off";
}else{
DispositivoOn();
cSalida = "On";
}
oMensaje.Mensaje = cSalida; //Confeccionamos el mensaje para el servidor
oMensaje.Destinatario = oMensaje.Remitente;
EnviaMensaje(oMensaje); //Y lo enviamos
}
if (oMensaje.Mensaje == "Get") //Si se recibe 'Get',
{ //se devuelve el estado de PinSalida al remitente
if ( GetDispositivo() )
{
cSalida = "On";
}else{
cSalida = "Off";
}
oMensaje.Mensaje = cSalida; //Confeccionamos el mensaje a para el servidor
oMensaje.Destinatario = oMensaje.Remitente;
EnviaMensaje(oMensaje);
cSalida = String(' '); //No ha habido cambio de estado,
//Vaciamos cSalida para que no se envie
//a WebSocket y a HomeKit
}
//--------------------------------------------------------------------
// Actualizacion ultimo valor
//--------------------------------------------------------------------
//Si hay cambio de estado, se lo indicamos al servidor para actualizar
//ultimo valor, daro que se usara para restablecer el dispositivo
//tras una desconexion no deseada ( fallo red electrica )
if ( cSalida != String(' ') )
{
EnviaValor (cSalida);
}
//--------------------------------------------------------------------
// Actualizacion WebSocket
//--------------------------------------------------------------------
//Si hay cambio de estado y está habilitado WebSocket se envia el
//nuevo estado a WebSocket
#ifdef WebSocket
if ( cSalida != String(' ') && lWebSocket )
{
EnviaMensajeWebSocket(cSalida);
}
#endif
//--------------------------------------------------------------------
// Actualizacion HomeKit
//--------------------------------------------------------------------
//Si hay cambio de estado y está habilitado HomeKit se envia el
//nuevo estado a HpmeKit
#ifdef HomeKit
if ( cSalida != String(' ') && oMensaje.Remitente != ( cDispositivo + String("_") ) && lHomeKit )
{
oMensaje.Destinatario = cDispositivo + String("_");
oMensaje.Mensaje = cSalida;
EnviaMensaje(oMensaje);
}
#endif
cSalida = String(' '); //Limpiamos cSalida para iniciar
//un nuevo analisis
if ( lEstadisticas ) //Si están habilitadas estadísticas
{ //Actualizamos numero comandos ejecutados
GrabaVariable ("comandos", 1 + LeeVariable("comandos") );
}
nMiliSegundosTest = millis(); //Refrescamos nMiliSegundosTest para no
//hacer test de conexión por que si se
//ha recibido mensaje es que hay conexion
}
wdt_reset(); //Refrescamos WDT
}
Para compilar AlimentadorUSB.ino se procede como de costumbre, en nuestro caso se ha utilizado Stino pero puede utilizarse el IDE de arduino.
Las conexiones se pueden ver en la siguente imagen
Las parametros para la compilación son los siguientes
Placa: Generic ESP8266 Module
CPU Frecuency: 80 MHZ
CRYSTAL Frecuency: 26 MHZ
Debug Level: none
Debug Port: Disabled
Esase Flash: Only sketch
Expressid FW: nonos-sdk 2.2.1 (legacy)
Exceptiosn: Disabled
Flash Frecuency: 40 MHZ
Flash Mode: DOUT ( compatible )
Flash Size: 1M(no SPIFFS)
IwIP Variant: v2 Lower Memory
Reset Method: ck
SSL SUport: ALL SSL chiphers (most compatible)
Upload Speed: 115200
VTables: Flash
Una vez compilado y cargado, la primera vez que se enciende, se crea la red Wifi Jusaba con password 24081960, nos conectamos a esa red y accedemos a la pagina de configuración 192.168.4.1, rellenamos los datos de configuración y enviamos el formulario, desconectamos y conectamos el dispositivo y si todo se ha realizado correctamente el dispositivo se conectará a Serverpic.
Lo primero que hará será chaquear si hay una versión de firmware publicada distinta a la que se le ha grabado y si es así, el dispositivo cargará la nueva versión.