0% encontró este documento útil (0 votos)
38 vistas44 páginas

Informe

Cargado por

jose
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
38 vistas44 páginas

Informe

Cargado por

jose
Derechos de autor
© All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Informe sobre los trabajos realizados durante la práctica

empresarial – Ecuaplus
1. Investigación sobre posibles microcontroladores a utilizar.

ESP32-C3-MINI-1
ESP32-C3-MINI-1 es un módulo LE de Wi-Fi y Bluetooth de uso general. El amplio conjunto de periféricos
y un tamaño pequeño hacen de estos módulos una opción ideal para hogares inteligentes, automatización
industrial, cuidado de la salud, electrónica de consumo, etc.

El ESP32-C3-MINI-1 viene con una antena PCB y tiene dos variantes:

• Versión de 85 °C que integra el chip ESP32-C3FN4 y funciona a –40 ~ 85 °C

• Versión de 105 °C que integra el chip ESP32-C3FH4 y funciona a –40 ~ 105 °C

El chip ESP32-C3FN4 y el chip ESP32-C3FH4, ambos con una memoria flash de 4 MB, pertenecen a la misma
categoría, a saber, la serie de chips ESP32-C3. La serie de chips ESP32-C3 tiene un procesador de un solo
núcleo RISC-V de 32 bits. Integran un amplio conjunto de periféricos, que van desde UART, I2C, I2S,
periférico de control remoto, controlador LED PWM, controlador DMA general, controlador TWAI®,
controlador USB Serial/JTAG, sensor de temperatura y ADC. También incluye interfaces SPI, Dual SPI y
Quad SPI.

De acuerdo con el fabricante, las aplicaciones más comunes para estos chips son:
Diagrama de bloques del ESP32-C3-MINI-1

Disposición de pines
ESP32-C3-DevKitM-1
ESP32-C3-DevKitM-1 es una placa de desarrollo de nivel de entrada basada en ESP32-C3-MINI-1, un
módulo llamado así por su pequeño tamaño. Esta placa integra funciones completas de Wi-Fi y Bluetooth
LE.

La mayoría de los pines de E/S en el módulo ESP32-C3-MINI-1 están divididos en los encabezados de pines
en ambos lados de esta placa para facilitar la interfaz. Los desarrolladores pueden conectar periféricos
con cables puente o montar ESP32-C3-DevKitM-1 en una placa de prueba.
Descripción de sus componentes

Componente Descripción
ESP32-C3-MINI-1 ESP32-C3-MINI-1 es un módulo combinado Wi-Fi y Bluetooth LE de
propósito general que viene con una antena PCB. El núcleo de este
módulo es ESP32-C3FN4, un chip que tiene una memoria flash
integrada de 4 MB. Dado que el flash está empaquetado en el chip
ESP32-C3FN4, en lugar de estar integrado en el módulo, ESP32-C3-
MINI-1 tiene un tamaño de paquete más pequeño.
5 V to 3.3 V LDO Regulador de potencia que convierte una fuente de 5 V en una salida
de 3,3 V.
5 V Power On LED Se enciende cuando la alimentación USB está conectada a la placa.
Pin Headers Todos los pines GPIO disponibles (excepto el bus SPI para flash) se
dividen en los encabezados de pines en la placa.
Boot Button Todos los pines GPIO disponibles (excepto el bus SPI para flash) se
dividen en los encabezados de pines en la placa.
Micro-USB Port Interfaz USB. Fuente de alimentación para la placa, así como la interfaz
de comunicación entre una computadora y el chip ESP32-C3FN4.
Reset Button Este botón se pulsa para reiniciar el sistema.
USB-to-UART Bridge El chip de puente USB-UART único proporciona velocidades de
transferencia de hasta 3 Mbps.
RGB LED RGB LED

Diagrama de bloques del ESP32-C3-DevKitM-1


Disposición de pines

Modulo TTGO T-Display ESP32 Wifi


El módulo ESP32 TTGO T-Display 1.14 Inch, cuenta con una pantalla IPS ST7789V 1.14″ una resolución de
135X240 por protocolo SPI, este módulo cuenta con un USB tipo C para su programación.

Especificaciones de hardware Descripción


ESPRESSIF-ESP32 Microprocesador LX6 de 32 bits de 240 MHz
conjunto de chips
Xtensa® de doble núcleo
DESTELLO Flash QSPI 4MB/16MB (Opcional)
SRAM 520 kB SRAM
Botón Reiniciar
USB a TTL CP2104 /CH340K / CH9102F (opcional)
UART, SPI, SDIO, I2C, LED PWM, TV PWM, I2S, IRGPIO,ADC, sensor
Interfaz
táctil de condensador, preamplificador DACLNA
Monitor IP ST7789V 1.14 Inch Resolución 135 * 240
Tensión de trabajo 2.7V-4.2V
Corriente de trabajo Acerca de 60mA
Corriente de sueño Acerca de 120uA
Rango de temperatura de trabajo -40C~+85°C
Tamaño y peso 51,52 x 25,04 x 8,54 mm (7,81 g)
Fuente de alimentación Descripción
Fuente de alimentación USB 5V/1A
Corriente de carga 500mA
Batería batería de litio de 3,7 V
JST Conector 2Pin 1.25mm
USB Tipo-C
Wifi Descripción
Estándar FCC/CE-RED/IC/TELEC/KCC/SRRC/NCC
802.11 b/g/n (802.11n, velocidad de hasta 150 Mbps) Polimerización A-
Protocolo
MPDU y A-MSDU, compatible con intervalo de protección de 0,4 us
Rango de frecuencia 2.4GH2~2.5GHz(2400M-2483.5M)
Potencia de transmisión 22dBm
Distancia de comunicación 300m
Bluetooth Descripción
Protocolo Admite bluetooth V4.2BR/EDR y estándar BLE
Con -97dBm de sensibilidad Receptor NZIF Clase-1, Clase-2 y Clase-3
Frecuencia de radio
emisor AFH
Frecuencia de audio Frecuencia de audio CVSD y SBC
Software Descripción
modo wifi Estación/SoftAP/SoftAP+Estación/P2P
mecanismo de seguridad WPA/WPA2/WPA2-Empresa/WPS
Cifrado Tipo AES/RSA/ECC/SHA
Descarga UART/OTA (a través de la red/host para descargar y escribir
Actualización de firmware
firmware)
Admite el desarrollo de servidores en la nube/SDK para el desarrollo de
Desarrollo de software
firmware de usuario
protocolo de red IPv4, IPv6, SSL, TCP/UDP/HTTP/FTP/MQTT
Conjunto de instrucciones AT +, servidor en la nube, aplicación
Configuración de usuario
Android/isistema operativo
sistema operativo FreeRTsistema operativo

Disposición de pines

Contiene software IoT:

