Весенняя открытка - стробоскоп


Вспомнился мне на днях этот пост про изделие 18\12 на Хабре. Забавно. Из почти что ничего получаем классную игрушку. Решил вот сделать в подарок девушке свою версию, только Spring Sun Edition:)
Забавный контакт в верней части изделия по ссылке явно намекает на отличие символического изображения сердца и сходство его же с иным органом.

Устройство.

Железо подверглось небольшим изменениям. МК поставил ATMEGA8515L. Толстоват он, конечно, просто единственный в закромах родины с достаточным количеством GPIO и напряжением питания нашелся только он. Диодов стало больше. При цене 20 коп. за резистор и 1р за диод, потратив целых 9.60 можно удвоить разрешение. Пробовал в прошивке гасить половину диодов — да, с шестнадцатью смотрится эффектней. Избавился за одно от таймаута включения железно и навсегда — выключателем. Ток через диоды ограничил резисторами на 10 Ом. Навскидку 16 диодов напрямую МК точно не одобрит. К тому же у этой модели ток по питанию ограничен 200мА. Питается все чудо от двух CR2032. 3V для ATMEGA8515L более чем хватит. Два потому, что я не люблю часто менять батарейки, зачем других заставлять?:) А так хватит и одной. Для наглядности схема:



Изделие с обратной стороны:



Прошивка.

Автор прошлого изделия немного удивил какой-то странной инициализацией-переинициализацией. Надеюсь, он возражать не станет, и только обрадуется, что его код не пропал даром и кому-то пригодился. Жаль нет аккаунта, я бы у него поинтересовался с удовольствием, зачем он переключает порты на вход в непрерывном цикле. Про неиспользуемый обработчик прерывания догадываюсь, что он хотел задействовать еще какую-то кнопку (или выводить контроллер из спящего режима, но потом спохватился, что на плате нет кварца и CPU погаснет до следующего включения питания), но торопясь сделал небрежно. В общем эти кляксы не сложно стереть, удалив лишнее и написав инициализацию портов заново.
Так же адаптировал его код 16 диодов, заменил порты, убрал уход в спячку по таймауту и реализовал показ нескольких картинок с интервалом в несколько секунд. Я сделал солнышко, смайлик, сердечко и звезду. Но можно что угодно. Памяти там хоть отбавляй остается, хотя в моем контроллере ОЗУ вдвое меньше, чем по ссылке в начале. Можно хоть целую стробогалерею вшить.

К ноге, моя блоха!

Выводить разъем для перепрошивки — испортить внешний вид. Поэтому поступим по хардкору — подпаяем по 0.2 мм проволочке ко всем нужным ногам корпуса (TQFP44, ага). А потом проволочки присоединим к программатору. Сразу прошу прощения у читателя, настолько увлекся процессом, что забыл сфоткать. Не паять же их туда заново только ради фотки:) Прошло все на удивление гладко. Надо только не забыть вынуть батарейки перед прошивкой и подключть внешнее питание в 5В. Дело в том, что при питании в 3В мой программатор отлично все читает из МК, но вот прошивать туда ничего не хочет. А пользуюсь я каким-то левым, совместимым с Atmel STK-500 монстром. Умеет прошивать и через ISP и через HVP. Второе может спасти, если сильно напутать во фьюзах. Вот он, волшебный:



Принцип действия игрушки. (Для тех, кто еще не догадался)

На удивление прост. Картинка представлена прямоугольником, высотой в 16 (в моей версии) столбцов. С интервалом в 5 мс диоды загораются в соответствии с каждым следующим столбцом. Когда машешь устройством — каждый следующий столбец загорается на новом месте, а из-за инертности глаза все сливается в одну картинку.

Технология.

Плату делал ЛУТом, красил из болончика сперва грунтовкой, затем краской ABRO (фиговая краска, только заборы на могилах красить). По обезжиренной 646 растворителем поверхности. Флюс ФКСп, припой ПОС-61. Отмывал остатки флюса спиртом. Для тех кто не в теме, спирт в аптеках продавать запретили, зато вместо этого теперь продают антибактериальные преператы, на которых сказано: «Состав: спирт этиловый 92,5%». Просто диву даешься в этой стране. Я покупаю «Антисептин».
Название на плате для разнообразия не лудил, а для защиты от почернения покрыл фоторезистом. Мне эта мерзость после покупки лазерного принтера как страшный сон. На защитные покрытия идет) Готовую плату не выкладываю по двум причинам:
1. Все таки моя девушка достойна уникального подарка.
2. Контроллер явно слишком толст, туда можно поставить что-то в несколько раз слабее.
3. И вы должны приложить фантазию, это увлекательнее, чем клонировать проект. Идею описал автор 18\12.

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

Список деталей.
1. Текстолит односторонний — 30р;
2. МК ATMEGA8515L — 45р;
3. Резисторы SMD 1206, 10 Ом — 16х20коп;
4. Светодиоды SMD, FYLS-1206SRC — 16x1р;
5. Колодки под CR2032 — 2х15р;
6. Переключатель — 5р.
7. Резисторы SMD 1206, 10 кОм — 20коп;
8. Грунтовка и краска в балончике ~100р за баллон;
9. Конденсаторы 22 пФ SMD 1206 — 2х20коп;
10. Элемент питания CR2032 — 2X20р;
11. Удовольствие от проделанной работы — бесценно.

