Простой вращающийся светодиодный дисплей

от автора

image В данной статье я хотел бы представить еще один вариант устройства, которое известно под названиями «часы-пропеллер», «светодиодный вентилятор», «часы Боба Блика», «светодиодный механический дисплей». Подобные устройства достаточно популярны, поэтому различных реализаций и статей про них написано много (есть парочка и на хабре). Основной особенностью предлагаемого мной варианта является простота механической части.

Когда я впервые искал информацию про светодиодные механические дисплеи, то был одновременно удивлен и испуган изобретательностью разработчиков — кто-то использовал моторы вытащенные из раритетных 5,25 дисководов с приделанными к ним скользящими контактами, кто-кто наматывал катушки вращающегося трансформатора, а хабраюзер Derailed вообще сделал часы-пропеллер из жесткого диска.

Насмотревшись на все это разнообразие я начал наматывать катушки:) В итоге получилось хорошо работающее устройство, которое, однако, было несколько переусложненным. После его изтоговления меня не покидало ощущение что подобный светодиодный вентилятор можно сделать гораздо проще.

Под катом большое количество изображений.

По сути, вот основное что требуется:

  1. Моторчик.
  2. Плата с микроконтроллером и подключенными к нему светодиодами, которая будет надеваться на ось моторчика, вращаться и светить.
  3. Питание к этой плате, подающееся одним из следующих способов: скользящий контакт, вращающийся трансформатор, батарейка или лазер сфокусированный системой зеркал на орбите.
  4. Что-нибудь для подсчета оборотов, например, пара из подключенного к микроконтроллеру фототранзистора и ИК-светодиода, находящегося на неподвижной части.

image
Через некоторое время подходящая механическая часть попалась на глаза – китайский USB LED вентилятор. Купить можно за ~3.5$ в каком-нибудь из китайских интернет-магазинов, например, в DealExtreme. Также можно найти в локальных магазинах за 200-300 рублей, одно из наименований — MobileData UF-211-06.

В нем есть многое из необходимого и даже больше: моторчик, скользящие контакты в виде пружин, корпус, кнопка и питание от USB. Остается только добавить регулятор напражения, счет оборотов, а также либо поменять верхнюю часть на собственную плату с микроконтроллером и светодиодами, либо подключить мк к уже имеющимся. Я сделал оба варианта, но описывать буду только второй, т.к. фотографии делал во время его выполнения.


Список использованных компонентов:

  1. Собственно, вентилятор.
  2. Микроконтроллер STM32F100C4.
  3. Регулятор напряжения LD1117S33.
  4. Фототранзистор KP-3216P3C.
  5. ИК-светодиод BL-L314IRBC.
  6. Резисторы 150 Ом — 5 шт.
  7. Резистор 68 Ом.
  8. Резистор 10 КОм.
  9. Конденсаторы 0,1 мкФ — 3 шт.

Модификация платы со светодиодами

Для начала разбираем устройство — аккуратно стягиваем верхнюю часть с оси моторчика. Затем отделяем крышку от корпуса и снимаем прозрачные лопасти с платы со светодиодами. Далее чем-нибудь тонким поддеваем плату снизу и аккуратно вытаскиваем ее из корпуса вместе со светодиодной платой.

На плате перерубаем дорожку питания микросхемы (отмечено желтым на фотографии ниже) и дорожки идущие к ней от светодиодов (также отмечено желтым, но на фотографии не перерублено, т. к. сделал это позднее когда понял что микросхему «пробивает»).

Резистор на плате (отмечено зеленым) необходимо выпаять, а контакты замкнуть либо поставив резистор номиналом 0 Ом, либо просто проводком\припоем.

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

Также припаиваем по проводку к площадкам с питанием и землей (отмечено красным и синим соответственно), а затем втставляем плату обратно в корпус, продев проводки в какие-нибудь отверстия. Данная часть теперь готова к подключению к микроконтроллеру.

«Обвес» моторчика

Аккуратно вытаскиваем моторчик из корпуса, никаких защелок внутри нет, достаточно просто вытянуть его. Для удобства можно отпаять проводки. Со стороны, где проходит контакт от центральной пружинки ставим регулятор напряжения. Припаиваем контакт от пружинки к Vout, к Vin и GND – питание и землю соответственно.
image
По даташиту регулятора напряжения между Vin и GND необходимо поставить конденсатор на 0,1 мкФ, а между Vout и GND – на 10мкФ. К сожалению, электролитическая бочка на 10мкФ, которая была у меня в наличии, была слишком большой, поэтому пришлось обойтись без нее.

С другой стороны моторчика устанавливаем ИК-светодиод. К одной из ножек припаиваем резистор на 68 Ом. Затем припаиваем к этому резистору и другой ножке питание и землю (что куда зависит от того к чему подключать резистор — к аноду или к катоду светодиода).

