Стробоскоп из подручных средств — ленивый проект на пару вечерков

Попросили меня склепать стробоскоп с регулируемой частотой вспышек на заданном интервале. ТЗ на словах, если можно так сказать, было следующее: интервал выбираемой частоты 21 — 27 Гц, выбор частоты вспышек до десятых долей, должно быть с аккумулятором, показывало как-то текущую частоту и … собственно, всё, ну разве что побыстрее бы. Мне заниматься этим, честно говоря, лениво было, но согласился, вроде как это для целей обучения нужен приборчик, почему бы и не помочь!

Для настоящих профи и просто шарящих спецов в статье не будет ничего нового или интересного… ну разве что поугарать над некоторыми решениями (а статья именно для этого и задумывалась). ;) Зато, думаю, пригодится новичкам в электронике и микроконтроллерах, да и просто пример устройства с питанием от Li-Ion аккумулятора, МК STM32F030F4P6 и управляемым драйвером светодиода из доступных средств.

Вечер первый

Итак. Раз это ленивый проект, то и делать всё будем с душой ленью! Сделаем всё максимально на мартышках и готовых платах-кирпичиках, а также из того, что есть по коробочкам\столе в принципе…

Начнём с питания, для питания есть вполне подходящий аккумулятор с планшета какого-то, гордо красуется на нём 3000 мАч, уже явно меньше, но для наших целей хватит:

B47-1

Главное, что у него есть встроенная плата защиты и от переразряда\КЗ\перезаряда аккумулятора в данном случае защищен — меньше запар в плане разработки. Для его зарядки у меня в наличии есть несколько плат на TP4056, вот таких:

B47-2

Они без защиты аккумулятора. Если сомневаетесь в своём аккумуляторе (или мастерстве схемотехники :) ), когда собираете устройство, лучше взять вот такие, с защитой:

B47-3

Ток смотрим\корректируем по даташиту резистором на плате (от второй ноги микросхемы к общему идёт, R3 на фото выше):

B47-3

Самое простое прошли. Теперь как сделать от тактильной кнопки (ну не тумблером же по-дедовски делать.. я хоть и ленивый, но уж совсем топорно делать не люблю) включение\выключение? Да вполне просто, если в схеме будет микроконтроллер! Паяем по такой схеме блок управления питанием из хлама на коленке мартышке:

B47-4

Логика проста как 5 копеек. К VBAT подключается аккумулятор, VCC — это уже питание следующих блоков и МК через любой подходящий LDO. В момент подключения аккумулятора транзистор VT1 закрыт, и через R2 на его затворе поддерживается высокий потенциал, что поддерживает его в закрытом состоянии. Напряжения на VCC нет, только через R1 \ R2-VD1 есть небольшой ток утечки в IO МК по линии BT_PWR, но на это пофиг, он не столь критичен (также еще есть важный момент, что напряжение на аккумуляторе больше, чем питающее МК, и если установить резистор R1 малого номинала, то через защитные диоды IO МК будет идти ощутимый ток, что может привести к выходу всего МК или его конкретного IO из строя по различным причинам как последствие этого, но номинал 100 кОм с лихвой ограничивает ток, который может втекать в IO МК, и в данном случае опять на это пофиг х2, проект ленивый же ;) ). Итак, есть кнопка SB1, при нажатии на которую затвор VT1 притягивается к общему через диод Шотки VD1 и транзистор VT1 открывается. Появляется напряжение на VCC и, соответственно, МК, а МК должен дать 1-цу на линию PWR_EN, тем самым открыв VT2 и притянув затвор VT1 к общему на время работы устройства. При необходимости выключить устройство нужно просто снять 1-цу с линии PWR_EN. Также МК может отслеживать нажатие кнопки SB1 во время работы устройства, т.к. нажатие на неё не мешает работе VT1, и на неё можно повесить дополнительные функции в прошивке МК. Просто как топор и работает! :)

