Informe
Informe
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 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
Disposición de pines
• 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
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.
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
-FLASH DE 16 MB
-PSRAM 8MB
-4,7 pulgadas, resolución de 540(H)X960(V), 16 niveles de gris ED047C1 y admite actualización parcial.
-Primer botón X1
-Botón personalizado X3
-TIPO-C
-arduino
-FDI
-Micropython
Escenario de aplicación:
-Educación STEM
-Dispositivo IoT
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.
- 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.
Código para configurar la dirección para la comunicación con cada uno de los PZEM
// 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/
/*///////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////*/////////////*/
/* 1- PZEM-Energy Meter */
static uint8_t address = 0x02; // Variable for Address. Kindly set address here.
void setup()
startMillis1 = millis();
startMillis2 = millis();
[Link](9600); /* To assign communication port to communicate with
meter. with 2 stop bits (refer to manual)*/
[Link](postTransmission);
void loop()
startMillis2 = millis();
delay(10);
[Link](SlaveParameter);
[Link](highByte(registerAddress));
[Link](lowByte(registerAddress));
[Link](highByte(NewslaveAddr));
[Link](lowByte(NewslaveAddr));
[Link](lowByte(u16CRC));
[Link](highByte(u16CRC));
delay(10);
delay(100);
Ubidots client(TOKEN);
//-----------------------------------------------------------------------------------------------------------------------------
----------------
/* 1- PZEM-017 DC Energy Meter */
//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.
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();
//[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
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](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();
//-----------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------
#include <LedControl.h>
#define DIN 0
#define CS 1
#define CLK 3
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//=============================================================================
===
void setup()
[Link](k, false);
[Link](k, 8);
[Link](k);
//----------------------------------
//=============================================================================
===
void loop()
OPENDisp();
delay(2000);
clearDisp();
delay(500);
//=============================================================================
===
void clearDisp()
//=============================================================================
===
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
MAX30105 particleSensor;
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](F("Attach sensor to finger with rubber band. Press any key to start conversion"));
while ([Link]() == 0) ; //wait until user presses a key
[Link]();
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];
}
redBuffer[i] = [Link]();
irBuffer[i] = [Link]();
[Link](); //We're finished with this sample so move to next sample
[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);
}
5. Sun Tracker de 2 ejes con servomotores para el seguimiento del sol para paneles solares.
#include <Wire.h>
#include <i2cdetect.h>
void setup() {
[Link]();
[Link](9600);
[Link]("i2cdetect example\n");
void loop() {
delay(2000);
}
//For OLED
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
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;
// Maximum of 3 servers
#define NTP_SERVERS "[Link]", "[Link]", "[Link]"
Ticker ticker1;
int32_t tick;
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.
}
[Link]();
[Link]();
void loop() {
// put your main code here, to run repeatedly:
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)));
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() {
delay(500);
while (!time(nullptr)) {
[Link]("#");
delay(1000);
}
}
[Link](1);
[Link](SSD1306_WHITE);
[Link](0,0);
[Link]("Iluminancia");
[Link]("---------------------");
[Link](28,27);
[Link](3);
[Link](lux, 1);
[Link]((char)247);
[Link]();
}