Приборы для дома http://myowndevice.ru Wed, 28 Aug 2024 12:10:43 +0000 Joomla! - Open Source Content Management ru-ru Кухонный таймер /index.php/pribory/item/33-kukhonnyj-timer /index.php/pribory/item/33-kukhonnyj-timer Кухонный таймер

Прямой и обратный отсчёт времени до 10 часов. Три предустановленных интервала таймера, с возможностью настройки. Громкий сигнал различной тональности. Встроенный литиевый аккумулятор и схема зарядки по micro usb. Игры — игральная кость, лото, бомба. Учёт рабочего времени с подтверждением. Компактный размер 40x40x16мм. Красивый пластиковый корпус.

{autotoc}

Прежде чем начать

Прежде чем читать эту статью, рекомендуем вам ознакомится со следующей теорией:

Кухонный таймер. Что это? сколько стоит?

На рынке существует очень много различных видов кухонных таймеров. Мы будем рассматривать только электронные варианты (еще есть механические). Основное применение данный прибор нашёл на кухне. Отсюда идёт и его название — кухонный таймер. Допустим, вы готовите какое-то блюдо, варите картошку. Через 20 минут после закипания, надо ее выключить — она готова. Можно, конечно запомнить по часам этот промежуток времени, но делать это с помощью таймера гораздо удобнее. Установили нужный интервал времени — нажали кнопку, начался обратный отсчёт времени. Через 20 минут кухонный таймер громко просигналит, обычно в течение 1 минуты. Вот такой простой прибор.

Купить электронный кухонный таймер на рынке можно по цене от 200 до 2000 рублей. Как правило, они отличаются дизайном, размерами и функциями. Все они умеют выполнять основную функцию — таймер обратного отсчёта. Интервал времени почти у всех моделей ограничен 99 минутами (4 разряда цифр — 2 на минуты и 2 на секунды). Дополнительные функции, которые можно встретить:

  • магнитное крепление, крепление на ремень

  • секундомер

  • быстрая установка времени (покрути корпус)

Все рыночные приборы, питаются от батареек, имеют, как правило, ЖК дисплей. Батареек хватает больше чем на 2-3 месяца регулярного использования.

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

{product id=32}

Постановка задачи, требования к прибору

Основные требования к нашему кухонному таймеру.

  • Компактный размер

  • Питание от аккумулятора, длительная работа от одного заряда

  • Зарядка от micro usb

  • Индикатор как минимум на 3 разряда, лучше 4-е

  • Низкая стоимость

  • Громкий сигнал

  • Широкий набор функций — Таймер, Секундомер, Игры: игральная кость, лото, бомба, возможность программирования.

Подбор компонентов

Компоненты будем подбирать самые простые, недорогие, и доступные на рынке.

Индикатор

Это самый сложный вопрос. На рынке есть следующие виды индикаторов:

  • LCD, TFT дисплей — дорого, большой размер




  • ЖК сегментный индикатор — на 3-4 цифры — вполне подойдёт, но тяжело купить (больше распространён китае), большой плюс — низкое энергопотребление.


  • Светодиодный сегментный индикатор — отличный, недорогой вариант, минусом является высокое энергопотребление, но с аккумулятором это не так страшно. За счет яркости, можно снизить энергопотребление до 2ма. Его несложно купить. Наш таймер будем делать на данном виде индикатора.


Данные индикаторы могут иметь прямое управление каждым светодиодом, но в этом случае у них будет много выводов. Мы выберем 3-х сегментный светодиодный индикатор красного цвета с общим анодом. У каждой цифры аноды светодиодов соединены вместе и выведены на один вывод. На таком индикаторе можно в одном время показать только одну цифру! Как же задействовать все три? Очень просто. Будем использовать динамическую индикацию, то есть очень быстро показывать первую цифру, потом вторую, потом третью. Глаз не успеет заметить этого подвоха, и будет складываться впечатление, что горят одновременно все три цифры! Такая схема очень часто используется в индикаторах, в том числе и в ЖК. Поэтому вам просто необходимо освоить модель программирования таких индикаторов.

Интерфейс общения

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

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

  • Таймер

  • Секундомер, с возможностью учета рабочего времени

  • Игры

При включении после сна, прибор автоматически возвращается в последний режим, в котором он был до сна.

В режиме таймера:

  • Отображается предустановленное значение таймера в минутах, первая кнопка перебираем предустановленные значения, которые можно запрограммировать

  • Вторая кнопка начинает Отсчет, при окончании раздаётся сигнал

  • Долгое нажатие второй кнопки позволяет поменять значение и запрограммировать новое предустановленное значение

В режиме Секундомера

  • Вторая кнопка старт/пауза

  • Первая кнопка выбор режима — простой секундомер или с подтверждением. В режиме с подтверждением, каждые 5 минут необходимо нажимать кнопку, если не нажали, то секундомер пищит и встаёт на паузу. Так можно измерять рабочее время, когда вы часто отвлекаетесь от рабочего процесса.

В режиме игр

  • Первая кнопка выбор игры

  • Вторая кнопка ход в игре

Конечно, вы можете сами написать свою программу, и сделать совершенно другие комбинации и режимы — это же ваш кухонный таймер — вы его создатель!

Микроконтроллер

Выберем микроконтроллер. Какие требования к микроконтроллеру в нашем проекте?

  • считывать показания 2 кнопок

  • наличие спящего режима для энергосбережения

  • для более полного погружения в программирование, необходим полноценный отладчик

  • удобный корпус для пайки

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

  • EEPROM память для хранения настроек

  • достаточное количество выводов для управления индикатором — нужно 11 выводов.

Выберем уже знакомую серию STM8, исключительно по цене. Дополнительно она имеет отличный отладчик ST-Link по 2-ум проводам, симулятор и всю необходимую периферию. Программа будет небольшая, выберем самый дешёвую модель - наш выбор STM8S003F3P6. Можно выбрать серию STM8L — с низким энергопотреблением, но на выбранном микроконтроллере прибор будет работать больше месяца. Этого вполне достаточно.

Аккумулятор

В этот раз будем использовать литиевый аккумулятор меньшего размера — LIR2032, ёмкостью 45 mAh, для того чтобы прибор поместился в небольшой корпус. Схема заряда аналогично велокомпьютеру. Дополнительно будем использовать схему защиты аккумулятора от глубокого разряда из данной статьи.

Составляем схему

Схема зарядки аккумулятора и обвязки МК будет очень похожа на велокомпьютер, так что, не будем повторяться. Для защиты аккумулятора от разряда добавим схему аналогично данной статьи. Для отображения информации добавим ещё светодиодный индикатор — это по сути просто набор светодиодов. При управлении индикатором будем использовать посегментное сканирование — одновременно может светиться только один сегмент из цифры. В этом случае управление сегментом напрямую можно подключить к выводу МК. Резисторы нужны только на общих выводах анода. Резисторы можно использовать 200 Ом, при этом ток свечения одного светодиода будет около 6мА, яркости будет достаточно. Дополнительно ее можно будет снизить за счет динамической индикации для уменьшения потребления. Итак, вот финальная схема.


Вторая часть схемы — зарядка и защита аккумулятора от разряда. Отметим, что резистор R7 здесь не нужен!! При его установке будет только увеличено потребление тока во сне до 50 мкА. Запаивать его не надо!!




Корпус

Подберём небольшой корпус для нашего прибора. Компания SANHE выпускает много универсальных корпусов. Нам подойдет корпус 20-31 размером 30х40мм. Данный корпус очень приятный на ощупь и совсем небольшой.


При трассировке платы будем учитывать необходимые размеры. В корпусе необходимо будет прорезать отверстия под экран и usb разъем. Также нужно будет просверлить отверстия под кнопки. Вот как выглядит собранный прибор в этом корпусе.




Стойки крепления платы необходимо будет убрать — это можно сделать пассатижами. Чтобы отделить аккумулятор от платы необходимо вырезать прокладку из толстого полиэтилена или плотной изоленты.

Программа

Программа, как обычно, для STM8, написана в среде ST Visual develop IDE. Заготовку проекта вы можете скачать с github данного прибора, папка timer. Мы специально не выкладываем полную программу! В этом приборе вы должны сделать ее сами! Только так вы научитесь программировать МК. В заготовке проекта мы сделали самую сложную часть — инициализация, динамическая индикация, спящий режим, обработка кнопок. Вот это мы и разберём в этой статье. В кухонном таймере будем использовать все виды нажатий кнопки — одиночное, двойное, долгое. Такие режимы обработки кнопок очень часто используются в различных устройствах. Читайте внимательно!

Если вы делаете подарок, то вы можете запрограммировать при включении какую-то небольшую мелодию. Это не сложно. В интернет есть много примеров. Заодно поработаете со звуком.

Структура файлов проекта

Проект создан на основе библиотеки SPL для STM8 от ST. Подробное описание, как развернуть проект, вы найдёте в этой статье. Вся программа содержится в файле main.c, обработка прерываний перенесена в этот файл.

Общее описание программы

Упрощённый алгоритм работы программы.

  1. При включении производится настройка всей периферии, тактирование от внутреннего генератора на частоте 2 МГц. Читаем данные из EEPROM. Сразу переходим в спящий режим.

  2. Прибор может находится в одном из трёх режимов — Игры, Таймер, Секундомер, перебор по долгому нажатию первой кнопки. Выбор подрежимов, по обычному нажатию первой кнопки. Запуск и остановка второй кнопкой.

  3. Индикация

    1. Если прибор в режиме игры — то левый сегмент индикация игры — L — лото, Б — бомба, Н — игральная кость. Остальные два разряда для игры.

    2. В режиме таймера. Таймер запущен — мигает точка в такт секундам. Таймер остановлен точка не горит. Таймер может отображать от 999 минут до 0. На экране всегда отображаем значащие разряды, точка разделитель секунд и минут. Например, 900 минут = 900. , 10 минут 15 секунд = 10.1, 1 минута 25 секунд = 1.25.

    3. В режиме секундомера. Запущен — мигает точка в такт секундам. Отображение как в таймере. При остановке секундомера, например на 10 мин 35 сек, показывает целую часть 10. 1сек потом дробную часть .35 1сек и так попеременно.

  4. Таймер

    1. Когда таймер не запущен. Первая кнопка выбираем предустановленные значения.

    2. Вторая кнопка старт таймера из предустановленного значения. Таймер в минутах.

    3. Долгое нажатие второй кнопки переходит в режим настройки значения. В этом режиме вторая кнопка и первая кнопка работают как плюс минус 1 минута. Долгое нажатие Второй кнопки записывает значение в настройку. Быстрое нажатие на кнопки прибавляет по 5 минут.

    4. При достижении конца таймера играем мелодию каждые 60с в течение 5 мин. Пока не остановим кнопкой.

    5. Когда таймер запущен — вторая кнопка долгое нажатие — сброс, первая кнопка - пауза

  5. Секундомер

    1. Когда запущен — мигает точка

    2. Вторая кнопка старт/пауза секундомера

    3. Первая кнопка выбор режима — с подтверждением или без. Когда выбран режим с подтверждением, то горит дополнительно первая точка

    4. Вторая кнопка долгое нажатие сброс

  6. Лото

    1. Игра не началась. Отображаем две тире

    2. Вторая кнопка следующее значение и выдаем звуковой сигнал

    3. Вторая кнопка долгое нажатие начать сначала

    4. в конце игры выдаем мелодию переливы и начинаем сначала

  7. Бомба

    1. Игра не началась — две тире

    2. Вторая кнопка — начать игру. Засекаем случайное время

    3. Игра идет — каждую секунду мигают нули и идет звук как часы пикают. Звук ускоряется каждые 10% оставшегося времени

    4. Когда время вышло — то звучит звук низкого тона — взрыв. У кого в руками остался прибор — тот проиграл. Игра начинается сначала.

  8. Спящий режим

    1. Если ничего не запущено, то через 30с неактивности — глубокий сон

    2. Если запущен таймер или секундомер — то через 30с гасим экран — остаётся только точка мигать каждую сек на 200мс. По кнопке показываем время. Когда осталось 30 сек. Кнопки работают как обычно. Но сначала будят как бы. То есть пробуждение не срабатывает как нажатие кнопки. Будить можно любой кнопкой.

    3. Если запущен секундомер, и про него забыли, не было активности 3ч, то заснуть совсем, а таймер оставить на моменте когда заснули.

Конечно, это один из возможных вариантов работы программы. Вы можете придумать свой собственный вариант. Это же ваш кухонный таймер.

Инициализация, прерывания

Первоначальная инициализация довольно простая.

[code]CLK->PCKENR1 = CLK_PCKENR1_TIM4+CLK_PCKENR1_TIM2;
CLK->PCKENR2 = 0b01110111;

CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV8);
[/code]

Выключаем лишнюю периферию, оставляем только таймер 4 и 2. Тактирование от внутреннего генератора 16 МГц, с делителем 8, для пониженного энергопотребления. В итоге, работаем на частоте 2 МГц. При тактировании от внутреннего генератора, периферия работает на частоте центрального процессора — то есть таймеры будут работать тоже на частоте 2Мгц, имейте это ввиду при настройке счетчиков таймеров.

[code]TIM4_TimeBaseInit(TIM4_PRESCALER_8, 249);
TIM4_ClearFlag(TIM4_FLAG_UPDATE);
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
TIM4->IER |= (uint8_t)TIM4_IT_UPDATE;

TIM2_TimeBaseInit(TIM2_PRESCALER_32, 50);
TIM2_ClearFlag(TIM2_FLAG_UPDATE);
TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);
TIM2->IER |= (uint8_t)TIM2_IT_UPDATE;
[/code]

TIM4 будем использовать для миллисекундного отсчета, а TIM2 для динамической индикации. Для TIM2 частота нужна повыше, чтобы не было заметно мерцания, также она не должна быть пропорциональна 50 Гц (частота мерцания лампочек в сети 220В). С другой стороны слишком высокая частота будет больше тратить энергии.

[code]EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOA,EXTI_SENSITIVITY_FALL_ONLY);	
EXTI_SetExtIntSensitivity(EXTI_PORT_GPIOB,EXTI_SENSITIVITY_RISE_ONLY);
[/code]

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

[code] GPIO_Init(GPIOA,GPIO_PIN_2,GPIO_MODE_IN_PU_IT);//кнопки
GPIO_Init(GPIOB,GPIO_PIN_5,GPIO_MODE_IN_FL_IT);//кнопки

