This project shows how to make a simple timer (start/stop/reset) using ATtiny13, LED Tube module based on TM1637 and one switch. Complete code is on GitHub.
Parts
- ATtiny13 – i.e. MBAVR-1 development board
- LED Tube Display based on TM1637
- Switch – i.e. simple tact-switch
Circuit Diagram
Software
This code is written in C and can be compiled using the avr-gcc. More details on how compile this project is here. Complete example code is on GitHub.
/** * Copyright (c) 2018, Łukasz Marcin Podkalicki <lpodkalicki@gmail.com> * ATtiny13/019 * Simple timer (START/RESET/STOP) using one button and 7-segments * display module based on TM1637. * * Note that this ATtiny13 project is using internal clock which is not precise * and time may flow forwards or backwards, but hey! * it's still enough to make a good eggs timer :) */ #include <stdint.h> #include <avr/io.h> #include <util/delay.h> #include <avr/interrupt.h> #include "tm1637.h" #define BUTTON_PIN PB2 #define TIMER_UPDATE (1 << 1) #define TIMER_STOP (1 << 2) #define TIMER_START (1 << 3) #define TIMER_RESET (1 << 4) static volatile uint8_t timer_counter; static volatile uint8_t timer_events; static volatile uint8_t timer_seconds; static volatile uint8_t timer_minutes; static volatile uint8_t timer_colon; static void timer_init(void); static void timer_handler(void); static void timer_process(void); static void timer_display(const uint8_t minutes, const uint8_t seconds, const uint8_t colon); ISR(TIM0_COMPA_vect) { timer_handler(); } int main(void) { /* setup */ timer_init(); /* loop */ while (1) { timer_process(); } } void timer_init(void) { TM1637_init(1, 4); DDRB &= ~_BV(BUTTON_PIN); // explicity set BUTTON pin as INPUT PORTB |= _BV(BUTTON_PIN); // set pull-up resitor for BUTTON pin TCCR0A |= _BV(WGM01); // set timer counter mode to CTC TCCR0B |= _BV(CS01)|_BV(CS00); // set prescaler to 64 (CLK=1200000Hz/64/250=75Hz) OCR0A = 249; // set Timer's counter max value (250 - 1) TIMSK0 |= _BV(OCIE0A); // enable Timer CTC interrupt timer_counter = timer_seconds = timer_minutes = 0; // reset counters timer_events = TIMER_UPDATE | TIMER_RESET; // reset timer & update display timer_colon = 1; // show colon sei(); // enable global interrupts } void timer_handler(void) { if (!(timer_events & TIMER_START)) { return; } timer_counter++; if (timer_counter == 38) { timer_colon = 1; timer_events |= TIMER_UPDATE; } else if (timer_counter == 75) { timer_colon = 0; timer_counter = 0; if (++timer_seconds == 60) { timer_seconds = 0; if (++timer_minutes == 100) { timer_minutes = 0; } } timer_events |= TIMER_UPDATE; } } void timer_process(void) { /* Process start/stop/reset */ if ((PINB & _BV(BUTTON_PIN)) == 0) { _delay_ms(10); // time for debounce while((PINB & _BV(BUTTON_PIN)) == 0); if (timer_events & TIMER_START) { timer_colon = 1; timer_events = TIMER_UPDATE | TIMER_STOP; } else if (timer_events & TIMER_STOP) { timer_minutes = timer_seconds = 0; timer_colon = 1; timer_events = TIMER_UPDATE | TIMER_RESET; } else if (timer_events & TIMER_RESET) { timer_events = TIMER_START; } } /* Update display */ if (timer_events & TIMER_UPDATE) { timer_display(timer_minutes, timer_seconds, timer_colon); timer_events &= ~TIMER_UPDATE; } } void timer_display(const uint8_t minutes, const uint8_t seconds, const uint8_t colon) { /* Display minutes */ TM1637_display_digit(0, minutes / 10); TM1637_display_digit(1, minutes % 10); /* Display seconds */ TM1637_display_digit(2, seconds / 10); TM1637_display_digit(3, seconds % 10); /* Show/hide colon */ TM1637_display_colon(colon); }
Great Work 🙂
Thank You