Далее… драйвер для светодиода и, собственно, сам светодиод. Светодиодов есть 2-3 шт типа 10 Вт китайских, белых, валяются уже года 2. Хватило бы и 1-2 Вт, но и этих не жалко — ставим один такой, остаётся драйвер… Да ещё и надо, чтобы он ШИМился. Городить что-то эдакое не хочется, спец. микросхем нет, зато есть горсть разнообразных DC-DC, понижающих и повышающих, от доисторических MC34063 до Российской экзотики типа К1290ЕФ1Х. Среди микросхем нашёлся десяток супер-популярных китайских повышающих DC-DC MT3608. Чем не готовый драйвер для светодиода? Вот его основные характеристики:

B47-6

Работает от 2 В и до 24 В — покрывает диапазон выходного напряжения Li-Ion аккумулятора. Выходное напряжение до 28 В более чем достаточно для одного светодиода мощностью 1-2 Вт. Тактовая (рабочая) частота 1,2 МГц, что с лихвой перекрывает рабочую частоту стробоскопа, и ШИМить можно посредством EN входа этого DC-DC.

Типичная схема включения из даташита:

B47-8

Типичный Boost-преобразователь, скажете вы… ну да, стабилизирует напряжение, а у нас светодиод, который требует стабилизации тока. А если посмотреть на внутреннюю функциональную схему этой микросхемы:

B47-7

Станет видно, что опорное напряжение для сравнения по входу FB равно 0,6 В и логика работы проста — если на входе FB напряжение превышает опорное, то Error Amplifier, работая как компаратор, на выходе выдает 0, который поступает на положительный вход PWM Comparator, вследствие чего на выходе компаратора тоже становится 0, что запрещает работу DC-DC (напряжение на выходе достигло нужного значения), и всё происходит в обратном порядке, если напряжение на входе FB падает ниже 0,6 В. Так вкратце и работает стабилизация по напряжению в этой микросхеме. А нам нужна стабилизация по току… что делать — подсказка на рисунке выше же, у транзистора M1 есть шунт, на котором измеряется напряжение падения на нём и в случае критического значения тока через транзистор работа преобразователя так же запрещается благодаря Current Sense Amplifier. Нам же просто надо собрать аналогичную схему для преобразования рекомендованной ОС по напряжению в ОС по току. У меня получилось следующая схема:

B47-5.PNG

По деталям, что здесь применены, и для чего они:

  • R1 — просто защита от случайного включения преобразователя в момент включения устройства, пока МК не инициализирован;
  • L1, VD1 — номиналы деталей из даташита, по току — любые подходящие с запасом для требуемого светодиода;
  • VD2 — защита от выгорания микросхемы в случае, если не будет нагрузки или обрыв в светодиоде (номинал стабилитрона любой в пределах выше напряжения работы светодиода и ниже максимально допустимого выходного напряжения микросхемы, 28 В);
  • С1, С2, С3 — фильтрация входного напряжения и пульсаций на выходе. Стоит отметить, что не стоит ставить большой номинал С3, если планируется ШИМить работу светодиода — может мешать работе ШИМа;
  • R2 — просто ограничивающий ток резистор для стабилитрона VD2 в случае его открывания при отсутствии нагрузки, номинал не особо критичен и может гулять в пределах +200\-50%;
  • R3 — измерительный шунт, благодаря которому и задаётся требуемый ток в нагрузке (светодиоде).

Расчёт тока в нагрузке прост как закон Ома, т.к. это он и есть в чистом виде — для заданного опорного напряжения 0,6 В и желаемого тока в нагрузке рассчитываем номинал резистора. У меня для 200 мА логично вышло 3 Ом, что в итоге на светодиоде даёт мощность около 2 Вт.

ЗЫ. Аналогичным способом можно доработать практически любой повышающий преобразователь и получить вполне удобный драйвер для светодиода.

Кроме обвязки микроконтроллера остался ещё один блок устройства — дисплей. Сначала думал применить SPI \ I2C дисплей, но все были довольно большими и сильно избыточными. Поискав ещё, нашел поломанный измеритель тока, как то выигранный на одном аукционе ebay, вот такого типа:

B47-9

3 знака… это же то, что надо! Выпаял 7-сегментный индикатор, сдул с платы всё, что есть на ней (STM8, ОУ, LDO и горстка пассивных компонентов) и припаял индикатор обратно — осталось только добавить сдвиговый регистр 74HC595D и удобный дисплей с ушками для крепления готов!

