Pull to refresh

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

Reading time6 min
Views25K
Камин — такая вещь, которая олицетворяет собой необычайное тепло, уют родного дома, конфеты, подарки, зимние вечера, да и вообще приятная штука. Сегодня мы построим настоящий хабракамин — в компьютерном корпусе, на нанотехнологичных светодиодах и «теплых ламповых» технологиях — 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;


Результаты


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


Исходники и схемы — на гитхабе.
Tags:
Hubs:
Total votes 40: ↑25 and ↓15+10
Comments5

Articles