• Arduino IDE version 1.8.13 / Boards esp8266 v2.74 / Boards esp32 v10.4
• Node-RED version 1.2.7
• Grafana-server version 7.3.7
• Influxdb version 1.8.3
• Chirpstack version 3.13.2
• ESP-IDF version 4.3-dev-2586-g526f68239
• MySQL version 8.0.22
• Mosquitto Broken MQTT version 1.6.9

LILYGO T5-4.7 inch E-paper ESP32 V3


16MB FLASH 8MB PSRAM WIFI BLE
Development board
El papel electrónico T5 de 4,7 pulgadas es otra versión de la serie T5 de pantallas de tinta electrónica.

La serie T5 de versiones de pantalla de tinta incluye 1,02, 1,54, 2,13, etc., de versiones de pantalla de tinta
electrónica pequeña a grande.

Esta versión de 4,7 pulgadas continúa con el diseño de baja potencia, la corriente del modo de suspensión
es de aproximadamente 170uA y dos modos de batería opcionales están diseñados en la parte posterior.

Una es la interfaz de paso 2pin PH 2,0, y la otra es un conector de metal de batería 18650.

Dos modos de alimentación.

Una interfaz de pantalla táctil de 6 pines está reservada como accesorio opcional para facilitar su
aplicación.

Hay 5 botones reservados en el lateral, 3 de los cuales son botones personalizados, que pueden definir
las funciones de forma flexible. Uno es el botón de Reinicio.
Disposición de pines

Descripción del producto:

-ESP32-WROVER-E (ESP32-D0WDQ6 V3)

-FLASH DE 16 MB

-PSRAM 8MB

-USB a TTL CP2104

-4,7 pulgadas, resolución de 540(H)X960(V), 16 niveles de gris ED047C1 y admite actualización parcial.

-Resolución 960X540 Puerto paralelo de 8 bits Pantalla de tinta de 4,7 pulgadas

-4pin 2.0 molex 4 p 53015-0410 X3

-Primer botón X1

-Botón personalizado X3

-TIPO-C

-Porta pilas PH 2.0 paso

-Conector metálico de batería 18650


-Conector de expansión de pantalla táctil FPC de 6 pines

-Chip de protección de carga y descarga de batería

-Alimentación de entrada USB 5V @ 1A

-La salida de la interfaz de expansión de 4 pines es de 3,3 V

-Modo de suspensión actual @ ~ 170uA

Desarrollo de software en:

-arduino

-FDI

-Micropython

Escenario de aplicación:

-Estación meteorológica de escritorio

-Educación STEM

-Dispositivo IoT

Información básica de la cubierta de pantalla táctil capacitiva de 4,7 pulgadas:

Se adapta al papel electrónico T5-4,7 pulgadas usando directamente la pantalla táctil del teléfono móvil y
modificando el controlador.

- Chip táctil: L58

- Marco de cristal blanco

- Soporte multitáctil
2. Medición de magnitudes eléctricas mediante un medidor energético PZEM, un ESP8266 .
- Se utilizan 3 PZEM-017 parala medición de parámetros DC, y 1 PZEM-016 para la medición de
parámetros AC.
- Se usa un MAX485 UART TTL RS485 converter para permitir la comunicación del PZEM-016
con el ESP8266.

Circuito de los componentes a utilizar

Código para configurar la dirección para la comunicación con cada uno de los PZEM

// Set Address for PZEM Series Energy Meter By Solarduino

// Note Summary

// Note : Safety is very important when dealing with electricity. We take no responsibilities while
you do it at your own risk.

// Note : This code is to allow user to set or change address of a PZEM Energy Meter. It can be
used for DC and AC Energy Meter.

// Note : You need to download and install (modified) Modbus Master library at our website
([Link] )

// Note : You need to download the Blynk App on your smart phone for display.

// Note : The Core of the code was from [Link] 2018 which based on the example from
[Link]
// Note : Blog page for this code : [Link]
together-using-blynk-app-for-nodemcu/

/*///////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////*/////////////*/

/* Virtual Serial Port */

#include <SoftwareSerial.h> /* include virtual Serial Port coding */

SoftwareSerial PZEMSerial; // Move the PZEM DC Energy Meter communication


pins from Rx to pin D1 = GPIO 5 & TX to pin D2 = GPIO 4

/* 1- PZEM-Energy Meter */

#include <ModbusMaster.h> // Load the (modified) library for modbus


communication command codes. Kindly install at our website.

#define MAX485_DE 16 // Define DE Pin to Arduino pin. Connect DE Pin of


Max485 converter module to Pin D0 (GPIO 16) Node MCU board

#define MAX485_RE 5 // Define RE Pin to Arduino pin. Connect RE Pin of


Max485 converter module to Pin D1 (GIPO 5) Node MCU board

// These DE anr RE pins can be any other Digital Pins to be


activated during transmission and reception process.

static uint8_t address = 0x02; // Variable for Address. Kindly set address here.

ModbusMaster node; /* activate modbus master codes*/

unsigned long startMillis1 ; /* Count time for transmission*/

unsigned long startMillis2 ; /* Count time for set address*/

void setup()

startMillis1 = millis();

startMillis2 = millis();
[Link](9600); /* To assign communication port to communicate with
meter. with 2 stop bits (refer to manual)*/

[Link](9600,SWSERIAL_8N2,4,0); // R0 connect to GPIO 4 (D2) & DI connect


to GPIO 0 (D3) on NodeMCU

[Link](preTransmission); // Callbacks allow us to configure the RS485


transceiver correctly

[Link](postTransmission);

void loop()

if(millis() - startMillis2 > 10000) // Every 10 second set the


address of the meter

