diFireplace: Новогодний хабракамин

от автора

Камин — такая вещь, которая олицетворяет собой необычайное тепло, уют родного дома, конфеты, подарки, зимние вечера, да и вообще приятная штука. Сегодня мы построим настоящий хабракамин — в компьютерном корпусе, на нанотехнологичных светодиодах и «теплых ламповых» технологиях — pic12f683, Hi-Tech PICC в IDE Hi-Tide.

Не так давно я разжился новым домашним компьютером и заботливые китайцы вставили в корпус спереди и сзади светящиеся красным 12-ти сантиметровые вентиляторы. Шума они издавали много, пользы — ноль, потому я живо их демонтировал. Вот только пустующее место и вечно свербящее чувство в одном месте на предмет самоделок не давало мне покоя и в итоге вылилось в идею устройства камина в лицевой части компьютера. Камин должен был бы разгораться в зависимости от количества и продолжительности обращений системы к жесткому диску и постепенно тухнуть при отсутствии оных.

Средства реализации

Микроконтроллер. pic12f683. Пока нам утверждают, что контроллеры за 100+ рублей дешевле и встопицот раз круче контроллеров за 30 рублей, посидим на старых, проверенных и популярных решениях. Что-то более масштабное, нежели восьминожечный контроллер, нам не понадобится. Я остановился на данном «потому что у меня их было», но сама реализация камина должна влезть и в pic12f629 или pic12f675. Какая-либо периферия, окромя двух таймеров и порта ввода-вывода не понадобится.
Светодиоды. Их два, для обеспечения и необходимой яркости в окошке корпуса, и для обеспечения реальности эффекта горения. Я взял 1-канделовые по мощности желтого цвета, потребляют по 20 мА (обязательная ремарка о том, что через МК нельзя проводить более 100 мА).
Программирование МК. Тот, кто знаком с продукцией компании Microchip чуть более, чем понаслышке, наверняка знает, что некоторое время назад Microchip поглотил за деньги компанию Hi-Tech, занимавшуюся разработкой компиляторов под эти самые контроллеры. И не так давно Microchip презентовал общественности свои новые продукты — компиляторы серии XС. По сути, это те же самые объединенные старые PICC, СNN в виде сумбурной мешанины правил старых диалектов. Длинные абзацы все равно никто не читает, как и не обращает внимания на интересные сервисы. Пока неприятных и противоречивых ощущений от них больше, чем чувства стандартизации и единственно верного вектора создания своих приложений.
Остаемся на старом и все еще достаточно приятном Hi-Tech PICC 9.60 STD. Инструкции, как достать этот раритет лежат на архивной страничке поглощенной компании.
IDE. Отдельно выделю использование чуть более, чем достаточно, приятной IDE от той же Hi-Tech — Hi-Tide. Эта надстройка над Eclipse характеризуется удобным гуевым волшебником для определения конфигурации и настроек контроллера. Hi-Tide ставится вместе с компилятором (чекбокс на одном из шагов установки) или, для тех, у кого не запустится версия 3.15, можно попробовать 3.13.

Некоторые соглашения о реализации планов

Вот некоторые наброски идей о функционировании создаваемого камина:
1. Оба светодиода должны независимо друг от друга создавать эффект пламени. Совместная их работа дает более приближенный к настоящему пламени свет.
2. Реализацию эффекта пламени разделим на три составляющих — программный ШИМ для задания моментальной яркости свечения от 0 до 255, кадры — этапы смены случайных яркостей свечения и границы этих яркостей в зависимости от общей яркости свечения. Экспериментально я выяснил, что хорошо — это когда нижняя граница может изменяться от 0 до 50 и верхняя — от 30 до 255.
3. Общая яркость свечения изменяется от 0 до 255 и зависит от количества или длительности обращений к диску. Если кадры будут «висеть» на нулевом таймере, то изменение общей яркости — на независимом первом и прерывании по изменению состояния на входе.
4. Для использования программного ШИМа придется использовать высокую тактовую частоту, я взял максимально возможную 20 МГц.
5. Состояние обращений к жесткому диску будем брать непосредственно с положительного контакта светодиода на корпусе. На светодиоде может быть всего два состояния — либо прижатый к земле, либо к +5 вольтам. Такое положение дел поможет избавиться от подтяжек и прочих подсхем обеспечения дискретности состояний на входе.

Железо

Схема устройства используется следующая:

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

Опустим также, как из этого:

Получается это:

Форм-фактор платы в основном определился размером окна и возможностей по ее креплению к корпусу компьютера.

Питание и вход сигнала жесткого диска на плате устройство выполнено в едином стандартном штыревом разъеме, на его обратной части — обыкновенный molex для запайки в текстолит, но с присоединенными проводами на +5 В (красный) и землю (черный) и заглушенными термоусадками остальными двумя контактами. Сигнал входа навсегда припаян к положительной ножке светодиода:

Прошивка