Далее необходимо припаять проводки из корпуса обратно к моторчику и вставить его в корпус. Можно проверить мультиметром напряжение между пружинками (естественно во включенном состоянии), должно быть 3,3В. ИК-светодиод можно проверить посмотрев на него через камеру телефона.

Плата с микроконтроллером

Теперь необходимо сделать плату с микроконтроллером. Особых требований к его выбору нет, главное чтобы хватало портов для подключения светодиодов и фототранзистора, да желатально чтобы корпус был поменьше. Я использовал STM32 в корпусе LQFP48, т. к. они были под рукой. Схема выглядит так:

Эмиттер фототранзистора подключается к питанию через резистор в 10КОм и к ножке микроконтроллера, коллектор подключается к земле. Про фотодатчики можно почитать в статье на easyelectronics.ru.

Аноды светодиодов подключаются к питанию, катоды через резисторы подключаются к ножкам микроконтроллера. Ножки выбраны через одну чтобы уменьшить шанс замкнуть их при пайке, но вообще это не обязательно. Про подключение светодиодов и многого другого к мк также есть статья на easyelectronics.ru.

На схеме не стал отображать, но у STM32 надо обязательно подключать все ножки питания и земли (Vdd и Vss), желательно и аналоговые (Vdda и Vssa). Также рекомендуется ставить по углам как можно ближе к ножкам питания конденсаторы по 0.1 мкФ.

SWDIO и SWCLK (а также питание и земля) выводятся на штырьки, чтобы подключать к ним программатор.

Разводка приведена ниже. К площадкам около резисторов подключаются проводки до светодиодов. Большой круг это просто очертание корпуса платы со светодиодами.

Схему и плату в формате DipTrace можно скачать здесь.

Плата выполняется по технологии ЛУТ, которая отлично описана в статье DIHALT‘а. Описание вкратце выглядит так:

  1. Печатаем рисунок на фотобумаге при помощи лазерного принтера.
  2. Переводим рисунок на плату путем проглаживания утюгом приложенной к плате бумаги с рисунком.
  3. Отмачиваем и отдираем бумагу, тонер остается на плате.

Далее травим плату, залуживаем дорожки. Затем припаиваем компоненты и соединяем землю и питание с разных сторон платы проводками.

Сборка

На гибкую плату со светодиодами надеваем отрезанную половинку лопасти. Устанавливаем плату с микроконтроллером сверху корпуса и припаиваем проводки светодиодов и питания. Куски зубочисток там для того чтобы плата ровно держалась:) Затем надеваем конструкцию на ось моторчика до момента когда пружинки начнут плотно касаться контактных площадок. Подгибаем ИК-светодиод так чтобы он был направлен на фототранзистор.

Далее любуемся собранной конструкцией и подключаем ее к программатору, в качестве которого в данном случае использовалась STM32VLDISCOVERY. Для того чтобы плата работала в режиме программатора внешних чипов необходимо убрать с нее две перемычки и подключить микроконтроллер к разъему SWD. Про STM32VLDISCOVERY можно почитать в статье хабраюзера ALPINE63rus. Через утилиту ST-LINK можно подключиться к микроконтроллеру и посмотреть все ли с ним в порядке, если подключения не происходит — проверяйте нормально ли припаялись ножки земли и питания к дорожкам и нет ли где-нибудь замыкания.

Прошивка

Алгоритм для расчета положения лопасти достаточно прост. При детектировании изменения уровня напряжения на ножке, подключенной к фототранзистору, устанавливается флаг turn. Также регулярно проверяется по таймеру установлен ли этот флаг, если нет, то счетчик count инкрементируется, если да, то количество отсчетов за оборот rate приравнивается к счетчику count, который сбрасывается вместе с флагом turn. Далее угол поворота лопасти рассчитывается исходя из значения количества отсчетов за оборот и текущего значения счетчика.

Выводить при помощи такого «дисплея» можно что душе угодно, но для начала пускай будет просто текст. Буквы выводятся по заранее записанным столбцам точек. «Шрифт» получается не очень красивый, зато просто:)

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

Код:

