Reloj basado en ATtiny85 minimalista usando 12 LED

Tiny Watch Time

3 ª de diciembre de el año 2016

Traduccion literal de: http://www.technoblogy.com/show?KVM

Aquí está mi diseño para un reloj basado en ATtiny85 minimalista usando 12 LED, dispuestos como una esfera de reloj, para mostrar el análogo de estilo de tiempo:

TinyTimeWatch.jpg

El reloj de tiempo Tiempo basado en ATtiny85; es cuatro y cinco.

Para mostrar el momento de pulsar el botón en la esfera del reloj, y luego se muestra el tiempo durante cuatro segundos. Se enciende un LED para mostrar la hora, y destella otro LED para mostrar los minutos a los cinco minutos más próximos, como la hora y los minutos en un reloj. Si sólo hay un LED se enciende usted sabe que ambas manos están apuntando a la misma hora de juego.

El reloj utiliza minúscula del tiempo de la década de ATtiny85 oscilador incorporado, sintonizar para conseguirlo lo más preciso posible, y mi reloj mantiene la hora dentro de un par de minutos a lo largo de 24 horas. Se puede ajustar el tiempo manteniendo pulsado el botón durante más de cuatro segundos.

Es impulsado por una pila de botón CR2032, y he utilizado varias técnicas para reducir el consumo de corriente, por lo que la batería debe durar más de un mes. El coste total de componentes, excluyendo el PCB, es alrededor de £ 5 / $ 5, y es fácil de construir.

Introducción

Me he inspirado para diseñar este reloj después de leer acerca de Watch empollón de Sam DeRose [1]  , que lleva el minimalismo un paso más allá. Parece fortuita que se puede conducir 12 LEDs de cuatro líneas de E / S utilizando Charlieplexing, exactamente el número que necesita para mostrar una cara de reloj, aprovechando el hecho de que se puede conducir dos LEDs de cada par diferente de las líneas de E / S . Se necesita una línea más de E / S para detectar el botón de prensa, cuidadosamente usando las cinco líneas de E / S disponibles en el ATtiny85.

Construcción

Aquí está el circuito del reloj minúscula del tiempo, presenta como la placa de circuito:

TinyTimeWatch.gif

Circuito del Reloj del tiempo Tiempo basado en ATtiny85.

Construí el reloj sobre una pequeña placa de circuito impreso, el uso de componentes SMD, con todos los componentes aparte del soporte de la batería soldada a un lado de la junta. He utilizado un ATtiny85 SOIC y 0805 resistencias y LEDs, por lo que son relativamente fáciles de soldar a mano. Arreglé los LEDs para evitar carreteras que recorren en la disposición que explica el orden en lugar azar, pero esto es fácilmente acomodado en el software. La siguiente tabla muestra los cuales LED se enciende cuando se toma una línea de E / S de alto y la otra línea de E / S de baja:

WatchLEDs.gif

El botón es un botón pulsador en miniatura SMD disponible de Sparkfun [2] , disponible en Proto-PIC en el Reino Unido [3] , y el soporte de la batería es un soporte de tipo botón SMD 20mm también disponible de Sparkfun [4] , o del proto-PIC en el Reino Unido [5] .

Los LED son de tamaño 0805, y yo elegimos LEDs blancos, ya que tienden a ser los más brillantes. Yo tengo la mía desde componentes brillantes en el Reino Unido, que los venden por menos de £ 1 por cada diez  [6] . Los LED se deben soldar con la misma orientación, con los lados negativos que enfrenta el centro del tablero.

Diseñé la junta en Eagle y como un experimento envió a ambos Seeed Fusión  [7]  y la SST Parque  [8]  para la fabricación. Aquí está la vista previa del servicio de la SST Park:

TinyTimeWatchPCB.gif

Hay un enlace a los archivos de águila en el final del artículo, si se desea crear una tabla. Por otra parte, debido a que el diseño de la pista evita cambios de cara se puede utilizar una sola cara placa, molidos utilizando una fresadora como el Othermill; usted podría entonces pegar el soporte de la batería hacia el otro lado, y conectarlo a través de dos agujeros al circuito principal.

