!!! Все что вы сделаете воспользовавшись информацией из этого поста - будет на вашей совести. Все на ваш страх и риск. Пост носит сугубо развлекательно-познавательный характер. Ну и похвастаться... чуть-чуть =)
Как всегда, DIY не имеет ничего общего с экономией. На мучения с данным девайсом потрачено времени вагон, думаю что под сотню а то и полторы сотни часов точно =) и результат еще не достигнут до конца. Безусловно, пойти и купить хоть новую, хоть с барахолки двухдиновую магнитолу с блютусом которая обучится понимать кнопки на руле моей машины более правильное решение. Но это не интересно.
Итак, имеем pioneer mvh-190ub которая заменила штатную магнитолу виновную в хреновом качестве звука и других косяках. В плюсе - звук стал намного лучше даже на штатной акустике без шумки. Из минусов - не работали штатные кнопки на руле и отсутствие блютуса. Ну да да, я понимаю что вроде жадина, но mvh-390bt стоила в те времена почти в два раза дороже, около 6.5к vs 3.4к за 190ub. Кстати, тут есть нюансик =) это СОВЕРШЕННО одинаковые устройства по схемотехнике (процессор, цап и усилитель и даже разводка платы), отличающиеся только наличием модуля bluetooth дополнительных разъемов типа тюльпанов под колонки и гнезда под jack 3.5 управления по проводам резистивными кнопками. Если посмотрите сервисмануалы для этих девайсов то отличия будут косметическими. Разве что модуль bluetooth нигде в интернете не фигурирует своими откровенными фотографиями своих внутренностей. Даже более чем верен что если впаять этот модуль, то он сразу заработает и появится в меню. Поскольку прошивки не просто похожи, они тупо одинаковые байт в байт для обоих устройств. Но моих знаний не хватило понять как заставить процессор подумать что модуль есть и включить все соответствующие фишки. Тогда можно было вообще поискать подходящую платку с али и передавать внутрь процессора сразу цифровой аудио сигнал.
Итак. Для имплантации был выбран модуль VHM-314 V2.0 с кнопками. Просто он оказался самым быстрым в достаке. В результате имеем вот это:
По моделям платок, заказал четыре штуки:
VHM-314 v1.0
+ цена
+ относительно годное качество звука
+ простота имплантации
+ мало шумит
+ громкость сразу максимальная
- мерзкие голоса учат меня жизни при включении и коннекте
- отсутствие вменяемой документации
VHM-314 v2.0
+ все тоже самое, кроме шума
+ не учит жизни
+ есть кнопки, которыми можно управлять туда-сюда-плейстоп
- шумит прям из коробки, даже от питания аккумулятором
- при регулировке громкости (долгое зажатие кнопки вперед\назад) громко бунькает при достижении максимального значения
- нельзя настроить включение с максимальной громкостью, по умолчанию она средняя что мало
VHM-314 PRO
Тоже самое что и первая версия, но можно управлять приложением. Но не пользовался вообще, платка стремится общаться вслух, а "голоса в голове" мне не нравятся.
CSR64215
Еще в пути, относительно дорого под 1к. рублей. Обещают приличный ЦАП и хорошее качество звука, можно настроить сквозное подключение к линиям, например AUX при ключении блюпупа релюшками отключается от внешнего источника и включается внутренний. Поставлю в колонки возле компьютера... почему? Потому что могу =)
Думаю, что если бы не торопился и изучил рынок внимательнее то заказал бы только последнюю платку, но о ней узнал после того как заказал VHM-314.
В целом в машине шум от VHM-314 v2.0 незаметен, есть подозрение что работает штатный шумодав на пионере. Вообще подозреваю что шумность и качество зависит от конкретного экземпляра и дело не в версии.
Ну приступим к созданию франкенштейна.
Итак, начнем с самого простого. Берем и припаиваемся к USB 5 вольт и AUX на нижней стороне платы возле разъема для "морды".
С прискорбием сообщаю, что где-то похерил все фотки. Вроде неоднократно фоткал процесс но О_о может быть в очередном приступе отчаяния они были удалены, не помню ^_^
Но в общем-то ничего сложного. Переворачиваем, отсчитываем ножки, припаиваемся. Для 5 вольт там даже пятаки отдельно есть, к ним припаиваться удобнее. Рекомендую не ленится и все промерять и проверять тестером на наличие контакта где должно быть и отсутствие где не должно.
Но! Это только самое простое и неинтересное решение 100500 раз обмусоленное в интернетах. Самый большой недостаток такого решения - платка блютуса подключается сразу после подачи питания и в моей магнитоле даже в выключенном состоянии магнитолы присутствуют пять вольт. То есть как только включил acc то сразу платка подключается к телефону и становится приемником звука по умолчанию. Что неудобно. Путем мозгошутрма и поиска по закромам было решено банально обесточивать платку тумблером:
Такое можно провернуть за пару часов, большая часть которых уйдет на изучение схемы и перепроверку контактов.
Дальше у меня возникла идея (ну раз я нашел схему) поменять местами кнопки MUTE и MENU. Я не знаю что курят эти идиоты, но в последних версиях магнитол (не только пионеров) при нажатии на джойстик-регулятор громкости вызывается меню, а кнопка приглушения звука либо отсутствует, либо расположена крайне неудобно в виде мелкой закорючки. Хотя это едва ли не важнейшая кнопка в магнитоле, но что-то нехорошее они употребляют там. Как часто вы лезете в меню магнитолы? Да один раз после установки в большинстве случаев. А mute нужен достаточно часто. Поэтому что мы сделаем? Правильно, на самую удобную кнопку мы заведем редко используемое меню.
Но в итоге мне этого не удалось - надоело разбираться куда какая дорожка через какой переходной пятак идет. И тут вспомнил, что есть же кнопки на руле и нагуглил схему адаптера на ардуино. Так как цифровой потенциометр у меня был другой - X9C104, пришлось немного переписать скетч.
// Коды имеющихся на руле кнопок
const int VOL_UP=1;
const int VOL_DN=2;
const int PREV_TR=3;
const int NEXT_TR=4;
const int MODE=5;
const int MUTE=6;
// контакты первого потенциометра
int INC = 7;
int UD = 6;
int CS=5; // CS на цифровом потенциометре
int wheelPin=A6; // аналоговый пин, на котором мы считываем сопротивление нажатой на руле кнопки
// контакты второго потенциометра
int INC1 = 2;
int UD1 = 3;
int CS1=4;
// переменные
int i=0;
int prevButton=4; // на всякий случай, чтобы при подаче питания сработал цикл и потенциометры были инициализированы
void setup() {
pinMode(CS, OUTPUT);
pinMode(INC, OUTPUT);
pinMode(UD, OUTPUT);
digitalWrite(CS, HIGH);
digitalWrite(INC, HIGH);
digitalWrite(UD, HIGH);
pinMode(wheelPin, INPUT);
Serial.begin(9600);
pinMode(CS1, OUTPUT);
pinMode(INC1, OUTPUT);
pinMode(UD1, OUTPUT);
digitalWrite(CS1, HIGH);
digitalWrite(INC1, HIGH);
digitalWrite(UD1, HIGH);
}
int getR() { // Эта функция читает сопротивление с кнопок на руле и возвращает код нажатой кнопки, либо 0
// читаем сопротивление (на самом деле напряжение, конечно) на аналоговом пине
int r=analogRead(wheelPin);
Serial.println(r); // для отладки
delay(100); // не знаю зачем =)
// Ищем, какая кнопка соответствует этому сопротивлению.
if (r>=95 && r<=180) return(VOL_UP);//130 значение r для моей машины
if (r>=190 && r<=270) return(VOL_DN);//230
if (r>=550 && r<=750) return(PREV_TR);//605
if (r>=400 && r<=530) return(NEXT_TR);//476
if (r>=250 && r<=390) return(MODE);//333
if (r>=10 && r<=90) return(MUTE);//30
// если ни одна из кнопок не нажата, возвращаем 0
return (0);
}
// ОСНОВНОЙ ЦИКЛ
void loop() {
int currButton=getR(); // заносим в переменную currButton код нажатой кнопки
// Serial.println(currButton);
// Serial.println(prevButton);
if (currButton!=prevButton) { // если значение поменялось с прошлого раза
delay(10);
currButton=getR(); // ждем 10ms и читаем еще раз, чтобы исключить "дребезг" кнопки
if (currButton!=prevButton) { // если код кнопки точно поменялся с прошлого раза
Serial.println(currButton);
prevButton=currButton; // сохраняем новое значение в переменную prevButton
int j = 100; // инициируем переменную для первого потенциометра управляющего магнитолой
int k = 85; // для второго управляющего блютус платкой, 85 значение подобранное опытным путем для падения напряжения ровно в 3.3 вольта.
switch(currButton) {
case VOL_UP: j = 15; break; //справка для значения сопротивлений pineer 16kОм (97Ом для моей машины)
case VOL_DN: j = 23; break; //24к (201)
case PREV_TR: j = 11; k=19; break; //11к (1153)
case NEXT_TR: j = 7; k=25; break; //8к (611)
case MODE: j = 1; break; //1,2к (344)
case MUTE: j = 3; break; //4к (31)
default: j = 100; k = 85; // вертаем максимальное сопротивление
}
setResistance(j); // выставляем сопротивление
setResistance1(k);
// Serial.println(j); // да да, я не знаю как нормально отладкой заниматься на ардуине, используем дедовский способ.
delay(5);
}
}
}
void setResistance(int percent) {
// Понижаем сопротивление до 0%:
digitalWrite(UD, LOW);
digitalWrite(CS, LOW); // выбираем потенциометр X9C
for (int i=0; i<100; i++) { // т.к. потенциометр имеет 100 доступных позиций
digitalWrite(INC, LOW);
delayMicroseconds(2);
digitalWrite(INC, HIGH);
delayMicroseconds(2);
}
// сопротивление до нужного:
digitalWrite(UD, HIGH);
for (int i=0; i<percent; i++) {
digitalWrite(INC, LOW);
delayMicroseconds(2);
digitalWrite(INC, HIGH);
delayMicroseconds(2);
}
digitalWrite(CS, HIGH); /* запоминаем значение
и выходим из режима настройки */
}
void setResistance1(int percent) {
// Понижаем сопротивление до 0%:
digitalWrite(UD1, LOW);
digitalWrite(CS1, LOW); // выбираем потенциометр X9C
for (int i=0; i<100; i++) { // т.к. потенциометр имеет 100 доступных позиций
digitalWrite(INC1, LOW);
delayMicroseconds(2);
digitalWrite(INC1, HIGH);
delayMicroseconds(2);
}
// сопротивление до нужного:
digitalWrite(UD1, HIGH);
for (int i=0; i<percent; i++) {
digitalWrite(INC1, LOW);
delayMicroseconds(2);
digitalWrite(INC1, HIGH);
delayMicroseconds(2);
}
digitalWrite(CS1, HIGH); /* запоминаем значение
и выходим из режима настройки */
}
Какой-то убогий редактор в пикабу, ничего не умеет. То есть умную ленту сделать могут, а спойлер или оформление для кода нет. Прям жж какой-то...
Из неприятного - все три экземпляра цифрового потенциометра которые у меня есть имеют разное сопротивление из коробки (использованы на 92 и 105 кОм), то есть точность без отладки плюс-минус два крокодила. И еще, я чуть не похоронил всю идею психанув, потому что эти потенциометры имеют свойство "плыть". То есть в какой-то рандомный момент сопротивление начинало потихоньку уменьшатся или увеличиваться. Решилось это соединением RL с землей. Может еще как-то можно это решить (может быть соединение любого вывода со схемой будет достаточно) но для меня сработал этот способ.
Сорян за рукотворное творчество, но то одно, то другое не срасталось с онлайн редакторами схем, так сильно быстрее получилось.
R1 в 680 Ом выбран потому что у меня кнопки на руле низкоомные, вообще от 30 Ом стартуют. При 680 относительные изменения падения напряжения максимально выражены а ток гарантированно ниже максимального для вывода. R2 должен быть 22 кОм, но такого не нашлось а городить составной резистор не хотелось.
Я сначала построил в экселе график значений выдаваемых ардуиной в зависимости от сопротивления на входе адаптера, и к моему удивлению он оказался нелинейным. В итоге после десятой переделки просто откалибровал по подобранным сопротивлениям соответствующим кнопкам на руле при питании от самой магнитолы чтобы минимизировать погрешность (там не ровно пять вольт а чуть ниже).
А теперь про платку блюпуп. Вот тут ссылки на китайские пэдэфки. Они прямо не подходят, но хотя бы дают понимание что искать. Мне кажется, что это действительно та же микросхема, но с другим порядком ножек. Вот здесь схема подключения кнопок. И тут до дотупета дошло, что все эти вещи управляются не сопротивлением как таковым а уровнем напряжения. То есть можно было обойтись даже не цифровыми резисторами а аналоговыми выводами на ардуине устанавливая нужный уровень сигнала (ну защищая это дело от чрезмерных токов резисторами, разумеется). Ну или простейшими транзисторными ключами, если уровни напряжения выше пяти вольт или токи и все такое. И чтобы избежать дрейфа - теми же аналоговыми входами можно было контролировать напряжение выставленное на выходе организовав обратную связь. Но отступать уже было поздно, схема уже была готова и собрана. Вообще хотел все сделать максимально компактно и вообще собрать в один бутерброд, но получилось как получилось. Опять же, задним числом дошло что можно было взять esp-12e, еще компактней вышло бы, но...
Блюпуп управляется по уровню напряжения. 3,3 ничего не делаем, 2,3 вперед, 2,0 назад и 0 пауза-плей. 3.3 вольта генерирует сама микросхема и нам не нужны, они приходят на R1 на плате. Который надо удалить и припаяться к пятачку с оранжевой стрелочкой идущему к ножке 16 (желтая стрелочка, четвертый снизу). Тут аккуратно, площадки контактные держатся плохо и моя оторвалась, пришлось паяться прямо к ножке. R3 в 350кОм на схеме адаптера в принципе лишний, если подобрать R2, то можно добиться падения напряжения в 3.3-3.5 вольта даже без инициализации резистора. Без подачи питания на цифровом резисторе между RH и RL присутствует сопротивление, а вот RW не промеряется.
Конечно, можно реализовать управление блютусом проще - через реле вместо кнопок на плате. Но у меня были только огромные платы с мощными реле и во время экспериментов я там порушил немного дорожки и сопротивления на плате.
Кстати, так как у меня нет штатного разъема под управление по проводам и пришлось немного поколхозить. Изучив схему обнаружил место куда можно подпаяться. Для этого нужно впаять резистор R912 номиналом в 1кОм в линии идущую в процессор и другим концом уже к схеме адаптера кнопок. Так как у меня нет smd компонентов, то воткнул туда обычный резистор на 0.25 ватт. Особо заострять внимание на реализации не буду (да я и фотки похерил а разбирать не буду уже), поскольку если вы не способны разобраться куда впаяться резистором по схеме, то лучше туда паяльнком не лезть. Если на разъеме и питании 5 вольт там все мегаочевидно, то тут уже все сложнее.
По этой же схеме можете найти как впаять ИК приемник на "морду" магнитолы, чтобы реализовать управление с пульта для пассажира. Например как тут.
А самая мякотка - я еще не реализовал автоматическое включение и выключение блюпуп платки по сигналам spi. Тут я уже спрашивал совета как жить, но никто не смог дать вразумительного ответа. Все сам, все сам.
Хитрая микросхемка коммутатор, цап и эквалайзер в одном флаконе управляется по SPI. Я даже этот SPI научился читать... но возникло подозрение что производительности ардуины не хватает для обработки пакетов. Точнее вроде как прочитать можно, но как только добавляешь хоть один if то следующий пакет а то и два летят мимо, а там важно поймать именно последовательность. Может быть там есть еще какая-то тема с регистрами и прочим, но моя твоя нипанимать. Ситуация осложняется тем, что я не хочу глубоко погружаться в тему и у меня нет логического анализатора. Но иногда я упрям и разобрался в последовательностях.
Если кому интересно то вот:
Я попробовал реализовать тупыми ifами на nano, вдруг кому интересно:
#include "SPI.h"
bool flag01, flag02, flag03, flag11, flag12, flag13, flag31, flag32, flag33;
void setup (void)
{
// Инициируем работу с последовательным портом
Serial.begin(9600);
// Устанавливаем вывод MISO в режим выхода
pinMode(MISO, OUTPUT);
// Устанавливаем режим ведомого в контрольном регистре SPI (SPI Control Register)
SPCR |= _BV(SPE);
// Подключаем прерывание SPI
SPI.attachInterrupt();
}
// Вызываем функцию обработки прерываний по вектору SPI
// STC - Serial Transfer Comlete
ISR(SPI_STC_vect)
{
// Получаем байт из регистра данных SPI
byte c = SPDR;
Serial.println(c, BIN);
if (c == 0b1) {
Serial.println("1 ok");
flag11 = true;
} else {
flag11 = false;
}
if (c == 0b11 && flag11) {
Serial.println("11 ok");
flag12 = true;
} else {
flag12 = false;
flag11 = false;
}
if (c == 0b1100000 && flag11 && flag12) {
Serial.println("1100000 ok");
flag13 = true;
} else {
flag13 = false;
flag12 = false;
flag11 = false;
}
}
void loop(void)
{
}
Подозреваю что если записывать это в массив или буфер, то можно потом как-то с этим делом разобраться. Но уже сил на вдумчивое курение мануалов по C++ и прочему не осталось. Как минимум я не понимаю как детектировать начало последовательности пакетов. В любом случае буду ждать STM32F401CCU6 и уже на нем реализовать данную фишку. Скорей всего мой говнокод на 70МГц будет нормально работать и просто добавлю в схему ключ на мосфете включающий и выключающий питание блюпуп платы. Попробую на этом котроллере совместить и с функциями адаптера кнопок, если смогу совместить все это в коде (что не факт), но на nano вообще не заработало =) так что только попробую.
Была мысль использовать для чтения spi платку nodemcu на esp8266, но там как-то все плохо с spi, один вечер потыкал палочкой, научился читать немного информации но почему-то в пять раз меньше чем через nano и забил. Пытался читать исходных код или документацию на SPIslave библиотеку для esp, но в результате забил, оно того не стоит.
Если еще смогу редактировать пост - то добавлю результат. А пока, выходные закончились, надо двигать на работу. Как промежуточным результатом я доволен, своего внутреннего самоделкина накормил и он заснул до следующего раза.