Hola, estoy implementando un proyecto que es la continuación de otro ya existente. Estoy trabajando con un totalizador que envía por medio de un módulo bluetooth a una app los datos de consumo de distintas cargas eléctricas que se puedan conectar al mismo.
La mejora que intento hacer es tomar esos mismos datos y enviarlos a una página web alojada en un servidor local que diseñé con ese fin. La página web ya está lista, sin embargo, al ser nuevo en arduino, me he encontrado con muchas dificultades para programar el mismo.
La placa con que cuenta el proyecto original es un Arduino Mega, del cual se encuentran utilizados los 6 pines Rx y Tx. Mi idea es comunicarlo con un Módulo Wifi NodeMCU v3.0, vía serial, esto lo haré a través de la librería Sofware.Serial, utilizando 2 pines digitales. Adjunto el código original modificado por mi (creo que está bien).
#define SERIAL_OUTPUT 1
#if SERIAL_OUTPUT
# define SERIAL_BEGIN(...) Serial.begin(__VA_ARGS__)
# define SERIAL_PRINT(...) Serial.print(__VA_ARGS__)
# define SERIAL_PRINTLN(...) Serial.println(__VA_ARGS__)
#else
# define SERIAL_BEGIN(...)
# define SERIAL_PRINT(...)
# define SERIAL_PRINTLN(...)
#endif
#include "ModbusSensor.h"
#define MB_SERIAL_PORT &Serial1
#define MB_BAUDRATE 2400 // VELOCIDAD EN BITS * SEG
#define MB_BYTEFORMAT SERIAL_8N2
#define TxEnablePin 17 // PIN CONMUTADOR TX RX
#define ID_1 1
#define REFRESH_INTERVAL 500 // TIEMPO DE REFRESCO MS
#define WRITE_INTERVAL 200UL
#define KWH_2_WS 36000000
#define VOL_ADR 0x0000 // VOLTAJE.
#define CUR_ADR 0x0006 // CORRIENTE.
#define POW_ADR 0x000C // POTENCIA ACTIVA.
#define APO_ADR 0x0012 // Potencia Aparente.
#define PFA_ADR 0x001E // Factor de potencia.
#define FRE_ADR 0x0046 // Frecuencia.
#define PEN_ADR 0x0048 // ENERGIA IMPORTADA KWH
#define REN_ADR 0x004A // Energia exportada.
#define TEN_ADR 0x0156 // Energia activa Total.
#define TRE_ADR 0x0158 // Energia reactiva Total.
// factor de division
#define VOL_FAC 10
#define CUR_FAC 100
#define POW_FAC 10
#define PFA_FAC 100
#define FRE_FAC 10
#define ENE_FAC 100
modbusMaster MBserial(MB_SERIAL_PORT, TxEnablePin); // instance to collect data using Modbus protocol over RS485
//variables a pedir formato para comunicarse con scketch modbus sensor y pedir datos
modbusSensor volt(&MBserial, ID_1, VOL_ADR, CHANGE_TO_ZERO);
modbusSensor curr(&MBserial, ID_1, CUR_ADR, CHANGE_TO_ZERO);
modbusSensor pwr(&MBserial, ID_1, POW_ADR, CHANGE_TO_ZERO);
modbusSensor enrg(&MBserial, ID_1, PEN_ADR, HOLD_VALUE);
modbusSensor freq(&MBserial, ID_1, FRE_ADR, CHANGE_TO_ZERO);
modbusSensor aPwr(&MBserial, ID_1, APO_ADR, CHANGE_TO_ZERO);
modbusSensor pwrFact(&MBserial, ID_1, PFA_ADR, CHANGE_TO_ONE);
// generamos variables que puedan contener 16 bits dentro de ellas
uint16_t voltage, maxVoltage, minVoltage; // factor x10
uint16_t current, maxCurrent, minCurrent; // factor x100
uint16_t power, maxPower, minPower; // factor x10
uint16_t lastEnergy, energy, avgPower; // factor x100
uint16_t frequency, maxFreq, minFreq; // factor x100
uint16_t aPower, maxApower, minApower; // factor x10
uint16_t powerFactor, maxPF, minPF; // factor x100
// cuenta en milisegundos para hacer los intervalos de refresco escritura
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
// variable utilizada para ver si hay datos
boolean firstData;
// variable para enviar datos a travez de puerto serial
char buffer[10];
int contador=0;
void setup() {
Serial3.begin(9600);
SERIAL_BEGIN(9600);
//inicia serial 1 con caracteristicas especificadas antes
MBserial.begin(MB_BAUDRATE, MB_BYTEFORMAT, REFRESH_INTERVAL);
delay(95);
#include <SoftwareSerial.h>
SoftwareSerial mySerial(10, 11); // Debido a que los pines TX y RX se encuentran utilizados, se asignan como pines virtuales RX y TX, 10 y 11 respectivamente.
mySerial.begin(9600); //inicia comunicación serial con Node Mcu
// inicializa datos en cero
firstData = false;
power = 0;
maxPower = 0;
minPower = 0;
lastEnergy = 0;
energy = lastEnergy;
}
void loop() {
// abilita interrupciones en el programa
sei();
// si puerto serial1 disponible hace
if (MBserial.available()) {
// leemos variables desde modbus sensor y guardamos en variables ejemplo leemos volt que tiene un formato predefinido lo pedimos con un factor que puede ser 10 o 100 dependiendo de la variable para guardar como entero esta y lo guardamos en voltaje
voltage = volt.read(VOL_FAC);
current = curr.read(CUR_FAC);
power = pwr.read(POW_FAC);
aPower = aPwr.read(POW_FAC);
frequency = freq.read(FRE_FAC);
energy = enrg.read(ENE_FAC);
powerFactor = pwrFact.read(PFA_FAC);
if (!firstData) {
if (maxVoltage < voltage) maxVoltage = voltage;
if (minVoltage > voltage) minVoltage = voltage;
if (maxCurrent < current) maxCurrent = current;
if (minCurrent > current) minCurrent = current;
if (maxPower < power) maxPower = power;
if (minPower > power) minPower = power;
if (maxApower < aPower) maxApower = aPower;
if (minApower > aPower) minApower = aPower;
if (maxFreq < frequency) maxFreq = frequency;
if (minFreq > frequency) minFreq = frequency;
if (maxPower < power) maxPower = power;
if (minPower > power) minPower = power;
}
else {
maxVoltage = voltage;
minVoltage = voltage;
maxCurrent = current;
minCurrent = current;
maxPower = power;
minPower = power;
maxApower = aPower;
minApower = aPower;
maxFreq = frequency;
minFreq = frequency;
firstData = false;
}
}
// se saca una muestra de millisegundos para comprara
currentMillis = millis();
//si los milisegundos son mayores o iguales a intervalo se hace
if (currentMillis - previousMillis >= WRITE_INTERVAL) {
previousMillis = currentMillis;
firstData = true;
contador = contador+1;
// realentiza envio de buffer
if (contador >= 20){
SERIAL_PRINT(currentMillis / 1000);
SERIAL_PRINT(",");
SERIAL_PRINT((float)maxVoltage / VOL_FAC, 1);
SERIAL_PRINT(",");
SERIAL_PRINT((float)minVoltage / VOL_FAC, 1);
SERIAL_PRINT(",");
SERIAL_PRINT((float)maxCurrent / CUR_FAC, 2);
SERIAL_PRINT(",");
SERIAL_PRINT((float)minCurrent / CUR_FAC, 2);
SERIAL_PRINT(",");
SERIAL_PRINT((float)maxPower / POW_FAC, 2);
SERIAL_PRINT(",");
SERIAL_PRINT((float)minPower / POW_FAC, 2);
SERIAL_PRINT(",");
SERIAL_PRINT((float)maxApower / POW_FAC, 2);
SERIAL_PRINT(",");
SERIAL_PRINT((float)minApower / POW_FAC, 2);
SERIAL_PRINT(",");
SERIAL_PRINT((float)maxFreq / FRE_FAC, 2);
SERIAL_PRINT(",");
SERIAL_PRINT((float)minFreq / FRE_FAC, 2);
SERIAL_PRINT(",");
SERIAL_PRINT((float)powerFactor / ENE_FAC, 2);
SERIAL_PRINT(",");
SERIAL_PRINTLN((float)energy / ENE_FAC, 2);
Serial.println("enviando datos");
sprintf(buffer, "%d,%d,%d,%d,%d,%d",energy,maxVoltage,maxCurrent,maxPower,powerFactor,maxFreq);
Serial3.println(buffer);
sprintf(buffer, "%d,%d,%d,%d,%d,%d",energy,maxVoltage,maxCurrent,maxPower,powerFactor,maxFreq);
mySerial.println(buffer);
contador = 0;
}
Sin embargo, tengo problemas desarrollando el código de la placa NodeMCU, ya que tiene que conectar a wifi, recibir los datos vía serial y tomar esa información y subirla a la página web. Además de que los datos deben llegar de forma separada, por lo que el código se complica aún más. ¿Me podrían sugerir algún código que sirviera para tales efectos? De antemano, muchas gracias.
#include <ESP8266WiFi.h>
#include <SoftwareSerial.h>
String str = "";
const char separator = ',';
const int dataLength = 3;
int data[dataLength];
void setup()
{
Serial.begin(9600);
WiFi.disconnect();
Serial.println("Inicio. Intentando conectar a red.");
delay(3000);
WiFi.begin("my-net","");
while ((WiFi.status() == WL_CONNECTED)){
delay(300);
}
Serial.println("Conectado!");
}
void loop()
{
if (Serial.available())
{
str = Serial.readStringUntil('\n');
for (int i = 0; i < dataLength ; i++)
{
int index = str.indexOf(separator);
data[i] = str.substring(0, index).toInt();
str = str.substring(index + 1);
Serial.print("Recibido: ");
Serial.println(incomingByte, DEC);
}
DEBUG_ARRAY(data);
}