Схема выглядит так:
1) Заголовок – текст «VOLUME» или «МUTE», в зависимости от текущего режима
2) Уровень громкости – цифры от 0 до 26 (при заданном шаге громкости (fadeAmount) – 3
3) Шкала громкости – графическая полоска: чем выше громкость – тем шкала длиннее
Визуально это выглядит так:
Для вывода информации на OLED-дисплей используется библиотека OLED_i2C. Подробное ее описание на русском языке и ссылки для скачивания описаны в этой статье.
Скетч Arduino:
#include <Wire.h> #include <EEPROM.h> #include <OLED_I2C.h> /******************************************************** ** Для управлением громкостью используется энкодер ** ** Arduino и pt2257 v5 ** ** Вращением энкодера регулируется громкость, нажатием ** ** кнопки включается-отключается режим "MUTE" ** ** Выключение "Mute" кнопкой и поворотом энкодера. ** ** Запоминает значение громкости при выключении ** ** http://mynobook.blogspot.com ** ** *********************************************************/ OLED myOLED(SDA, SCL, 8); extern uint8_t SmallFont[]; extern uint8_t BigNumbers[]; int Volume; // Переменная уровня громкости int Mute=0; // Переменная значения "Mute" (Отключение звука) - 0 отключено, 1 включено int fadeAmount = 3; // шаг изменения громкости unsigned long currentTime; unsigned long loopTime; const int pin_A = 12; // Подключение вывода A (CLK) энкодера const int pin_B = 11; // Подключение вывода B (DT) энкодера const int pin_SW = 9; // Подключение вывода кнопки (SW) энкодера unsigned char encoder_A; unsigned char encoder_B; unsigned char encoder_A_prev=0; int i2c_write(int Az){ // функция записи данных в pt2257 121 - MUTE ON, 120 -MUTE OFF, 0 - Volume Wire.beginTransmission(0x44); // i2c адрес pt2257 if (Az == 0) { Wire.write(Volume/10+224); // Отправляем десятки громкости в pt2257 значение 224-231(00-70) Wire.write(Volume%10+208); // Отправляем единицы громкости в pt2257 значение 208-217(0-9) EEPROM.write(0, Volume);} // Сохраняем значение громкости во встроенную память EEPROM else Wire.write(Az); Wire.endTransmission(); } int oled_out(int Vol){ myOLED.setFont(SmallFont); if (Mute == 1) myOLED.print(" M U T E ",CENTER,0); else myOLED.print("V O L U M E",CENTER,0); //Вывести на дисплей "VOLUME" или "MUTE" myOLED.setFont(BigNumbers); if (((79-Vol)/fadeAmount) <= 9) for (int i=70; i<77; i++) for (int j=20; j<44; j++) myOLED.clrPixel(i, j); // Если значение громкости занимает один знак - стереть мусор myOLED.printNumI((79-Vol)/fadeAmount, CENTER, 20); // Вывести на экран текущее значение громкости for (int i=0; i<79; i++) for (int j=55; j<60; j++) if (i<(79-Vol)) myOLED.setPixel(i+24,j); else myOLED.clrPixel(i+24,j); //Вывести шкалу myOLED.update(); } void setup() { Wire.begin(); pinMode(pin_SW,INPUT); // устанавливаем pin pin_SW как вход digitalWrite(pin_SW,HIGH); // Поддяжка вывода к 1 pinMode(pin_A, INPUT); pinMode(pin_B, INPUT); currentTime = millis(); loopTime = currentTime; Volume=EEPROM.read(0); if (Volume == 255) Volume = 40; //Если считано значение 255, то установить громкость 50% myOLED.begin(); oled_out(Volume); i2c_write(120); // "Mute" при включении отключен i2c_write(0); // Задаем громкость при включении } void loop() { currentTime = millis(); if(currentTime >= (loopTime + 5)){ // проверяем каждые 5мс (200 Гц) encoder_A = digitalRead(pin_A); // считываем состояние выхода А энкодера encoder_B = digitalRead(pin_B); // считываем состояние выхода B энкодера if((!encoder_A) && (encoder_A_prev)){ // если состояние изменилось с положительного к нулю if (Mute == 1) {Mute=0; i2c_write(120); oled_out(Volume);} // если включен режим "Mute" то выключить его, иначе регулировать громкость else if(encoder_B) { // выход В в полож. сост., значит вращение по часовой стрелке // увеличиваем громкость, не более чем до 79 и записываем в pt2257 if(Volume + fadeAmount <= 79) {Volume += fadeAmount; oled_out(Volume); i2c_write(0); } } else { // выход В в 0 сост., значит вращение против часовой стрелки // уменьшаем яркость, но не ниже 0 и записываем в pt2257 if(Volume - fadeAmount >= 0) {Volume -= fadeAmount; oled_out(Volume); i2c_write(0); } } } encoder_A_prev = encoder_A; // сохраняем значение А для следующего цикла if (digitalRead(pin_SW) == 0) // Если нажата кнопка то выключить или включить звук { if (Mute == 0) { Mute = 1; while (digitalRead(pin_SW) == 0) delay(100); // Дождаться отпускания кнопки i2c_write(121); oled_out(Volume); } else { while (digitalRead(pin_SW) == 0) delay(100); // Дождаться отпускания кнопки Mute = 0; i2c_write(120); oled_out(Volume); } } loopTime = currentTime; } }
Скачать скетч можно здесь
На этом все!
Upd 31.05.2022:Выложил файлы в девятом комментарии к данной статье на нашем телеграмм канале. Не забудьте подписаться на канал!
Спасибо большое за проделанную работу, Вячеслав. Благодаря Вам я нашел применее найденной в донорах PT-шке Если кто будет собирать этот регулятор на 2259, просто измените значения mute байтов в коде со 121 и 120 на 119 и 116. 2259 отличается от 2251 только расшеренным mute режимом.
ОтветитьУдалитьДень добрый. Возможно ли приспособить эту схему для нескольких устройств вывода (колонки/наушники) с запоминанием уровня громкости для каждого?
ОтветитьУдалитьК сожалению нет. В этой микросхемы 1 стереовыход.
УдалитьСпасибо за быстрый ответ.
ОтветитьУдалитьСмысл не в одновременном использовании двух устройств, а в переключении между ними. Т.е. в каждый момент времени работает только одно выходное устройство.
Может использовать 2 микросхемы и переключаться между ними?
Скетч не загружается. Выдаёт ошибку
ОтветитьУдалитьКакую?
УдалитьЭтот комментарий был удален автором.
ОтветитьУдалитьа можно ли ещё прикрутить пульт ir?
ОтветитьУдалить