Как стать автором
Обновить

Светящиеся снежки, или Украшаем Новый Год «подручными материалами»

Время на прочтение 4 мин
Количество просмотров 31K
Вдохновлённый статьёй о светодиодах в снегу, я захотел попробовать сделать что-то похожее и у себя. В комментариях к той статье я публиковал идеи и небольшую кучку фотографий. Даже несмотря на то, что в Подмосковье сейчас снег — штука дефицитная, это не убавило энтузиазма, скорее наоборот — реализовать идею как можно скорее, пока снег ещё есть.

Первой попыткой была колба со статично светящимся светодиодом, но чуть позже была закончена плата с небольшой долькой динамики.



Как это работает и как сделать что-то похожее — смотрите под катом.
P.S. «Подручность» материалов, скорее всего, распространяется на радиолюбителей.

Как всё начиналось


Для начала нам понадобится:
  • Прозрачная колбочка из-под бахил (можно взять в ближайшей поликлинике)
  • Холдер для батарейки типа CR2032 (они бывают разные, нам нужен с зажимом сбоку)
  • Светодиод RGB (я использовал планарный, типоразмера 5050, рассеивающий)
  • Немножко резисторов (тоже планарных, на 100 Ом — питать будем от 3В — батарейки)
  • Кусок стеклотекстолита с медной фольгой
  • Медный купорос или хлорное железо (или ещё в чём вы привыкли травить платы)

image
Плата рисуется элементарно (я даже не стал раскочегаривать принтер, достал маркер для рисования на CD-дисках и быстренько нацарапал, после чего моментально забросил это в раствор травиться, сфотографировать не успел).
Вот так выглядит рисунок платы:


После вытравливания плату следует вырезать по форме холдера для батарейки (проще всего это сделать, заранее просверлив отверстия и вставив холдер сзади, затем обвести маркером холдер. ВНИМАНИЕ! Полярность имеет значение! Следите за положением «ушка» холдера!) и напаять светодиод, резисторы и холдер.

Вот что из этого получается:
image

На плате нарочно не запаян один резистор, я хотел получить пурпурное свечение, для этого нужно включить красный и синий каналы, отключив зелёный.

Вот так получается простейшая светилка. Плату покрываем лаком (на самом деле не обязательно, но так дорожки с меньшей вероятностью потемнеют), вставляем батарейку, упаковываем в колбу и идём лепить снежки!

И тут Остапа понесло


Как программист, который неровно дышит в сторону всякой микроконтроллерной техники, я решил приспособить к делу небольшой чип, который привнесёт чуть больше радости в эту штуковину, заставляя светодиод красиво переливаться разными цветами.

Для этого я взял широко известный в узких кругах контроллер Atmel ATtiny45 (хотел ATtiny13, но их неожиданно в ящике не оказалось, разница только в размере памяти. Программа для этой светилки поместится в ATtiny13), нарисовал плату в Eagle и с помощью лазерно-утюжной технологии перенёс полученный рисунок на фольгированный текстолит.
image
По сравнению с предыдущей версией, на плате появился конденсатор для более стабильного питания и сам микроконтроллер. В плане компонентов тут приходится обходиться малой кровью, так как пространство на плате ограничено. Даже разъёма для программирования я не предусмотрел, подпаивался проводками к пинам (специально для этого каналы светодиода оказались на пинах для программирования, а RESET я вывел отдельной площадкой). Резисторы и конденсаторы на этой плате типоразмера 0805.

Пока платы травились, я занялся программой. В ATtiny45 аппаратный вывод ШИМ-сигнала поддерживается на ножках PB0, PB1 и ещё на нескольких. PB2 в этом списке не оказалось. Но плата уже нарисована и травится, поэтому я решил сделать программный ШИМ, применив второй таймер (Timer1).

Для того, чтобы сделать светилку более гибкой в настройке, я применил такой механизм. В чипе есть ПЗУ (EEPROM). В первой ячейке будем хранить число, которое задаёт режим работы. После каждого включения будем увеличивать это значение на 1 и сохранять его в ПЗУ. Так, дёргая батарейкой в разъёме, можно переключать режимы работы. Для того, чтобы не пропустить нужный, каждый режим я продублировал (фактически, следующий режим включится после двух передёргиваний батарейки).