GPIO_Init(GPIOD,GPIO_PIN_4,GPIO_MODE_OUT_PP_LOW_SLOW);//пищалка

GPIO_Init(GPIOD,GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_6,GPIO_MODE_OUT_PP_HIGH_SLOW);//индикатор
GPIO_Init(GPIOA,GPIO_PIN_1,GPIO_MODE_OUT_PP_HIGH_SLOW);//
GPIO_Init(GPIOB,GPIO_PIN_4,GPIO_MODE_OUT_PP_HIGH_SLOW);//
GPIO_Init(GPIOC,GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7,GPIO_MODE_OUT_PP_HIGH_SLOW);

halt();
[/code]

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

Динамическая индикация

Настройка динамической индикации не очень сложная. Для удобства, необходимо сделать несколько дефайнов:

[code]#define ON1 GPIO_WriteHigh(GPIOC,GPIO_PIN_3)
#define ON2 GPIO_WriteHigh(GPIOD,GPIO_PIN_5)
#define ON3 GPIO_WriteHigh(GPIOD,GPIO_PIN_6)

#define OFF1 GPIO_WriteLow(GPIOC,GPIO_PIN_3)
#define OFF2 GPIO_WriteLow(GPIOD,GPIO_PIN_5)
#define OFF3 GPIO_WriteLow(GPIOD,GPIO_PIN_6)

#define AON GPIO_WriteLow(GPIOB,GPIO_PIN_4)
#define BON GPIO_WriteLow(GPIOA,GPIO_PIN_1)
#define CON GPIO_WriteLow(GPIOC,GPIO_PIN_6)
#define DON GPIO_WriteLow(GPIOD,GPIO_PIN_3)
#define EON GPIO_WriteLow(GPIOD,GPIO_PIN_2)
#define FON GPIO_WriteLow(GPIOC,GPIO_PIN_4)
#define GON GPIO_WriteLow(GPIOC,GPIO_PIN_5)
#define TON GPIO_WriteLow(GPIOC,GPIO_PIN_7)

#define ALLOFFGPIO_WriteHigh(GPIOC,GPIO_PIN_6|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_7);GPIO_WriteHigh(GPIOD,GPIO_PIN_2|GPIO_PIN_3);GPIO_WriteHigh(GPIOA,GPIO_PIN_1|GPIO_PIN_3);GPIO_WriteHigh(GPIOB,GPIO_PIN_4);
[/code]

ONx.. OFFx — позволяют включить и выключить 1 цифру. AON..TON — один сегмент в цифре. ALLOFF — выключить все сегменты. Далее, нам нужна вспомогательная функция — cifraS(), которая будет отображать в одной цифре нужный сегмент для выбранного символа (например буквы L, прочерка и т. д.). В функцию передаем нужный сегмент. Информация о том, что необходимо выводить содержится в массиве ind[] и tchk[] для символов и точек.

[code]void cifraS(u8 seg){
u8 j=0;

if(seg==0) AON;
if(seg==1) BON;
if(seg==2) CON;
if(seg==3) DON;
if(seg==4) EON;
if(seg==5) FON;
if(seg==6) GON;
if(seg==7) TON;

for (j=0;j<3;j++) {
u8 num;
u8 flag=0;

if (seg==7) {
if (tchk[j] * tchkmig) flag = 1;
} else {

num = ind[j];


if (num==0) {
//AON;BON;CON;DON;EON;FON;
if(seg==0) flag=1;
if(seg==1) flag=1;
if(seg==2) flag=1;
if(seg==3) flag=1;
if(seg==4) flag=1;
if(seg==5) flag=1;
}
if (num==1) {
//BON;CON;
if(seg==1) flag=1;
if(seg==2) flag=1;

}
if (num==2) {
//AON;BON;GON;EON;DON;
if(seg==0) flag=1;
if(seg==1) flag=1;
if(seg==3) flag=1;
if(seg==4) flag=1;
if(seg==6) flag=1;
}
if (num==3) {
//AON;BON;CON;DON;GON;
if(seg==0) flag=1;
if(seg==1) flag=1;
if(seg==2) flag=1;
if(seg==3) flag=1;
if(seg==6) flag=1;
}
if (num==4) {
//FON;GON;BON;CON;
if(seg==1) flag=1;
if(seg==2) flag=1;
if(seg==5) flag=1;
if(seg==6) flag=1;

}
if (num==5) {
//AON;FON;GON;CON;DON;
if(seg==0) flag=1;
if(seg==2) flag=1;
if(seg==3) flag=1;
if(seg==5) flag=1;
if(seg==6) flag=1;
}
if (num==6) {
//AON;EON;FON;GON;CON;DON;
if(seg==0) flag=1;
if(seg==2) flag=1;
if(seg==3) flag=1;
if(seg==4) flag=1;
if(seg==5) flag=1;
if(seg==6) flag=1;
}
if (num==7) {
//AON;BON;CON;
if(seg==0) flag=1;
if(seg==1) flag=1;
if(seg==2) flag=1;
}
if (num==8) {
//AON;BON;CON;GON;DON;EON;FON;
if(seg==0) flag=1;
if(seg==1) flag=1;
if(seg==2) flag=1;
if(seg==3) flag=1;
if(seg==4) flag=1;
if(seg==5) flag=1;
if(seg==6) flag=1;
}
if (num==9) {
//AON;BON;CON;GON;DON;FON;
if(seg==0) flag=1;
if(seg==1) flag=1;
if(seg==2) flag=1;
if(seg==3) flag=1;
if(seg==5) flag=1;
if(seg==6) flag=1;
}

if (num==14) {
//-
if(seg==6) flag=1;
}

if (num==11) {
//L
if(seg==3) flag=1;
if(seg==4) flag=1;
if(seg==5) flag=1;
}

if (num==12) {
//K
if(seg==0) flag=1;
if(seg==3) flag=1;
if(seg==4) flag=1;
if(seg==5) flag=1;
}

if (num==15) {
//K
if(seg==0) flag=1;
if(seg==3) flag=1;
if(seg==4) flag=1;
if(seg==5) flag=1;
}
}

if (flag==1 && j==0 ) ON1;
if (flag==1 && j==1 ) ON2;
if (flag==1 && j==2 ) ON3;


}
}
[/code]

С дефайнами она выглядит симпатично. Активируем нужный сегмент и проверем в каких из трех цифр он активен. Там где активен — включаем общий анод. Если вам нужны другие символы на индикаторе, то надо добавить еще условия, например, (num==11) — вывести на индикатор L.

Для того, чтобы вывести что-то на индикатор, достаточно положить в массивы ind[] и tchk[] нужные нам значения, остальное будет сделано в прерываниях. Вот так можно вывести число от 0 до 999.

[code]void shownumber(u16 num){
ind[0]=num/100;
ind[1]=num/10-ind[0]*10;
ind[2]=num - ind[0]*100 - ind[1]*10;
}
[/code]

Теперь, собственно сам вывод на индикатор. Вся работа ведётся в обработчике прерывания TIM2. Введём переменную numind, которая будет обозначать, какой сегмент показывать в данный вызов прерывания.

[code] INTERRUPT_HANDLER(TIM2_UPD_OVF_BRK_IRQHandler, 13)
{
TIM2_ClearITPendingBit(TIM2_IT_UPDATE);

OFF1;
OFF2;
OFF3;
ALLOFF

if (numind<8) {
cifraS(numind);
}

numind++;

if (numind==16) numind=0;
}
[/code]

Очищаем бит контроля обработки прерывания. Далее выключаем все разряды. Выводим нужные сегменты по всех трех цифрах. А потом несколько раз ничего не выводим. Пропуски нужны для регулирования яркости. У нас получится такая картина

Первый Сегмент, Второй Сегмент, Третий Сегмент, Ничего не горит …. Ничего не горит, Первый сегмент и т.д….

и так, очень быстро. Чем больше мы выводим пустых разрядов — тем более тускло светится индикатор, и меньше тратит энергии.

Обработка кнопок

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

Для настройки процедуры обработки кнопок есть несколько дефайнов:

[code]#define KNNUM  2  //колво кнопок
#define KNONE 4 //обычное нажатие
#define KNLONG 5 //долгое
#define KNTWO 6 //двойное

#define KNDTIME 50 //время в мс дребезга контактов
#define KNTIMETWO 300 //время в мс двойногонажатия
#define KNTIMELONG 1000 //время в мс долгогонажатия
[/code]

Количество кнопок, значения, которые возвращает функция определения кнопок, время необходимое для устранения дребезга, время в течение которого должно произойти двойное нажатие, время фиксации долгого нажатия. Для хранения обработанных данных используется массив kn[], для хранения предыдущего состояния кнопок массив knstatus[], времени, прошедшего с начала нажатия первой кнопки — kntime[]. При инициализации МК, необходимо очистить все эти массивы.

Сама процедура обработки кнопок вызывается из миллисекундного таймера каждые 50 мс (время нужное для устранения дребезга), так сразу решается проблема с дребезгом контактов.

[code]		u8 i,pd;

if(kndtime) kndtime--;
if (kndtime==0) {
//опрос кнопок редко для избежаниядребезга
kndtime = KNDTIME;

pa = GPIOA->IDR;//GPIO_ReadInputData(GPIOA);
pb = ~(GPIOB->IDR);//_ReadInputData(GPIOB);
knint(0, pa, GPIO_PIN_2);
knint(1, pb, GPIO_PIN_5);
}
for (i=0;i<KNNUM;i++) if(kntime[i]) kntime[i]--;
[/code]

Предварительно считываем состояние порта, на котором висят кнопки. Далее, передаем это значение, номер кнопки, номер вывода кнопки в функцию, в которой будет вся обработка — knint(). Так как кнопка на порту B нажата когда там будет значение 0, то используем операцию инверсии битов.

В конце уменьшаем на единицу переменные таймеры кнопок.

Рассмотрим саму функцию обработки кнопок.

[code]	if (knstatus[knum] && ((zn&pin) == 0)) {//кнопкунажали
knstatus[knum] = zn&pin;
if (kn[knum]>=KNONE) return; //еще не обработалипредыдущее нажатие в основном циклепропустим это нажатие

kn[knum]++;//колво нажатий плюс один
if (kn[knum]==1) kntime[knum] = KNTIMELONG;//первый разначнм замер времени

if (kn[knum]==2) {
if (kntime[knum] > (KNTIMELONG-KNTIMETWO) ) kn[knum] =KNTWO;
else kn[knum] = KNONE;
}
}

if ((kn[knum]==1) && (kntime[knum]==0)) kn[knum]=KNLONG;
if ((kn[knum]==1) &&(kntime[knum]<(KNTIMELONG-KNTIMETWO)) && zn&pin)kn[knum]=KNONE;

knstatus[knum] = zn&pin;
[/code]

Чтобы определить, что мы нажали кнопку, сравним предыдущее состояние кнопки и состояние вывода. Если кнопка нажата, но мы еще не обработали в основном цикле значение кнопки, то делать ничего не будем. Каждое нажатие увеличиваем на один счётчик нажатий, он будет у нас хранится в элементе массива результата кнопки kn[]. Таким образом, пока мы не знаем точно, какой вид нажатия, то будем там хранить количество нажатий. Если это первое нажатие, то засекаем время определения долгого нажатия. Если это второе нажатие, то проверим уложились ли мы во время двойного нажатия — если да, то фиксируем двойное нажатие, если нет — то обычное.

Каждый раз проверяем, если время долгого нажатия было засечено и оно вышло, то это долгое нажатие кнопки. Если кнопку отпустили, время двойного нажатия вышло и у нас одинарное нажатие, то это обычное нажатие кнопки.

Все! Так несложно можно определить все нужные нам виды нажатия. В основном цикле вы можете обработать их

[code]		if (kn[0] == KNONE) {
secundomer = 0;
sleeptime=30;
kn[0]=0;
}
if (kn[0] == KNTWO) {
secundomer = 100;
sleeptime=30;
kn[0]=0;
}
if (kn[0] == KNLONG) {
secundomer = 200;
sleeptime=30;
kn[0]=0;
}
[/code]

После обработки, необходимо очистить элемента массива kn[], для фиксирования нового нажатия. Вы можете использовать этот код в своих проектах, добавить количество кнопок, поменять время обработки различных ситуаций.

Начало положено, остальной код программы мы не приводим, так как это ваше творчество!

Как изготовить кухонный таймер самостоятельно

Делаем плату и все запаиваем

  1. Подготовить или приобрести необходимые инструменты: все для пайки, ST-LINK (будет нужен для программирования и отладки МК)

  2. Внимательно прочитать статьи из раздела Обязательная теория.

  3. Скачать необходимые файлы по данному прибору с github.

  4. Изготовить плату для прибора самостоятельно (это совсем несложно, в нашей инструкции все подробно описано).

  5. Приобрести все необходимые комплектующие.

  6. Запаять все компоненты на плату, смотри наше видео.

  7. Плата готова!

Для программирования вам понадобятся временно припаять провод выводу J3 (PRG). Питание можно подключить сразу с ST-Link в разъем аккумулятора.

Переходим к программированию

Данный прибор достаточно простой в программировании. В этой статье подробно разобрана самая сложная часть программы — динамическая индикация. Остальную программу вам надо написать самостоятельно. Только так вы сможете изучить программирование микроконтроллеров.

Рекомендуем написать программу совсем с нуля, с разворачивания проекта.

Приобретённые навыки

Пайка: пайка корпуса TTSOP, пайка корпуса SOT-23-5, пайка micro USB разъёма

Корпус: самодельный корпус из короба

Схемотехника: LDO, схема зарядки Liion аккумулятора, типовая схема подключения STM8, подключение пищалки, работа с кнопками.

Программирование: сложная обработка кнопок, миллисекундный таймер, динамическая индикация, спящий режим, работа с EEPROM

Самостоятельная работа

Прибор очень простой, но интересный и полезный. На github мы выкладываем только шаблон проекта. В данном шаблоне настроено энергопотребление, прерывания, таймеры, обработка кнопок, динамическая индикация с выводом трёх символов и точек. Остальное мы рекомендуем сделать самостоятельно. У вас получится отличный кухонный таймер, для себя или в подарок.

]]>
(Super User) Приборы Tue, 01 Aug 2017 09:02:00 +0000
Мини пирометр /index.php/pribory/home/item/50-mini-pirometr /index.php/pribory/home/item/50-mini-pirometr Мини пирометр