Схема подключения регистра и дисплея вполне стандартна, и выглядит так:

B47-10.PNG

Выбор активного знакоместа напрямую к МК, а сегменты к регистру. Выводить можно как и через SPI, так и банально ногодрыгом соответствующий код (о программной реализации ниже).

Вот и всё! Пара дополнительных кнопок и обвязка МК — это уже слишком банально и показывать отдельно схемой не буду. Собираем всё вышеописанное вместе.

Запускаем STM32CubeMX (проект то ленивый!), выбираем наш МК — STM32F030F4P6 (самое маленькое, что нашел в наличии и подходящее по количеству IO) и настраиваем периферию:

B47-11.png

Припаиваем всю обвязку в соответствии с выбранными ножками, осталось проверить это добро, написав прошивку…

Будем делать с FreeRTOS, таймером для ШИМ и, собственно, всё… разве что SWD не забываем включить (можно и без него, если нужны ещё 2 ноги)! Тактирование тоже незатейливое, используется внешний кварц 8 МГц и PLL на 48 МГц и всё тактируется от PLL:

B47-12

Добавляем пару дополнительных тредов для FreeRTOS, генерим проект (Keil uVision v5) и начинаем писать код. Следующим вечером.

Вечер второй

Открываем SolidWorks. Не, ну а чё, надо же размяться! :D Да и пока будет печататься корпус — можно времени не терять и как раз написать прошивку…

Начинаем с габаритных вещей, а это радиатор для светодиода и аккумулятор. Радиатор снят с какой то давно сгоревшей видеокарты, стоял для охлаждения ключей DC-DC питания. Рисуем вначале радиатор для удобства сборки в SolidWorks:

B47-13

B47-14

Далее уже можно нарисовать заднюю крышку с фиксаторами для аккумулятора:

B47-15

B47-16

Ну и самое обьёмное, рисуем основную часть корпуса с крепёжными отверстиями, отверстиями для элементов управления\отображения и фиксаторами для макеток:

B47-17

B47-18

B47-19

Проверяем в сборке это всё:

B47-21

B47-20

B47-22

Да, чуть не забыл! Еще надо нарисовать простейший световод из полупрозрачного пластика, чтобы показывать статус зарядки (киллер-фича):

B47-23

Вот и всё, ставим на печать и идём кодить.

Начнём с драйвера для дисплея, нужно, чтобы он умел:

  • Выводить целочисленное 3-х значное число, деля его на 10 (float и т.д. пользоваться в проекте не будем, нафиг);
  • Выводить типа загрузочного экрана (тире), чтобы показывать какие-либо состояния.

Получилось следующее:

74HC595.h :

#ifndef _74HC595_H_
#define _74HC595_H_

#include "main.h"
#include "stm32f0xx_hal.h"
#include "cmsis_os.h"

void Dig_Init(void);
void Dig_Update(void);
void Dig_SetValue(uint16_t v);
void Dig_SetLoad(uint8_t l);
void Dig_ShowValue(void);

#endif // _74HC595_H_

Функцию Dig_Update надо вызывать в цикле регулярно для обновления значений на дисплее, остальное и так вполне понятно из названий, что они делают.

74HC595.c :

#include "74HC595.h"

uint16_t val = 0, val_old = 0;
uint8_t load = 0;
// 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , dp, -, SPACE
uint8_t digits[13]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,0x1,0x2,0x00};

void Dig_Send(uint8_t data)
{
 uint8_t i = 0;

 HAL_GPIO_WritePin(DIG_SCK_GPIO_Port, DIG_SCK_Pin, GPIO_PIN_RESET);
 HAL_GPIO_WritePin(DIG_DATA_GPIO_Port, DIG_DATA_Pin, GPIO_PIN_RESET);
 HAL_GPIO_WritePin(DIG_OE_GPIO_Port, DIG_OE_Pin, GPIO_PIN_RESET);

 for(i=0;i> i) & 0x1)
 HAL_GPIO_WritePin(DIG_DATA_GPIO_Port, DIG_DATA_Pin, GPIO_PIN_RESET);
 else
 HAL_GPIO_WritePin(DIG_DATA_GPIO_Port, DIG_DATA_Pin, GPIO_PIN_SET);
 HAL_GPIO_WritePin(DIG_SCK_GPIO_Port, DIG_SCK_Pin, GPIO_PIN_SET);
 __NOP();__NOP();__NOP();__NOP(); // nope, nope, nope...
 HAL_GPIO_WritePin(DIG_SCK_GPIO_Port, DIG_SCK_Pin, GPIO_PIN_RESET);
 }

 HAL_GPIO_WritePin(DIG_OE_GPIO_Port, DIG_OE_Pin, GPIO_PIN_SET);
}

