I3231C를 통해 통합 DS2의 날짜와 온도를 확인하는 Arduino 라이브러리
업데이트됨: 또한 새로운 페이지를 방문하세요. DS3231 RTC 모듈 및 Arduino를 사용하여 날짜와 시간을 관리하는 라이브러리 계절별 시간 등의 개선을 통해
의 운영 IC de 실시간 시계(RTC) 가장 인기 있는 것은 버스 I2C 일반적으로 매우 유사합니다. 게다가, 와이어 라이브러리 de 아두 이노 장치와의 통신을 크게 단순화합니다. 2선 직렬 인터페이스(TWI), I2C, 특정한.
광범위하게 말하면 프로세스는 다음과 같이 구성됩니다.
-
기능을 사용하여 슬레이브 또는 마스터(기본적으로 설정됨)로 통신을 시작합니다. Wire.begin(주소). "주소"가 생략되면 통신은 다음 주소로 시작됩니다. μC 선생님 버스 I2C.
-
커뮤니케이션 활성화 I2C 다음 명령을 사용하여 장치가 위치한 메모리 주소를 통해 장치와 함께 Wire.beginTransmission(주소).
-
에 주문을 작성하세요. 버스 I2C 장치에 수행하려는 작업을 알려주려면 다음을 사용하세요. Wire.write(명령), 여기서 "order"는 작업 코드입니다.
-
통신을 비활성화하여 버스 I2C 기능 Wire.endTransmission ().
-
해당 기능을 사용하여 요청한 작업(이 경우 날짜 및 시간)에 해당하는 일정량의 데이터를 장치에 전송하도록 요청합니다. Wire.requestFrom(주소,금액).
-
해당 기능으로 요청된 데이터를 읽을 수 있을 때까지 기다립니다. Wire.available (), 이미 수신되어 읽을 수 있는 데이터 수를 반환합니다.
-
장치에서 보낸 데이터를 읽습니다( 실시간 시계, 이 경우) 함수를 사용하여 와이어.읽기() 표시된 바이트만큼 Wire.available () 사용할 수 있습니다.
-
일반적으로 데이터는 매우 컴팩트한 형식으로 전송되므로 장치를 사용하는 프로그램에서 생성된 데이터 표현에 해당하는 방식으로 수신된 데이터를 해석해야 할 가능성이 높습니다.
DS3231(및 동일한 시리즈의 호환 제품: DS3232) 및 통합 사양에 따른 데이터 해석, 예를 들어 시간을 나타내는 다양한 숫자의 값은 다음과 같이 표시됩니다. BCD(이진 코드 십진수) 10진수 값으로 표현하는 것이 더 편리할 것입니다(a 바이트)에서 사용 아두 이노
같은 줄에서 온도는 바이트로 표시됩니다. 2의 보수 정수 부분의 경우 1/4도의 분해능을 갖는 단계의 경우 2비트, 소수 부분. 시계의 데이터 표현에 대한 이러한 측면과 기타 측면은 아래 라이브러리 코드에서 철저하게 논의되었습니다. DS3231
이 라이브러리로 온도를 확인하려면 다음 메소드를 사용하십시오. 읽기_온도() 목적 DS3231 처음에 인스턴스화되었습니다. 날짜와 시간을 읽으려면 먼저 로드된 다음 다양한 용도로 사용할 수 있는 형식(컴팩트, 휴먼...) 중 하나로 요청됩니다. 이는 아래 코드 라이브러리의 헤더 문서에 설명되어 있습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | //DS3231.h #if defined(ARDUINO) && ARDUINO>=100 #include “Arduino.h” #else #include “WProgram.h” #endif #include <Wire.h> #define TEMPERATURA_MAXIMA_DS3231 85.0 // Máxima temperatura que se puede medir con un DS3231 (70 grados en la versión comercial / no-industrial) #define TEMPERATURA_MINIMA_DS3231 -40.0 // Mínima temperatura que se puede medir con un DS3231 (0 grados en la versión comercial / no-industrial) #define DIRECCION_DS3231 B1101000 // Según datasheet #define TIMEOUT_I2C_DS3231 200 // Máximo tiempo de espera del bus I2C del DS3231 #define NUMERO_ELEMENTOS_FECHA 7 // Número de elementos (un byte por elemento) que tiene la matriz con los datos de la fecha #define NUMERO_BYTES_TEMPERATURA 2 // Número de bytes con los que se representa la temperatura (uno para la parte entera y el signo y otro para la parte decimal representada con una resolución de 0.25 grados) #define RESOLUCION_DECIMALES_DS3231 0.25 // Grados de cada paso de la parte decimal #define ROTACION_DECIMALES 6 // Rotación necesaria hasta llegar a los bits que contienen la parte que representa los decimales de la temperatura (rotar 6 corresponde a atender a los bits 7 y 8) #define MASCARA_DECIMALES B11000000 // Máscara para eliminar con una operación and la parte no significativa. En el caso el DS3231 no hace nada ya que al rotar queda sólo la parte relevante. class DS3231 { private: char valor_fecha_hora_DS3231[7]; // Matriz de valores numéricos (7 char) de la fecha y la hora. El índice 0 representa los segundos, el 1 los minutos, el 2 las horas (en formato de 24), el 3 el día de la semana empezando en el domingo que es 1, el 4 el día del mes, el 5 el número del mes y el 6 los dos últimos dígitos del año char hora_humana_DS3231[11]; // Hora en el formato hh:mm:ss siendo hh la hora (en formato de 24) representada con 2 dígitos, mm los minutos con 2 dígitos y ss los segundos con 2 dígitos char fecha_humana_DS3231[11]; // Fecha en formato DD/MM/AAAA siendo DD el día representado con 2 dígitos, MM el mes con 2 dígitos y AAAA el año con 4 dígitos char fecha_hora_MySQL_DS3231[20]; // Fecha en formato AAAA-MM-DD hh:mm:ss (estilo MySQL) siendo AAAA el año representado con 4 dígitos, MM el mes con 2 dígitos, DD el día con 2 dígitos, hh la hora (en formato de 24) con 2 dígitos, mm los minutos con 2 dígitos y ss los segundos con 2 dígitos char fecha_hora_compacta_DS3231[13]; // Fecha en formato compacto (como la anterior pero sin adornos y dos dígitos para el año) para escribir en log y en bases de datos char bcd_a_decimal(char bcd); // Convertir de BCD a decimal char decimal_a_bcd(char decimal); // Convertir de decimal a BCD protected: public: DS3231(); ~DS3231(); void cargar_fecha_hora(); void grabar_fecha_hora(char *fecha); char *valor_fecha_hora(); char *hora_humana(); // Hora en el formato hh:mm:ss siendo hh la hora (en formato de 24) representada con 2 dígitos, mm los minutos con 2 dígitos y ss los segundos con 2 dígitos unsigned int reloj_4_digitos_7_segmentos(); // La hora tal como la esperan la mayoría de relojes de cuatro dígitos LED de 7 segmentos char *fecha_humana(); // Fecha en formato DD/MM/AAAA siendo DD el día representado con 2 dígitos, MM el mes con 2 dígitos y AAAA el año con 4 dígitos char numero_dia_semana(); // Eso y empezando en domingo que es el 1 char *fecha_hora_MySQL(); // Fecha en formato AAAA-MM-DD hh:mm:ss (estilo MySQL) siendo AAAA el año representado con 4 dígitos, MM el mes con 2 dígitos, DD el día con 2 dígitos, hh la hora (en formato de 24) con 2 dígitos, mm los minutos con 2 dígitos y ss los segundos con 2 dígitos char *fecha_hora_compacta(); // Fecha en formato compacto (como la anterior pero sin adornos y dos dígitos para el año) para escribir en log y en bases de datos double leer_temperatura(); double temperatura_minima(); double temperatura_maxima(); }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | //DS3231.cpp #include “DS3231.h” DS3231::DS3231() { //Wire.begin(); // Dependiendo de la versión del IDE puede ser maestro por defecto o no y habrá que activar en la librería o en la aplicación que la use (en el ejemplo se activa desde la aplicación, lo que permite un uso más genérico) } DS3231::~DS3231() { } void DS3231::cargar_fecha_hora() { unsigned long timeout_i2c; byte contador; Wire.beginTransmission(DIRECCION_DS3231); // Comunicar con el DS3231 en la dirección correspondiente Wire.write(0x00); // pedir registros desde la primera dirección Wire.endTransmission(); // Liberar el bus I2C Wire.requestFrom(DIRECCION_DS3231,NUMERO_ELEMENTOS_FECHA); // esperar NUMERO_ELEMENTOS_FECHA bytes timeout_i2c=millis()+TIMEOUT_I2C_DS3231; while(Wire.available()<NUMERO_ELEMENTOS_FECHA&&millis()<timeout_i2c){} // Esperar a que lleguen los datos o a que pase el tiempo mínimo de espera // Para usar sin espera: if(Wire.available()) for(contador=0;contador<NUMERO_ELEMENTOS_FECHA;contador++) { valor_fecha_hora_DS3231[contador]= Wire.read(); // Leer todos los datos sin discriminar aunque luego tendrán distinto tratamiento } valor_fecha_hora_DS3231[0]=bcd_a_decimal(valor_fecha_hora_DS3231[0]); // segundos en BCD valor_fecha_hora_DS3231[1]=bcd_a_decimal(valor_fecha_hora_DS3231[1]); // minutos en BCD valor_fecha_hora_DS3231[2]=((valor_fecha_hora_DS3231[2]&B00110000)>>4)*10+(valor_fecha_hora_DS3231[2]&B00001111); // BCD en modo de 24 horas valor_fecha_hora_DS3231[3]=valor_fecha_hora_DS3231[3]&B00000111; // Número de día de la semana empezando en 1 que es domingo valor_fecha_hora_DS3231[4]=((valor_fecha_hora_DS3231[4]&B00110000)>>4)*10+(valor_fecha_hora_DS3231[4]&B00001111); // Número del día del mes valor_fecha_hora_DS3231[5]=((valor_fecha_hora_DS3231[5]&B00010000)>>4)*10+(valor_fecha_hora_DS3231[5]&B00001111); // Número de mes (sin MSB) valor_fecha_hora_DS3231[6]=bcd_a_decimal(valor_fecha_hora_DS3231[6]); // Año en BCD (dos últimos dígitos) } char *DS3231::valor_fecha_hora() { //cargar_fecha_hora(); return valor_fecha_hora_DS3231; } char *DS3231::hora_humana() { //cargar_fecha_hora(); sprintf ( hora_humana_DS3231, “%02d:%02d:%02d”, valor_fecha_hora_DS3231[2], valor_fecha_hora_DS3231[1], valor_fecha_hora_DS3231[0] ); return hora_humana_DS3231; } unsigned int DS3231::reloj_4_digitos_7_segmentos() { //cargar_fecha_hora(); return (int)valor_fecha_hora_DS3231[2]*100+(int)valor_fecha_hora_DS3231[1]; } char *DS3231::fecha_humana() { //cargar_fecha_hora(); sprintf ( fecha_humana_DS3231, “%02d/%02d/20%02d”, // Formato de fecha y hora estilo español ¡Olé! valor_fecha_hora_DS3231[4], valor_fecha_hora_DS3231[5], valor_fecha_hora_DS3231[6] ); return fecha_humana_DS3231; } char DS3231::numero_dia_semana() { //cargar_fecha_hora(); return valor_fecha_hora_DS3231[3]; } char *DS3231::fecha_hora_compacta() { //cargar_fecha_hora(); sprintf ( fecha_hora_compacta_DS3231, “%02d%02d%02d%02d%02d%02d”, // Formato de fecha y hora compacta para log y base de datos valor_fecha_hora_DS3231[6], valor_fecha_hora_DS3231[5], valor_fecha_hora_DS3231[4], valor_fecha_hora_DS3231[2], valor_fecha_hora_DS3231[1], valor_fecha_hora_DS3231[0] ); return fecha_hora_compacta_DS3231; } char *DS3231::fecha_hora_MySQL() { //cargar_fecha_hora(); sprintf ( fecha_hora_MySQL_DS3231, “20%02d-%02d-%02d %02d:%02d:%02d”, // Formato de fecha y hora estilo MySQL valor_fecha_hora_DS3231[6], valor_fecha_hora_DS3231[5], valor_fecha_hora_DS3231[4], valor_fecha_hora_DS3231[2], valor_fecha_hora_DS3231[1], valor_fecha_hora_DS3231[0] ); return fecha_hora_MySQL_DS3231; } void DS3231::grabar_fecha_hora(char *fecha) { byte contador; Wire.beginTransmission(DIRECCION_DS3231); // Comunicar con el DS3231 en la dirección correspondiente Wire.write(0x00); // Empezar el envío en la primera dirección for(contador=0;contador<NUMERO_ELEMENTOS_FECHA;contador++) { Wire.write(decimal_a_bcd(fecha[contador])); // Escribir cada valor expresándolo en BCD } Wire.endTransmission(); // Liberar el bus I2C } double DS3231::leer_temperatura() { byte msb; // El byte más significativo contiene la parte entera de la temperatura (en complemento a 2 para poder representar temperaturas bajo cero) byte lsb; // El byte menos significatico contiene la parte decimal con una resolución de un cuarto de grado float temperatura=TEMPERATURA_MAXIMA_DS3231+1.0; // Un número mayor que el máximo como aviso de que algo va mal boolean negativo=false; // Inicialmente se considera postivo unsigned long timeout_i2c; Wire.beginTransmission(DIRECCION_DS3231); // Preparar el dispositivo Wire.write(0x11); // Solicitar temperatura (empieza en 11h y termina en 12h) Wire.endTransmission(); Wire.requestFrom(DIRECCION_DS3231,NUMERO_BYTES_TEMPERATURA); // Esperar temperatura: pedir dos bytes en la dirección del integrado timeout_i2c=millis()+TIMEOUT_I2C_DS3231; while(Wire.available()<NUMERO_BYTES_TEMPERATURA&&millis()<timeout_i2c){}// Esperar a que lleguen los datos o pase el tiempo de espera máximo // Para usar sin espera: if(Wire.available()) msb=Wire.read(); // parte entera con signo en complemento a dos lsb=Wire.read(); // parte fraccional con resolución de 0.25 grados negativo=msb>B01111111; // Es negativo si el primer dígito es uno temperatura=msb&B01111111; // revertir complemento a dos temperatura+=((lsb&MASCARA_DECIMALES)>>ROTACION_DECIMALES)*RESOLUCION_DECIMALES_DS3231; // atender sólo a los bits que contienen la parte decimal (7 y 8), multiplicar por el paso de la resolución y sumar a la parte entera de la temperatura if(negativo) { temperatura*=–1; // Cambiar el signo } return temperatura; } double DS3231::temperatura_minima() { return TEMPERATURA_MINIMA_DS3231; } double DS3231::temperatura_maxima() { return TEMPERATURA_MAXIMA_DS3231; } char DS3231::bcd_a_decimal(char bcd) // Convertir de BCD a decimal { return ((bcd&B11110000)>>4)*10+(bcd&B00001111); } char DS3231::decimal_a_bcd(char decimal) // Convertir de decimal a BCD { return decimal/10*16+(decimal%10); } |
다음은 라이브러리 사용 방법을 보여주는 예제 코드입니다. 위에서 언급했듯이 온도는 함수로 간단히 읽혀집니다.
클래스 객체의 그러나 판독 오류를 무시하기 위해 데이터 시트에 따라 장치의 최대 및 최소 온도를 각각 저장하고 해당 기능으로 판독하는 두 개의 상수가 사용됩니다.온도 판독은 두 단계로 수행됩니다. 먼저 값이 로드되어 날짜나 시간의 다양한 사용이 일관되게 유지되고(불리한 경우에는 더 높은 값이 표시되지 않음) 두 번째는 다음 형식에 따라 사용됩니다. 필요합니다. 예제 프로그램(모든 가능성을 설명하지만 그다지 실용적이지는 않음)은 사용 가능한 모든 형식을 보여줍니다.
-
함수 이륜 전차 (바이트) 시계의 날짜와 시간을 나타내는 7개의 숫자 값을 포함합니다. DS3231 십진수로 변환됩니다(그들은 BCD 장치에서)
배열에 대한 포인터를 반환합니다. -
기능 사용
일요일부터 시작하는 요일의 숫자에 해당하는 값을 구합니다. 텍스트로 표시하려면 배열을 사용하고 인덱스 0인 일요일부터 시작하여 1을 뺍니다. -
"로컬"(스페인어) 형식으로 날짜를 확인하려면 다음 기능을 사용하세요.
는 날짜가 DD/MM/YYYY 형식으로 표시되는 문자열에 대한 포인터를 반환합니다. 여기서 DD는 2자리 숫자로 표시되는 일, MM은 2자리 숫자로 표시되는 월, YYYY는 4자리 숫자로 표시되는 연도입니다. -
함수
hh:mm:ss 형식으로 시간을 반환합니다. 여기서 hh는 24자리의 시간(2 형식)이고, mm은 2자리의 분, ss는 2자리의 초입니다. -
날짜와 시간을 쉽게 사용하려면 로그 파일 기능이 프로그래밍되었습니다 , YYMMDDhhmmss 형식으로 날짜 및 시간 값을 전달합니다. 여기서 AA는 마지막 2자리 연도, MM은 2자리 월, DD는 2자리 일, hh는 시간(24 형식) 2입니다. mm는 2자리의 분, ss는 2자리의 초입니다. 이 형식은 텍스트임에도 불구하고 공간을 거의 차지하지 않으며 매우 간단한 알파벳 순서를 허용합니다.
-
함수 MySQL의 (또는 새롭고 자유로운 MariaDB) YYYY-MM-DD hh:mm:ss, 여기서 YYYY는 4자리로 표시되는 연도, MM은 2자리로 표시되는 월, DD는 2자리로 표시되는 일, hh는 24자리로 표시되는 시간(2 형식)입니다. , mm은 2자리의 분, 2자리의 초입니다.
데이터베이스 관리자가 사용하는 형식으로 날짜와 시간을 표시하는 데 사용됩니다.
날짜와 시간을 표현하는 형식은 다양하지만 필요한 형식이 없을 수도 있지만 확실히 기존 형식 중 하나를 기반으로 하고 이를 예로 사용하면 다음과 같이 새 메서드를 쉽게 추가할 수 있습니다. 다른 사양. 새로운 기능을 추가하시면 코드를 공유(공개!) 해주시고, 어떻게 작동하는지 설명해주시면 조금씩 라이브러리를 개선할 수 있도록 해주세요. 감사합니다!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #define INTERVALO_MEDICION 100000 // Medir temperatura cada 100 segundos (se renueva internamente en el DS3231 cada 64 segundos) #define ESPERA_ERROR 1000 // Tiempo de espera antes de volver a medir si se ha producido un error #define ELEMENTOS_MATRIZ_FECHA 7 #include “DS3231.h” #include <Wire.h> char buffer_fecha[ELEMENTOS_MATRIZ_FECHA]; char *puntero_fecha; float temperatura; unsigned long cronometro; byte contador; String dia_semana[]={“lunes”,“martes”,“miércoles”,“jueves”,“viernes”,“sábado”,“domingo”}; DS3231 reloj; void setup() { Serial.begin(9600); Wire.begin(); // Inicializar Wire sólo si no se hace dentro del constructor (de la librería) Este método, hacerlo en la aplicación, supone que se usa Wire para comunicar con otros dispositivos, no sólo con el DS3231 cronometro=0; // para que empiece inmediatamente } void loop() { if(millis()>cronometro) { temperatura=reloj.leer_temperatura(); if(temperatura>reloj.temperatura_maxima()||temperatura<reloj.temperatura_minima()) { cronometro=millis()+ESPERA_ERROR; } else { cronometro=millis()+INTERVALO_MEDICION; reloj.cargar_fecha_hora(); puntero_fecha=reloj.valor_fecha_hora(); for(contador=0;contador<ELEMENTOS_MATRIZ_FECHA;contador++) { buffer_fecha[contador]=*(puntero_fecha+contador); Serial.println(“Contenido de la posición “+String(contador,DEC)+” del buffer de la fecha -> “+String(int(buffer_fecha[contador]),DEC)); } Serial.print(“El día “); Serial.print(reloj.fecha_humana()); Serial.print(“, “); Serial.print(dia_semana[reloj.numero_dia_semana()–1]); Serial.print(“, a las “); Serial.println(reloj.hora_humana()); Serial.print(“(“); Serial.print(reloj.reloj_4_digitos_7_segmentos()); Serial.print(” en un reloj de 4 dígitos y “); Serial.print(reloj.fecha_hora_MySQL()); Serial.print(” según MySQL o “); Serial.print(reloj.fecha_hora_compacta()); Serial.println(” abreviadamente)”); Serial.print(“la temperatura era de “); Serial.print(temperatura); // Mostrar la temperatura Serial.println(” grados centígrados”); } } } |
위 예제 프로그램의 출력은 다음 이미지에 표시된 것과 유사할 수 있습니다. 7개 값 목록(초, 분, 시간, 요일, 월, 월, 연도), 날짜 및 "인간의" 방식으로 표현된 시간(스페인 스타일에 따름) XNUMX자리 시계 형식의 정수로 표시된 시간, 데이터베이스 형식의 날짜 및 시간 MySQL의, 간단한 형식의 날짜 및 시간(예: 로그) 및 내부 온도 DS3231.
코멘트 남기기