Компактный пирометр — точное измерение температуры поверхности на расстоянии. Размер — всего 3см на 4 см. Питание от аккумулятора, более 300 измерений на одном заряде. Расстояние измерения до 50cм, угол рассеивания 10 градусов. Измерение температуры в широком диапазоне от +300 до -100 градусов. Яркий светодиодный индикатор. Автоматическое отключение через 30 секунд для экономии энергии. Измерение температуры чая или молока, воды в ванной, поверхности моря, воздуха на улице, компонентов на плате.

{autotoc}

Прежде чем начать

Прежде чем читать эту статью рекомендуем вам ознакомится со следующей теорией:

Что такое пирометр и где его можно использовать

Пирометр, или его равнозначные названия – инфракрасный термометр - это точный инженерный прибор нового поколения для бесконтактного и быстрого измерения температурных показателей на расстоянии от исследуемого объекта. В основе его работы лежит принцип определения по тепловому излучению практически любого объекта температурного значения его поверхности.




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

С этим прибором можно измерить температуру:

  • молока в детской бутылочке или горячего чая

  • воды в ванной

  • масла при жарке во фритюре

  • компонентов в изготавливаемом приборе

  • моторов квадрокоптера

  • детали в автомобиле

  • воздуха на улице

  • внутри холодильника или морозилки

  • поверхности моря

{product id=38}

Постановка задачи, требования к прибору

Основные требования к прибору.

  • Компактный размер, карманный вариант

  • Питание от аккумулятора, автоматическое отключение по окончанию измерения

  • Высокая абсолютная и относительная точность измерений

  • Автоматическая компенсация внешней температуры

  • Индикация измеренных данных на компактном индикаторе

Подбор компонентов для самодельного пирометра

Выбираем датчик ИК излучения

Практически все пирометры содержат оптическую систему для увеличения разрешения (расстояния на котором работает прибор). Сделать ее в домашних условиях достаточно сложно, поэтому будем делать прибор без нее. Нам понадобится датчик ИК излучения, желательно цифровой и с минимальным оптическим разрешением.

Компания Melexis как раз выпускает такие датчики. Серия MLX90614 имеет очень хорошие параметры. Данный датчик представляет собой сочетание в одном 4-контактном корпусе ТО-39 инфракрасного высокочувствительного детектора на термоэлементах и специализированного стандартного формирователя сигналов. Этот термометр включает в себя малошумящий усилитель, 17-разрядный аналого-цифровой преобразователь и мощный процессор цифровых сигналов. Он откалиброван на заводе-изготовителе с возможностью использования на цифровом выходе широтно-импульсной модуляции (ШИМ) и системной шины управления (SMBus — I2C). К датчику идёт подробный datasheet, в котором подробно описано как работает датчик и какие у него есть модификации. Подберём нужную модификацию датчика из возможных вариантов.




Так как прибор должен работать от аккумуляторов, то необходима версия датчика на 3 вольта. За это отвечает первая буква в номере датчика — B или D.

Вторая буква определяет возможность автоматической температурной компенсации внешней температуры — очень полезная функция, она повышает точность измерений, особенно вне дома. Выбираем этот тип датчика — вторая буква C.

Третья — определяет оптическое разрешение датчика. Чем меньше поле обзора, тем дороже датчик, а значит с большего расстояния можно измерять температуру небольших объектов. Разрешение определяется углом конуса поля обзора датчика. Есть датчики с углом 80 градусов, 35 градусов, 10 градусов и 5 градусов. Выберем датчик серии C — угол 35 градусов, он имеет вот такой график области обзора (датчик с углом в 5 градусов стоит очень дорого).




Грубо можно сказать, что с расстояния в 20см область обзора датчика равна окружности диаметром 15см. Это не самый лучший результат, но его достаточно для домашнего использования. А учитывая размер прибора и его стоимость, польза его неоспорима.

Выбираем датчик — MLX90614ESF-BCC. Иногда проще купить датчик MLX90614ESF-ACF, он может обойдись даже дешевле, но он на 5В. Для повышения напряжения до 5В можно использовать простые конденсаторные повышающие микросхемы. Потребляемый ток самого датчика очень небольшой.

Выдавать показания датчик может по шине I2C или через PWM выход. Будем использовать I2C, как более удобный и функциональный вариант (есть возможность настроить коэффициент отражения поверхности).

Датчик определяет температуру в диапазоне от -70 градусов до 380. Погрешность измерения отображена в следующей таблице. Наибольшую точность он имеет в диапазоне от 0 до 60 градусов.




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

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

Индикатор

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




На данном индикаторе всего три разряда, не очень удобно показывать отрицательные температуры. Будем использовать вместо минуса две светящиеся точки.

Микроконтроллер

Возьмём уже знакомый по другим приборам, самый дешёвый вариант — STM8S003F3. Все что нужно у него есть.

Аккумулятор

Питаться прибор будет от аккумулятора. Потребление за счёт включения индикатора в режиме неполной яркости в рабочем режиме составляет около 1-2 мА. Достаточно будет самого маленького аккумулятора, например LIR2032. Плату будем делать как можно меньше, поэтому заряжать будем через внешний разъем с помощью небольшой отдельной платы зарядки. Саму зарядную микросхему размещать внутри прибора не будем.

В данном приборе используется схема отключения питания самим микроконтроллером. Таким образом, тратиться энергия будет только во время работы прибора. Можно не заботиться о защите аккумулятора от глубокого разряда. То есть схема контроля разряда тоже не нужна.

Регулятор питания

Так как на аккумуляторе максимально может быть 4.2В, а для датчика максимальное напряжение составляет 3.6В, то необходим регулятор питания. Возьмём серию NCP603 на 3.3 вольта.

Подбираем корпус

Корпус возьмём аналогично кухонному таймеру «Sanhe 20-31». Датчик будет плотно держаться на своих выводах, дополнительного крепления не нужно. Разъёмов, кроме подключения аккумулятора не нужно.

Составляем схему




На данной схеме обратим внимание на механизм включения и выключения прибора тактовой кнопкой. При нажатии на тактовую кнопку на входе 3 ENABLE регулятора питания NCP551 появляется напряжение 3.08В при напряжении аккумулятора 3.7В (делитель напряжения 10к и 50к). Такое напряжение включает регулятор, и питание подаётся на МК. МК переключает вывод 14 в HIGH, и таким образом удерживает регулятор включённым. В случае если необходимо выключить прибор, например при простое более 30 сек, МК подаёт на вывод 14 сигнал LOW и регулятор выключается обесточивая всю схему.

Управляющий вывод одновременно является входом для ADC микроконтроллера, что позволяет, используя внутреннюю подтяжку (около 40к) различать напряжение при нажатии кнопки и удержании микроконтроллером. Таким образом, данная кнопка становится доступной и для работы прибора. Отметим, что не во всех микроконтроллерах можно производить изменения с помощью ADC, когда одновременно включена подтяжка вывода. В этом случае необходимо очень быстро переключить вывод в режим чистого ADC, измерить напряжение и вернуть поддержку обратно. У регулятора, как правило, есть время срабатывания выхода Enable и его обычно достаточно для такой быстрой операции.

При таком использовании регулятора важно посмотреть в datasheet такой параметр как ток потребления самого регулятора (Quiescent Current) в режиме выключения:


Для данного регулятора он составляет максимум 1 мкА, а обычно составляет всего 100 нА. Это очень мало, гораздо меньше чем работающий микроконтроллер в режиме сна.

Такая схема позволяет не ставить схему защиты аккумулятора от глубокого разряда. Так как на одном заряде аккумулятора прибора хватает более чем на 300 непрерывных измерений в течение 30 секунд, то заряжать его придётся очень редко. Схему зарядки аккумулятора в этом приборе использовать не будем. Заряжать аккумулятор будет отдельная плата.

Печатную плату вы сможете найти в проекте на github.

Программа

Программа для STM8 написана в среде ST Visual develop IDE. Полный проект вы можете скачать с github данного прибора, папка pirometr. В статье мы разберём ключевые моменты работы программы.

Общая логика работы программы

  1. При включении производится настройка ADC, I2C, тактирования процессора, прерываний, выводов и система переходит в рабочий режим

  2. Производятся непрерывные измерения (каждые 500мс) и отображение результата на индикаторе

  3. Через 30с простоя прибор выключается

  4. В случае нажатия на кнопку прибор показывает последнее измерение в течение 3с и выключается (очень удобно если нужно куда-то подлезть и произвести измерение, а потом посмотреть результат)

Инициализация

Установим частоту работы микроконтроллера в 2 МГц и отключим всю периферию, кроме ADC, I2C, TIM1 TIM2 и TIM4. Настроим выходы управления индикатором.

[code]	//питание - оставляем только нужнуюпериферию!
CLK->PCKENR1 =CLK_PCKENR1_TIM4+CLK_PCKENR1_TIM2+CLK_PCKENR1_I2C+CLK_PCKENR1_TIM1;
CLK->PCKENR2 = 0b01111111;

CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV8);//2mghэнергосбережение

//индикатор
GPIO_Init(GPIOD,GPIO_PIN_2|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6,GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(GPIOA,GPIO_PIN_1|GPIO_PIN_2,GPIO_MODE_OUT_PP_HIGH_SLOW);
GPIO_Init(GPIOC,GPIO_PIN_3|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7,GPIO_MODE_OUT_PP_HIGH_SLOW);
[/code]

Теперь настроим ADC и подключим PULL UP на выводе ADC. Таким образом регулятор будет удерживаться во включённом состоянии.

[code]	//ADC кнопки
ADC1_DeInit();

ADC1_Init(ADC1_CONVERSIONMODE_SINGLE, ADC1_CHANNEL_2,ADC1_PRESSEL_FCPU_D2, \
ADC1_EXTTRIG_TIM, DISABLE, ADC1_ALIGN_RIGHT,ADC1_SCHMITTTRIG_CHANNEL2,\
ENABLE);
ADC1_Cmd(DISABLE);

GPIO_Init(GPIOC,GPIO_PIN_4,GPIO_MODE_IN_PU_NO_IT);//кнопка!
[/code]

Инициализируем таймеры и I2C.

[code]	TIM4_TimeBaseInit(TIM4_PRESCALER_8, 249);
TIM4_ClearFlag(TIM4_FLAG_UPDATE);
TIM4_ITConfig(TIM4_IT_UPDATE, ENABLE);
TIM4->IER |= (uint8_t)TIM4_IT_UPDATE;

enableInterrupts();
TIM4_Cmd(ENABLE);

TIM2_TimeBaseInit(TIM2_PRESCALER_8, 249);
TIM2_ClearFlag(TIM2_FLAG_UPDATE);
TIM2_ITConfig(TIM2_IT_UPDATE, ENABLE);
TIM2->IER |= (uint8_t)TIM2_IT_UPDATE;
TIM2_Cmd(ENABLE);

I2C_Cmd( ENABLE);
I2C_Init(I2C_MAX_STANDARD_FREQ, (uint8_t)0xA0, I2C_DUTYCYCLE_2,I2C_ACK_CURR, I2C_ADDMODE_7BIT, 7); I2C_Init(I2C_MAX_STANDARD_FREQ,(uint8_t)0xA0, I2C_DUTYCYCLE_2, I2C_ACK_CURR, I2C_ADDMODE_7BIT, 7);
[/code]

Подождём немного и инициализируем ИК датчик. Прибор готов к работе.

[code]	Delay(1000);
mlxinit();

ind[0]=1;
ind[1]=2;
ind[3]=3;
tchk[1]=1;
[/code]

В качестве инициализации датчика прочитаем из его EEPROM данные Tomax и Tomin. Находятся они по адресам 0x0 и 0x1, а для доступа к EEPROM используется пятый бит.


Драйвер I2C используем аналогично прибору Измеритель УФ индекса и температуры. Получается вот такой код.

[code]	int mlxinit(void)
{
buff[0] = (uint8_t) 0x20;
if( ! I2C_writenbyte((uint8_t)MLXaddr, buff, 1,1) )
{
I2C->CR2 |= I2C_CR2_STOP;//I2C_GenerateSTOP(ENABLE);
return 0;
};

if (! I2C_readnbyte((uint8_t)MLXaddr, buff, 3,1) )
{
return 0;
};

tomax = (u16) (buff[1]<<8) | buff[0];

buff[0] = (uint8_t) 0x21;
if( ! I2C_writenbyte((uint8_t)MLXaddr, buff, 1,1) )
{
I2C->CR2 |= I2C_CR2_STOP;//I2C_GenerateSTOP(ENABLE);
return 0;
};

if (! I2C_readnbyte((uint8_t)MLXaddr, buff, 3,1) )
{
return 0;
};

tomin = (u16) (buff[1]<<8) | buff[0];

return 1;
}
[/code]

Приступаем к основной программе.

Обработка кнопок и индикатор

Обработку кнопок и управление индикатором возьмём из проекта кухонный таймер.

Таймеры

TIM2 — используется для управления индикатором.

TIM4 — основной миллисекундный таймер и управление кнопкой.

Обработка кнопки с помощью ADC

Для того чтобы понять, что кнопка нажата необходимо получить напряжение на входе управления регулятором. Как было ранее рассмотрено в схеме, при нажатии на кнопку напряжение будет составлять около 3В, а при отпущенной кнопке около 1.5В (за счет делителя с резистором PULL UP).

Кнопка опрашивается каждые 50мс, за это отвечает макрос KNDTIME.

[code]	ADC1_Cmd(ENABLE);
ADC1_StartConversion();
while( ADC1_GetFlagStatus(ADC1_FLAG_EOC) == RESET);
ADC1_Cmd(DISABLE);
adcval = ADC1_GetConversionValue();

if (adcval > 700 )
knall = GPIO_PIN_0;

knint(0, ~knall, GPIO_PIN_0);
[/code]

Стартуем измерение ADC, ждём пока оно закончится и сравниваем полученное значение с граничной величиной. Если значение больше 2.5В - то кнопка нажата. Вот так просто реализуется опрос кнопки с помощью ADC.

Получение данных с датчика

За получение данных отвечает функция mlxdata().

[code]	int mlxdata(void)
{
buff[0] = (uint8_t) 0x06;
if( ! I2C_writenbyte((uint8_t)MLXaddr, buff, 1,1) )
{
I2C->CR2 |= I2C_CR2_STOP;//I2C_GenerateSTOP(ENABLE);
return 0;
};

if (! I2C_readnbyte((uint8_t)MLXaddr, buff, 3,1) )
{
return 0;
};

ta = (u16) (buff[1]<<8) | buff[0];

buff[0] = (uint8_t) 0x07;
if( ! I2C_writenbyte((uint8_t)MLXaddr, buff, 1,1) )
{
I2C->CR2 |= I2C_CR2_STOP;//I2C_GenerateSTOP(ENABLE);
return 0;
};

if (! I2C_readnbyte((uint8_t)MLXaddr, buff, 3,1) )
{
return 0;
};

tobj= (u16) (buff[1]<<8) | buff[0];

temp1 = (ta - 0x2DE4) * 0.02f - 38.2f;
temp2 = (tobj) * 0.02f - 273.15f;

return 1;
}
[/code]

Процедура очень простая, читаем данные из RAM датчика по адресам 0x6, 0x7 и 0x8.


И получаем температуру объекта и параметры для линейной аппроксимации. Далее согласно советам из datasheet производим вычисления. Нам нужна температура объекта — temp2.

Основная программа

В основной программе обработаем различные ситуации.

[code]	if (timevykl==0) {
ADC1_Cmd(DISABLE);
GPIO_Init(GPIOC,GPIO_PIN_4,GPIO_MODE_OUT_PP_LOW_SLOW);//vykl!!
}
[/code]

Если пришло время выключить прибор, то просто отключаем периферию ADC и опускаем вывод на LOW.

[code]	if (kn[0] == KNONE) {
kn[0]=0;
Delay(3000);
ADC1_Cmd(DISABLE);
GPIO_Init(GPIOC,GPIO_PIN_4,GPIO_MODE_OUT_PP_LOW_SLOW);//vykl!!
halt();
}
[/code]

Если нажали кнопку, то оставим на индикаторе в течение 3 секунд последнее измерение и выключим прибор.

[code]	if (timemcp==0)  {
mlxdata();

tchk[0]=0;
tchk[1]=0;
tchk[2]=0;
if (temp2<0) {
temp2 = -temp2;
tchk[0]=1;
}
if (temp2<100) {
shownumber(temp2*10);
tchk[1]=1;
} else {
shownumber(temp2);
tchk[2]=1;
}

timemcp=500;
}
[/code]

И сам вывод информации на индикатор. Каждые 500 мс считываем новые значения датчика и выводим на индикатор. Так как здесь нет отдельного разряда для отображения минуса, то отрицательные температуры обозначаем двумя точками. Например -10 градусов выводим как «1.0.». Температуры меньше 100 градусов показываем с точностью до одной десятой, а выше в целых градусах.

Как изготовить домашний пирометр

Делаем плату и все запаиваем

  1. Подготовить или приобрести необходимые инструменты: все для пайки, ST-LINK (будет нужен для программирования и отладки МК)

  2. Внимательно прочитать статьи из раздела Обязательная теория.

  3. Скачать необходимые файлы по данному прибору с github.

  4. Изготовить плату для прибора самостоятельно (это совсем несложно, в нашей инструкции все подробно описано).

  5. Приобрести все необходимые комплектующие.

  6. Запаять все компоненты на плату, смотри наше видео.

  7. Плата готова!

Для программирования вам понадобятся провода мама-мама. Вы можете их сделать сами из данного набора. Во время программирования, можно сразу подключить питание с ST-Link, вместо аккумулятора и SWIM вывод.

Размещение ИК датчика в корпусе

Для размещения датчика в корпусе необходимо аккуратно сделать на плате вырез, чтобы датчик поместился в корпусе. На трассировке для этого специально выделена область без меди.


Вывод программирования удобно сделать проводом припаяв к нему один пин разъем мама и одев его в термоусадку.


Приобретённые навыки

Схемотехника: Включение выключение прибора тактовой кнопкой, I2C, типовая схема подключения STM8, работа с кнопками.

Программирование: I2C, работа с ИК датчиком температуры, миллисекундный таймер, динамическая индикация светодиодного индикатора, включение выключение тактовой кнопкой.

Самостоятельная работа

Вы можете расширить функционал прибора в части измерения температуры объекта — добавить возможность учитывать различный коэффициент диффузии поверхности объекта.

---

]]>
(Super User) Приборы для дома Thu, 26 Dec 2019 17:13:24 +0000
Беспроводная акустическая система /index.php/pribory/home/item/67-besprovodnaya-akusticheskaya-sistema /index.php/pribory/home/item/67-besprovodnaya-akusticheskaya-sistema Беспроводная акустическая система