Настройки я предпочитаю сначала сделать в волшебнике Hi-Tide’а, а затем переписать по-новому восполнить не указанными еще в них присвоениями значений в конфигурационные байты.
FUSE-ы отключают watchdog-таймер, предписывают использовать внешний высокочастотный резонатор и внешний же пин перезагрузки программы.

__CONFIG(HS & WDTDIS & PWRTDIS & MCLREN & UNPROTECT & UNPROTECT & BORDIS & IESODIS & FCMDIS); 

Настройки периферии следующие:

void initHardware(void) { 	// По переполнению таймера 1 будет вызываться прерывание 	PIE1 = 0b00000001; 	 	// Включаем прерывания нулевого таймера и возможность получения прерываний периферии 	INTCON = 0b01101000; 	 	// К 0 и 1 контактам подключены светодиоды, прочие - на вход 	TRISIO = 0b00111100; 	 	// Таймер 0 используется с минимальным делителем частоты 	OPTION = 0b00000000; 	 	// Также как и таймер 1 	T1CON = 0b00000001; 	 	// Выключение компараторов 	CMCON1 = 0x07; 	CMCON0 = 0x07; 	CCP1CON = 0x00; 	 	// Выключение АЦП и концигурация всех выводов ка дискретные 	ADCON0 = 0x00; 	ANSEL = 0x00; 	 	// Включение прерываний по изменению состояния на пине 2 	IOC = 0b00000100; } 

В 683 контроллере, как и в некоторых других есть проблема с невозможностью отдельно задавать или принимать значения на конкретных пинах порта ввода-вывода и приходится использовать все значение порта GPIO. Для упрощения вывода я использую следующие функции установки высокого, низкого уровней и результирующего вывода:

volatile uint8 fIoBuffer;  void setIoPinHigh(uint8 aPinNumber) { 	fIoBuffer |= (1 << aPinNumber); }  void setIoPinLow(uint8 aPinNumber) { 	fIoBuffer &= ~ (1 << aPinNumber); }  void updateIoBuffer(void) { 	GPIO = GPIO & 0b11111100 | fIoBuffer; } 

Рандомайзер необходим только в рамках генерации одного байта, потому я использовал выпиленные и модифицированные из стандартных модулей функции генератора псевдослучайных последовательностей:

volatile uint32 fRandomSeed;  void srand(void) { 	fRandomSeed = TMR0 ^ TMR1H ^ TMR1L; }  uint8 randomByte(void) { 	fRandomSeed = fRandomSeed * 1103515245L + 12345; 	return fRandomSeed >> 16; } 

По событию переполнения первого таймера должны выполняться две подпрограммы. Первая — программный ШИМ для вывода моментальных яркостей светодиодов. Логика простая: всегда инкрементируется счетчик, если он переполняется, то падает в ноль. Моментальная яркость (fPwmLedValue1 или fPwmLedValue2) принимает значение от 0 до 255, и, если счетчик меньше этого значения, то светодиод горит, если больше, то нет. Чем выше частота прибавления счетчика, тем менее заметно мерцание светодиода, оно в наших глазах сливается в изменение его яркости.

fPwmLedCounter1++; fPwmLedCounter2++; 		 if(fPwmLedValue1 > fPwmLedCounter1) 	setIoPinHigh(PIN_LED1); else 	setIoPinLow(PIN_LED1); 			 if(fPwmLedValue2 > fPwmLedCounter2) 	setIoPinHigh(PIN_LED2); else 	setIoPinLow(PIN_LED2); 		 updateIoBuffer(); 

Второе действие — кадры. Экспериментально я подобрал длину кадра в 0.3 секунды, что, согласно калькулятору, соответствует 2930 событиям переполнения нулевого таймера. Каждый кадр производится вычисление новой моментальной яркости каждого из светодиодов (зависит от установленных границ fPwmHi и fPwmLo) и по возможности, определяемой булевым fCanIncrement, снижение общей яркости камина:

uint8 randPwmValue(void) { 	return fPwmLo + randomByte() % (fPwmHi - fPwmLo); } 
fFrameCounter++; if(fFrameCounter >= FRAME_DELAY) { 	fPwmLedValue1 = randPwmValue(); 	fPwmLedValue2 = randPwmValue();  	if(!fCanIncrement) 		decBrightness();  	fFrameCounter = 0; } 

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

void calcEdges(void) { 	fPwmLo = (uint8)(0.1953125 * (float)fBrightness); 	fPwmHi = (uint8)(0.8828125 * (float)fBrightness + 30); }  void incBrightness(void) { 	if(fBrightness < 255) 	{ 		fBrightness++; 		calcEdges(); 	} } 
if(GPIO & 0b00000100) { 	fCanIncrement = 1; 	incBrightness();  	TMR1H = 0; 	TMR1L = 0; } else 	fCanIncrement = 0; 

Результаты

Нехитрая программа и нехитрая же схема позволяют добиться неплохих результатов. Даже если видео, снятое на микроволновку, не способно показать действительные результаты работ, то реальная работа устройства заставляет помедитировать, сидя у «огня». Вот видео ночью, днем несколько иначе:

Исходники и схемы — на гитхабе.

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


Комментарии

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

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