void Dig_Init(void)
{
 val = 0;
 load = 0;
}

void Dig_SetValue(uint16_t v)
{
 val_old = val = v;
}

void Dig_SetLoad(uint8_t l)
{
 val = 1001;
 load = l;
}

void Dig_ShowValue(void)
{
 val = val_old;
}

void Dig_Update(void)
{
 if(val >= 1000) // экран загрузки
 {
 if(load & 0x1) Dig_Send(digits[11]);
 else Dig_Send(digits[12]);
 HAL_GPIO_WritePin(DIG_0_GPIO_Port, DIG_0_Pin, GPIO_PIN_SET);
 osDelay(5);
 HAL_GPIO_WritePin(DIG_0_GPIO_Port, DIG_0_Pin, GPIO_PIN_RESET);

 if((load >> 1) & 0x1) Dig_Send(digits[11]);
 else Dig_Send(digits[12]);
 HAL_GPIO_WritePin(DIG_1_GPIO_Port, DIG_1_Pin, GPIO_PIN_SET);
 osDelay(5);
 HAL_GPIO_WritePin(DIG_1_GPIO_Port, DIG_1_Pin, GPIO_PIN_RESET);

 if((load >> 2) & 0x1) Dig_Send(digits[11]);
 else Dig_Send(digits[12]);
 HAL_GPIO_WritePin(DIG_2_GPIO_Port, DIG_2_Pin, GPIO_PIN_SET);
 osDelay(5);
 HAL_GPIO_WritePin(DIG_2_GPIO_Port, DIG_2_Pin, GPIO_PIN_RESET);
 }
 else if(val < 10) // показываем значение val ...
 {
 Dig_Send(digits[0]);
 HAL_GPIO_WritePin(DIG_0_GPIO_Port, DIG_0_Pin, GPIO_PIN_SET);
 osDelay(5);
 HAL_GPIO_WritePin(DIG_0_GPIO_Port, DIG_0_Pin, GPIO_PIN_RESET);

 Dig_Send(digits[0] | digits[10]);
 HAL_GPIO_WritePin(DIG_1_GPIO_Port, DIG_1_Pin, GPIO_PIN_SET);
 osDelay(5);
 HAL_GPIO_WritePin(DIG_1_GPIO_Port, DIG_1_Pin, GPIO_PIN_RESET);

 Dig_Send(digits[val]);
 HAL_GPIO_WritePin(DIG_2_GPIO_Port, DIG_2_Pin, GPIO_PIN_SET);
 osDelay(5);
 HAL_GPIO_WritePin(DIG_2_GPIO_Port, DIG_2_Pin, GPIO_PIN_RESET);
 }
 else if(val < 100)
 {
 Dig_Send(digits[0]);
 HAL_GPIO_WritePin(DIG_0_GPIO_Port, DIG_0_Pin, GPIO_PIN_SET);
 osDelay(5);
 HAL_GPIO_WritePin(DIG_0_GPIO_Port, DIG_0_Pin, GPIO_PIN_RESET);

 Dig_Send(digits[val/10] | digits[10]);
 HAL_GPIO_WritePin(DIG_1_GPIO_Port, DIG_1_Pin, GPIO_PIN_SET);
 osDelay(5);
 HAL_GPIO_WritePin(DIG_1_GPIO_Port, DIG_1_Pin, GPIO_PIN_RESET);

 Dig_Send(digits[val%10]);
 HAL_GPIO_WritePin(DIG_2_GPIO_Port, DIG_2_Pin, GPIO_PIN_SET);
 osDelay(5);
 HAL_GPIO_WritePin(DIG_2_GPIO_Port, DIG_2_Pin, GPIO_PIN_RESET);
 }
 else
 {
 Dig_Send(digits[val/100]);
 HAL_GPIO_WritePin(DIG_0_GPIO_Port, DIG_0_Pin, GPIO_PIN_SET);
 osDelay(5);
 HAL_GPIO_WritePin(DIG_0_GPIO_Port, DIG_0_Pin, GPIO_PIN_RESET);

 Dig_Send(digits[(val%100)/10] | digits[10]);
 HAL_GPIO_WritePin(DIG_1_GPIO_Port, DIG_1_Pin, GPIO_PIN_SET);
 osDelay(5);
 HAL_GPIO_WritePin(DIG_1_GPIO_Port, DIG_1_Pin, GPIO_PIN_RESET);

 Dig_Send(digits[val%10]);
 HAL_GPIO_WritePin(DIG_2_GPIO_Port, DIG_2_Pin, GPIO_PIN_SET);
 osDelay(5);
 HAL_GPIO_WritePin(DIG_2_GPIO_Port, DIG_2_Pin, GPIO_PIN_RESET);
 }
}

