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



Вспомнился мне на днях этот пост про изделие 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 — 16×1р;
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 марта.


0 комментариев на «“Весенняя открытка — стробоскоп”»

Добавить комментарий

Arduino

Что такое Arduino?
Зачем мне Arduino?
Начало работы с Arduino
Для начинающих ардуинщиков
Радиодетали (точка входа для начинающих ардуинщиков)
Первые шаги с Arduino

Разделы

  1. Преимуществ нет, за исключением читабельности: тип bool обычно имеет размер 1 байт, как и uint8_t. Думаю, компилятор в обоих случаях…

  2. Добрый день! Я недавно начал изучать программирование под STM32 и ваши уроки просто бесценны! Хотел узнать зачем использовать переменную типа…

3D-печать AI Android Arduino Bluetooth CraftDuino DIY IDE iRobot Kinect LEGO OpenCV Open Source Python Raspberry Pi RoboCraft ROS swarm ИК автоматизация андроид балансировать бионика версия видео военный датчик дрон интерфейс камера кибервесна конкурс манипулятор машинное обучение наше нейронная сеть подводный пылесос работа распознавание робот робототехника светодиод сервомашинка собака управление ходить шаг за шагом шаговый двигатель шилд

OpenCV
Робототехника
Будущее за бионическими роботами?
Нейронная сеть - введение