Доработка и усовершенствования.

1. Подобрать получше краску.
2. Разжиться более подходящим МК.
3. Можно адаптировать игрушку под RGB светодиоды.
4. Купить полиуретановый или акриловый лак. Незащищенные дорожки на плате — плохо.
5. Похимичить с акселерометром. Добиться независимости от скорости и направления взмаха.

Насчет последнего. Не могу никак найти микросхем акселерометров по адекватной цене. Как найду — сразу же возьмусь за изучение.

О, и да, чуть не забыл, оно работает!



Видео весьма плохо передает весь эффект, но принцип понять можно.

Исходный код сего чуда для WinAVR-GCC:



#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>


#define LINETIME 5	 // Интервал между линиями
#define STROBETIME 3 // Время показа каждого строба в срабатываниях таймера :)

unsigned char count = 0;
unsigned char strobe = 0;

#define MAXSTROBE 3

void Init() {
// IO  PORTS
DDRC = 0xFF;
PORTC = 0x00;
DDRA = 0xFF;
PORTA = 0x00;

// TC1 (16bit)
TCCR1B |= (0 << CS12) | (1 << CS11) | (0 << CS10);
TIMSK |= (1 << TOIE1);
}


void ShowLine (unsigned int line)
{
	PORTC = 0x00;
	PORTA = 0x00;

	if(line & _BV(0)) PORTC |= _BV(0);
	if(line & _BV(1)) PORTC |= _BV(1);
	if(line & _BV(2)) PORTC |= _BV(2);
	if(line & _BV(3)) PORTC |= _BV(3);
	if(line & _BV(4)) PORTC |= _BV(4);
	if(line & _BV(5)) PORTC |= _BV(5);
	if(line & _BV(6)) PORTC |= _BV(6);
	if(line & _BV(7)) PORTC |= _BV(7);

	if(line & _BV(8)) PORTA |= _BV(7);
	if(line & _BV(9)) PORTA |= _BV(6);
	if(line & _BV(10)) PORTA |= _BV(5);
	if(line & _BV(11)) PORTA |= _BV(4);
	if(line & _BV(12)) PORTA |= _BV(3);
	if(line & _BV(13)) PORTA |= _BV(2);
	if(line & _BV(14)) PORTA |= _BV(1);
	if(line & _BV(15)) PORTA |= _BV(0);

	_delay_ms(LINETIME);
}

int main(void) {
Init();
sei();


   for (;;) {
   
   switch (strobe) {
	   case 0:
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000100000000);
			ShowLine(0b0000000100000000);
			ShowLine(0b0100000100000100);
			ShowLine(0b0010000100001000);
			ShowLine(0b0001000000010000);
			ShowLine(0b0000001110000000);
			ShowLine(0b0000011111000000);
			ShowLine(0b1111011111101111);
			ShowLine(0b0000011111000000);
			ShowLine(0b0000001110000000);
			ShowLine(0b0001000000010000);
			ShowLine(0b0010000100001000);
			ShowLine(0b0100000100000100);
			ShowLine(0b0000000100000000);
			ShowLine(0b0000000100000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
	   break;
	   case 1:
	   		ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000001111000000);
			ShowLine(0b0001111001111000);
			ShowLine(0b0111000000001110);
			ShowLine(0b1100000000000011);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000110000000);
			ShowLine(0b0000000110000000);
			ShowLine(0b0000000110000000);
			ShowLine(0b0000000110000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0011100000011100);
			ShowLine(0b0011100000011100);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
       break;
       case 2:
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000010000000000);
			ShowLine(0b0000011000000100);
			ShowLine(0b0000011100001100);
			ShowLine(0b0000011110111000);
			ShowLine(0b0000011111110000);
			ShowLine(0b0001111111110000);
			ShowLine(0b1111111111100000);
			ShowLine(0b0001111111110000);
			ShowLine(0b0000011111111000);
			ShowLine(0b0000011100111000);
			ShowLine(0b0000011000001100);
			ShowLine(0b0000011000000100);
			ShowLine(0b0000010000000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);

	   break;
	   case 3:
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000111100000000);
			ShowLine(0b0011111111000000);
			ShowLine(0b1111111111110000);
			ShowLine(0b0011111111111100);
			ShowLine(0b0000111111111111);
			ShowLine(0b0011111111111100);
			ShowLine(0b1111111111110000);
			ShowLine(0b0011111111000000);
			ShowLine(0b0000111100000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
			ShowLine(0b0000000000000000);
	   break;

			}

    }

};


ISR (TIMER1_OVF_vect) {
count++;
if (count >= STROBETIME) {
  count = 0;
  strobe++;
  if (strobe >= (MAXSTROBE + 1)) strobe = 0;
}
}


А всех милых дам, читающих этот пост, с первыми днями весны и 8 марта.
  • +3
  • 7 марта 2012, 21:23
  • Ozze

Комментарии (1)

RSS свернуть / развернуть
+
0
Отличный проект! Спасибо!
Присоединяюсь к поздравлениям :)
Если хотите, чтобы ваш проект участвовал в конкурсе КиберВесна, то просто отредактируйте статью и добавьте тег кибервесна
avatar

admin

  • 8 марта 2012, 08:03

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.