Супер-портянка. Отменный говнокод-стайл, но это как раз то, что и нужно для ленивого проекта, тем более оно работает и причём стабильно хорошо (можно было бы переписать на голых регистрах или даже Bit-Banding, но… лень)!

И остался main.c файл… :) У нас используется FreeRTOS и 3 треда. Приведу только код, внутри них.

Task_DigUpdate — самый сложный по количеству кода, отвечает за дисплей :

void Task_DigUpdate(void const * argument)
{
 /* USER CODE BEGIN Task_DigUpdate */
 Dig_Init();

 for(;;)
 {
 Dig_Update();
 }
 /* USER CODE END Task_DigUpdate */
}

Task_BTUpdate — самый сложный в плане математики (об этом ниже), отвечает за ШИМ:

void Task_BTUpdate(void const * argument)
{
/* USER CODE BEGIN Task_BTUpdate */
uint16_t val = 240, val_old = 0; // реальное значение частоты = val / 10
osDelay(500);

for(;;)
{
osDelay(100);
if(HAL_GPIO_ReadPin(BT_P_GPIO_Port, BT_P_Pin) == 0) if(val  210) val-=1;

if(val != val_old)
{
val_old = val;
Dig_SetValue(val);
uint32_t tim_autorel = 100000/val;
__HAL_TIM_SET_AUTORELOAD(&htim3, tim_autorel);
__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, tim_autorel/2); // заполнение 50%
}
}
/* USER CODE END Task_BTUpdate */
}

StartDefaultTask — и наконец-то основной, самый говнокодистый, отвечает за основную кнопку ВКЛ\ВЫКЛ:

void StartDefaultTask(void const * argument)
{

/* USER CODE BEGIN 5 */
uint16_t val = 0, val_state = 0;
uint32_t timeout_cnt = 0;
// включаем питание
HAL_GPIO_WritePin(PWR_EN_GPIO_Port, PWR_EN_Pin, GPIO_PIN_SET);
osDelay(1000);

for(;;)
{
// детектируем нажатие на кнопку
if(HAL_GPIO_ReadPin(BT_PWR_GPIO_Port, BT_PWR_Pin) == 0) if(val  40) // удержание до 3-х полосок
{
Dig_SetLoad(0x7);
// выкл
if(HAL_GPIO_ReadPin(BT_PWR_GPIO_Port, BT_PWR_Pin) != 0)
{
osDelay(500);
HAL_GPIO_WritePin(PWR_EN_GPIO_Port, PWR_EN_Pin, GPIO_PIN_RESET);
val = 0;
}
}
else if(val > 20) // удержание до 2-х полосок
{
Dig_SetLoad(0x6);
// что ли бо... но ничего нет.
if(HAL_GPIO_ReadPin(BT_PWR_GPIO_Port, BT_PWR_Pin) != 0)
{

Dig_ShowValue();
val = 0;
}
}
else if(val > 1) // кратковременное нажатие
{
Dig_SetLoad(0x4);
if(HAL_GPIO_ReadPin(BT_PWR_GPIO_Port, BT_PWR_Pin) != 0)
{
if(val_state)
{
val_state = 0;
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_4);
}
else
{
val_state = 1;
timeout_cnt = 0;
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_4);
}
Dig_ShowValue();
val = 0;
}
}