He utilizado una pistola de aire caliente Youyue 858D + a 250 ° C para soldar los componentes SMD en la parte frontal de la junta, y, finalmente, soldadas al soporte de la batería en la parte posterior de la placa utilizando un soldador convencional. Si usted no tiene una pistola de aire caliente que debe ser capaz de soldar los componentes SMD con un poco de cuidado utilizando un soldador de punta fina.

Me encontré con una correa de reloj de hilo a través de ancho 12 mm adecuada de un proveedor alemán [9] :

TinyTimeStrap.jpg

El programa

Esta sección explica las diferentes secciones del programa Tiempo diminuto reloj.

La pantalla

Los 12 LEDs son impulsados ​​por los cuatro de E / S líneas PB0, PB1, PB3 y PB4. PB2 se utiliza para el botón pulsador, porque se asigna a la interrupción INT0, lo que hace que la detección en el botón un poco más fácil.

La matriz Pin [5] [5] especifica cómo los LEDs están conectados a las cinco líneas de E / S:

int botones [5] [5] = {{-1, 10, -1, 2, 0},
                  {11, -1, -1, 3, 7},
                  {-1, -1, -1, -1, -1},
                  {1, 9, -1, -1, 5},
                  {6, 8, -1, 4, -1}};

La primera fila de la matriz especifica qué LEDs tienen sus cátodos conectados a PB0: el LED a las 10 horas tiene su ánodo conectado a PB1, el LED a las 2 tiene su ánodo conectado a PB3, y los dirigidos a las 12 'reloj tiene su ánodo conectado a PB4. Los valores de la matriz correspondiente a PB2 se establecen en -1.

Solía temporizador / Counter0 funcionando a 250 Hz tanto para contar el número de segundos, y para multiplexar la pantalla. Esto se configura en la configuración () de la siguiente manera:

  TCCR0A = 2 << WGM00; // Modo de CTC; contar hasta OCR0A
  TCCR0B = 0 << WGM02 | 2 << CS00; // Dividir por 8 = 62500Hz
  OCR0A = 249; // Dividir por 250 -> 250 Hz
  TIMSK = TIMSK | 1 << OCIE0A; // Habilitar comparar partido de interrupción

Aquí está la rutina de servicio de interrupción:

ISR (TIM0_COMPA_vect) {
  Las garrapatas ++;
  si (== Las garrapatas Tickspersec) {garrapatas = 0; ++ Segundos; }
  si el retorno (DISPLAY en!);
  DisplayNextRow ();
  Se acabó el tiempo--;
  si (Tiempo de espera = 0) return;
  si (PINB y 1 << PINB2) {
  // Si el botón es ahora, desactivar la visualización
    DDRB = 0; // Pantalla en blanco - todas las entradas
    PORTB = 0xFF; // Todos los dominadas en
    DISPLAY en = false;
  } Else {
  // Si el botón aún es baja, el tiempo establecido
    Timeout = Tickspersec / 2; // Medio segundo de retardo
    Secs = (unsigned long) (seg + 300);
    Fivemins = (unsigned long) ((seg + 299) / 300) 12%;
    Horas = (unsigned long) ((segundos) + 1799/3600) 12%;
  }
}

En primer lugar se incrementa el contador de segundos, Secs , cada 250 llamadas.

Entonces, si la pantalla se ha encendido, llama  DisplayNextRow () para mostrar la siguiente fila de LEDs.

Por último, se cuenta hacia atrás la variable tiempo de espera de poner en blanco la pantalla automáticamente después de cuatro segundos el botón ha sido presionado.

Si el botón se mantiene pulsado durante más de cuatro segundos, el tiempo comienza a avanzar 5 minutos cada medio segundo, para que pueda configurar la hora correcta, hasta que suelte el botón.

pantalla de multiplexación

La rutina DisplayNextRow () funciona como sigue:

DisplayNextRow void () {
  Ciclo ++;
  fila de bytes = Cycle & 0x03;
  si (fila> 1) fila ++; // Saltar PB2
  bits de byte = 0;
  for (int i = 0; i <5; i ++) {
    if (Horas == Pasadores [fila] [i]) bits = Bits | 1 << i;
    if ((Cycle & 0x20) && (Fivemins == Pasadores [fila] [i])) bits = Bits | 1 << i;
  }
  DDRB = 1 << fila | los bits;
  PORTB = Bits | 0x04; // Mantener alta PB2
}