Пришло время заняться звуком - делаем беспроводную акустическую систему. Мощный качественный Hi-Fi стерео звук. Встроенный DSP процессор. Небольшой вес - всего 2кг. Стильный дизайн - печать на 3D принтере. Проигрывание музыки по Bluetooth, со встроенной sd карты, с USB флешки, FM радио. Работа в режиме пауер банка. Встроенная цветомузыка. Долгое время работы от одного заряда. Работа в режиме USB колонки.

{autotoc}

Прежде чем начать

Прежде чем читать эту статью рекомендуем тебе ознакомится со следующей теорией:

Как сделать качественную bluetooth колонку в домашних условиях

Сейчас все делают bluetooth колонки из компонентов с aliexpress. В интернет очень много различных инструкций, youtube завален видео. К сожалению все эти поделки не удовлетворяют даже базовым параметрам Hi-Fi звука. В них обычно используются устаревшие компоненты и технологии звука. Только использование самых современных компонент позволит в домашних условиях сделать переносную Hi-Fi акустику. Перечислим основные пункты, которые приведут нас у успеху:

  • Весь звуковой тракт должен быть цифровым. Аналоговый сигнал очень капризен к трассировке платы, качеству сборки и требует настройки на специальном оборудовании. Цировой же сигнал наоборот, практически не требователен к трассировке, спокойно относится к "кривым рукам". Bluetooth модуль должен быть подключен только по цифровому каналу.
  • Обязательно нужен DSP процессор. Получить мощный звук в компактном корпусе очень сложно. DSP процессор позволит расширить акустический диапазон акустики, особенно в области низких частот. Дополнительно, новейшие разработки в этой области, сделают процесс настройки очень простым, а звук качественным на любом уровне громкости.
  • В домашних условиях очень сложно сделать качественный, красивый корпус. На помощь приходит 3D печать. Качество 3D печати на домашних принтерах сейчас очень высоко. Современные пластики позволяют получить прочный, стильный корпус. Самостоятельная разработка модели позволяет учесть все особенности расположения компонент и обеспечить быстрый доступ к ним.
  • Динамики - сердце нашей системы. Только брендовые компоненты позволят получить натуральный мощный звук. Обязательно использование 2-ух динамиков: Широкополосный - НЧ и СЧ диапазона и ВЧ динамик. Также для малого корпуса просто необходим пассивный динамик. Динамики обязательно должны иметь паспорт и документацию, график АЧХ, без этого сложно будет произвести их точную настройку без специального оборудования, а его как правило дома нет.
  • Вся переносная акустика работает на аккумуляторах, поэтому экономичность и эффективность энергопотрбления всех компонент не на последнем месте. В следствие этого усилитель должен быть D-класса с максмимально высоким кпд. Большую часть времени вы будете слушать акустику на среднем уровне громкости - именно в этом режиме колонка должна работать очень долго. Для получения мощного звука нужен большой ток, а значит нужны высокомощные литиевые аккумуляторы.

Какой Hi-Fi нам нужен

В этой статье в разделе "Что такое хайфай" отлично написано, что же такое Hi-Fi и какой он бывает. Не буду повторять всю статью, напишу только итоговые выводы. Hi-Fi бывает 4 видов:

  • Абсолютный или полный – 20-20 000 Гц, 0,03% (–70 дБ), 90 дБ (в 31 600 раз), 1 дБ (в 1,12 раза), 2 дБ (в 1,25 раза).
  • Высокий или тяжелый – 31,5-18 000 Гц, 0,1% (–60 дБ), 75 дБ (в 5600 раз), 2 дБ, 3 дБ (в 1,41 раза).
  • Средний или базовый – 40-16 000 Гц, 0,3% (–50 дБ), 66 дБ (в 2000 раз), 3 дБ, 6 дБ (в 2 раза).
  • Начальный – 63-12 500 Гц, 1% (–40 дБ), 60 дБ (в 1000 раз), 6 дБ, 12 дБ (в 4 раза).

Качество звука определяется воспроизводимым диапазоном частот, а также отклонениями АЧХ в этом диапазоне. Учитывая, что на переносных колонках практически невозможно воспроизводить нижние частоты (ниже 60 Гц обязательно нужен сабвуфер, а он тяжелый и "кушает" много энергии), нашей целью будет базовый уровень Hi-Fi с небольшими "доработками" - диапазон частот сместим в область высоких частот. Будем стремиться к диапазону 60 - 20 000 Гц с нелинейностью 3 дБ, а на краях диапазона 6 дБ. Это чуть-чуть не дотягивает до высокого уровня Hi-Fi, но для переносной акустики - это супер хорошо.

К сожалению, в домашних условиях качественно замерить АЧХ колонки не получится, так что будем довольствоваться расчетными величинами и своими ушами для оценки того, что у нас получится.

Постановка задачи, требования к прибору

Вот какие получаются требования к нашей переносной акустической системе:

  • Компактный размер (конечно все относительно, кто-то назовет это лошадью) - не более 40х15х15см
  • Вес до 3 кг (больше - уже тяжело носить с собой)
  • сумарная мощность звука 40-60 Вт (это то что нужно! меньше не годится, больше уже будет другой размер и вес)
  • Hi-Fi звук "высокого уровеня" - 60-20 000 Гц с нелинейностью 3дБ и с КНИ < 1%
  • Цифровой тракт bluetooth, протокол Apt-X
  • Цифровой стерео усилитель звука 48кГц, 16бит
  • DSP процессор со встроенными эффектами
  • Режим пауер банк (неприятно когда телефон, передающий музыку сел)
  • Режим mp3, flac плейра, со встроенной sd карты (очень удобный режим, меньше потребление тока, чем bluetooth и телефон не нужен)
  • Проигрывание mp3 с внешней флешки
  • FM-радио - иногда приятно в дороге или на пикнике послушать радио
  • Цветомузыка на основе RGB светодиодов - сейчас это модно и выглядит красиво - must have
  • Качественные динамики, двух-полосная акуситическая система, пассивные динамики
  • Подключение колонки по USB, удобно "озвучить" компьютер по проводам, линейный вход уже устарел
  • Литиевые аккумуляторы минимум 2000 mAh - долгое время работы просто необходимо
  • Wi-Fi модуль для управления плеером с телефона и получения обратной связи от колонки

Схема основных модулей колонки

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

Глядя на данную иллюстрацию, начинаем понимать, что работа предстоит большая.

Подбор компонентов для изготовления прибора своими руками

Аудио компоненты

Динамики

Сначала я решил сделать ход конем и купить автомобильные динамики со встроенной вч головкой - ESX QE32. Но качество звука в области НЧ расстроило - бас они "не прокачивали". У них совсем не большой ход диффузора, и в общем и целом они рассчитаны на средние частоты.

Потом стал изчуать форумы и нашел тут подробнейший анализ динамиков для переносной акустики. Вот то что нужно! Прочитав форум до конца я понял, что самый правильный выбор - это AURA NS3-193 (НЧ-СЧ диапазон). А в качестве высокочастотных - Хейлы Dayton Audio AMT Mini-8. Пассивные радиаторы - Peerless_SDS-P830878. Вот замечательная тройка:

Aura и Peerless купил на сайте madisound. Это оказалось не сложно, пришли очень быстро. А вот ВЧ купил на aliexpress. Если будете выбирать другие, то следите чтобы на динамики была документация, как минимум параметры Тиля Смола, они в дальнейшем будут нужны для настройки DSP процессора. Конечно их можно замерить, но я как то больше доверяю производителю.

Усилитель звука и DSP процессор

Когда я подбирал усилитель для колонки, то изучил рынок продаваемых колонок (JBL и другие). Коротко опишу базовую схему всех этих агрегатов. Цифровой звук по стандарту I2S поступает на DSP процессор (конечно его роль может выполнить мощный микроконтроллер, но писать софт довольно сложно), далее на DAC (цифроаналоговый преобразователь) и с него уже на усилитель D-класса. Как видно цепочка длинная и самое не приятное место в ней - DAC. Качественный DAC требует грамотной трассировки платы, двухполяного питания и много дополнительного обвеса. И тут я случайно наткнулся на новый чип от компании TI - TAS5782m. Прочитав datasheet, я сразу понял - это то что нужно! Что особенно понравилось:

  • однополярное питание
  • высокая мощность - до 60 Вт звука
  • все внутри одной микросхемы - DSP, DAC и усилитель
  • мощный DSP со SMART функциями, и все это на частоте сэмплов до 96 кГц
  • услитель D-класса работает на очень высокой частоте - 768 кГц, что позволяет снизить размеры выходных LC фильтров
  • минимальный нагрев при работе благодаря 90 мОм транзисторам на выходе - возможность работать без радиатора совсем
  • удобный корпус для домашней пайки
  • минимальный обвес - в основном только конденсаторы и резисторы
  • отличная документация
  • удобный софт по настройке DSP и настройка в два клика

В общем, лучшего решения на текущий момент нет! Скажу наперед - к нему вообще нет претензий, завелся сразу, паять легко, ставлю твердую пять. Единственный момент - купить в России сложно, заказывал напрямую у TI.

Bluetooth модуль

Лучшее что смог найти - модуль на базе чипа CSRA64215. На aliexpress продается под маркировкой BTM625. Вот как он выглядит.

Сам чип очень продвинутый, в интернет есть программа для его программирования, есть отдельный софт на Android для управления им - громкость, эквалайзер и другие настройки. Но самое главное - цифровой выход звука I2S (при покупке будьте внимательны - есть версия под аналоговый выход - придется ее препрограммировать) 48 Кгц 16Бит, наличие кодека Apt-X - существенно улучшаюшего качество звука и задержку (можно смотреть кино).

FM радио

В качестве радиоприемника используется модуль на базе чипа TEA5767. Звук с него подается напрямую на ADC микроконтроллера.

Скажу сразу - чип работает, но качество приема у него среднее. В качестве антенны используется провод от наушников (как в сотовом телефоне). В квартире ловится хорошо, но иногда стерео теряется. Также стоит отметить, что выход звука на данном чипе соответсвует уровню 0.7в по размаху. И он напрямую передается на оцифровку в МК. В итоге имеем очень низкое разрешение звука - всего 8бит. В следующей версии планируется заменить этот модуль на цифровой вариант на базе чипа Si4705 с выходом I2S - это лучшее что я нашел.

