Официальный сайт компании Arduino по адресу arduino.cc
Игрушечный светофор
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
увидел сразу на этом и другом форумах обсуждение светофоров и загорелся сделать такой для ребенка (или для себя?)
чтобы проект не получился банальным, решено было его сделать на современных решениях - используя stepup преобразователь с питанием от одной батарейки и самый маленький МК в линейки атмела - tiny9 (в этой серии есть еще tiny4/5/10).
Извините, что не совсем ардуино, но разница минимальна, код моей программы можно практически напрямую вставлять в ардуино. Его особенность в том, что основной цикл программы практически пустой и все делается на прерываниях, по сути алгоритм работы светофора представлен в виде массива данных - пара чисел цвет и время. Еще одна особенность в том, что питание ни когда не отключается, но потребление в режиме сна минимизировано.
Нажатие кнопки сначала обрабатывается в прерывании PCINT где запускается таймер, по истечении таймера уже в обработчике таймера проверяется нажата ли еще кнопки и если нажато генерится событие нажатия. Так решена проблема с дребезгом контактов. Но так обрабатывается кнопка только в активном режиме. В режиме сна таймер не работает и мы реагируем на первое событие нажатия кнопки.
Во фьюзах запрограмирован RSTDISBL, чтобы использовать все четыре пина - три для светодиодов и один для кнопки. Кнопкой можно включать и выключать. Еще осталось место и можно запрограмировать на кнопку 2-3 режима работы. Питание отключается и по тайматуту в 20 минут. Надеюсь такие хитрости обеспечат весьма продолжительную работу от одной пальчиковой батарейки. Напряжение питания выбрано минимально-оптимальноре - 2.4В, оно по идее должно сохраняться до глубокой разрядки батарейки (степап перестает работать при падении напряжения ниже 0,35в). Частота МК снижена до оптимального значения 128000/16=8000Гц
степаап сделан на mcp1640, заодно хотелось освоить эту микросхему, планирую ее дальше использовать в батарейных сенсорах.
схема:
скетч ниже (для atmel studio)
/* * P7005_traffic_lights_v1.c * * Created: 09.11.2013 18:46:39 * Author: axillent */ #define RED_PIN (1 << PB2) #define YELLOW_PIN (1 << PB1) #define GREEN_PIN (1 << PB0) #define BUTTON (1 << PB3) #define TIMEOUT 20 * 60 * 10 // seconds * 10 - timeout to switch off #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include <avr/pgmspace.h> #include <util/delay.h> volatile enum { power_off=0, power_on, power_to_on } status; enum color_enum { led_red=0, led_yellow, led_green, led_none }; typedef enum color_enum color_enum; typedef struct { uint8_t color; uint8_t delay; } led_data; volatile struct { uint8_t timer; uint8_t pressed; } button; volatile struct { uint8_t index; uint8_t timer; // const led_data* data; uint8_t size; } run_data; volatile uint16_t timeout; const led_data data01[] PROGMEM = { { led_green, 150 }, { led_none, 5 }, { led_green, 5 }, { led_none, 5 }, { led_green, 5 }, { led_none, 5 }, { led_green, 5 }, { led_yellow, 15 }, { led_red, 150 }, { led_red, 5 }, { led_none, 5 }, { led_red, 5 }, { led_none, 5 }, { led_red, 5 }, { led_none, 5 }, { led_yellow, 15 } }; void redOff() { PORTB |= RED_PIN; } void redOn() { PORTB &= ~RED_PIN; } void yellowOff() { PORTB |= YELLOW_PIN; } void yellowOn() { PORTB &= ~YELLOW_PIN; } void greenOff() { PORTB |= GREEN_PIN; } void greenOn() { PORTB &= ~GREEN_PIN; } void switchLed(color_enum color, uint8_t s) { switch(color) { case led_green: if(s) greenOn(); else greenOff(); break; case led_yellow: if(s) yellowOn(); else yellowOff(); break; case led_red: if(s) redOn(); else redOff(); break; case led_none: break; } } void start(const led_data* d, uint8_t size) { //run_data.data = d; run_data.index = 0; run_data.size = size; switchLed(pgm_read_byte(&data01[0].color), 1); run_data.timer = pgm_read_byte(&data01[0].delay); } ISR(TIM0_COMPA_vect) { if(status == power_on) { if(run_data.timer) { if(!--run_data.timer) { //redOn(); switchLed(pgm_read_byte(&(data01[run_data.index].color)), 0); if(++run_data.index >= run_data.size) run_data.index = 0; switchLed(pgm_read_byte(&(data01[run_data.index].color)), 1); run_data.timer = pgm_read_byte(&data01[run_data.index].delay); } } } // button if(button.timer) if(!--button.timer && (PINB & BUTTON)) button.pressed = 1; // timeout if(timeout) if(!--timeout) status = power_off; } ISR(PCINT0_vect) { if(status == power_on) { if(!button.pressed && (PINB & BUTTON)) button.timer = 1; } else { if(PINB & BUTTON) button.pressed = 1; } } int main(void) { // switch to 128000 hz CCP = 0xD8; CLKMSR = (1 << CLKMS0); CCP = 0xD8; CLKPSR &= ~0b1111; CCP = 0xD8; CLKPSR |= (1 << CLKPS2); status = power_to_on; button.pressed = 0; button.timer = 0; while(1) { switch(status) { case power_off: //DDRB &= ~(RED_PIN | YELLOW_PIN | GREEN_PIN); PORTB |= (RED_PIN | YELLOW_PIN | GREEN_PIN | BUTTON); ACSR |= (1 << ACD); //PRR |= (1 << PRTIM0) | (1 << PRADC); //SMCR = (1 << SM1); set_sleep_mode(SLEEP_MODE_PWR_DOWN); sei(); sleep_enable(); //SMCR |= (1 << SE); sleep_cpu(); //SMCR &= ~(1 << SE); sleep_disable(); //PRR &= ~(1 << PRTIM0); //sei(); if(button.pressed) { status = power_to_on; button.pressed = 0; } break; case power_on: set_sleep_mode(SLEEP_MODE_IDLE); sleep_enable(); sei(); sleep_cpu(); sleep_disable(); //sei(); if(button.pressed) { status = power_off; button.pressed = 0; } break; case power_to_on: cli(); PORTB |= (RED_PIN | YELLOW_PIN | GREEN_PIN | BUTTON); DDRB |= RED_PIN | YELLOW_PIN | GREEN_PIN; ACSR |= (1 << ACD); PCICR |= (1 << PCIE0); PCMSK |= (1 << PCINT3); TCCR0B = (1 << CS01) | (1 << WGM02); OCR0A = 1600 / 16; TCNT0 = 0; TIMSK0 |= (1 << OCIE0A); timeout = TIMEOUT; cli(); start(data01, sizeof(data01)/sizeof(data01[0])); status = power_on; sei(); break; } } }
все детали на этой платке, приведу ее для представления миниатюрности:
симпатично!
а из чего корпус делали?
Корпус напечатан на 3д принтере
http://radiokot.ru/forum/viewtopic.php?f=9&t=90961
Как аккуратно! Лудили обычным паяльником?
Как аккуратно! Лудили обычным паяльником?
ничего сложного - ЛУТ + лужение сплавом розе в кипятке с лимонной кислотой
(для atmel studio)
простите а второй cli() тут зачем? мы же один уже отправил ранее, а sei() только вконце включаем
Да, у вас всё серьёзно.) А мы с малой делали из подручных средств - картонка, бумага, 10 мм фанера в качестве подскавки. Правда, индикация на всех 4х сторонах, а на двух по 2 7-сегментных индикатора, типа как у взрослых.) Вот эта порнография.)
CW предпочитаете? )))
Ну никак от вас не спрячешься.) Да, есть такой грех.)