Hasta dos LED se pueden encender a la vez. El LED especificado por la variable Horas se utiliza para mostrar las horas, y se visualiza de forma continua. El LED especificado por la variable  Fivemins  se utiliza para los minutos, y destella cada 32 veces la rutina es llamada.

La parte inferior dos bits de la variable ciclo de determinar qué fila se está mostrando. Para una fila dada la matriz botones [fila] [i] se comprueba para ver si alguno de los LED en la fila necesita ser visualizado o contrachapado. Si es así, los bits apropiados se establecen en la variable de bits de . Esto entonces se escribe en el puerto.

Viendo el tiempo

El botón pulsador está conectado a la entrada INT0 interrupción, lo que genera una interrupción para mostrar la hora. Se creó en setup () de la siguiente manera:

  PORTB = 0xFF; // Todos los dominadas en
  MCUCR = MCUCR | 2 << ISC00; // Interrupción en el flanco descendente
  GIMSK = 1 << INT0; // Habilitar INT0 interrumpir

La rutina de servicio de interrupción restablece la variable de tiempo de espera , para mantener la pantalla en, y calcula los valores de las variables Horas y Fivemins :

ISR (INT0_vect) {
  // Activar la visualización
  Timeout = Tickspersec * 4; // Display de 4 segundos
  DISPLAY en = true;
  Fivemins = (unsigned long) ((seg + 299) / 300) 12%;
  Horas = (unsigned long) ((segundos) + 1799/3600) 12%;
  Paso = 0;
}

El +299 dos correcciones y 1799 requieren algunas explicaciones:

Decidí que ya que el reloj sólo le muestra el tiempo para el plazo de cinco minutos, se debe redondear el tiempo para la siguiente marca de cinco minuto, por lo que son los primeros en lugar de tarde a las citas! La corrección 299 en el cálculo de Fivemins logra esto.

Mi primera versión del programa de vigilancia muestra el número de horas como una luz iluminada de forma continua y la marca de cinco minuto, como una luz intermitente, pero para los tiempos después de media después de la hora lo que dio una exhibición confusa. Por ejemplo, para el reloj 02:50 sería encender las 2 y 10 LEDs, pero uno de instinto es para leer este como uno y cincuenta; es decir, 1:50. Por consiguiente, la versión actual muestra veces más tarde de medio más allá de la hora por la iluminación del siguiente número de horas, lo que da una pantalla más familiar. Esto se implementa con la corrección de 1799 en el cálculo de las horas .

La reducción del consumo de corriente

Tenía ganas de hacer que el reloj pasado el mayor tiempo posible con una sola batería. Debido a que el oscilador interno se utiliza para mantener el momento no es posible ahorrar energía poniendo el procesador a dormir, y el temporizador de vigilancia no es suficientemente preciso para la hora normal. Por lo tanto, he investigado otras formas de ahorro de energía.

El consumo de corriente de 5V sin que ninguno de estos ahorros de energía fue de 1,68 mA. Estas son las técnicas que utiliza, con el consiguiente ahorro de energía en paréntesis después de cada uno:

Desactivar el ADC (0,32 mA)

Puesto que no estamos utilizando el ADC I inhabilitó con la línea:

ADCSRA & = ~ (1 << ADEN);
Desconectar los relojes de la USI, ADC, y el temporizador / contador 1 (0,20 mA)

Como se describe en la hoja de datos ATtiny85, se puede ahorrar energía apagando los relojes a los circuitos que no está usando fijando los bits en el registro de reducción de energía, PRR:

PRR = 1 << PRUSI | 1 << PRADC | 1 << PRTIM1; // Desactivar relojes
Cambiar al modo entre interrupciones (0,70 mA) Idle

Entre las interrupciones podemos cambiar el procesador al modo, lo que detiene el reloj del procesador, pero deja el sistema de interrupciones y temporizadores de marcha en vacío:

set_sleep_mode (SLEEP_MODE_IDLE);
...
sleep_enable ();
sleep_cpu ();
Reducir la velocidad de reloj del sistema a partir de 1 MHz a 0,5 MHz (0,10 mA)

Por último, podemos reducir el reloj del sistema a 0,5 MHz para reducir aún más el consumo de corriente:

CLKPR = 1 << CLKPCE;
CLKPR = 4 << CLKPS0;