Центральная плата

Микроконтроллер

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

  • управление зарядкой
  • управление цветомузыкой
  • декодирование mp3 и flac Сразу выбирал процессор с поддержкой DSP инструкций и float вычислений. Эта модель отлично подходит по всем параметрам, в том числе и по цене.

Wi-Fi модуль

Колонка имеет встроенный Wi-Fi модуль ESP-12F. Зачем он здесь? Через bluetooth модуль можно передавать только звук, использовать его для управления колонкой не получится. Так как в колонке будет mp3 плейер со встроенной флешкой, то хотелось иметь возможность управлять плейлистами, получать информацию о проигрываемой песни и т.д. Этот модуль отлично подойдет для этих задач.

Преобразователи DC-DC

Для питания колонки используется 4S аккумулятор напряжение которого составляет 15В. Базовое питание всех схем - 5В. Для преобразования нужна специальная микросхема DC-DC преобразователь. Будем использовать отличный проверенный чип NCP3170B (версия B работает на частоте 1МГц). Высокая частота - малый размер конденсаторов и индуктора. Микросхема имеет низкое энергопотребление в спящем режиме, встроенные MOSFET транзисторы - нужен только индуктор. В колонке два таких - для питания подсветки и режима пауербанка, а второй для основного питания цифровой части.

Светодиодная подстветка

Управляемые светодиоды RGB - правильный выбор. Решение на базе чипа WS2812b подойдет (можно конечно найти что-то более современное, если найдете - то переписать код в прошивке будет не сложно). Покупал такие - на плате. Удобно паять и меньше нагреваются.

Самое главное в этих светодиодах - управление по одному проводу. Почти вся лицевая панель колонки будет состоять из светодиодов - используется около 100 штук. Это позволяет создать шикарные эффекты цветомузыки, а также выводить с помощью светодиодов служебную информацию.

Корпус

В интернет можно почерпнуть много идей по изготовлению корпуса для колонки, вот несколько примеров:

И еще:

Вдохновившись ими первую колонку я выпилил из МДФ:

Впоследствие изучив различные программы для расчета корпуса акустики (особенно понравилась bass6 pro и dev) я понял, что для получения более мощных басов нужен больший объем корпуса или пассивные излучатели. Для выбранных динамиков нужен объем минимум 2л на каждый. Я сделал комбинированный корпус - текстолит + 3д печать. Супер прочно, легко, но не компактно:

В итоге от этого корпуса я отказался (потеряв в басах) и разработал новый, по размеру как первый, на базе 3Д печати. Этот вариант полностью меня устроил.

3Д печать повозволила учесть все нюансы расположения компонент. Удобство модернизации и ремонта - это главное. Вес корпуса получился около 600гр. Пластик для печати использовал PETG. Специально проверял и расчитывал прочность - на высоте. Корпус легко печатается (нет поддержек), состоит из большого количества деталей, которые склеиваются между собой (я клеил на суперклей Cosmofen).

На этом фото из 3D редактора отлично видно как он устроен.

Для корректной работы пассивного динамика корпус должен быть герметичным. Поэтому все электронику, вместе с аккумулятором, вынес в отдельный отсек. Для упрощения печати (без поддержек) основная часть раделена на 6 частей. После печати они склеиваются суперклеем. Площадь склеивания большая, поэтому соединение получается очень прочным (прочнее чем сама печать). Центральная плата установлена в специальной нише корпуса, сверху она закрывается блоком с акумулятором, вч динамиками и светодиодным экраном. Специальные вставки со светодиодами фиксируют основные динамики болтами. Крышка с отверстиями под разъемы завершает лицевую панель. С обратной стороны вставляется пассивный излучатель, который прижимается крышкой. Для защиты динамиков используются металлические сетки (заказывал на aliexpress).

Составляем схему колонки

Схема колонки довольно сложная. Многие части взяты из datasheet на компоненты. В этом разделе рассмотрим только сложные моменты, над которыми пришлось поломать голову. Весь проект в Kicad доступен в полной версии статьи.

Начнем с кнопок. Кнопок будет 6. Чтобы было меньше проводов - подключим их по схеме с участием ADC и делителей на резисторах. В итоге получается по одному проводу сразу 5 кнопок и одна кнопка для включения питания - с ней все просто.

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

Управление зарядкой на базе классического понижающего DC-DC:

Частота работы DC-DC - 250 кГц. Такая высокая частота выбрана специально для снижения требования к индуктивности, что позволяет минимизировать ее размер. Входное напряжение - 18V. Для управления мосфетом используется биполярный драйвер с очень неплохими характристиками zxgd3003e6. Единственный его минус - небольшое смещение напряжения постоянно присутсвующее на базе мосфета. Из-за него выбирать мосфет с повышенным напряжением отпирания завтора. Такая схема отлично работает с токами до 3А без существенного нагрева. Реально зарядка идет током не более 2А (ограничено программно, потому что аккумуляторы 2000mAh). Емкости везде используются керамические, для уменьшения толщины печатной платы. На выходе DC-DC стоит пара мосфетов Q3A Q3B для аварийного отключения процесса зарядки от аккумулятора.

Для анализа тока заряда и разряда аккумулятора используем rail-to-rail операционный усилитель подключенный к шунту, у которого делителями задано смещение нуля:

Такая схема позволяет измерять ток в двух направлениях - заряд и разряд. Смещение настроено в сторону большего тока разряда. Измерять ток заряда необходимо для контроля процедуры заряда, а ток разряда - для анализа оставшейся емкости аккумулятора.

Байпас внешнего питания - класическая схема на диоде и мосфете.

Максимальный средний ток в такой схеме не превышает 5А. При использовании диода шотке с очень малым падением напряжения 0.3В его нагрев будет минимальным. Во всех схемах компоненты подобраны для работы без радиатора, что существенно уменьшает размеры и упрощает сборку прибора.

Схема усилителя полностью из datasheet, поэтому приводить не буду. А вот над разделением потоков I2S пришлось подумать. Данные с Bluetooth модуля поступают на усилитель через управляемый буфер, там есть различие в уровнях напряжения, а также есть необходимость отключать bluetooth модуль от усилителя. Прямо с микроконтроллера сигнал I2S также идет на усилитель. Здесь важно чтобы одновременно не включились буферы и выход микроконтроллера, это обеспечивается програмно. Усилитель позволяет вывести результирующий сигнал I2S на отдельный вывод (для работы двух усилителей в связке) - заведем его на МК, чтобы анализировать звук для цветомузыки.

Печатная плата

Трассировка платы выполнена по рекомендациям используемых микросхем. Специально для изготовления в домашних условиях по нашему методу увеличен диаметр переходных отверстий до 1.6мм. Минимальное расстояние между дорожками - 0.25мм, минимальная ширина дорожек 0.25мм. Для удобства размещения в корпусе вся электроника разбита на три платы:

  • центральная
  • кнопки
  • разъемы
  • плата балансировки аккумулятора

В полную версию статьи включен проект в Kicad и вы можете модернизировать платы, если это необходимо. Толщина центральной платы с учетом двухсторонней компоновки составляет всего 10мм, что позволило разместить ее в компактном корпусе. Все платы не сложные в сборке. В основном используются SMD компоненты размера 0603. Только в модуле усилителя есть конденсаторы размером 0402. Паять их нужно очень аккуратно, желательно под увеличительным стеклом. Также сам усилитель имеет площадку для отвода тепла, для его пайки можно исопльзовать (паяльный фен) или просверлить отверстия с обратной стороны, залудить площадку на микросхеме и припаять к ней проводки для лучшего теплоотвода. В таком варианте микросхема отлично работает без радиатора.

В первой версии платы я допустил ошибку. Жжелая съэкономить на деталях, решил управлять высовольтными P-мосфетами сразу от микроконтроллера. Так делать нельзя. В итоге пришлось добавить маломощные N-канальные транзисторы для смещения уровня напряжения на отдельной мини плате и припаять все проводами. Во второй ревизии платы - это было исправлено.

Отметим также, что в случае расположения на плате RF модулей необходимо оставлять место на текстолите без меди для корректной работы встроенной антенны. Это можно видеть на плате около модуля bluetooth, и еще одно место - модуль Wi-Fi.

Для сборки проводов в жгуты очень удобно на плате делать петельки из провода или медной жилы:

Плата балансировки описана в отдельной статье.

Сборка колонки

Решил написать отдельное руководство по сборке. Весь процесс оказался нетривиальным.

Необходимые инструменты и всякая мелочовка

Для сборки колонки тебе понадобяться следующие инструменты и дополнительные материалы:

  • ST-link - для программирования и отладки микроконтроллера
  • мощный паяльник (минимум 60 Вт) для сборки аккумуляторов (или нужно использовать аккумуляторы с приваренными контактами)
  • провод МГТФ 0.05 мм2 - как основной сигнальный, 0.14 мм2 - как основной силовой, желательно 0.2мм2 для аккумуляторов
  • витая пара или одножильный провод диаметром жилы 0.5 мм - для шин питания подсветки
  • микро коаксиальный провод 75 Ом для вывода антенны радио на внешний разъем
  • термоусадочная трубка диаметром 3мм - для изоляции разъемов и соединений
  • герметик - Soudal Fix ALL Turbo (только он хорошо клеится к PETG пластику) - для герметизации краев и стыков
  • краска резиновая Super Decor Rubber - для герметизации корпуса изнутри - полная окраска изнутри
  • винты диаметр 3мм различной длины и гайки к ним
  • оплетка для снятия припоя - ее отлично можно использовать для соединения аккумуляторов в сборку
  • разъемы JST-RCY 2 - используется для подключения аккумуляторов (хорошие высокотовые разъемы - до 10А)
  • листовой пвх пластик 3мм куски - как вспомогательный элемент для фиксации различных элементов
  • аллюминиевый профиль П образный 40см 10мм х 1.5мм х 8мм - для усиления конструкции в районе крепления ручки
  • кусочки фольгированного текстолита - для формирования контактных площадок для проводов
  • кусок текстолита без меди толщиной 1.5мм 15см х 4см - для ребра жесткости под аккумулятор и по крепления ручки
  • фиксатор резьбы Локтайт синий (слабый) для фиксирования болтов крепления ремешка
  • фоамиран 2мм - прокладки для герметизации посадочных мест динамика

Печатаем и склеиваем корпус

Про саму печать на 3Д принтере рассказывать нечего. Тут особенностей нет. Пластик используем PETG - он самый экологичный и прочный. Вы можете скачать все детали в формате stl, а также рекомендации по параметрам печати в полной версии статьи.

Для склеивания деталей используется супер клей. Перед склеиванием нужно зашкурить детали мелкой шкуркой и проверить на плотное примыкание. Если стык неплотный, то лучше сначала нанести на углубления супер клей и посыпать стружкой PETG пластика (предварительно наточив например мелким надфилем от ненужных кусочков) и выровнять напильником. Склеивание нужно проводить в хорошо провертриваемом помещении, в защитных очках и желательно респираторе (в большом объеме супер клей сильно испаряется, а его испарения вредны). Важно не забыть перед приклеиванием последней детали вставить внутрь корпуса аллюминиевый профиль для крепления ручки.

После склеивания основного корпуса необходимо укрепить швы пластиковыми заплатками - кусок пластика 1мм толщиной длиной 3см и шириной 1см - поперек шва. Изнутри корпуса.

Точно также склеиваем остальные элементы, которые были разрезаны для удобства печати. В некоторых местах нужно обработать детали надфилем, чтобы они входили в замок.

Собираем все до конца

Полная сборка колонки делается в несколько этапов:

  • прикручиваем на винт М4 крепления для ремешка к корпусу
  • Собираем все платы, соединяем их проводами и проверяем работу электроники. Удобно, что усилитель работает от 5В - то есть можно проигрывать музыку питая всю схему от 5В
  • Делаем сборку аккумулятора 4S
  • Собираем центральный блок - вставляем ВЧ динамики, припаиваем к ним разъемы, вставляем аккумулятор, фиксируем все текстолитом
  • Вставляем в специальные отверстия в корпусе провод для подключения динамиков и герметизируем эти отверстия вместе с проводом
  • Клеим на центральную плату специальные блоки для фиксировования платы в корпусе - можно на обычный герметик
  • Приклеиваем на герметик или клей момент распечатанные колпачки-кнопки
  • Клеим на супер клей фиксаторы платы разъемов - предварительно выравняв плату с помощью пвх пластика (его потом легко срезать)
  • Вставляем светодиоды в распечатанные экраны и припиваем их согласно схеме, на концах припаиваем разъемы
  • Вставляем сеточки в блоки подсветки динамиков и фиксируем точечно герметиком
  • Вставляем модуль светодиодов центрального экрана и припаиваем его к плате разъемов
  • Подключаем аккумулятор и все проверяем
  • Фиксируем центральную часть винтами побокам
  • Устаналиваем фиксаторы динамиков и все собираем

Подробный фото отчет, который поможет в этом процессе есть в полной версии статьи.

Программирование DSP процессора

Встроенный DSP процессор очень мощный и имеет отдельный софт для настройки. В этой статье подробно описано зачем вообще он нужен в переносной акустике. Здесь же приведем основные опции, которые используются в этой колонке. Немного про сам софт, установку и как им пользоваться.

После покупки микросхемы у TI по запросу они дают доступ к скачиванию софта. Установка элементарная. Далее принцип работы примерно такой - делаем в софте нужные настройки, сохраняем выгрузу регистров в Си формате. Копируем эти данные в проект STM32 IDE и при инциализации системы загружаем эти данные в регистры DSP по I2C. Важный момент - загружать регистры необходимо только тогда, когда на DSP уже идет стабильный клок сигнал по I2S, чтобы он мог автоматически определить частоту и настроить внутренние делители. Если так не сделать, то никаких ошибок не будет, но настройки не применятся. Следует отметить что прямо в режиме он-лайн менять какие либо параметры не получится, но можно сделать готовые предустановки и их менять по кнопке или по Wi-Fi. Задача DSP сделать звучание максимально натуральным для именно этой акустической системы, а не постоянно менять настройки под настроение. Хорошо настроенная система одинаково отлично играет любую музыку. Перейдем к описанию настроек, которые необходимо сделать.

Начнем с основного режима. Будем Использовать Smart Amp Processing 48k - в этом режиме настройка максимально простая и автоматическая.