{changeAddress(0XF8, address); // Activate change the


address

startMillis2 = millis();

void changeAddress(uint8_t OldslaveAddr, uint8_t NewslaveAddr) //Change


the slave address of a node

static uint8_t SlaveParameter = 0x06; /* Write command


code to PZEM */

static uint16_t registerAddress = 0x0002; /* Modbus RTU


device address command code */

uint16_t u16CRC = 0xFFFF; /* declare CRC check 16


bits*/

u16CRC = crc16_update(u16CRC, OldslaveAddr); // Calculate


the crc16 over the 6bytes to be send

u16CRC = crc16_update(u16CRC, SlaveParameter);


u16CRC = crc16_update(u16CRC, highByte(registerAddress));

u16CRC = crc16_update(u16CRC, lowByte(registerAddress));

u16CRC = crc16_update(u16CRC, highByte(NewslaveAddr));

u16CRC = crc16_update(u16CRC, lowByte(NewslaveAddr));

preTransmission(); /* trigger transmission mode*/

delay(10);

[Link](OldslaveAddr); /* these whole


process code sequence refer to manual*/

[Link](SlaveParameter);

[Link](highByte(registerAddress));

[Link](lowByte(registerAddress));

[Link](highByte(NewslaveAddr));

[Link](lowByte(NewslaveAddr));

[Link](lowByte(u16CRC));

[Link](highByte(u16CRC));

delay(10);

postTransmission(); /* trigger reception mode*/

delay(100);

while ([Link]()) /* while receiving signal


from Serial3 from meter and converter */

[Link]("Address Changed Successful...");

void preTransmission() /* transmission pro gram


when triggered*/
{

/* 1- PZEM-017 DC Energy Meter */

if(millis() - startMillis1 > 5000) // Wait for 5 seconds as ESP


Serial cause start up code crash

digitalWrite(MAX485_RE, 1); /* put RE Pin to high*/

digitalWrite(MAX485_DE, 1); /* put DE Pin to high*/

delay(1); // When both RE and DE Pin are


high, converter is allow to transmit communication

void postTransmission() /* Reception program when


triggered*/

/* 1- PZEM-017 DC Energy Meter */

if(millis() - startMillis1 > 5000) // Wait for 5 seconds as


ESP Serial cause start up code crash

delay(3); // When both RE and DE Pin are


low, converter is allow to receive communication

digitalWrite(MAX485_RE, 0); /* put RE Pin to low*/

digitalWrite(MAX485_DE, 0); /* put DE Pin to low*/

Código para el medidor de energía


#include "Ubidots.h"
#include <SoftwareSerial.h>
SoftwareSerial PZEMSerial;
#include <ESP8266WiFi.h>
//char ssid[] = "";
//char pass[] = "";

//---------------------------------------------------------UBIDOTS INIT VARS-------------------------------------------


------------------------
#define DEVICE "dc4f2218xxx"
//#define VARIABLE "var_led"

#define ID_volt "voltage_1"


#define ID_curr "current_1"
#define ID_pow "power_1"
#define ID_en "energy_1"

#define ID_volt2 "voltage_2"


#define ID_curr2 "current_2"
#define ID_pow2 "power_2"
#define ID_en2 "energy_2"

#define ID_volt3 "voltage_3"


#define ID_curr3 "current_3"
#define ID_pow3 "power_3"
#define ID_en3 "energy_3"

#define ID_volt4 "voltage_4"


#define ID_curr4 "current_4"
#define ID_pow4 "power_4"
#define ID_en4 "energy_4"
#define ID_freq "freq_4"
#define ID_pf "power_factor"

#define TOKEN "BBFF-q9rp4TVHMv7dAj4ThWiDDw1pm0jq8H" // Put here your Ubidots TOKEN


#define WIFISSID "XTRIM_PATINO" // Put here your Wi-Fi SSID
#define PASSWORD "18100918" // Put here your Wi-Fi password

Ubidots client(TOKEN);

//-----------------------------------------------------------------------------------------------------------------------------
----------------
/* 1- PZEM-017 DC Energy Meter */

#include <ModbusMaster.h> // Load the (modified) library for modbus


communication command codes. Kindly install at our website.

#define MAX485_DE 16 // Define DE Pin to Arduino pin. Connect DE Pin of


Max485 converter module to Pin D0 (GPIO 16) Node MCU board
#define MAX485_RE 5 // Define RE Pin to Arduino pin. Connect RE Pin of
Max485 converter module to Pin D1 (GIPO 5) Node MCU board
// These DE anr RE pins can be any other Digital Pins to be activated
during transmission and reception process.

//PZEM 017 - 1
static uint8_t pzemSlaveAddr = 0x01; // Declare the address of device (meter 1) in term
of 8 bits.
static uint16_t NewshuntAddr = 0x0000; // Declare your external shunt value for DC
Meter. Default 0x0000 is 100A, replace to "0x0001" if using 50A shunt, 0x0002 is for 200A, 0x0003
is for 300A

//PZEM 017 - 2
static uint8_t pzemSlaveAddr2 = 0x02; // Declare the address of device (meter 1) in term
of 8 bits.
static uint16_t NewshuntAddr2 = 0x0000; // Declare your external shunt value for DC
Meter. Default 0x0000 is 100A, replace to "0x0001" if using 50A shunt, 0x0002 is for 200A, 0x0003
is for 300A

//PZEM 017 - 3
static uint8_t pzemSlaveAddr3 = 0x03; // Declare the address of device (meter 1) in term
of 8 bits.
static uint16_t NewshuntAddr3 = 0x0000; // Declare your external shunt value for DC
Meter. Default 0x0000 is 100A, replace to "0x0001" if using 50A shunt, 0x0002 is for 200A, 0x0003
is for 300A

//PZEM 016
static uint8_t pzemSlaveAddr4 = 0x04; // Declare the address of device (meter 1) in term
of 8 bits.

ModbusMaster node; /* activate modbus master codes*/


ModbusMaster node2; /* activate modbus master codes*/
ModbusMaster node3; /* activate modbus master codes*/
ModbusMaster node4; /* activate modbus master codes*/

// Values for PZEM 017 - 1


float PZEMVoltage =0; /* Declare value for DC voltage */
float PZEMCurrent =0; /* Declare value for DC current*/
float PZEMPower =0; /* Declare value for DC Power */
float PZEMEnergy=0; /* Declare value for DC Energy */

// Values for PZEM 017 - 2


float PZEMVoltage2 =0; /* Declare value for DC voltage */
float PZEMCurrent2 =0; /* Declare value for DC current*/
float PZEMPower2 =0; /* Declare value for DC Power */
float PZEMEnergy2 =0; /* Declare value for DC Energy */

// Values for PZEM 017 - 3


float PZEMVoltage3 =0; /* Declare value for DC voltage */
float PZEMCurrent3 =0; /* Declare value for DC current*/
float PZEMPower3 =0; /* Declare value for DC Power */
float PZEMEnergy3 =0; /* Declare value for DC Energy */

// Values for PZEM 016


float PZEMVoltage4 =0; /* Declare value for AC voltage */
float PZEMCurrent4 =0; /* Declare value for AC current*/
float PZEMPower4 =0; /* Declare value for AC Power */
float PZEMEnergy4 =0; /* Declare value for energy */
float PZEMHz =0; /* Declare value for frequency */
float PZEMPf=0;

unsigned long startMillisPZEM; /* start counting time for LCD Display */


unsigned long currentMillisPZEM; /* current counting time for LCD Display */
unsigned long startMilliSetShunt;
const unsigned long periodPZEM = 500; // refresh every X seconds (in seconds) in LED
Display. Default 1000 = 1 second

unsigned long startMillis1; // to count time during initial start up (PZEM Software
got some error so need to have initial pending time)
unsigned long startMillisReadData; /* start counting time for data collection */
unsigned long currentMillisReadData; /* current counting time for data collection */
const unsigned long periodReadData = 1000; /* refresh every X seconds (in seconds) in LED
Display. Default 1000 = 1 second */
int a = 0;

void setup() {
// put your setup code here, to run once:

[Link](WIFISSID, PASSWORD);

startMillis1 = millis();
[Link](9600); /* To assign communication port to communicate with
meter. with 2 stop bits (refer to manual)*/
[Link](9600,SWSERIAL_8N2,4,0); // 4 = Rx/R0/ GPIO 4 (D2) & 0 = Tx/DI/ GPIO
0 (D3) on NodeMCU
startMilliSetShunt = millis();

/* 1- PZEM-017 DC Energy Meter */

startMillisPZEM = millis(); /* Start counting time for run code */


pinMode(MAX485_RE, OUTPUT); /* Define RE Pin as Signal Output for RS485
converter. Output pin means Arduino command the pin signal to go high or low so that signal is
received by the converter*/
pinMode(MAX485_DE, OUTPUT); /* Define DE Pin as Signal Output for RS485
converter. Output pin means Arduino command the pin signal to go high or low so that signal is
received by the converter*/
digitalWrite(MAX485_RE, 0); /* Arduino create output signal for pin RE as LOW
(no output)*/
digitalWrite(MAX485_DE, 0); /* Arduino create output signal for pin DE as LOW
(no output)*/
// both pins no output means the converter is in communication
signal receiving mode

[Link](preTransmission); // Callbacks allow us to configure the RS485


transceiver correctly
[Link](postTransmission);
[Link](preTransmission); // Callbacks allow us to configure the RS485
transceiver correctly
[Link](postTransmission);
[Link](preTransmission); // Callbacks allow us to configure the RS485
transceiver correctly
[Link](postTransmission);
[Link](preTransmission); // Callbacks allow us to configure the RS485
transceiver correctly
[Link](postTransmission);

//[Link](pzemSlaveAddr,PZEMSerial);
delay(1000); /* after everything done, wait for 1 second */

startMillisReadData = millis();
}

void loop() {
// put your main code here, to run repeatedly:

currentMillisPZEM = millis();

/* 3- Set Shunt */
if (millis()- startMilliSetShunt == 10000)
{setShunt(0x01);}
if (millis()-startMilliSetShunt == 15000)
{setShunt2(0x02);}
if (millis()-startMilliSetShunt == 20000)
{setShunt3(0x03);}

// By default I allow this code to run every program startup. Will not
have effect if you only have 1 meter

/* 1- PZEM-017 DC Energy Meter */

if(a == 0)
{
[Link](pzemSlaveAddr, PZEMSerial); /* Define and start
the Modbus RTU communication. Communication to specific slave address and which Serial port
*/
if (currentMillisPZEM - startMillisPZEM >= periodPZEM) /* for every x
seconds, run the codes below*/
{
uint8_t result; /* Declare variable "result" as 8 bits
*/
result = [Link](0x0000, 6); /* read the 9 registers
(information) of the PZEM-014 / 016 starting 0x0000 (voltage information) kindly refer to
manual)*/
if (result == node.ku8MBSuccess) /* If there is a response */
{
uint32_t tempdouble = 0x00000000; /* Declare variable
"tempdouble" as 32 bits with initial value is 0 */
PZEMVoltage = [Link](0x0000) / 100.0; /* get the
16bit value for the voltage value, divide it by 100 (as per manual)- 0x0000 to 0x0008 are the
register address of the measurement value*/
PZEMCurrent = [Link](0x0001) / 100.0; /* get the
16bit value for the current value, divide it by 100 (as per manual) */
tempdouble = ([Link](0x0003) << 16) + [Link](0x0002);
/* get the power value. Power value is consists of 2 parts (2 digits of 16 bits in front and 2 digits
of 16 bits at the back) and combine them to an unsigned 32bit */
PZEMPower = tempdouble / 10.0; /* Divide the value by 10
to get actual power value (as per manual) */
tempdouble = ([Link](0x0005) << 16) + [Link](0x0004);
/* get the energy value. Energy value is consists of 2 parts (2 digits of 16 bits in front and 2 digits
of 16 bits at the back) and combine them to an unsigned 32bit */
PZEMEnergy = tempdouble;
}
if (pzemSlaveAddr==5) /* just for checking purpose to
see whether can read modbus*/
{}
else
{}
a = 1;
startMillisPZEM = currentMillisPZEM ;
}
}

if(a ==1)
{
[Link](pzemSlaveAddr2, PZEMSerial);
if (currentMillisPZEM - startMillisPZEM >= periodPZEM) /* for every x
seconds, run the codes below*/
{
uint8_t result2; /* Declare variable "result" as 8
bits */
result2 = [Link](0x0000, 6); /* read the 9
registers (information) of the PZEM-014 / 016 starting 0x0000 (voltage information) kindly refer
to manual)*/
if (result2 == node2.ku8MBSuccess) /* If there is a response
*/
{
uint32_t tempdouble2 = 0x00000000; /* Declare variable
"tempdouble" as 32 bits with initial value is 0 */
PZEMVoltage2 = [Link](0x0000) / 100.0; /* get the
16bit value for the voltage value, divide it by 100 (as per manual)- 0x0000 to 0x0008 are the
register address of the measurement value*/
PZEMCurrent2 = [Link](0x0001) / 100.0; /* get the
16bit value for the current value, divide it by 100 (as per manual) */
tempdouble2 = ([Link](0x0003) << 16) +
[Link](0x0002); /* get the power value. Power value is consists of 2 parts
(2 digits of 16 bits in front and 2 digits of 16 bits at the back) and combine them to an unsigned
32bit */
PZEMPower2 = tempdouble2 / 10.0; /* Divide the value by
10 to get actual power value (as per manual) */
tempdouble2 = ([Link](0x0005) << 16) +
[Link](0x0004); /* get the energy value. Energy value is consists of 2 parts
(2 digits of 16 bits in front and 2 digits of 16 bits at the back) and combine them to an unsigned
32bit */
PZEMEnergy2 = tempdouble2;
}
if (pzemSlaveAddr==5) /* just for checking purpose to
see whether can read modbus*/
{}
else
{}
a=2;
startMillisPZEM = currentMillisPZEM ;
}
}

if(a ==2)
{
[Link](pzemSlaveAddr3, PZEMSerial);
if (currentMillisPZEM - startMillisPZEM >= periodPZEM) /* for every x
seconds, run the codes below*/
{
uint8_t result3; /* Declare variable "result" as 8
bits */
result3 = [Link](0x0000, 6); /* read the 9
registers (information) of the PZEM-014 / 016 starting 0x0000 (voltage information) kindly refer
to manual)*/
if (result3 == node3.ku8MBSuccess) /* If there is a response
*/
{
uint32_t tempdouble3 = 0x00000000; /* Declare variable
"tempdouble" as 32 bits with initial value is 0 */
PZEMVoltage3 = [Link](0x0000) / 100.0; /* get the
16bit value for the voltage value, divide it by 100 (as per manual)- 0x0000 to 0x0008 are the
register address of the measurement value*/
PZEMCurrent3 = [Link](0x0001) / 100.0; /* get the
16bit value for the current value, divide it by 100 (as per manual) */
tempdouble3 = ([Link](0x0003) << 16) +
[Link](0x0002); /* get the power value. Power value is consists of 2 parts
(2 digits of 16 bits in front and 2 digits of 16 bits at the back) and combine them to an unsigned
32bit */
PZEMPower3 = tempdouble3 / 10.0; /* Divide the value by
10 to get actual power value (as per manual) */
tempdouble3 = ([Link](0x0005) << 16) +
[Link](0x0004); /* get the energy value. Energy value is consists of 2 parts
(2 digits of 16 bits in front and 2 digits of 16 bits at the back) and combine them to an unsigned
32bit */
PZEMEnergy3 = tempdouble3;
}
if (pzemSlaveAddr==5) /* just for checking purpose to
see whether can read modbus*/
{}
else
{}
a=3;
startMillisPZEM = currentMillisPZEM ;
}
}

if(a ==3)
{
[Link](pzemSlaveAddr4, PZEMSerial);
if (currentMillisPZEM - startMillisPZEM >= periodPZEM) /* for every x
seconds, run the codes below*/
{
uint8_t result4; /* Declare variable "result" as 8 bits
*/
result4 = [Link](0x0000, 9); /* read the 9 registers
(information) of the PZEM-014 / 016 starting 0x0000 (voltage information) kindly refer to
manual)*/
if (result4 == node4.ku8MBSuccess) /* If there is a response
*/
{
uint32_t tempdouble4 = 0x00000000; /* Declare variable
"tempdouble" as 32 bits with initial value is 0 */
PZEMVoltage4 = [Link](0x0000) / 10.0; /* get the
16bit value for the voltage value, divide it by 10 (as per manual) */
// 0x0000 to 0x0008 are the register
address of the measurement value
tempdouble4 = ([Link](0x0002) << 16) +
[Link](0x0001); /* get the currnet value. Current value is consists of 2 parts
(2 digits of 16 bits in front and 2 digits of 16 bits at the back) and combine them to an unsigned
32bit */
PZEMCurrent4 = tempdouble4 / 1000.00; /* Divide the value
by 1000 to get actual current value (as per manual) */
tempdouble4 = ([Link](0x0004) << 16) +
[Link](0x0003); /* get the power value. Power value is consists of 2 parts (2
digits of 16 bits in front and 2 digits of 16 bits at the back) and combine them to an unsigned 32bit
*/
PZEMPower4 = tempdouble4 / 10.0; /* Divide the value by
10 to get actual power value (as per manual) */
tempdouble4 = ([Link](0x0006) << 16) +
[Link](0x0005); /* get the energy value. Energy value is consists of 2 parts (2
digits of 16 bits in front and 2 digits of 16 bits at the back) and combine them to an unsigned 32bit
*/
PZEMEnergy4 = tempdouble4;
PZEMHz = [Link](0x0007) / 10.0; /* get the 16bit
value for the frequency value, divide it by 10 (as per manual) */
PZEMPf = [Link](0x0008) / 100.00; /* get the 16bit
value for the power factor value, divide it by 100 (as per manual) */
}
if (pzemSlaveAddr==5) /* just for checking purpose to
see whether can read modbus*/
{}

else
{}
a=0;
startMillisPZEM = currentMillisPZEM ;
}
}
currentMillisReadData = millis(); /* Set counting time for data
submission to server*/
if (currentMillisReadData - startMillisReadData >= periodReadData) /* for every
x seconds, run the codes below*/
{
[Link]("Energy Meter 1 : ");
[Link]("Vdc : "); [Link](PZEMVoltage); [Link](" V ");
[Link]("Idc : "); [Link](PZEMCurrent); [Link](" A ");
[Link]("Power : "); [Link](PZEMPower); [Link](" W ");
[Link]("Energy : "); [Link](PZEMEnergy); [Link](" Wh ");

[Link]("Energy Meter 2 : ");


[Link]("Vdc : "); [Link](PZEMVoltage2); [Link](" V ");
[Link]("Idc : "); [Link](PZEMCurrent2); [Link](" A ");
[Link]("Power : "); [Link](PZEMPower2); [Link](" W ");
[Link]("Energy : "); [Link](PZEMEnergy2); [Link](" Wh ");

[Link]("Energy Meter 3 : ");


[Link]("Vdc : "); [Link](PZEMVoltage3); [Link](" V ");
[Link]("Idc : "); [Link](PZEMCurrent3); [Link](" A ");
[Link]("Power : "); [Link](PZEMPower3); [Link](" W ");
[Link]("Energy : "); [Link](PZEMEnergy3); [Link](" Wh ");

[Link]("Energy Meter 4 : ");


[Link]("Vac : "); [Link](PZEMVoltage4); [Link](" V ");
[Link]("Iac : "); [Link](PZEMCurrent4); [Link](" A ");
[Link]("Power : "); [Link](PZEMPower4); [Link](" W ");
[Link]("Energy : "); [Link](PZEMEnergy4); [Link](" Wh ");
[Link]("Power Factor : "); [Link](PZEMPf); [Link](" pF ");
[Link]("Frequency : "); [Link](PZEMHz); [Link](" Hz ");

[Link](ID_volt, PZEMVoltage);
[Link](ID_curr, PZEMCurrent);
[Link](ID_en, PZEMPower);
[Link](ID_pow, PZEMEnergy);

[Link](ID_volt2, PZEMVoltage2);
[Link](ID_curr2, PZEMCurrent2);
[Link](ID_en2, PZEMPower2);
[Link](ID_pow2, PZEMEnergy2);
[Link](ID_volt3, PZEMVoltage3);
[Link](ID_curr3, PZEMCurrent3);
[Link](ID_en3, PZEMPower3);
[Link](ID_pow3, PZEMEnergy3);

[Link](ID_volt4, PZEMVoltage4);
[Link](ID_curr4, PZEMCurrent4);
[Link](ID_en4, PZEMPower4);
[Link](ID_pow4, PZEMEnergy4);
[Link](ID_freq, PZEMPf);
[Link](ID_pf, PZEMHz);

[Link]();
delay(5000);
startMillisReadData = millis();

//-----------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------

void preTransmission() /* transmission program


when triggered*/
{
/* 1- PZEM-017 DC Energy Meter */
if(millis() - startMillis1 > 5000) // Wait for 5 seconds as ESP
Serial cause start up code crash
{
digitalWrite(MAX485_RE, 1); /* put RE Pin to high*/
digitalWrite(MAX485_DE, 1); /* put DE Pin to high*/
delay(1); // When both RE and DE Pin are
high, converter is allow to transmit communication
}
}

void postTransmission() /* Reception program when


triggered*/
{

/* 1- PZEM-017 DC Energy Meter */


if(millis() - startMillis1 > 5000) // Wait for 5 seconds as ESP
Serial cause start up code crash
{
delay(3); // When both RE and DE Pin are
low, converter is allow to receive communication
digitalWrite(MAX485_RE, 0); /* put RE Pin to low*/
digitalWrite(MAX485_DE, 0); /* put DE Pin to low*/
}
}

void setShunt(uint8_t slaveAddr) //Change the slave


address of a node
{

/* 1- PZEM-017 DC Energy Meter */

static uint8_t SlaveParameter = 0x06; /* Write command


code to PZEM */
static uint16_t registerAddress = 0x0003; /* change shunt
register address command code */

uint16_t u16CRC = 0xFFFF; /* declare CRC check 16


bits*/
u16CRC = crc16_update(u16CRC, slaveAddr); // Calculate the
crc16 over the 6bytes to be send
u16CRC = crc16_update(u16CRC, SlaveParameter);
u16CRC = crc16_update(u16CRC, highByte(registerAddress));
u16CRC = crc16_update(u16CRC, lowByte(registerAddress));
u16CRC = crc16_update(u16CRC, highByte(NewshuntAddr));
u16CRC = crc16_update(u16CRC, lowByte(NewshuntAddr));

preTransmission(); /* trigger transmission mode*/


[Link](slaveAddr); /* these whole process
code sequence refer to manual*/
[Link](SlaveParameter);
[Link](highByte(registerAddress));
[Link](lowByte(registerAddress));
[Link](highByte(NewshuntAddr));
[Link](lowByte(NewshuntAddr));
[Link](lowByte(u16CRC));
[Link](highByte(u16CRC));
delay(10);
postTransmission(); /* trigger reception mode*/
delay(100);
while ([Link]()) /* while receiving signal
from Serial3 from meter and converter */
{
}

void setShunt2(uint8_t slaveAddr2) //Change the slave


address of a node
{

/* 1- PZEM-017 DC Energy Meter */

static uint8_t SlaveParameter2 = 0x06; /* Write command


code to PZEM */
static uint16_t registerAddress2 = 0x0003; /* change shunt
register address command code */

uint16_t u16CRC2 = 0xFFFF; /* declare CRC check 16


bits*/
u16CRC2 = crc16_update(u16CRC2, slaveAddr2); // Calculate
the crc16 over the 6bytes to be send
u16CRC2 = crc16_update(u16CRC2, SlaveParameter2);
u16CRC2 = crc16_update(u16CRC2, highByte(registerAddress2));
u16CRC2 = crc16_update(u16CRC2, lowByte(registerAddress2));
u16CRC2 = crc16_update(u16CRC2, highByte(NewshuntAddr2));
u16CRC2 = crc16_update(u16CRC2, lowByte(NewshuntAddr2));

preTransmission(); /* trigger transmission mode*/


[Link](slaveAddr2); /* these whole process
code sequence refer to manual*/
[Link](SlaveParameter2);
[Link](highByte(registerAddress2));
[Link](lowByte(registerAddress2));
[Link](highByte(NewshuntAddr2));
[Link](lowByte(NewshuntAddr2));
[Link](lowByte(u16CRC2));
[Link](highByte(u16CRC2));
delay(10);
postTransmission(); /* trigger reception mode*/
delay(100);
while ([Link]()) /* while receiving signal
from Serial3 from meter and converter */
{
}
}

void setShunt3(uint8_t slaveAddr3) //Change the slave


address of a node
{

/* 1- PZEM-017 DC Energy Meter */

static uint8_t SlaveParameter3 = 0x06; /* Write command


code to PZEM */
static uint16_t registerAddress3 = 0x0003; /* change shunt
register address command code */

uint16_t u16CRC3 = 0xFFFF; /* declare CRC check 16


bits*/
u16CRC3 = crc16_update(u16CRC3, slaveAddr3); // Calculate
the crc16 over the 6bytes to be send
u16CRC3 = crc16_update(u16CRC3, SlaveParameter3);
u16CRC3 = crc16_update(u16CRC3, highByte(registerAddress3));
u16CRC3 = crc16_update(u16CRC3, lowByte(registerAddress3));
u16CRC3 = crc16_update(u16CRC3, highByte(NewshuntAddr3));
u16CRC3 = crc16_update(u16CRC3, lowByte(NewshuntAddr3));

preTransmission(); /* trigger transmission mode*/

[Link](slaveAddr3); /* these whole process


code sequence refer to manual*/
[Link](SlaveParameter3);
[Link](highByte(registerAddress3));
[Link](lowByte(registerAddress3));
[Link](highByte(NewshuntAddr3));
[Link](lowByte(NewshuntAddr3));
[Link](lowByte(u16CRC3));
[Link](highByte(u16CRC3));
delay(10);
postTransmission(); /* trigger reception mode*/
delay(100);
while ([Link]()) /* while receiving signal
from Serial3 from meter and converter */
{
}
}

Variables creadas en Ubidots

3. Letrero de OPEN mediante un ATtiny-85 y una matriz de leds 32x8


- En este proyecto se pretende utilizar un ATtiny -85 para programar un letrero de OPEN que
realice parpadeo de los leds de la Matriz MAX7219 en un tiempo establecido.

Conexiones de los componentes del ATtiny-85 con la matriz de LEDs

Código para la programación del letrero

#include <LedControl.h>

#define DIN 0

#define CS 1

#define CLK 3

LedControl disp=LedControl(DIN, CLK, CS, 4);

//--------------------------------------------------------------------------------

//--------------------------------------------------------------------------------

//=============================================================================
===

void setup()

for(int k=0; k<4; k++)

[Link](k, false);

[Link](k, 8);
[Link](k);

//----------------------------------

//=============================================================================
===

void loop()

OPENDisp();

delay(2000);

clearDisp();

delay(500);

//=============================================================================
===

void clearDisp()

for(int k=0; k<4; k++) [Link](k);

//=============================================================================
===

void OPENDisp()

//O

[Link](0,1,B11111111);

[Link](0,2,B10000001);

[Link](0,3,B10000001);
[Link](0,4,B10000001);

[Link](0,5,B10000001);

[Link](0,6,B11111111);

//P

[Link](1,1,B11111111);

[Link](1,2,B10010000);

[Link](1,3,B10010000);

[Link](1,4,B10010000);

[Link](1,5,B10010000);

[Link](1,6,B11110000);

//E

[Link](2,1,B11111111);

[Link](2,2,B10010001);

[Link](2,3,B10010001);

[Link](2,4,B10010001);

[Link](2,5,B10010001);

[Link](2,6,B10000001);

//N

[Link](3,1,B11111111);

[Link](3,2,B01000000);

[Link](3,3,B00110000);

[Link](3,4,B00001100);

[Link](3,5,B00000010);

[Link](3,6,B11111111);

4. Código para programar un medidor biométrico de oxígeno y ritmo cardíaco mediante un ESP C3
mini y un pulsioxímetro MAX30102
#include <Wire.h>
#include "MAX30105.h"
#include "spo2_algorithm.h"
#include "heartRate.h"
#include "BluetoothSerial.h"

BluetoothSerial SerialBT;

#define SDA 8
#define SCL 9

uint32_t irBuffer[100]; //infrared LED sensor data


uint32_t redBuffer[100]; //red LED sensor data

MAX30105 particleSensor;

int32_t bufferLength; //data length


int32_t spo2; //SPO2 value
int8_t validSPO2; //indicator to show if the SPO2 calculation is valid
int32_t heartRate; //heart rate value calcualated as per Maxim's algorithm
int8_t validHeartRate; //indicator to show if the heart rate calculation is valid

byte pulseLED = 2; //onboard led on esp32 nodemcu


byte readLED = 19; //Blinks with each data read

long lastBeat = 0; //Time at which the last beat occurred

void setup() {
// put your setup code here, to run once:
[Link](115200); // initialize serial communication at 115200 bits per second:

pinMode(pulseLED, OUTPUT);
pinMode(readLED, OUTPUT);

[Link]("Initializing Pulse Oximeter..");

TwoWire I2Cone = TwoWire(0);


[Link](SDA,SCL);

if (![Link](I2Cone, I2C_SPEED_FAST)) //Use default I2C port, 400kHz speed


{
[Link]("MAX30105 was not found. Please check wiring/power. ");
while (1);
}

[Link](F("Attach sensor to finger with rubber band. Press any key to start conversion"));
while ([Link]() == 0) ; //wait until user presses a key
[Link]();

byte ledBrightness = 50; //Options: 0=Off to 255=50mA


byte sampleAverage = 1; //Options: 1, 2, 4, 8, 16, 32
byte ledMode = 2; //Options: 1 = Red only, 2 = Red + IR, 3 = Red + IR + Green
byte sampleRate = 100; //Options: 50, 100, 200, 400, 800, 1000, 1600, 3200
int pulseWidth = 69; //Options: 69, 118, 215, 411
int adcRange = 4096; //Options: 2048, 4096, 8192, 16384

[Link](ledBrightness, sampleAverage, ledMode, sampleRate, pulseWidth,


adcRange); //Configure sensor with these settings

void loop() {
// put your main code here, to run repeatedly:

bufferLength = 100; //buffer length of 100 stores 4 seconds of samples running at 25sps

//read the first 100 samples, and determine the signal range
for (byte i = 0 ; i < bufferLength ; i++)
{
while ([Link]() == false) //do we have new data?
[Link](); //Check the sensor for new data

redBuffer[i] = [Link]();
irBuffer[i] = [Link]();
[Link](); //We're finished with this sample so move to next sample

[Link](F("red="));
[Link](redBuffer[i], DEC);
[Link](F(", ir="));
[Link](irBuffer[i], DEC);
}

//calculate heart rate and SpO2 after first 100 samples (first 4 seconds of samples)
maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2,
&validSPO2, &heartRate, &validHeartRate);
//Continuously taking samples from MAX30102. Heart rate and SpO2 are calculated every 1
second
while (1)
{
//dumping the first 25 sets of samples in the memory and shift the last 75 sets of samples to
the top
for (byte i = 25; i < 100; i++)
{
redBuffer[i - 25] = redBuffer[i];
irBuffer[i - 25] = irBuffer[i];
}

//take 25 sets of samples before calculating the heart rate.


for (byte i = 75; i < 100; i++)
{
while ([Link]() == false) //do we have new data?
[Link](); //Check the sensor for new data

digitalWrite(readLED, !digitalRead(readLED)); //Blink onboard LED with every data read

redBuffer[i] = [Link]();
irBuffer[i] = [Link]();
[Link](); //We're finished with this sample so move to next sample

//send samples and calculation result to terminal program through UART


[Link](F("red="));
[Link](redBuffer[i], DEC);
[Link](F(", ir="));
[Link](irBuffer[i], DEC);

[Link](F(", HR="));
[Link](heartRate, DEC);

[Link](F(", HRvalid="));
[Link](validHeartRate, DEC);

[Link](F(", SPO2="));
[Link](spo2, DEC);

[Link](F(", SPO2Valid="));
[Link](validSPO2, DEC);

//Send via BT
[Link](validHeartRate);
[Link](validSPO2);
}

//After gathering 25 new samples recalculate HR and SP02


maxim_heart_rate_and_oxygen_saturation(irBuffer, bufferLength, redBuffer, &spo2,
&validSPO2, &heartRate, &validHeartRate);

5. Sun Tracker de 2 ejes con servomotores para el seguimiento del sol para paneles solares.

- Para el siguiente dispositivo se utilizarán un ESP8266, 2 servomotores y una pantalla OLED de


0.96”. Se utilizará el reloj del ESP8266 para calcular el posicionamiento del sol. Además, se
utilizará un sensor de luz BH1750 para obtener la luminiscencia monitoreada.
- A continuación, se propone el código para realizar el tracking de la posición del sol.

Código para obtener la dirección de la pantalla OLED

#include <Wire.h>

#include <i2cdetect.h>

void setup() {

[Link]();

[Link](9600);

[Link]("i2cdetect example\n");

[Link]("Scanning address range 0x03-0x77\n\n");

void loop() {

i2cdetect(); // default range from 0x03 to 0x77

delay(2000);
}

Código para programar el dispositivo

#include <Wire.h> // adds I2C library


#include <BH1750.h> // adds BH1750 library file
#include <time.h> // adds I2C library
#include <ESP8266WiFi.h>
#include <Ticker.h>
#include <simpleDSTadjust.h>
#include <Servo.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <SPI.h>

//For OLED
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)


#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// -------------- Configuration options -----------------

const char* ssid = "ssid"; // your ssid


const char* password = "password"; // your password

float Lon = -79.92115 * DEG_TO_RAD, // your lon data - get it from [Link]
Lat = -2.15909 * DEG_TO_RAD, // your lat data - get it from [Link]
elevation,
azimuth;

#define elevation_servo 12
#define azimuth_servo 13

int sun_azimuth;
int sun_elevation;

// Update time from NTP server every 5 hours


//#define NTP_UPDATE_INTERVAL_SEC 5*3600
#define NTP_UPDATE_INTERVAL_SEC 5*1

// Maximum of 3 servers
#define NTP_SERVERS "[Link]", "[Link]", "[Link]"

#define Timezone -5 // US or EC Eastern Time Zone


struct dstRule StartRule = {"EDT", Second, Sun, Mar, 2, 3600}; // Daylight time = UTC/GMT -4
hours
struct dstRule EndRule = {"EST", First, Sun, Nov, 2, 0}; // Standard time = UTC/GMT -5 hour

// --------- End of configuration section ---------------

Ticker ticker1;
int32_t tick;

String Hour, Minute, Day, Month, Year;


int Hour24;
Servo Azi_servo;
Servo Ele_servo;

// flag changed in the ticker function to start NTP Update


bool readyForNtpUpdate = false;

// Setup simpleDSTadjust Library rules


simpleDSTadjust dstAdjusted(StartRule, EndRule);

BH1750 lightMeter;
void setup() {
// put your setup code here, to run once:
[Link](1,2);
[Link]();

[Link](115200);
[Link](false);

[Link](WIFI_STA);
[Link](ssid, password);
[Link]("\nConnecting to WiFi");
while ([Link]() != WL_CONNECTED) {
[Link](".");
delay(1000);
}

[Link]("\nConnected to network");
updateNTP(); // Init the NTP time
printTime(0); // print initial time time now.

tick = NTP_UPDATE_INTERVAL_SEC; // Init the NTP update countdown ticker


[Link](1, secTicker); // Run a 1 second interval Ticker
[Link]("Next NTP Update: ");
printTime(tick);
Azi_servo.attach(azimuth_servo);
Ele_servo.attach(elevation_servo);
test_azimuth(); // Bring panel to center
delay(1000);
test_elevation(); // Stop at 145 which is vertical or 0 elevation
delay(1000);

if(![Link](SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64


[Link](F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever

}
[Link]();
[Link]();

void loop() {
// put your main code here, to run repeatedly:

float lux = [Link]();


displaylux(lux);
delay(500);
if(readyForNtpUpdate)
{
readyForNtpUpdate = false;
printTime(0);
updateNTP();
[Link]("\nUpdated time from NTP Server: ");
printTime(0);
[Link]("Next NTP Update: ");
printTime(tick);

Calculate_Sun_Position([Link](), [Link](), 0, [Link](), [Link](), [Link]());


// parameters are HH:MM:SS DD:MM:YY start from midnight and work out all 24 hour positions.

Azi_servo.write(map(sun_azimuth, 90, 270, 180, 0)); // Align to azimuth


if (sun_elevation < 0) sun_elevation = 0; // Point at horizon if less than horizon
Ele_servo.write(145 - sun_elevation); // map(value, fromLow, fromHigh, toLow, toHigh)
delay(5000); // to reduce upload failures

void Calculate_Sun_Position(int hour, int minute, int second, int day, int month, int year) {
float T, JD_frac, L0, M, e, C, L_true, f, R, GrHrAngle, Obl, RA, Decl, HrAngle;
long JDate, JDx;
int zone = 0;
JDate = JulianDate(year, month, day);
JD_frac = (Hour24 - (24+Timezone) + minute / 60.0 + second / 3600.0) / 24.0 - 0.5;
T = JDate - 2451545; T = (T + JD_frac) / 36525.0;
L0 = DEG_TO_RAD * fmod(280.46645 + 36000.76983 * T, 360);
M = DEG_TO_RAD * fmod(357.5291 + 35999.0503 * T, 360);
e = 0.016708617 - 0.000042037 * T;
C = DEG_TO_RAD * ((1.9146 - 0.004847 * T) * sin(M) + (0.019993 - 0.000101 * T) * sin(2 *
M) + 0.00029 * sin(3 * M));
f = M + C;
Obl = DEG_TO_RAD * (23 + 26 / 60.0 + 21.448 / 3600. - 46.815 / 3600 * T);
JDx = JDate - 2451545;
GrHrAngle = 280.46061837 + (360 * JDx) % 360 + 0.98564736629 * JDx + 360.98564736629 *
JD_frac;
GrHrAngle = fmod(GrHrAngle, 360.0);
L_true = fmod(C + L0, 2 * PI);
R = 1.000001018 * (1 - e * e) / (1 + e * cos(f));
RA = atan2(sin(L_true) * cos(Obl), cos(L_true));
Decl = asin(sin(Obl) * sin(L_true));
HrAngle = DEG_TO_RAD * GrHrAngle + Lon - RA;
elevation = asin(sin(Lat) * sin(Decl) + cos(Lat) * (cos(Decl) * cos(HrAngle)));
azimuth = PI + atan2(sin(HrAngle), cos(HrAngle) * sin(Lat) - tan(Decl) * cos(Lat)); // Azimuth
measured east from north, so 0 degrees is North
sun_azimuth = azimuth / DEG_TO_RAD;
sun_elevation = elevation / DEG_TO_RAD;
[Link](); [Link]("Elevation: "); [Link](sun_elevation); [Link](" Azimuth: ");
[Link](sun_azimuth); [Link]();
[Link]("Longitude and latitude " + String(Lon / DEG_TO_RAD, 3) + " " + String(Lat /
DEG_TO_RAD, 3));
[Link]("Year\tMonth\tDay\tHour\tMinute\tElevation\tELServo\tAzimuth\tAZServo");
[Link](String(year) + "\t" + String(month) + "\t" + String(day) + "\t" + String(hour - zone) +
"\t" + String(minute) + "\t");
[Link](String(elevation / DEG_TO_RAD, 0) + "\t\t" + (145 - sun_elevation) + "\t" +
String(azimuth / DEG_TO_RAD, 0) + "\t" + (map(sun_azimuth, 90, 270, 180, 0)));

long JulianDate(int year, int month, int day) {


long JDate;
int A, B;
if (month <= 2) {year--; month += 12;}
A = year / 100; B = 2 - A + A / 4;
JDate = (long)(365.25 * (year + 4716)) + (int)(30.6001 * (month + 1)) + day + B - 1524;
return JDate;
}

void test_azimuth() {
Azi_servo.write(90); // Centre position
delay(500);
Azi_servo.write(60); // Centre position
delay(500);
Azi_servo.write(120); // Centre position
delay(500);
Azi_servo.write(90); // Centre position
delay(500);
}

void test_elevation() {
for (int a = 5; a < 145; a = a + 2) {
Ele_servo.write(a); // Centre position
delay(30);
}
Ele_servo.write(145); // Centre position
delay(1000);
}
//----------------------- Time Functions -------------------------------

void updateNTP() {

configTime(Timezone * 3600, 0, NTP_SERVERS);

delay(500);
while (!time(nullptr)) {
[Link]("#");
delay(1000);
}
}

void printTime(time_t offset)


{
char buf[30];
char *dstAbbrev;
time_t t = [Link](&dstAbbrev)+offset;
struct tm *timeinfo = localtime (&t);

int hour = (timeinfo->tm_hour+11)%12+1; // take care of noon and midnight


sprintf(buf, "%02d/%02d/%04d %02d:%02d:%02d%s %s\n",timeinfo->tm_mon+1, timeinfo-
>tm_mday, timeinfo->tm_year+1900, hour, timeinfo->tm_min, timeinfo->tm_sec, timeinfo-
>tm_hour>=12?"pm":"am", dstAbbrev);
Hour = hour;
Hour24 = timeinfo->tm_hour;
Minute = timeinfo->tm_min;
Day = (timeinfo->tm_mday);
Month = (timeinfo->tm_mon+1);
Year = (timeinfo->tm_year+1900);
[Link](buf);
[Link]();
[Link]("Current Hour: ");
[Link](timeinfo->tm_hour);
}

// NTP timer update ticker


void secTicker()
{
tick--;
if(tick<=0)
{
readyForNtpUpdate = true;
tick= NTP_UPDATE_INTERVAL_SEC; // Re-arm
}

// printTime(0); // Uncomment if you want to see time printed every second


}

void displaylux(float lux) {


[Link]();
[Link]();

[Link](1);
[Link](SSD1306_WHITE);
[Link](0,0);
[Link]("Iluminancia");
[Link]("---------------------");
[Link](28,27);
[Link](3);
[Link](lux, 1);
[Link]((char)247);
[Link]();
}

También podría gustarte