Si por error reducir el reloj del sistema por debajo de 500 kHz que no será capaz de reprogramar el chip usando ISP (In-System Programming), debido a que el procesador no está funcionando lo suficientemente rápido para ejecutar las instrucciones para borrar la memoria flash. Por lo tanto, he incluido un retraso de 5 segundos antes de reducir la velocidad de reloj; si falla ISP, restablecer el procesador y vuelva a intentarlo dentro de los 5 segundos, y entonces debería funcionar.

El consumo de energía final es de aproximadamente 0.36mA a 5V, cayendo a 0.23mA a 3V. Una batería típica CR2032 tiene una capacidad de 225mAH, por lo que debe durar más de un mes.

La compilación del programa

He compilado el programa usando de Spence Konde nuevo y excelente ATtiny subyacente, que ahora es compatible con todos los procesadores ATtiny y reemplaza los diversos núcleos ATtiny anteriores  [10] . Seleccione la serie ATtinyx5 opción prevista en el ATtiny universal partida en la Juntas de menú. A continuación, seleccione el temporizador 1 Reloj de la CPUDBO personas de movilidad reducida , ATtiny85 , 1 MHz (interna) de los menús siguientes. Esta es la configuración de nuevos ATtiny85s fusible por defecto; de lo contrario seleccione  Burn Bootloader  para establecer los fusibles adecuadamente.

He cargado el programa usando un clip que se monta en la parte superior del SMD ATtiny85 [11] , utilizando AVR programador de bolsillo de Sparkfun [12] . La ventaja de este sobre el Tiny Junta programador AVR que yo suelo usar es que le permite programar un circuito mientras es alimentado por su propio suministro, por lo que no tenga que quitar la pila de botón del reloj minúscula del tiempo.

La calibración del oscilador interno

Para evitar la necesidad de un cristal, y los dos pasadores de E / S adicionales que sería necesario, el reloj utiliza el oscilador interno ATtiny85 por su cronometraje. El oscilador interno no es tan preciso como un cristal, pero incluye la posibilidad de poner a punto, para conseguir el reloj tan preciso como sea posible.

Me decidí a calibrar el reloj mediante el ajuste del temporizador / Counter0 valor de comparación partido, OCR0A, en lugar de utilizar el registro OSCCAL incorporado para la calibración. El valor OCR0A nos permite ajustar la calibración de aproximadamente 0,25%, mientras que la calibración OSCCAL es de aproximadamente 1%. Además, la calibración OCR0A es lineal, por lo que después de medir el error se puede calcular cuál debe ser el valor. He utilizado el siguiente procedimiento:

  • Impulsar el reloj de una batería CR2032, como el oscilador se ve afectada por la tensión de alimentación.
  • Ejecute el siguiente programa para generar una frecuencia en el pin PB0.
  • Medir la frecuencia con un medidor de frecuencia, y volver a compilar el programa de pruebas con diferentes valores de OCR0A.
  • Ajustar el valor hasta que se obtiene la frecuencia lo más cerca posible a 1000 Hz.
  • Copiar el valor OCR0A a la  configuración ()  de rutina en el programa Tiempo de vigilancia de Tiny.

Aquí está el programa:

// Reloj Calibre
void setup () {
  retardo (5000);
  CLKPR = 1 << CLKPCE;
  CLKPR = 4 << CLKPS0; // Reloj de 0,5 MHz
  
  // Configurar señal en PB0
  TCCR0A = 1 << COM0A0 | 2 << WGM00; // Toggle PB0
  TCCR0B = 0 << WGM02 | 1 << CS00; // Dividir por 1
  OCR0A = 249; // Dividir por 250
  pinMode (0, OUTPUT); // Ajuste de 1000 Hz en PB0
}

void loop () {
}

Me pareció que me llevó a sólo unos minutos para conseguir la frecuencia dentro mejor que 1 Hz de 1000 Hz.

Si usted no tiene un medidor de frecuencia que podría funcionar el reloj por un par de horas, y luego desde el error de tiempo de calcular el ajuste que necesita para tomar.

Aquí está todo el programa Tiny Tiempo de reloj:  Programa de Vigilancia minúscula del tiempo .

Por otra parte, conseguir que en GitHub aquí junto con los archivos de Eagle para el PCB: Reloj minúscula del tiempo en GitHub .