Чтобы смарт режим работал идеально необходима специальная тестовая плата от TI, она позволяет снять характеристики динамика, проводить тесты в он-лайн режиме и многое другое. Но покупать ее для разового проекта смысла нет. У TI есть отличный документ application report (SLAA737B), в нем полностью описан процесс настройки DSP. Читать обязательно. В итоге руководствуясь этим документом я проводил все настройки в слепую, используя данные из datasheet на динамики (вот тут они и пригодились) и на сам усилитель. Полученный результат меня полностью устроил. Для корректной работы необходимо задать следующие параметры:

  • параметры Тиля Смола на основной динамик
  • параметры на пассивный динамик
  • внутренний объем корпуса (в пересчете на один динамик)
  • максимальную RMS мощность динамика
  • пиковый ход диффузора динамика
  • измерить напряжение на динамиках на максимальной громкости обычным вольтметром (мерял на половине громкости и пересчитывал)
  • снятое АЧХ на динамик для использования эквалайзера для нормализации АЧХ (делал без нее)

Самая нужная и важная для переносной акустики функция - Смарт Бас. Основная фишка этого режима состоит в том, чтобы обеспечить максимальный бас на любой громкости и не испортить динамик. Скажу сразу - это действительно работает на твердую пять. Функция очень интересная, посмотрим как она работает. Для этого изучим график АЧХ нашего основного динамика из datasheet.

Как мы видим на графике, ниже 120 Гц начинается падение звукового давления. Это типичная характеристика всех динамиков на границах диапазона. Посмотрим в самое начало нашей статьи - какой Hi-Fi нам нужен. Нижний диапазон 60Гц с падением не ниже 3 Дб - это наша цель. Если взять по графику уровень 80 db за нулевую отметку, то динамик имеет на частоте 60Гц - (-5 ДБ) от нулевого уровня. Но это еще не все. Данный график - динамик без оформления. Если же мы его засунем в наш малюсенький корпус, то получим вот такой график в нижнем диапазоне частот (мне понравилась программа для расчета корпуса акустики внутри эксель файла (UniBox) - просто и наглядно):

тут видно, что на частоте 60Гц - спад еще больше (-10 Дб). Покажу как бы было хорошо этому динамику в большом корпусе:

почти 3 Дб разницы - это много. Но компактность тоже нужна. Так что работаем с тем, что имеем, а вот DSP пусть старается и помогает добиться нужного результата. Итак, для получения нужного эффекта необходимо усилить звук в области низких частот на 7 Дб (по мощности это в 5 раз!). Когда акустика работает не на полную громкость у нас есть запас для увеличения мощности баса, а вот при увеличении громкость он теряется. Функция смарт бас делает усиление автоматически на максимально возможную величину, в зависимости от композиции, громкости, хода динамика и это звучит реально очень сильно. Самое главное она делает это сама - нужно только задать требуемую частоту, параметры динамика и коэффициенты динамики переходных процессов и все! Вот как выглядит диалог настройки функции смарт бас:

Для правильной настройки этой функции (у нас нет спец платы для настройки звука) необходимо создать несколько пресетов и слушать их на колонке, переключая кнопками или по Wi-Fi. Нужно выбрать тип фильтра, коэффициент морфинга, скорость морфинга, коэффициент гармоник. Суть этих параметров описана в документе от TI, а также методика настройки. Скажу сразу - сделать для любого динамика 60 Гц неполучится. Основное препятствие - ход диффузора, чем он меньше, тем частоту придется задавать все выше и выше. Общее правило примерно такое - DSP должен увеличивать мощность не более чем на 10 db.

Вторая очень полезная для нашего проекта функция - моно бас. Она позволяет разместить два динамика в одном общем корпусе и использовать один пассивный радиатор на два динамика. Это очень удобно. Чтобы динамики в области низких частот не работали в противофазе, звук из стерео делается автоматически монофоническим. Так динамики не мешают друг другу, а работают вместе. Можно задать частоту среза - я сделал 300 Гц.

Высокочастотные динамики в корпусе расположены слишком близко друг к другу, что снижает стерео базу, поэтому добавим эффект расширения стерео зоны. Ну и напоследок необходимо выровнять чувствительность динамиков СЧ и ВЧ. У ВЧ чувствительность заметно выше, именно поэтому мы взяли ВЧ на 8 ом, а основной динамик на 4 ом. Но этого все равно мало, ВЧ без корректировки слишком много. По расчетам нужно около (-5Дб) на частоты выше 4000 гЦ - это и выставим с помощью эквалайзера. Можно поднять громкость еще за счет снижения качества (можно снизить THD до 5%), но я этого делать не стал и тебе не советую. Громкости мне хватает. Отмечу здесь, что если бы питание колонки было бы от 5S то можно было бы получить еще большую пиковую мощность - до 80 Вт (но все это выше 150 Гц, поэтому делать этого не стал)!

На этом тюнинг закончен. Далее можно на базе этой настройки строить уже свои пресеты с помощью эквалайзера - работа дома, на улице, больше баса, больше голоса и т.д.

В этом подразделе стоит сказать и про аккумулятор. Беда заключается в том, что один полностью заряженный аккумулятор имеет напряжение 4.2В, а полностью разряженный 2.8В. Для 4-х аккмуляторов размах еще больше целых 5.6В. Если рассчитывать работу DSP от самого низкого напряжения, то мы потеряем часть мощности на полностью заряженном аккумуляторе, а если на самое большое - то при просадке емкости будем иметь сильные искажения на полной громкости. В итоге правильное решение - динамическое изменение максимальной выходной мощности от текущего минимального напряжения аккумулятора.

Для этого программа анализирует минимум напряжения и задает снижение громкости в последнем каскаде работы DSP - output crossbar

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

Программа для микроконтроллера

Программа написана в среде STM32 Cube IDE. Все исходники доступы в полной версии статьи. Здесь рассмотрим ключевые моменты кода.

Общая логика работы программы

  1. При включении проводим инициализацию всех подсистем микроконтроллера и отображаем на несколько секунд на переднем экране состояние аккумулятора. Если в течение этого времени кнопку не отпустили, то подпираем включенное состояние ножкой микроконтроллера и переходим в рабочий режим. Аналогичное решение было в приборе Мини пирометр. Если же кнопку отпустили - то колонка выключается. Получается такой быстрый вариант проверки заряда колонки.
  2. С помощью ADC мониторим (через прерывание) все внешние процессы, связанные с питанием. Автоматически идет определение подключения внешнего источника питания, определение начала и окончания процесса зарядки, определение слишком низкого уровня заряда аккумулятора. В зависимости от этих ситуаций МК может переключаться в различные режимы.
  3. Если аккумулятор заряжен, внешний БП не подключен, то колонка переходит в основной режим - проигрывание музыки по bluetooth. Включается bluetooth модуль, потом устанавливается средний уровень громкости и включается аудиоусилитель. Ожидаем стабилизации сигнала I2S от модуля, после получения 512 пакетов инициализируем DSP процессор и устанавливаем громкость на 100%. Далее все управление идет по bluetooth с телефона, компьютера и т.д.
  4. Если аккумулятор разряжен то колонка ожидает начала зарядки.
  5. Если проигрывается музыка по bluetooth, то идет анализ полученного потока и работает цветомузыка. Отдельная процедура управляет сложными эффектами. Выделяются три области подсветки - центральный экран, и два круга вокруг основных динамиков. На экране отображаются в случайном порядке различные эффекты, которые начинаются в такт музыки в среднем диапазоне частот. Одновременно над динамиками светодиоды меняют цвет на случайный.
  6. При однократном нажатии второй кнопки меняется режим работы колонки по кругу - Bluetooth, радио, mp3 плейер, USB device.
  7. В режиме радио приемник настраивается на фиксированную стануцию, указанную в прошивке и включается на уровень громкости 60%. Кнопками 4,5 производится поиск радиостанций вниз и вверх.
  8. В режиме mp3 плейер выбирается случайный трек и начинается проигрывание с внутренней sd карты. Кнопками 4,5 можно включать следующий или предыдущий трек.
  9. В режиме USB device проигрываем аудиопоток полученный по USB.
  10. Во всех режима кнопки 3,6 управляют громкостью.
  11. Если подключен внешний БП, то колонка переходит в режим зарядки. На экране отображаются столбиками напряжение и ток заряда.

Инициализация

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

  • Частота работы микроконтролера - максимальная 168 МГц. Чем быстрее тем лучше.
  • ADC работает на частоте 21 Мгц. Один сэмпл - 84 такта (в связи с большими сопротивлениями на входе ADC). Центральный ADC делает последовательно 6 измерений в непрерывном цикле - получается частота одного измерения около 40 кГц.
  • I2S (SAI) работает на частоте 48 кГц, 16 бит. Используется встроенный PLLI2S на частоте 49.142857 МГц - это позволяет получить 48 Кгц с минимальной ошибкой 0.1%. Так как I2S в зависимости от режима работает на передачу или чтение, а в Cube можно настроить только один, то делаем "хитрый" ход. Настраиваем один режим - генерируем проект. Копируем настройки в свою функцию. Потом настраиваем второй режиме - и опять в свою функцию. В итоге имеем готовый код инциализации для каждого случая.
  • Таймеры. TIM2 - ШИМ управления зарядкой, TIM3 - 96Кгц оцифровка радио в режиме over sampling.
  • I2C1 - управление усилителем, I2C3 - управление радио и балансировкой. Тут настройки стандартные.
  • SDIO - sd карта. Шина 1 бит, частота 48 МГц.
  • SPI2 - управление RGB светодиодами. Частота 2.625 MBit\s - подобрана специально чтобы 3 бита попадали в тайминг управления светодидом.
  • UART3 - 115200, подключен к WI-FI модулю, можно использовать для его прошивки через USB.
  • USB 1 в режиме OTG - чтение флешек.
  • USB 2 в режиме USB device - работа в качестве AUDIO device , mass storage, serial port. Настройки делаются также как с I2S. Включаем один режим - формируем проект, записываем все в функцию и т.д. Очень удобный подход.

При старте идет подготовка всех массивов и настройка радио модуля - тут ничего интересного нет.

Для меньшего потребления тока во время выключения колонки, усилитель звука подключен через P-Mosfet. На самом усилителе стоит около 100 мкФ емкостей с очень низким ESR (керамические кондерсаторы). Поэтому при включении колонки нужно не просто включить данный мосфет, а делать это в режиме PWM с очень короткими импульсами включения. Для выбранного транзистора (IRF9321) подходит режим 3мкс вкл \ 50мкс выкл. Полная зарядка емкостей происходит за 10-20 циклов. Вот программа которая это делает:

  HAL_GPIO_WritePin(spk_reset_GPIO_Port,spk_reset_Pin,GPIO_PIN_RESET);

  CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
  DWT->CTRL = DWT_CTRL_CYCCNTENA_Msk;

  //soft start
  for (int i=0 ; i< 100;i++) {
        GPIOD->BSRR = pvdd_on_Pin;//set PIN
        DWT->CYCCNT = 0; while(DWT->CYCCNT < 500) {}; //3 us
        GPIOD->BSRR = (uint32_t)pvdd_on_Pin<< 16U;//RESET PIN
        DWT->CYCCNT = 0; while(DWT->CYCCNT < 8330) {}; //50 us
  }
  HAL_GPIO_WritePin(pvdd_on_GPIO_Port,pvdd_on_Pin,GPIO_PIN_SET);

В начале выключаем усилитель через вывод RESET (на всякий случай). Далее запускаем таймер отладки (он считает каждый такт, то есть при частоте 168 МГц - около 6нс на одно значение) и используем его для генерации микросекундных задержек. В папке проекта есть моделирование заряда емкостей для этого случая в LT-Spice.

Зарядка аккумулятора

Заряд литиевого аккумулятора довольно сложный процесс. Программа обязательно должна уметь отслеживать различные сбои и во время отключать аккумулятор от процесса зарядки. В противном случае возможно возгорание аккумулятора или выход его из строя. Краткое описание процедуры заряда:

  • ADC постоянно измеряет три показателя: напряжение на аккумуляторе, ток заряда, напряжение на внешнем БП. Измерение происходит на частоте 40кГц. Это слишком много, поэтому к данным измерениям применяется скользящее усреднее с размером окна в 32 сэмпла. Этого вполне достаточно для принятия решений. В процедуре обработки прерывания ADC отрабатываются все "опасные" ситуации зарядки, и в случае их возникновения процесс тут же прекращается. Само управление зарядкой идет в основном цикле.
  • В основном цикле программа простая. Пока напряжение на аккумуляторе не достигло 16.2V (пока нет программы балансировки заряжаю чуть ниже, чтобы не контролировать напряжение на каждой банке) или ток заряда не превышает 2A - повышаем время включения DC-DC через таймер TIM3. Если же наступило превышение - то понижаем. При этом понижение происходит каждые 5мс, а повышение раз в 200мс. Так организуется стабилизация работы DC-DC. PID регулятор не используется.

Посмотрим как это выглядит в коде на Си.

newz = (int32_t)adcbuff[ADC_IBAT]-1468;
newz = newz * 411 * (int32_t) KV / 100;
adcbuff_sr[ADC_IBAT] = get_newsamplewindow_current(newz);

Измеряем значение тока, переводим его в мА. Коэффициенты пересчета предварительно были расчитаны согласно схеме, а потом уточнены прямо в режиме отладки. Это обязательно нужно сделать, так как используются не высокоточные резисторы в делителях. При запуске платы без аккумулятора имеем нулевой ток заряда\разряда аккумулятора. При такой схеме легко посчитать смещение нуля. Для более точного расчета коэффициента усиления необходимо подключить потребитель тока, который мы знаем сразу после шунта. Я включал точно измеренный резистор на 50 Ом к источнику питания 5В (ток 100 мА) и таким образом можно легко уточнить коэффициенты усиления внешнего операционного усилителя. После измерения значение передается в функцию которая осуществляет оконное усреднение и возращает новое усредненное значение тока.

Если идет процес заряда и мгновенный ток (а не усредненный) по какой то причине превысил максимальный ток заряда на 30% - выставляем флаг ошибки и сразу снижаем на 40 единиц ШИМ DC-DC. Частота измерения ADC довольно высокая, поэтому все ошибки прогоняем через фильтр - ошибка должна повторится 10 раз, тогда зарядка будет прекращена, а тип ошибки зафиксирован и будет отображен на экране.

