Мой локдаун проект

Вот такие колонки с энкодером.

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

Размер колонок 15 х 15 х 30 см, две полосы, усилитель класса D, импульсный БП, управление громкостью при помощи энкодера. Прототипирование корпусов было проведено при помощи листов из вспененного полистирола. Звучание мне понравилось, в основном, наверно, из-за безымянных шелковых твиттеров с Aliexpress.

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

Для намотки дросселей собрал намоточную установку и электронный счетчик для подсчета оборотов.

Клееные деревяшки и счетчик с питанием от USB зарядки.

Счетчик собран из МК STM32L011, символьного дисплея и вынесенной кнопки. Как оказалось, ни одна программа не дает правильного расчета для дросселя с прямоугольным воздушным сердечником, поэтому конструкция отправилась под кровать и были намотаны обычные круглые дроссели.

Первая версия платы управления была построена на TDA7318, но похоже обе были неисправные или поддельные, а в радио ларьке их больше не было, поэтому переделал на PT2259, потеряв заодно тонкомпенсацию. Также заменил понижающий преобразователь MP2225 на BL8032.

Плата управления.
Плата усиления.

Усилитель сделан на TPA3116D2. Управление на том же STM32L011. Таймер TIM21 управляет энкодером, LPTIM1 ожидает 3 секунды от последнего изменения громкости, чтобы минимизировать запись значения в EEPROM.

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

#include "pt2259.h"
#include "utils.h"

extern I2C_HandleTypeDef hi2c1;

#define PT2259_ADDR (BIT3 | BIT7)
#define PT_DUAL_1DB_STEP (BIT7 | BIT6 | BIT4)
#define PT_DUAL_10DB_STEP (BIT7 | BIT6 | BIT5)
#define PT_LEFT_1DB_STEP (BIT7 | BIT5)
#define PT_LEFT_10DB_STEP (BIT7 | BIT5 | BIT4)
#define PT_RIGHT_1DB_STEP BIT5
#define PT_RIGHT_10DB_STEP (BIT5 | BIT4)
#define PT_CLEAR (BIT7 | BIT6 | BIT5 | BIT4)
#define PT_MUTE_SELECT (BIT6 | BIT5 | BIT4 | BIT2)
#define PT_ATT_MAX 79

const uint8_t LogScale[31] = 
	{0, 0, 17, 26, 33, 38, 42, 46, 49, 52, 54, 56, 58, 60, 62, 63, 65,
	66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 79};

uint8_t PT_Packet[4];

void PT2259Send(uint8_t* data, uint8_t len)
{
	while (HAL_I2C_Master_Transmit(&hi2c1, PT2259_ADDR, data, len, 300) != HAL_OK)
	{};
}

void PT2259Init()
{
	PT_Packet[0] = PT_CLEAR;
	PT_Packet[1] = PT_MUTE_SELECT; //mute none
	PT_Packet[2] = PT_DUAL_10DB_STEP | (PT_ATT_MAX / 10U);
	PT_Packet[3] = PT_DUAL_1DB_STEP | (PT_ATT_MAX % 10U);
	PT2259Send(PT_Packet, 4);
}

void PT2259SetVolume(uint8_t vol)
{
	if (vol > 30)
		vol = 30;
	
	uint8_t att = PT_ATT_MAX - LogScale[vol];
	PT_Packet[0] = PT_DUAL_10DB_STEP | (att / 10U);
	PT_Packet[1] = PT_DUAL_1DB_STEP | (att % 10U);
	
	PT2259Send(PT_Packet, 2);
}

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