if(val_state == 0) // автовыключение, если не используется
{
timeout_cnt += (50);

if(timeout_cnt > (50 * 20) * 60 * 10) // (задержка в цикле * до 1 сек) * (n сек) = 10 минут
{
HAL_GPIO_WritePin(PWR_EN_GPIO_Port, PWR_EN_Pin, GPIO_PIN_RESET);
}
}
}
/* USER CODE END 5 */
}

Всё просто как топор. ;)

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

Сначала смотрим как инициализирован таймер, для нас важен делитель частоты тактирования этого самого таймера:

 htim3.Init.Prescaler = 4800-1;
 htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
 htim3.Init.Period = 100-1;
 htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

 

В данном случае частота работы таймера получается:

Fclk = Fmcu / Prescaler = 48 МГц / 4800 = 10 кГц

Теперь находим период работы таймера:

Ttim = 1 сек / Fclk = 1 / 10.000 = 0,0001 сек

Далее находим период требуемой частоты ШИМ:

Tout = 1 сек / Fout = 1 / 24 = 0,041(6) сек

И последнее — получение значения AUTORELOAD таймера:

AutoReloadValue= Tout / Ttim = 0,041(6) / 0,0001 = 416,(6) ~ 417

И это значение и записывается в таймер командой:

__HAL_TIM_SET_AUTORELOAD(&htim3, tim_autorel);

Также стоит всегда помнить и про регистр сравнения, им мы выставляем желаемое заполнение ШИМ, 100% — это текущее значение AutoReload, а, к примеру, для 50% заполнения можно сделать вот так:

__HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_4, tim_autorel/2);

Таким образом всегда будет выставляться автоматически 50% заполнение ШИМ при обновлении частоты, что и показано в коде выше.

Также стоит отметить, что для повышения точности следовало бы при возможности использовать какой -о такой псевдо-код расчёта частоты (не проверял):

 float tim_per = (float)(1.0 / 10000.0); // 1 сек / на частоту тактирования таймера
 float pwm_per = (float)(1.0 / (float)val); // 1 сек / на частоту ШИМ
 float tim_autorel = (float)(pwm_per / tim_per);

Но в моём случае используется только целочисленные переменные и я постарался сократить всё по максимуму + т.к. используется очень удобное значение частоты тактирования таймера (10 кГц), это еще больше упрощает получение упрощённой формулы:


uint32_t tim_autorel = 100000/val;

Всё гениально просто. :) Вот вроде бы и готов код прошивки, а тут как раз уже и допечатывается корпус… компилируем, прошиваем и собираем — будем тестить!

Начинаем со светодиода — сверлим отверстия в радиаторе для крепления проводов и прикручиваем к корпусу:

B47-24

Мажем цапонлаком для дополнительной защиты от влаги (хотя если таки вода попадёт внутрь, особо это не спасёт, имхо) и устанавливаем их в слоты или на крепёжные стоечки:

B47-25

Тут и вышел первый косяк… я-то спаял сразу, потом замазал сверху цапонлаком, а вот длина проводов не везде получилась достаточной, ну, не проблема — это ленивый проект и сделаем всё по топорному! Да ещё закрепим всё по-колхозному — клеем пистолетом. ;)

B47-26

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

Прикручиваем плату кнопок, вроде нормально:

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

B47-29

Закручиваем корпус, проверяем зарядку:

B47-30

Работает! :) Правда не так и ярко, но вполне отчетливо можно видеть красный (идёт заряд) \ синий (заряжено).

И под конец видео работы:

Частота кадров камеры накладывается на частоту мигания светодиода и выходит забавный эффект, якобы светодиод мигает с заметно более низкой частотой. Так же на видео показан процесс включения \ выключения полученного устройства.

На этом всё! Не воспринимайте всерьез эту статью, это ради прикола попробовал разбавить трудовые будни пересказом простой, банальной просьбы сделать скучный прибор . ;)

 

 

 

Реклама

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

Please log in using one of these methods to post your comment:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

w

Connecting to %s