if (mode == MODE_CHARGE) {
   if (newz < -1000) {
       chgte=1; //тип ошибки
       fault=1;
       if (TIM2->CCR3 > 40) {
                TIM2->CCR3 -= 40;

}}}

Аналогично проверяются ошибки на превышение максимального напряжения на аккумуляторе (более 16.8V), и дополнительный контроль на падение входного напряжения ниже 17V.

Процедура в главном цикле, которая контролирует процесс заряда выглядит так:

if (timecharge == 0) {
        if (adcbuff_sr[ADC_VBAT] > 16800) {
                //stop
                TIM2->CCR3--;
                timecharge_numplus=0;
        }
        else if (adcbuff_sr[ADC_VIN] < 17200) {
                //stop
                TIM2->CCR3--;
                timecharge_numplus=0;
        }
        else if (adcbuff_sr[ADC_IBAT] < -2000) {
                //stop
                TIM2->CCR3--;
                timecharge_numplus=0;
        } else {
                timecharge_numplus++;
                if (timecharge_numplus>40) {
                        timecharge_numplus=0;
                        TIM2->CCR3++;
        }
}

В случае возникновения ошибки в процессе заряда выйти из нее можно по нажати кнопки 2 или выключив и включив заново колонку. По окончанию зарядки - когда ток заряда упадет до 50 мА и напряжение на аккумуляторе будет больше 16V, колонка выключается.

Балансировка в текущей прошивке еще не реализована. Плата балансировки может по команде I2C автоматически проводить балансировку на одной ячейке, чье напряжение максимальное. Процесс зарядки нужно поменять на контроль не общего напряжения, а максимального на одной ячейке. При этом если ячейка достигла 4.2В нужно включить балансировку. В следующей версии этот процесс будет реализован. Пока процесс балансировки не работает нужно обязательно контролировать напряжение на ячейках вручную, иначе аккумулятор может выйти из строя, вплоть до самовозгорания! Ячейки в моей сборке оказались очень в хорошем состоянии, без балансировки они работают идеально. Расхождения до сих пор нет.

Цветомузыка

Для цветомузыки используется 90 RGB управляемых светодидов. Расположены они в трех областях: Т-образный экран в центре и два круга на месте динамиков. Для управления светодиодами используется периферия SPI. В этой статье подробно описана методика управления светодиодами. Функция setsvet устанавливает нужный цвет светодиоду с указанным номером. Далее по SPI сформированные данные по всем светодиодам отправляются через DMA режим.

Рассмотрим подробнее как реализована анимация. Начнем с центрального Т-образного экрана. Для удобства работы со светодиодами используется специальный двумерный массив 11х8 элементов, который перекодирует номер светодиода в квадратной сетке экрана в его порядковый номер.

const uint8_t ekrandecode0[8][11] = {
        {0,0,0,1,2,3,4,5,0,0,0},
        {0,0,0,10,9,8,7,6,0,0,0},
        {0,0,0,11,12,13,14,15,0,0,0},
        {0,0,0,20,19,18,17,16,0,0,0},
        {0,0,0,21,22,23,24,25,0,0,0},
        {36,35,34,33,32,31,30,29,28,27,26},
        {37,38,39,40,41,42,43,44,45,46,47},
        {74,73,72,71,70,69,68,67,66,65,64}
};

Нулевые значения обозначают отсутсвие светодиода. Функция setsvet_xy позволяет установить нужный цвет светодиоду с указанными координатами.

void setsvet_xy(int ekran,int x,int y,cvetstruct cvet) {
        int num;

        if (ekran ==0) {
                if (x > 7) x=7;
                if (y > 10) y=10;
                num = ekrandecode0[x][y];
                if (num==0) return;
                ekranram[x][y] = cvet;
        } else {
                if (x > 1) x=1;
                if (y > 15) y=15;
                num = ekranDindecode0[x][y];
                if (num==0) return;
                ekranDinram[x][y] = cvet;
        }

        setsvet(num+3,cvet.red,cvet.green,cvet.blue);
}

Используется два виртуальных экрана - центральный и круги вокруг динамиков. Второй экран представляется как две линии длиной 16 светодиодов.

const uint8_t ekranDindecode0[2][16] = {
        {63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48},
        {75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90}
};

В основном цикле программы каждые 40мс вызывается функция screenAnimate(), которая отрабатывает следующий шаг анимации экрана. Анимация реализована по следующему алгоритму:

  • каждому эффекту анимации соответствует шаблон (по сути рисунок) размером 11х8, где каждому светодиоду указан номер шага анимации, на котором он должен быть включен
  • дополнительно к шаблону существует структура, которая описывает состояние одного эффекта: скорость, цвет новой точки, координаты центра эффекта и другие параметры
  • одновременно может быть активно не более 10 эффектов
  • под экран выделен массив точек в оперативной памяти (на каждую точку хранится текущий цвет RGB) и каждый вызов функции screenAnimate() яркость каждой точки с ненулевым цветом уменьшается на 10 единиц
  • каждый шаг согласно шаблону, зажигаются новые точки номер которых совпадает с номером шага, а старые гаснут с некоторой скоростью (в итоге имеем эффект плавного затухания и шлейфа)
  • сами шаблоны генерируются в момент определения максимума в музыке. В этот момент определеяется случайный цвет, координаты эффекта и другие его параметры

Данная схема позволяет сделать любое количество шаблонов, анимация которых выглядит очень красиво. Шаблоны также используются для отображения иконок режимов работы колонки.

Разберем как работает определение ритма в музыке.

В качестве представления энергии звука используется сумма всех значений порции данных с I2S взятых модулю.

        for (i=0l;i<N_WAVE;i++) {
                if (musicbuff[i]<0)
                        tekenergy -= (float)musicbuff[i];
                else tekenergy += (float)musicbuff[i];
        }

Таким образом, базовая частота потока данных для цветомузыки снижается с 48кГц до 93Гц. Каждое полученное новое значение энергии проходит через функцию peakdetector, которая на выходе возвращает - обнаружен новый пик или нет. Если пик найден, то генерируется случайный цвет для эффекта, ищется свободный слот (из 10-ти эффектов) и запускается новый эффект.

Функция peakdetector работает чуть сложнее. Сначала накладывается НЧ-фильтр на поток данных с параметром peakA.

        x[1] = peakA * newdata + (1-peakA)*x[0];

Далее накладывается ВЧ-фильтр с параметрами peakB и peakB2.

        y[peakMod-1] = peakB2 * x[1] + peakB * (y[peakMod-2]-x[0]);

После этого данные приводятся к ступенькам - максимум на участке 10 значений (peakMod). И уже после этого определяется пик.

        for (int z=0;z<peakMod-1;z++) {
                y[z] = y[z+1];
        }

        if (nummod % peakMod == 0) {
                float tmpmax=0;
                for (int z=0;z<peakMod;z++) {
                        float tyz = (y[z]>0)?y[z]:-y[z];
                        if (tyz>tmpmax) tmpmax = tyz;
                }
                if (tmpmax < 3) tmpmax = 0;

                zmax[2] = tmpmax;

                if ((zmax[0]<zmax[1]) && (zmax[1]>zmax[2])) {
                        peak = 1;
                }

                zmax[0] = zmax[1];
                zmax[1] = zmax[2];
        }

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

Хочется сказать, что удобнее настраивать все фильтры не на самом микроконтроллере, а в программе Sci-lab (бесплатный аналог matlab). Там можно использовать wav файл как поток данных и графически смотреть результаты работы фильтров. Это сильно ускоряет разработку процедур обработки и анализ данных в музыке. В исходниках вы найдете файлы формата sci-lab и сможете самостоятельно "поиграть" с параметрами.

Управление FM-радио

Для FM радио используется мини модуль на базе чипа tea5767, купленный на aliexpress. Выход у него аналоговый, управление по I2C. Для управления чипом нужно передать последовательно 5 байт данных, в которых определенные биты отвечают за различные команды и режимы. Для получения информации от чипа - читаем 5 байта. Все просто. Хочется отметить, что в такой схеме очень удобно использовать битовые структуры в Си. Вот как выглядит определение структуры на запись данных в чип:

struct
{
        // REGISTER R1
        uint8_t PLL_13_8 : 6;
        uint8_t SM: 1;
        uint8_t MUTE : 1;

        // REGISTER R2
        uint8_t PLL_7_0;                        // PLL[7:0] setting of synthesizer programmable counter after search or preset

        // REGISTER R3
        uint8_t SWP1 : 1;
        uint8_t ML : 1;
        uint8_t MR : 1;
        uint8_t Mono : 1;
        uint8_t HiLo: 1;
        uint8_t SSL: 2;
        uint8_t SUD: 1;


        // REGISTER R4
        uint8_t SI: 1;
        uint8_t SNC: 1;
        uint8_t HCC: 1;
        uint8_t SMUTE: 1;
        uint8_t XTAL: 1;
        uint8_t BL: 1;
        uint8_t STBY: 1;
        uint8_t SWP2: 1;

        // REGISTER R5
        uint8_t R5_dummy :6;                            // Reserved for future extensions; these bits are internally set to logic 0
        uint8_t DTC :1;                         // Reserved for future extensions; these bits are internally set to logic 0
        uint8_t PLLREF :1;                              // Reserved for future extensions; these bits are internally set to logic 0
} TEA5767WriteRegister;

а так выглядит структура на чтение:

struct
{
        // REGISTER R1
        uint8_t PLL_13_8 : 6;           // PLL[13:8] setting of synthesizer programmable counter after search or preset
        uint8_t BLF : 1;                        // Band Limit Flag:if BLF = 1 then the band limit has been reached; if
                                                                // BLF = 0 then the band limit has not been reached
        uint8_t RF : 1;                         // Ready Flag:if RF = 1 then a station has been found or the band limit
                                                                // has been reached; if RF = 0 then no station has been found

        // REGISTER R2
        uint8_t PLL_7_0;                        // PLL[7:0] setting of synthesizer programmable counter after search or preset

        // REGISTER R3
        uint8_t PLL_IF : 7;                     // PLL[13:8] IF counter result
        uint8_t STEREO : 1;                     // Stereo indication:if STEREO = 1 then stereo reception;
                                                                // if STEREO = 0 then mono reception

        // REGISTER R4
        uint8_t Dummy : 1;                      // this bit is internally set to logic 0
        uint8_t CI : 3;                         // CI[3:1] Chip Identification:these bits have to be set to logic 0
        uint8_t LEV : 4;                        // LEV[3:0] level ADC output

        // REGISTER R5
        uint8_t R5Data;                         // Reserved for future extensions; these bits are internally set to logic 0
} TEA5767ReadRegister;

Пользоваться такими структурами очень удобно. Делаем две функции - записать данные и прочиать. Осталось устанавить нужные значения через структуру и записать данные в чип. Вот как выглядит настройка на нужную станцию вместе с функциями чтения и записи.

void tea5767_write(void) {
        HAL_I2C_Master_Transmit(&hi2c3,(uint16_t)0xC0,(uint8_t *)&TEA5767WriteRegister,5,1000);
}

void tea5767_read(void) {
        HAL_I2C_Master_Receive(&hi2c3,(uint16_t)0xC0,(uint8_t *)&TEA5767ReadRegister,5,1000);
}

void tea5767_setfreq_base(uint32_t freq) {
        //106800  in kgz
        uint32_t pll;
        if (TEA5767WriteRegister.HiLo) {
                pll = 4 * 1000 * (freq+225) / 32768;
        } else {
                pll = 4 * 1000 * (freq-225) / 32768;
        }

        TEA5767WriteRegister.PLL_7_0 = pll & 0xff;
        TEA5767WriteRegister.PLL_13_8 = (pll>>8) & 0x3f;

        tea5767_write();
        HAL_Delay(30);
        tea5767_read();
}

void tea5767_setfreq(uint32_t freq) {
        //106800  in kgz
        uint32_t pll;
        int lev1,lev2;

        TEA5767WriteRegister.HiLo = 1;
        tea5767_setfreq_base(freq+450);
        HAL_Delay(30);
        tea5767_read();
        lev1 = TEA5767ReadRegister.LEV;

        tea5767_setfreq_base(freq-450);
        HAL_Delay(30);
        tea5767_read();
        lev2 = TEA5767ReadRegister.LEV;

        if (lev1 > lev2) TEA5767WriteRegister.HiLo = 0;

        tea5767_setfreq_base(freq);
        HAL_Delay(30);
        tea5767_read();
}

При чтении данных важный параметр - показания ADC (качество приема) - LEV. На него нужно ориентироваться при настройке на станцию, он отражает качество приема. Все управление модулем идет в основном цикле, после получения команд с кнопок.

Звук с модуля поступает на входы ADC микронтроллера, оцифровывается и передается по I2S на усилитель. Разберем как это делается.

Оцифровка звука идет на удвоенной частоте для повышения качества - 96 кГц. Далее применяется НЧ-фильтр настроенный на частоту 24 кГц и поток преобразуется к 48 кГц. И только теперь передается на I2S. Ведущем в этом процессе является поток I2S.

ADC непрерывно захватывает данные и помещает их через DMA в кольцевой буфер. Частоту захвата регулирует таймер TIM3 (Все настройки сделаны в STM32Cube - так что вы их легко можете посмотреть в исходниках). Поток I2S непрерывано передается из кольцевого буфера в памяти. Используются два прерывания - половина буфера передана и весь буфер передан. Когда срабатывает прерывание I2S, анализируем счетчик переданных байт DMA потока ADC и определяем в какое место в буфере сейчас пишутся данные. С данного места отсчитываем нужное колво байт назад (в кольцевом буфере ADC) и их передаем на кодирование (фильтр и т.д.). Полученную новую порцию записываем в буфер I2S в начало. В это время на I2S передается вторая половина буфера. Когда она передана, то делаем тоже самое - но перезаписываем вторую половину данных. Частоту работы ADC нужно настроить так, чтобы скорости были максимально равны - это можно сделать расчетным путем или подобрать частоту таймера в отладчике.

Посмотрим код.

void SAI1_halfcomplete() {
        //from usbd_audio_if.c
        uint32_t tekposadc = hdma_adc2.Instance->NDTR;

        convertRadionew(&saibuff[0], tekposadc);
}

void SAI1_fullcomplete() {
        uint32_t tekpos = hdma_adc2.Instance->NDTR;

        convertRadionew(&saibuff[256], tekpos);
}

В прерывании I2S "половина буфера передана" получаем позицию буфера ADC и передаем на конвертацию, перезаписывая начало буфера. Тоже самое в конце.

void convertRadionew(uint16_t* buff,uint32_t tekposadc) {
        //simple decimation //middle
        int pos = (512*2 + 512*2 - tekposadc - 512) % 1024;

        lastdelta = (1024 + lastpos - pos)%1024;
        lastpos = pos;

        for (int i=0;i<256;i=i+2) {
                uint16_t templ=0;
                uint16_t tempr=0;

                templ = filtrleft24(adcradiobuff[pos]);
                pos = (pos + 1) % 1024;
                tempr = filtrright24(adcradiobuff[pos];
                pos = (pos + 1) % 1024;
                templ += filtrleft24(adcradiobuff[pos]);
                pos = (pos + 1) % 1024;
                tempr += filtrright24(adcradiobuff[pos]);
                pos = (pos + 1) % 1024;

                buff[i] = (templ-2040);
                buff[i+1] = (tempr-2040);
        }
}

При обработке буфера отдельно обрабатываем левый и правый канал. Размер буфера ADC в два раза больше. Переменная lastdelta позволяет получить колво отсчетов ADC за время срабатывания прерывания - оно должно быть максимально приближено к 512, тогда потоки будут работать синхронно. В отладчике легко сделать это меняя ARR таймера 3. Код фильтров удобно брать из программы WinFilter. Используется IIR фильтр 2 порядка. Громкость увеличивать смысла нет - это можно сделать с помощью громкости усилителя. Отметим последние две строки - вычитаем 2040. Это необходимо для получения знакопеременного потока данных - по сути вычитаем среднее значение потока данных. Так как у нас в схеме не используются точные резисторы, то это значение нужно вычислить для каждого канала отдельно в отладчике измеряя среднее потока за длительный интервал - 10 секунд.

Работа с USB Device

Колонка может подключаться по micro USB разъему к компьютеру и работать при таком подключении в трех режимах: audio device, UART, mass storage (предоставляя доступ к внутренней флешке). На данный момент реализован только режим audio device. Остальные режимы несложно дописать самостоятельно. С audio device тоже все несложно. Но все же напишу несколько слов. Вся настройка делается средствами STM32 cube. В статье описано как все это работает. Единственное что нужно дописать после инициализации - связку USB и I2S. Как это сделать? Разберемся подробнее.

Вся работа ведется в файле "usbd_audio_if.c". В этом файле есть уже ряд готовых функций, в которые нужно дописать код. Первая функция: "AUDIO_AudioCmd_FS", она вызывается при получении команд по usb протоколу. Нам нужны команды START и PLAY:

static int8_t AUDIO_AudioCmd_FS(uint8_t* pbuf, uint32_t size, uint8_t cmd)
{
  /* USER CODE BEGIN 2 */

        if (mode != MODE_USBAUDIO) {
                return (USBD_OK);
        }

        switch(cmd)
        {
                case AUDIO_CMD_START:
                HAL_SAI_Transmit_DMA(&hsai_BlockA1,pbuf,size);
                break;

                case AUDIO_CMD_PLAY:
                HAL_SAI_Transmit_DMA(&hsai_BlockA1,pbuf,size);
                break;
        }

        return (USBD_OK);
  /* USER CODE END 2 */
}

При получении этих команд нужно передать указанный буфер на I2S через DMA, что и делаем. Для синхронизации потока USB и I2S необходимо вставить специальные вызовы из прерываний полученных при передаче половины буфера и полного буфера I2S. Добавляем вызовы из прерываний и туда прописываем нужные функции.

void HAL_SAI_TxCpltCallback(SAI_HandleTypeDef *hsai)
{
  /* Manage the remaining file size and new address offset: This function
     should be coded by user (its prototype is already declared in stm32446e_eval_audio.h) */
if (mode == MODE_USBAUDIO) {
        TransferComplete_CallBack_FS();
} else {
        SAI1_fullcomplete();
}
}

Как видно по комментарию, Пример работы с USB audio есть в документации к плате stm32446e_eval. Многое взято оттуда. Так как у нас I2S (он же SAI) используется не только в USB режиме, то проверяем это и вызываем нужные функции. Аналогично поступаем с половиной буфера.

void HAL_SAI_TxHalfCpltCallback(SAI_HandleTypeDef *hsai)
{
  /* Manage the remaining file size and new address offset: This function
     should be coded by user (its prototype is already declared in stm32446e_eval_audio.h) */
  if (mode == MODE_USBAUDIO) {
                HalfTransfer_CallBack_FS();
        } else {
                SAI1_halfcomplete();
        }
}

На этом настройка USB AUDIO закончена. Подключаем колонку, появляется звуковое устройство - проигрываем через него файл и наслаждаемся музыкой. Дополнительно отмечу, что при работе с USB активно используются динамические буферы, поэтому нужно в настройках STM32 cube увеличить размер heap и stack. Также, в этом файле можно вставить команды управления громкостью, но я этого делать не стал.

Как сделать колонку своими руками

Если ты решил сделать себе такую же колонку, то необходимо прочитать полную версию этой статьи, купить все необходимые компоненты и инструменты. Выделить побольше времени. Будет непросто, но очень интересно. Это один из сложных проектов на этом сайте. Если у тебя нет отпыта - то лучше начать с более простых приборов.

В файле приложенном к статье BOM.xls ты сможешь найти полный перечень компонент, чтобы оценить то, что нужно будет купить.

Самостоятельная работа

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

  • mp3 плейер пока не готов, разработка ведется (есть процедура чтения и декодирования файла)
  • цветомузыка - бесконечное расширение эффектов, задействование преобразования фурье для анализа частот
  • управление по Wi Fi - смена различных режимов работы DSP, управление плеером, анализ показателей колонки (есть пример общения с Wi-Fi модулем)
  • процесс зарядки с учетом балансировки (есть пример кода получения данных с платы балансировки)
  • FM-радио - сейчас реализован пример прослушивания радио на одной фиксированной радиостанции и поиск каналов
  • USB-device - не реализованы режимы копирования файлов на SD карту по usb и usb serial

Как ты видишь - проект очень большой, и тебе точно будет чем заняться. Это же твоя колонка! Сделай себе такую же, реализуй нужные тебе функции. Получи уникальный продукт высочайшего качества.

]]>
(Super User) Приборы для дома Fri, 17 Dec 2021 11:13:47 +0000
Беспроводной выключатель света /index.php/pribory/home/item/81-besprovodnoj-vyklyuchatel-sveta /index.php/pribory/home/item/81-besprovodnoj-vyklyuchatel-sveta Беспроводной выключатель света

