Paso 8: Con la RTC a los indicadores
También necesitamos algo de código para avanzar los minutos y horas y regresar los medidores a cero cuando máximo hacia fuera. Esto es realmente sencillo, pero me topé con un problemita. Cuando las agujas se regresan a cero de su recorrido completo, lo hacen con bastante fuerza. Basta hacer un clic en ruido y causa preocupación la longevidad de los movimientos de d ' Arsonval en los medidores. Quería implementar una rutina suave de vuelta en el software que a primera vista parecía bastante fácil de hacer. Finalmente llego a trabajar y le mostrará cómo. Algunos gurús de la electrónica podrían ser capaces de determinar una solución de hardware para este (cap cargos y drena a través de un arreglo de diodo resistencia cuando el PWM a cero o algo). Si es así, hágamelo saber. Tomó el camino del software y no ha pasado ningún más tiempo pensando en él.
Un pequeño vídeo del código de abajo corriendo. El rastro de O'scope es la onda cuadrada de la RTC. Aviso cada vez que se levanta, los incrementos de mano de segundos.
Aquí es un programa que leerá el RTC basado en una interrupción generada por la onda cuadrada de RTC conectado al pin 2 de arduino y el valor de segundos en el pin 5 (PWM).
Esta rutina no incluye la devolución suave de la aguja.
#include < Wire.h >
#define DS3231_I2C_ADDRESS 104
#define int_pin 2
#define gauge_pin 5
byte segundos, minutos, horas, día, fecha, mes, año;
secpos de bytes;
día de la semana Char [4];
int_tick Boolean;
byte tMSB, tLSB;
Float temp3231;
void setup()
{
Wire.Begin();
Serial.Begin(9600);
Wire.beginTransmission(DS3231_I2C_ADDRESS); 104 es DS3231 dispositivo dirección
Wire.Send(0x0E); //
Wire.Send(B00000000);
Wire.endTransmission();
pinMode (int_pin, entrada);
digitalWrite(2,HIGH); suba en tirón interno del perno 2
attachInterrupt (0, int0handler, RISING); una interrupción cero al pin 2 y llamar a la función int0handler cada vez que ve a pin 2 una tensión creciente
secpos = 0;
}
void loop()
{
Si (int_tick) {}
updategauge();
}
watchConsole(); permite cambiar la hora y fecha
}
void int0handler() {}
int_tick = 1;
}
void updategauge() {}
Serial.println("int");
get3231Date();
Serial.Print(weekDay); Serial.Print (","); Serial.Print (mes, DEC); Serial.Print("/"); Serial.Print (fecha, DEC); Serial.Print("/"); Serial.Print (año, DEC); Serial.Print ("-");
Serial.Print (horas, DEC); Serial.Print(":"); Serial.Print (minutos, DEC); Serial.Print(":"); Serial.Print (segundos, DEC);
Serial.Print ("temperatura:"); Serial.println(get3231Temp());
secpos = segundos * 4;
Si (secpos > = 240) secpos = 0; devolverá la segunda aguja en final de recorrido
analogWrite (gauge_pin, secpos);
int_tick = 0; restablecer la bandera de señal de int
}
Convierte a números decimales normales a binario codificado decimal
decToBcd(byte val) bytes
{
regresar ((val/10 * 16) + (val % 10));
}
void watchConsole()
{
Si (Serial.available()) {/ / buscar carbón en proceso de cola de la serie y si encuentra
Si (Serial.read() == 84) {//If comando = "T" fijar fecha
set3231Date();
get3231Date();
Serial.println("");
}
}
}
void set3231Date()
{
T(SEC)(min)(hour)(dayOfWeek)(dayOfMonth)(month)(Year)
T(00-59)(00-59)(00-23)(1-7)(01-31)(01-12)(00-99)
Ejemplo: 02 de febrero de 09 a 19:57:11 para el 3 º día de la semana -> T1157193020209
segundos = (byte) ((Serial.read()-48) * 10 + (Serial.read() - 48)); Uso de las matemáticas de fundición y ascii de tipo (byte) para lograr el resultado.
minutos = (byte) ((Serial.read()-48) * 10 + (Serial.read() - 48));
horas = (byte) ((Serial.read()-48) * 10 + (Serial.read() - 48));
día = (byte) (Serial.read() - 48);
fecha = (byte) ((Serial.read()-48) * 10 + (Serial.read() - 48));
mes = (byte) ((Serial.read()-48) * 10 + (Serial.read() - 48));
año = (byte) ((Serial.read()-48) * 10 + (Serial.read() - 48));
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.Send(0x00);
Wire.Send(decToBcd(seconds));
Wire.Send(decToBcd(minutes));
Wire.Send(decToBcd(hours));
Wire.Send(decToBcd(Day));
Wire.Send(decToBcd(Date));
Wire.Send(decToBcd(month));
Wire.Send(decToBcd(Year));
Wire.endTransmission();
}
void get3231Date()
{
enviar solicitud para recibir los datos a partir de registro 0
Wire.beginTransmission(DS3231_I2C_ADDRESS); 104 es DS3231 dispositivo dirección
Wire.Send(0x00); desde el registro 0
Wire.endTransmission();
Wire.requestFrom (DS3231_I2C_ADDRESS, 7); solicitar siete bytes
{if(Wire.Available())}
segundos = Wire.receive(); segundos
minutos = Wire.receive(); obtener minutos
horas = Wire.receive(); Haz horas
día = Wire.receive();
fecha = Wire.receive();
mes = Wire.receive(); mes temperatura
año = Wire.receive();
segundos = (((seconds & B11110000) >> 4) * 10 + (segundos / B00001111)); convertir de BCD a decimal
minutos = (((minutes & B11110000) >> 4) * 10 + (minutos / B00001111)); convertir de BCD a decimal
horas = (((hours & B00110000) >> 4) * 10 + (horas / B00001111)); convertir de BCD a decimal (asumir el modo de 24 horas)
día = (día & B00000111); 1-7
fecha = (((date & B00110000) >> 4) * 10 + (fecha & B00001111)); 1-31
mes = (((month & B00010000) >> 4) * 10 + (mes & B00001111)); msb7 es desbordamiento del siglo
año = (((year & B11110000) >> 4) * 10 + (año & B00001111));
}
Else {}
Oh noes, no hay datos!
}
interruptor (día) {}
caso 1:
strcpy (día de la semana, "Sol");
rotura;
caso 2:
strcpy (día de la semana, "Lunes");
rotura;
caso 3:
strcpy (día de la semana, "Martes");
rotura;
caso 4:
strcpy (día de la semana, "Mie");
rotura;
caso 5:
strcpy (día de la semana, "Jue");
rotura;
caso 6:
strcpy (día de la semana, "Viernes");
rotura;
caso 7:
strcpy (día de la semana, "se sentó");
rotura;
}
}
flotador get3231Temp()
{
registros de temperatura (11h - 12h) Haz actualizan automáticamente cada 64s
Wire.beginTransmission(DS3231_I2C_ADDRESS);
Wire.Send(0x11);
Wire.endTransmission();
Wire.requestFrom (DS3231_I2C_ADDRESS, 2);
{if(Wire.Available())}
tMSB = Wire.receive(); 2 complementar la porción int
tLSB = Wire.receive(); parte de la fracción
temp3231 = (tMSB & B01111111); de 2 matemáticas en Tmsb
temp3231 += ((tLSB >> 6) * 0.25); atención sólo de bits 7 y 8
}
Else {}
Oh noes, no hay datos!
}
volver temp3231;
}