Весь код на Си (для компилятора AVR-GCC)
#include <avr/io.h>
#include <avr/eeprom.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#define r_pwm(pwm) OCR0A = pwm 
#define b_pwm(pwm) OCR0B = pwm
#define g_pwm(pwm) OCR1A = pwm

#define NUM_MODES 16

int main(void)
{
    /* Init LED GPIO pins */
    DDRB = 7; /* pins 0, 1, 2 */

    /* Init PWM timers */
    /* Timer0 is for R and G channels */
    TCCR0A = (1<<COM0A1)|(1<<COM0B1)|(WGM01)|(WGM00);
    TCCR0B = (1<<CS00); /* divide by 1 */

    /* Timer 1 is for B channel; enable interrupts */
    TIMSK = (1<<OCIE1A)|(1<<TOIE1);
    TCCR1 = (1<<CS10); /* divide by 1 */

    sei();

    /* Get mode value from the EEPROM and update it */
    uint8_t mode = eeprom_read_byte((uint8_t *) 1);
    mode++;
    if (mode >= NUM_MODES)
        mode = 0;
    eeprom_write_byte((uint8_t *) 1, mode);

    uint8_t i;
    while(1) {
        switch(mode >> 1) {
            case 0:
                r_pwm(255);
                break;
            case 1:
                g_pwm(255);
                break;
            case 2:
                b_pwm(255);
                break;
            case 3:
                r_pwm(255);
                g_pwm(255);
                break;
            case 4:
                g_pwm(255);
                b_pwm(255);
                break;
            case 5:
                r_pwm(255);
                b_pwm(255);
                break;
            case 6:
                r_pwm(255);
                g_pwm(255);
                b_pwm(255);
                break;
            case 7:
                for (i=0; i < 255; i++) {
                    r_pwm(255-i); g_pwm(i);
                    _delay_ms(20);
                }
                for (i=0; i < 255; i++) {
                    g_pwm(255-i); b_pwm(i);
                    _delay_ms(20);
                }
                for (i=0; i < 255; i++) {
                    b_pwm(255-i); r_pwm(i);
                    _delay_ms(20);
                }
        }
    }

    return 0;
}

ISR(TIM1_OVF_vect)
{
    if (OCR1A != 0)
        PORTB |= (1<<2);
}

ISR(TIM1_COMPA_vect)
{
    PORTB &= ~(1<<2);
}


Электрическая схема и разводка печатной платы (из Eagle CAD)




Fuse-биты можно посчитать здесь, я посчитал, что 1МГц мне хватит для комфортного ШИМ и для низкого энергопотребления. Вообще говоря, фьюз-биты оказались стандартными для tiny45, так что их можно не менять.

Мне уже не терпелось поскорее опробовать новую поделку на практике, потому, наспех прыснув лаком из баллончика и дав 5 минут полежать под лампой, я взял её и выбежал на улицу с камерой (был уже довольно поздний вечер, как раз годные условия для тестирования).

И вот результат (видео не отличается от вставленного сверху для привлечения внимания):

Снежки совсем не хотели лепиться, и всё-таки я разогрел в руках горстку снега и всё получилось!


Немаловажно


За идею огромное спасибо тов. Kidar.

Все материалы по этому проектику я выложил в Dropbox. Когда появится время, подготовлю отдельный makefile, а сейчас после распаковки: make antares && make build, после чего удобным для вас способом загружаете файл images/antares.hex на чип.

Спасибо за внимание!

UPD: Обновил архивы с исходными файлами; теперь в комплекте с печатной платой идёт PDF-файл для самостоятельной печати, а в архиве с программой — hex-файл с готовой прошивкой.
Теги:
Хабы:
+43
Комментарии 30
Комментарии Комментарии 30

Публикации

Истории

Ближайшие события

Московский туристический хакатон
Дата 23 марта – 7 апреля
Место
Москва Онлайн
Геймтон «DatsEdenSpace» от DatsTeam
Дата 5 – 6 апреля
Время 17:00 – 20:00
Место
Онлайн