Беспроводной выключатель света - очень нужная и удобная вещь. Цифровой радиомодуль с кварцевым резонатором - надежная связь. Компактный модуль реле на 2 или 4 реле (всего 50х50х24мм). Надежный блок питания в модуле реле. Компактный пульт на 4 кнопки в заводском корпусе. Реле до 1 кВт. Возможность программирования любой логики работы. Работа пульта от одной батарейки более 3 лет.

{autotoc}

Прежде чем начать

Прежде чем читать эту статью рекомендуем вам ознакомится со следующей теорией:

Обзор рынка дистанционных выключателей

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

На рынке сейчас продается большое количество дистанционных выключателей. Среди дешевых моделей - Feron, Navigator (около 1 тыс рублей). Функции самые простые. Долго пользовался именно такими и оказалось, что у них есть большой минус. Со временем они перестают работают. Сильно падает дальность. То работает, то нет. Wi-fi или другой передатчик сильно мешает работе. При большой влажности или на жаре вообще могут перестать работать. В итоге танцы с бубном вокруг люстры надоели, и я стал искать им замену. Нашел другие качественные выключатели на базе цифровых передатчиков, но цена их не обрадовала совсем - около 3тыс за сам модуль реле, плюс пульт. Получается очень дорого.

В итоге я решил сделать свои выключатели. Об этом данная статья.

Постановка задачи, требования к прибору

Требования к модулю реле:

  • компактный размер, чтобы можно было встроить в практически любую люстру
  • 2 или 4 канала управления
  • малое потребление во время сна - реле всегда в сети и ждет команду
  • схема на основе реле, а не семисторов (может быть различная нагрузка, не нужно заморачиваться со снабберами)
  • цифровой радиомодуль с кварцевым резонатором - надежно, легко программировать, не уплывает частота
  • низкая стоимость

Требования к пульту:

  • компактный размер
  • дальность работы около 200м - достаточно для покрытия средней квартиры
  • работа от одной батарейки более 3 лет (забота об окружающей среде)
  • возможность управлять с одного пульта всеми реле или нужными (хотелось одной кнопкой выключить свет во всей квартире)
  • возможность с нескольких пультов управлять одним реле (вариант проходного выключателя)

Подбор компонентов для изготовления прибора своими руками

Радио модуль

Начну с радиомодуля. Его я выбрал сразу - это дешевый китайский модуль NRF24L01-M. Формат модуля - самый маленький (mini) - всего 12x18 мм. Купить его можно на aliexpress. Цена копеечная. Связь цифровая, программировать его очень легко.

Микроконтроллеры для реле и пульта

Микроконтроллера будем использовать два: STM8 - в модуле реле, и STM8L - в пульте. Особых требований к ним нет, нужна только шина SPI, которую легко эмулировать даже ногодрыгом. В пульте специально ставим микроконтроллер с низким потреблением - во сне всего 350 nA.

Реле

Подойдет любое реле. Я выбрал широкораспространненый вариант - HJR-3FF на напряжение 12В. Ток коммутации около 10А, ток управления около 30 мА.

Блок питания 220В -> 12В для реле

Для питания реле нужен блок питания 220В на 12В. Он должен быть компактным, дешевым и обеспечивать ток около 140 мА. Существует масса схемных решений на этот случай. Все они делятся на две основные категории - на базе мини трансформатора и на базе гасящего конденсатора. Трансформатор сложно купить, а гасящий конденсатор имеет большой размер. В итоге в этом проекте я решил исползовать готовый заводской блок питания, который уже доказал свою надежность (в приборе Цифровая паяльная станция) - B2M003ESB компании ECOLA.

Регулятор питания 12В -> 3.3В

Так как радиомодуль работает от 3.3В, то нужно понизить напряжение с 12В до 3.3В. Будем использовать надежный маломощный линейный регулятор питания L78L33. У него очень много различных защит, убить его практически невозможно.

Составляем схему радиореле

Схема в итоге получилась максимально простая, ее вы можете найти в формате Kicad в исходниках проекта. Единственный момент, на который хотелось обратить внимание - это управление реле микроконтроллером. Вот схема этого участка:

Используется дешевый маломощный N-канальный мосфет 2N7002. И обязательно необходим маломощный диод, как минимум на 1000В, для гашения высоковольтных импульсов.

Составляем схему пульта дистанционного управления

С пультом все совсем просто. Схему приводить не буду (в проекте она конечно тоже есть). Питание пульта производится от батарейки CR2032. Ее емкости хватит на 5 лет работы. Пульт имеет 4 кнопки, которые подключены к выводам микроконтроллера. Модуль подключен к переферии SPI. Батарейка напрямую постоянно питает всю схему.

Печатные платы

Полный проект в Kicad вы найдете в исходниках проекта. Стоит отметить, что при трассировке высоковольной части обязательно нужно придерживаться минимального расстояния между дорожками - 1мм.

Корпус

Для пульта я выбрал заводской корпус-брелок компании GAINTA на 2 кнопки G1402-2G. Его размер - 55х43х14 мм.

А для реле - разработал корпус на 3д принтере. Два варианта - на 2 реле и на 4 реле. В варианте на 2 реле - 50х50х24мм.

Необходимые инструменты и всякая мелочовка

Для сборки колонки вам понадобяться следующие инструменты и дополнительные материалы:

  • провод многожильный 1.5мм2
  • супер клей, чтобы приклеить крышку реле на пару капель
  • кусочек листового пвх пластика толщиной 3мм - для фиксирования платы в корпусе пульта
  • провод - МГТФ-0.5 - для припайки радиомодулей

Программа для микроконтроллера

Программа написана в среде (ST VD IDE). Все исходники доступы в полном проекте. В этой статье опишем только общую логику работы программы.

Общая логика работы программы

  1. Для повышения надежности сигнал управления передается последовательно на 3-х каналах, обратной связи нет.
  2. Начнем с реле. Тут все совсем просто. Микроконтроллер все время работает.
  3. Каждые 30мс меняем канал и ожидаем пакета данных. Если пакет получен, обрабатываем его. Для блокировки приемки одинаковых пакетов, каждый пакет имеет номер. И если такой номер уже был получен и обработан, то пакет игнорируется.
  4. Каждое модуль реле имеет свой адрес, дополнительно есть общий адрес, который слушают все реле! Таким образом, можно управлять именно этим модулем реле, а можно всеми модулями в квартире.
  5. Каждому реле можно передать 4 команды. Включить, выключить, ничего не делать, сменить состояние (если было включено - то выключить, иначе включить).
  6. С пультом чуть сложнее. Он все время находится в спящем режиме. При нажатии на любую кнопку срабытвает прерывание и пульт передает команду.
  7. Если кнопка нажата один раз - то реле меняет состояние, долгое нажатие - выключение всех реле во всей квартире!
  8. Команда посылается в течение 100мс, постоянно чередуя каналы. После отправки команды пульт переходит в спящий режим.

Настройка адресов реле и пульта производится прямо в исходниках прошивки. Поэтому необходим компилятор и st-link для прошивки. Вам нужно только прописать в коде адреса модулей реле, а также по какой кнопке какое реле какого модуля должно сработать.

Как купить полный проект данного прибора

Если тебе понравился прибор и ты хочешь сделать такие же выключатели, то пиши на почту сайта в разделе контакты по вопросу приобретения полной версии проекта. В полную версию входит:

  • Два проекта Kicad - для пульта и реле
  • 3Д модель корпуса для реле
  • Исходный проект на Си для ST VD - для пульта и реле
  • Поддержка по электронной почте при сборке прибора

В файле приложенном к статье BOM.xls ты сможешь найти полный перечень компонент, чтобы оценить то, что нужно будет купить.

Самостоятельная работа

Это полностью готовый проект. Но всегда есть куда развиваться. Ты можешь добавить следующие функции:

  • выключение света с задержкой
  • режим присутсвия - имитация присутствия хозяина дома
  • режим проходного выключателя - несколько пультов, одно реле
  • встроить пульт в обычный клавишный выключатель - плата минимальная по габаритам
]]>
(Super User) Приборы для дома Thu, 24 Nov 2022 15:18:26 +0000