#include "stm32f10x.h" #include <stm32f10x_rcc.h> #include <stm32f10x_gpio.h> #include <stm32f10x_exti.h> #include <misc.h>  unsigned int 	turn, 	// флаг завершения оборота 				angle,	// текущий угол лопасти 				count, 	// счетчик отсчетов 				rate; 	// количество отсчетов за оборот  //текст "ХАБР" uint16_t text[] = { 0x0085, 0x002c, 0x0008, 0x002c, 0x0085, 	// Х 					0x0000, 0x0000, 0x0000, 			// пробел 					0x002d, 0x0084, 0x0084, 0x0084, 0x002d, 	// А 					0x0000, 0x0000, 0x0000, 			// пробел 					0x00ad, 0x0089, 0x0089, 0x0089, 0x0085, 	// Б 					0x0000, 0x0000, 0x0000, 			// пробел 					0x00ad, 0x0088, 0x0088, 0x0088, 0x0028 }; 	// Р  void EXTI15_10_IRQHandler(void) // обработчик внешнего прерывания {   if (EXTI_GetITStatus(EXTI_Line12) != RESET) // проверяем конкретную линию   { 	turn = 1; // устанавливаем флаг завершения оборота     	EXTI_ClearITPendingBit(EXTI_Line12); // сбрасываем бит прерывания   } }  void SysTick_Handler(void) { 	if (turn == 1) 		// проверяем был ли совершен полный оборот 	{				// если да, 		turn = 0; 		// то сбрасываем флаг оборота, 		rate = count; 		// сохраняем значение количества отсчетов за оборот, 		count = 0; 		// сбрасываем счетчик 		angle = 0; 		// и уставливаем положение лопасти на 0 градусов 	} 	else 	{				// если оборот еще не совершен, 		count++; 		// то прибавляем счетчик 		if (rate != 0) 		// проверяем не стоит ли вентилятор на месте 		{ 			angle = count * 360 / rate; // рассчитываем текущий угол положения лопасти 			angle /= 5; // это для быстрой растяжки текста, уменьшаем кол-во "градусов" в круге:) 		} 	}  	if (angle >= 0 && angle < 29) 	// если текущий угол лопасти находится в нужном нам месте, 		GPIOA->ODR = ~text[angle]; 	// то выводим текст по столбцам 		// инверсия применяется из-за того что светодиоды зажигаются при низком уровне на ножках 	else 		GPIOA->ODR = 0xFFFF; 		// а иначе просто гасим светодиоды высоким уровнем на ножках }   int main(void) { 	turn = angle = count = rate = 0;  	//---------------------------- Настройка системного таймера -------------------------------  	SysTick_Config (800);  	//--------------- Настройка ножек, подключенных к светодиодам -----------------------------  	// включаем тактирование портов A, B и альтернативных функций 	RCC_APB2PeriphClockCmd (RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);  	GPIO_InitTypeDef GPIO_InitStructure; 		// структура для настройки портов 	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_5 | GPIO_Pin_7;  	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 	// настраиваем ножки на вывод 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; 	// устанавливаем скорость их работы 	GPIO_Init (GPIOA , &GPIO_InitStructure); 	// записываем значения в регистры настройки порта A  	GPIOA->ODR = 0xFFFF; // устанавливаем высокий уровень на ножках, светодиоды не горят  	//----------- Настройка на прерывание ножки, подключенной к фототранзистору  --------------  	 // выбираем 12 ножку как источник внешнего прерывания 	GPIO_EXTILineConfig (GPIO_PortSourceGPIOB, GPIO_PinSource12);  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;	// используем имеющуюся структуру для настройки 12 ножки 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // на вход 	GPIO_Init (GPIOB, &GPIO_InitStructure); 	// записываем значения в регистры настройки порта B  	EXTI_InitTypeDef EXTI_InitStructure; 		// структура для настройки внешних прерываний 	EXTI_InitStructure.EXTI_Line = EXTI_Line12; 	// выбираем 12 линию внешних прерываний 	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;	// выбираем режим прерывания 	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;// срабатывание по одному из фронтов 	EXTI_InitStructure.EXTI_LineCmd = ENABLE; 		// включаем линию 	EXTI_Init (&EXTI_InitStructure); 			// записываем значения в регистры  	NVIC_InitTypeDef NVIC_InitStructure; 		// структура для настройки контроллера прерываний 	NVIC_InitStructure.NVIC_IRQChannel = 40; 		// выбираем канал обрабатывающий линии с 10 по 15 	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; // пишем какое-нибудь значение приоритета 	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; 	// и субприоритета 	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 	// включаем канал прерывания 	NVIC_Init (&NVIC_InitStructure);		// записываем значения в регистры контроллера прерываний  	//----------------------------- Пустой бесконечный цикл -----------------------------------  	while (1) 	{ 	} }  

Комплируем и загружаем прошивку, затем подключаем устройство к USB и нажимаем кнопку.

Оборотов хватает, контакт стабильный. Минус — вибрирует сильнее чем до модификации, надо уравновешивать. Также с разноцветными светодиодами текст читается намного хуже, чем с одинаковыми. Вообще можно сделать даже еще проще;)

Другие варианты

Ниже слева показан вариант с полностью замененной верхней частью вентилятора. Справа же вариант на основе обычного кулера и вращающегося трансформатора. Если кому-нибудь будет интересно, могу написать аналогичную статью про его изготовление.

ссылка на оригинал статьи http://habrahabr.ru/post/156419/


Комментарии

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

Ваш адрес email не будет опубликован. Обязательные поля помечены *