Un reloj preciso con la fecha mostrada en una pantalla LCD de 16×2 usando solo el Arduino, la pantalla y algunos botones. No se requiere módulo RTC.
COMPONENTES Y SUMINISTROS
- Arduino Nano R3
- Protoboard 800p
- LCD alfanumérico, 16 x 2
- Interruptor táctil, accionado por la parte superior
- Potenciómetro de ajuste, 10 kohm
- Cables de puente
El código del reloj
Las principales áreas de interés en el código de reloj son la configuración de la interrupción, cómo se usa y la forma en que se mantiene y se manipula la fecha.
La interrupción
El siguiente código establecerá una interrupción que se activará cada milisegundo. Esto desvía la interrupción utilizada para mantener millis () por lo que millis () y delay () ya no funcionarán.
// Set up time interrupt - millis() rolls over after 50 days so
// we are using our own millisecond counter which we can reset at
// the end of each day
//Set the CTC mode Compare time and trigger interrupt
TCCR0A = (1 << WGM01);
//Set value for time to compare to ORC0A for 1ms = 249 (8 bits so max is 256)
//[(Clock speed/Prescaler value)*Time in seconds] - 1
//[(16,000,000/64) * .001] - 1 = 249 = 1 millisecond
OCR0A = 0xF9;
//set timer compare interrupt
TIMSK0 |= (1 << OCIE0A);
//Set the prescale 1/64 clock
// ie 110 for last 3 bits
TCCR0B |= (1 << CS01);
TCCR0B |= (1 << CS00);
//initialize counter value to 0
TCNT0 = 0;
//Enable interrupt
sei();
Este es el código que se llamará cada segundo:
// This is interrupt is called when the compare time has been reached
// hence will be called once a millisecond based on the
// OCR0A register setting.
ISR(TIMER0_COMPA_vect) {
if (currentMode != SET_TIME)
currentTime++;
elapsed++;
}
currentTime y transcurrido son variables largas sin firmar. Tenga en cuenta que estos se califican como volátiles cuando se definen, ya que también estamos manipulando las variables en el código principal. Esto obliga al sistema a leer la variable cada vez que se utiliza y no a utilizar un valor almacenado en caché.
currentTime almacena el número de milisegundos desde la medianoche y hay rutinas para convertir esto a HH: MM: SS y restablecerlo cuando establezca la hora.
Cuando han transcurrido 24 horas, el sistema deduce el número de milisegundos en un día de la hora y aumenta la fecha en 1 día. Por lo tanto, el reloj no se ve afectado por el valor máximo que puede almacenar la variable, a diferencia de millis ().
// If at end of the day reset time and increase date
if ((currentMode == SHOW_TIME) &&
(currentTime > millisecondsInADay)) {
//Next day
// Stop interrupts while reset time
noInterrupts();
currentTime -= millisecondsInADay;
interrupts();
currentDate++;
}
Tenga en cuenta que deshabilitamos las interrupciones mientras manipulamos la variable currentTime, de lo contrario, la llamada de interrupción podría activarse en medio del cálculo para deducir milisegundos de InADay que corrompen el cálculo.
Después de que ha pasado cada hora, el sistema ajusta el número de milisegundos transcurridos por el ajuste de velocidad que calculamos anteriormente, ajustando la hora actual para compensar el reloj interno rápido o lento.
// At the end of each hour adjust the elapsed time for
// the inacuracy in the Arduino clock
if (elapsed >= millisecondsInHour) {
noInterrupts();
// Adjust time for slow/fast running Arduino clock
currentTime += speedCorrection;
// Reset to count the next hour
elapsed = 0;
interrupts();
}
Almacenamiento y cálculo de fechas
La fecha se lleva a cabo como una fecha juliana, que es el número de días que han transcurrido desde el lunes 1 de enero de 4713 a. C. Se incluyen rutinas para calcular la fecha juliana y convertirla de nuevo al calendario gregoriano.
float JulianDate(int iday, int imonth, int iyear) {
// Calculate julian date (tested up to the year 20,000)
unsigned long d = iday;
unsigned long m = imonth;
unsigned long y = iyear;
if (m < 3) {
m = m + 12;
y = y - 1;
}
unsigned long t1 = (153 * m - 457) / 5;
unsigned long t2 = 365 * y + (y / 4) - (y / 100) + (y / 400);
return 1721118.5 + d + t1 + t2;
}
void GregorianDate(float jd, int &iday, int &imonth, int &iyear) {
// Note 2100 is the next skipped leap year - compensates for skipped leap years
unsigned long f = jd + 68569.5;
unsigned long e = (4.0 * f) / 146097;
unsigned long g = f - (146097 * e + 3) / 4;
unsigned long h = 4000ul * (g + 1) / 1461001;
unsigned long t = g - (1461 * h / 4) + 31;
unsigned long u = (80ul * t) / 2447;
unsigned long v = u / 11;
iyear = 100 * (e - 49) + h + v;
imonth = u + 2 - 12 * v;
iday = t - 2447 * u / 80;
}
Los botones de ajuste
El botón Modo avanza el modo actual de Mostrar hora, a Establecer hora, Establecer año, Establecer fecha, Establecer ajuste de velocidad y volver a Mostrar hora. Cada uno de estos se explica por sí mismo y utiliza los otros 2 botones para ajustar la configuración actual.
Una vez que el reloj está funcionando, si está ganando o perdiendo tiempo, puede cambiar el ajuste de velocidad, accediendo al modo Establecer ajuste de velocidad y usando el botón arriba y abajo para aumentar o reducir esto en 5 segundos a la vez.
Programa de reloj
// Incluya el controlador de la biblioteca para su visualización:
#include <LiquidCrystal.h>
// LCD de cristal líquido (RS, EN, D4, D5, D6, D7)
LiquidCrystal lcd ( 12 , 13 , 6 , 7 , 8 , 9 ); // crea un objeto lcd y asigna los pines
// Definir botones y conexiones de zumbador
#define MODE_BUTTON 2
#define HOUR_BUTTON 3 // El mismo botón, diferentes definiciones para
#define UP_BUTTON 3 // hace que el código sea más fácil de entender
#define DAY_BUTTON 3
#define MINUTE_BUTTON 4 // El mismo botón, diferentes definiciones para
#define DOWN_BUTTON 4 // hace que el código sea más fácil de entender
#define MONTH_BUTTON 4
// Configuración del modo actual
#define SHOW_TIME 1 // 1 = corriendo - mostrar hora
#define SET_TIME 2 // 2 = tiempo establecido
#define SET_YEAR 3 // 3 = año establecido
#define SET_DATE 4 // 4 = día / mes establecido
#define SET_SPEED_ADJ 5 // 5 = modificar la variable speedCorrection
int speedCorrection = 3545 ; // Número de milisegundos que mi reloj Nano funciona lento por hora
// número negativo aquí si se está ejecutando rápido
// cambia para que coincida con tu Arduino
// Variables volátiles modificadas en una interrupción y
// Necesito forzar al sistema a leer la variable real
// cuando se usa fuera de la interrupción y no usa una versión en caché
volatile unsigned long currentTime ; // Duración en milisegundos desde la medianoche
unsigned long lastTime = - 1000 ; // lastTime que se llamó ShowTime inicializado a -1000 por lo que se muestra inmediatamente
volátil sin firmar mucho tiempo transcurrido ; // Temporizador utilizado para demora y recuento de horas
unsigned long millisecondsInADay ; // Milisegundos en 24 horas
unsigned long millisecondsInHour ; // Milisegundos en 1 hora
int currentMode ; // 1 = corriendo - mostrar la hora
// 2 = tiempo establecido
// 3 = año establecido
// 4 = día / mes establecido
float currentDate ; // Fecha de Julian
flotar lastDate = 0.0 ; // última fecha en la que se llamó ShowDate
int currentDay ;
int currentMonth ;
int currentYear ;
char * dayArray [] = { "Tue." , // Mostrará una advertencia del compilador pero funciona bien
"Mié" ,
"Jue." ,
"Vie." ,
"Sáb." ,
"Sol" ,
"Lun. "
};
configuración vacía () {
// Configurar interrupción de tiempo: millis () se transfiere después de 50 días, por lo que
// estamos usando nuestro propio contador de milisegundos que podemos restablecer en
// el final de cada día
TCCR0A = ( 1 << WGM01 ); // Establecer el modo CTC Comparar tiempo y disparar interrupción
OCR0A = 0xF9 ; // Establezca el valor del tiempo para compararlo con ORC0A durante 1 ms = 249 (8 bits, por lo que el máximo es 256)
// [(Velocidad del reloj / Valor de preescalador) * Tiempo en segundos] - 1
// [(16,000,000 / 64) * .001] - 1 = 249 = 1 milisegundo
TIMSK0 | = ( 1 << OCIE0A ); // establecer interrupción de comparación del temporizador
TCCR0B | = ( 1 << CS01 ); // Establecer el reloj de preescala 1/64
TCCR0B | = ( 1 << CS00 ); // es decir, 110 para los últimos 3 bits
TCNT0 = 0 ; // inicializar el valor del contador a 0
sei (); // Habilitar interrupción
pinMode ( MINUTE_BUTTON , INPUT_PULLUP );
pinMode ( BOTÓN_HORA , INPUT_PULLUP );
pinMode ( MODE_BUTTON , INPUT_PULLUP );
// pinMode (ZUMBADOR, SALIDA);
currentTime = 0 ; // Establecer la hora actual a la noche mental
currentDate = JulianDate ( 1 , 1 , 2021 ); // Establecer fecha base
transcurrido = 0 ; // Establecer el contador de períodos en 0
milisegundosInADay = 24ul * 60 * 60 * 1000 ;
milisegundosInHour = 60ul * 60 * 1000 ;
CurrentMode = SHOW_TIME ; // El modo inicial se está ejecutando y muestra la fecha y la hora
// Configurar LCD
lcd . comenzar ( 16 , 2 );
lcd . noAutoscroll ();
lcd . display ();
lcd . claro ();
ShowTime ( currentTime );
}
bucle vacío () {
// el bucle se ejecuta cada 150 milisegundos
// Si al final del día restablece la hora y aumenta la fecha
si (( CurrentMode == SHOW_TIME ) &&
( currentTime > milisegundosInADay )) {
//Día siguiente
// Detener las interrupciones mientras se reinicia el tiempo
noInterrupts ();
currentTime - = milisegundosInADay ;
interrumpe ();
currentDate ++ ;
}
// Al final de cada hora ajusta el tiempo transcurrido para
// la inexactitud en el reloj Arduino
if ( transcurrido > = milisegundosEnHora ) {
noInterrupts ();
// Ajustar el tiempo para el reloj Arduino de funcionamiento lento / rápido
currentTime + = speedCorrection ;
// Restablecer para contar la próxima hora
transcurrido = 0 ;
interrumpe ();
}
// Comprueba si se ha pulsado algún botón
CheckButtons ();
// Mostrar pantalla según el modo actual
switch ( currentMode ) {
caso SHOW_TIME :
// Muestra la fecha y la hora actuales
ShowTime ( currentTime );
ShowDate ( currentDate );
romper ;
caso SET_TIME :
// Pantalla de visualización para configurar la hora
ShowTimeSet ( currentTime );
romper ;
caso SET_YEAR :
// Pantalla de visualización para configurar el año
ShowYearSet ( currentDate );
romper ;
caso SET_DATE :
// Pantalla de visualización para configurar el día y el mes
ShowDDMMSet ( currentDate );
romper ;
caso SET_SPEED_ADJ :
// Pantalla de visualización para ajustar la corrección de velocidad
ShowSpeedSet ();
romper ;
}
Espere ( 150 );
}
// Esta interrupción se llama cuando se alcanza el tiempo de comparación
// por lo tanto, se llamará una vez por milisegundo según el
// Configuración de registro OCR0A.
ISR ( TIMER0_COMPA_vect ) {
if ( currentMode ! = SET_TIME )
currentTime ++ ;
transcurrido ++ ;
}
float JulianDate ( int iday , int imonth , int iyear ) {
// Calcular la fecha juliana (probado hasta el año 20.000)
unsigned long d = iday ;
unsigned long m = imonth ;
unsigned long y = iyear ;
si ( m < 3 ) {
m = m + 12 ;
y = y - 1 ;
}
unsigned long t1 = ( 153 * m - 457 ) / 5 ;
largo sin signo t2 = 365 * y + ( y / 4 ) - ( y / 100 ) + ( y / 400 );
return 1721118.5 + d + t1 + t2 ;
}
void GregorianDate ( float jd , int & iday , int & imonth , int & iyear ) {
// Nota 2100 es el próximo año bisiesto omitido: compensa los años bisiestos omitidos
unsigned long f = jd + 68569.5 ;
unsigned long e = ( 4.0 * f ) / 146097 ;
largo sin signo g = f - ( 146097 * e + 3 ) / 4 ;
largo sin signo h = 4000ul * ( g + 1 ) / 1461001 ;
largo sin signo t = g - ( 1461 * h / 4 ) + 31 ;
unsigned long u = ( 80ul * t ) / 2447 ;
unsigned long v = u / 11 ;
i año = 100 * ( e - 49 ) + h + v ;
mes = u + 2 - 12 * v ;
viernes = t - 2447 * u / 80 ;
}
void SplitTime ( unsigned long curr , unsigned long & ulHour ,
unsigned long & ulMin , unsigned long & ulSec ) {
// Calcular HH: MM: SS a partir del recuento de milisegundos
ulSec = curr / 1000 ;
ulMin = ulSec / 60 ;
ulHour = ulMin / 60 ;
ulMin - = ulHour * 60 ;
ulSec = ulSec - ulMin * 60 - ulHour * 3600 ;
}
unsigned long SetTime ( unsigned long ulHour , unsigned long ulMin ,
unsigned long ulSec ) {
// Establece el número de milisegundos desde la medianoche hasta la hora actual
retorno ( ulHour * 60 * 60 * 1000 ) +
( ulMin * 60 * 1000 ) +
( ulSec * 1000 );
}
void Wait ( valor largo sin firmar ) {
// Crea nuestra propia función de reparto
// Hemos establecido nuestra propia interrupción en TCCR0A
// por lo tanto millis () y delay () ya no funcionarán
tiempo de inicio largo sin firmar = transcurrido ;
while (( transcurrido - hora de inicio ) < valor ) {
// Solo espera
}
}
void CheckButtons () {
// Si se ha pulsado el botón de modo, el pin pasará a BAJO
if ( digitalRead ( MODE_BUTTON ) == LOW ) {
// Avanzar al siguiente modo
switch ( currentMode ) {
caso SHOW_TIME :
CurrentMode = SET_TIME ;
lcd . claro ();
romper ;
caso SET_TIME :
CurrentMode = SET_YEAR ;
lcd . claro ();
romper ;
caso SET_YEAR :
CurrentMode = SET_DATE ;
lcd . claro ();
romper ;
caso SET_DATE :
CurrentMode = SET_SPEED_ADJ ;
lcd . claro ();
romper ;
caso SET_SPEED_ADJ :
CurrentMode = SHOW_TIME ;
lcd . claro ();
// Restablecer las variables para que la pantalla se vea obligada a actualizarse
// la próxima vez que se llame a ShowTime y ShowDate
lastTime = 0 ;
lastDate = 0.0 ;
romper ;
}
}
if ( currentMode ! = SHOW_TIME ) {
switch ( currentMode ) {
// Si el modo es diferente a los botones de verificación SHOW_TIME
// El pin pasa a BAJO cuando se presiona el botón asociado
caso SET_TIME :
if ( digitalRead ( MINUTE_BUTTON ) == LOW ) {
// Avanzar minuto
iHours largos sin firmar ;
iMinutes largos sin firmar ;
iSeconds largos sin firmar ;
SplitTime ( CurrentTime , iHours , iMinutes , iSeconds );
si ( iMinutos < 59 ) {
iMinutes ++ ;
}
else {
iMinutos = 0 ;
}
// Establecer milisegundos almacenados según la configuración actual
noInterrupts ();
currentTime = SetTime ( iHours , iMinutes , 0 );
transcurrido = 0 ;
interrumpe ();
}
if ( digitalRead ( HOUR_BUTTON ) == LOW ) {
// Hora de avance
iHours largos sin firmar ;
iMinutes largos sin firmar ;
iSeconds largos sin firmar ;
SplitTime ( CurrentTime , iHours , iMinutes , iSeconds );
si ( iHoras < 23 ) {
iHours ++ ;
}
else {
iHoras = 0 ;
}
// Establecer milisegundos almacenados según la configuración actual
noInterrupts ();
currentTime = SetTime ( iHours , iMinutes , 0 );
transcurrido = 0 ;
interrumpe ();
}
romper ;
caso SET_YEAR :
if ( digitalRead ( UP_BUTTON ) == LOW ) {
// Incrementar año
int iDay ;
int iMonth ;
int iYear ;
GregorianDate ( currentDate , iDay , iMonth , iYear );
iYear ++ ;
// Establecer la fecha almacenada según la configuración actual
currentDate = JulianDate ( iDay , iMonth , iYear );
}
if ( digitalRead ( DOWN_BUTTON ) == LOW ) {
// Disminuir año
int iDay ;
int iMonth ;
int iYear ;
GregorianDate ( currentDate , iDay , iMonth , iYear );
iYear - ;
// Establecer la fecha almacenada según la configuración actual
currentDate = JulianDate ( iDay , iMonth , iYear );
}
romper ;
caso SET_DATE :
if ( digitalRead ( MONTH_BUTTON ) == LOW ) {
// Mes de avance
int iDay ;
int iMonth ;
int iYear ;
GregorianDate ( currentDate , iDay , iMonth , iYear );
iMonth ++ ;
if ( iMonth > 12 ) {
iMes = 1 ;
}
// Establecer la fecha almacenada según la configuración actual
currentDate = JulianDate ( iDay , iMonth , iYear );
}
if ( digitalRead ( DAY_BUTTON ) == LOW ) {
// Día de avance
int iDay ;
int iMonth ;
int iYear ;
GregorianDate ( currentDate , iDay , iMonth , iYear );
iDay ++ ;
if ( iDay > 31 ) {
iDay = 1 ;
}
si ((( iMonth == 4 ) || ( iMonth == 6 ) || ( iMonth == 9 ) || ( iMonth == 11 ))
&& ( iDay > 30 )) {
iDay = 1 ;
}
if (( iMonth == 2 ) && ( iDay > 29 )) {
iDay = 1 ;
}
if (( iMonth == 2 ) && (( iYear % 4 ) ! = 0 ) && ( iDay > 28 )) {
iDay = 1 ;
}
// Establecer la fecha almacenada según la configuración actual
// Si posteriormente ajusta el mes para que el día no sea válido
// luego la pantalla avanzará a la siguiente fecha válida
currentDate = JulianDate ( iDay , iMonth , iYear );
}
romper ;
caso SET_SPEED_ADJ :
// aumentar o disminuir la corrección en 5 milisegundos
if ( digitalRead ( UP_BUTTON ) == LOW ) {
speedCorrection + = 5 ;
}
if ( digitalRead ( DOWN_BUTTON ) == LOW ) {
speedCorrection - = 5 ;
}
romper ;
}
}
}
String FormatNumber ( valor int ) {
// Para agregar un 0 a la izquierda si es necesario
si ( valor < 10 ) {
devuelve "0" + Cadena ( valor );
}
else {
return String ( valor );
}
}
void ShowTime ( valor largo sin firmar ) {
// Actualizar la pantalla una vez por segundo
// o cuando pasa la medianoche
if (( valor > lastTime + 1000 ) || ( valor < lastTime )) {
lastTime = valor ;
iHours largos sin firmar ;
iMinutes largos sin firmar ;
iSeconds largos sin firmar ;
SplitTime ( valor , iHours , iMinutes , iSeconds );
// Muestra la hora en la línea 0
lcd . setCursor ( 0 , 0 );
lcd . print ( "Hora:" + FormatNumber ( iHours ) + ":" +
FormatNumber ( iMinutes ) + ":" +
FormatNumber ( iSeconds ));
}
}
void ShowDate ( valor flotante ) {
// Actualizar la pantalla si la fecha ha cambiado desde
// la fecha se mostró por última vez
if ( lastDate ! = value ) {
lastDate = valor ;
int iday ;
int imonth ;
int iyear ;
String currentDay ;
GregorianDate ( valor , iday , imonth , iyear );
int dayOfWeek = ( unsigned long ) valor % 7 ;
// Muestra la fecha en la línea 0
lcd . setCursor ( 0 , 1 );
lcd . print ( dayArray [ dayOfWeek ]);
lcd . imprimir ( FormatNumber ( iday ) + ":" +
FormatNumber ( imonth ) + ":" +
un año );
}
}
void ShowDDMMSet ( valor flotante ) {
int iday ;
int imonth ;
int iyear ;
String currentDay ;
GregorianDate ( valor , iday , imonth , iyear );
// Mostrar día y mes para ajustar
lcd . setCursor ( 0 , 0 );
lcd . print ( "Establecer día y mes:" );
lcd . setCursor ( 0 , 1 );
lcd . print ( "Día:" + FormatNumber ( iday ) + "Mes:" +
FormatNumber ( imonth ));
}
void ShowYearSet ( float jd ) {
int iday ;
int imonth ;
int iyear ;
GregorianDate ( jd , iday , imonth , iyear );
// Mostrar año para ajustar
lcd . setCursor ( 0 , 0 );
lcd . print ( "Establecer año:" );
lcd . setCursor ( 0 , 1 );
lcd . print ( "Año:" + FormatNumber ( iyear ));
}
void ShowTimeSet ( valor largo sin firmar ) {
iHours largos sin firmar ;
iMinutes largos sin firmar ;
iSeconds largos sin firmar ;
// Mostrar tiempo para ajustar
SplitTime ( valor , iHours , iMinutes , iSeconds );
lcd . setCursor ( 0 , 0 );
lcd . print ( "Establecer hora:" );
lcd . setCursor ( 0 , 1 );
lcd . print ( "Horas:" + FormatNumber ( iHours ) + "Mins:" +
FormatNumber ( iMinutes ));
}
void ShowSpeedSet () {
// Muestra la figura de corrección de velocidad para ajustar
// podría ser + o -
lcd . setCursor ( 0 , 0 );
lcd . print ( "Ajustar velocidad ajusta:" );
lcd . setCursor ( 0 , 1 );
lcd . imprimir ( "Millis:" );
lcd . imprimir ( speedCorrection );
lcd . imprimir ( "" );
}
Programa de temporizador
int inByte = 0 ;
unsigned long firstReading = 100000 ; // millis () cuando se envía la primera lectura
configuración vacía () {
Serial . comenzar ( 9600 );
// Envía el byte de saludo a Processing
sayHello ();
}
bucle vacío () {
// si se recibe un byte en el puerto serie
// luego leer y descartar y enviar actual
// valor de millis ()
if ( Serial . disponible () > 0 ) {
// obtener el byte entrante
inByte = Serie . leer ();
// enviar el tiempo transcurrido desde el procesamiento de la primera lectura
Serial . print ( millis () - firstReading );
Serial . imprimir ( 'E' );
// repetir cada 2 segundos
retraso ( 2000 );
}
}
void sayHello () {
// Espere hasta que el puerto serie esté disponible
// luego envía un byte de saludo para iniciar el protocolo de enlace
while ( Serial . disponible () <= 0 ) {
Serial . imprimir ( 'Z' ); // Enviar Z al procesamiento para decir hola
retraso ( 200 );
}
firstReading = millis ();
}
Procesamiento de secuencia de comandos de prueba de temporizador
import processing.serial.*;
Serial theSerialPort; // create the serial port object
int[] serialBytesArray = new int[15]; // array to store incoming bytes
int bytesCount = 0; // current number of bytes received
boolean init = false; // false until handshake completed by receiving the character Z
int fillColor = 255; // defining the initial fill colour
long mills = 0; // last reading received
long first = 0; // time of first mills received so we can calculate the difference over an hour
long now; // number of millis elapsed since first mills received
long firstReading = 100000; // millis() in processing of first message received from Arduino
long DiffPerHour = 0; // the difference after the first hour has passed
int inByte; // last byte read
void setup() {
// define some canvas and drawing parameters
size(500, 500);
background(70);
noStroke();
// print the list of all serial devices so you know which one to set for the Arduino
// will need to run program and edit if the correct port is not set below
printArray(Serial.list());
// instantate the Serial Communication
String thePortName = Serial.list()[1];
theSerialPort = new Serial(this, thePortName, 9600);
}
void draw() {
// Display time settings
background(70);
fill(fillColor);
textSize(25);
text(hour() + ":" + minute() + ":" + second(), 50, 50);
// the last read millis sent by the Arduino
text("Incoming elapsed: " + mills, 50, 100);
// the current elapsed since first read in Processing
text("Local elapsed: " + (now - firstReading), 50, 150);
// display the current difference
text("Diff: " + (mills - (now - firstReading)), 50, 200);
// Check if 1 hour has passed and if the first hour store the difference
if (((now - firstReading)>= 3600000) && (DiffPerHour == 0)){
DiffPerHour = mills - (now - firstReading);
}
// Display the first difference and the difference after the first hour
text("Diff after 1 hour: " + DiffPerHour, 50, 300);
}
void serialEvent(Serial myPort) {
// read a byte from the serial port
inByte = myPort.read();
if (init == false) { // if not yet handshaked the see if handshake byte
if (inByte == 'Z') { // if the byte read is Z
myPort.clear(); // clear the serial port buffer
init = true; // store the fact we had the first hello
myPort.write('Z'); // tell the Arduino to send more
if (first == 0){
first = millis();
}
}
}
else {
// if there already was the first hello
// Add the latest byte from the serial port to array
if (inByte != 69) { // Check not the end of message character E
if (bytesCount < 14) {
serialBytesArray[bytesCount] = inByte;
bytesCount++;
}
}
if (inByte == 69) {
// End of message
// store local time elapsed
now = millis();
// calculate incoming millis()
mills = 0;
for (int i = 1; i <= bytesCount; i++) {
mills += (serialBytesArray[i - 1] - 48) * pow(10, (bytesCount - i));
}
// Say we are ready to accept next message
// if this is the first reading then set the first difference
if (firstReading == 100000) {
firstReading = now;
}
myPort.write('Z');
// Reset bytesCount:
bytesCount = 0;
}
}
}
-
Arduino ATmega 2560 R3¡Oferta!
$20.50$19.00 -
Arduino Uno Wifi¡Oferta!
$15.00$13.00 -
Arduino Mini USB Nano V3.0 CH340 Chip Board 5V 16M + Cable¡Oferta!
$9.00$8.50