Подключение штатных кнопок на руле и не только, по IBUS. перед прошивкой положить библиотеку MsTimer2 в arduino-0017\hardware\libraries
код для Arduino Mega.
Код предназначен для управления внешним устройством (например не штатная магнитола) и компом одновременно.PHP код:#include <MsTimer2.h>
byte IBUSbyte[6] = {0,0,0,0,0,0}; // массив сообещний
bool MafonPin = false; //true - данные идут в комп; false - управляют пинами ардио
void setup()
{
MsTimer2::set(100, ResetPinButton); // Таймер для установки выходов IBUS
Serial.begin(115200); // открываем порт для передачи в ПК
Serial1.begin(9600); // настройка порта IBUS
pinMode(7, INPUT); // Вход мафон
pinMode(8, OUTPUT); // Громкость +
pinMode(9, OUTPUT); // Громкость -
pinMode(10, OUTPUT); // Кнопка Next
pinMode(11, OUTPUT); // Кнопка Previous
pinMode(12, OUTPUT); // Кнопка Dial
pinMode(13, OUTPUT); // Кнопка R/T
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(10, LOW);
digitalWrite(11, LOW);
digitalWrite(12, LOW);
digitalWrite(13, LOW);
}
void loop()
{
ReadIBUSmsg();
ReadMAfonPin();
}
boolean ReadIBUSmsg()
{
while( Serial1.available() > 0 )
{
for( int i=1; i<6; i++ )
IBUSbyte[i-1] = IBUSbyte[i];
IBUSbyte[5] = Serial1.read();
if( IBUSbyte[0] == 0x50 && IBUSbyte[(IBUSbyte[1]+1)] == CalcXOR(IBUSbyte) )
{
if( MafonPin )
Serial.write(IBUSbyte, 6);
else
{
if( IBUSbyte[3] == 0x32 && IBUSbyte[4] == 0x11 ) digitalWrite(8, HIGH); // Нажал +
else if( IBUSbyte[3] == 0x32 && IBUSbyte[4] == 0x10 ) digitalWrite(9, HIGH); // Нажал -
else if( IBUSbyte[3] == 0x3B && ( IBUSbyte[4] == 0x01 || IBUSbyte[4] == 0x11 ) ) digitalWrite(10, HIGH); // Нажата next
else if( IBUSbyte[3] == 0x3B && IBUSbyte[4] == 0x21 ) digitalWrite(10, LOW); // Отпустил next
else if( IBUSbyte[3] == 0x3B && ( IBUSbyte[4] == 0x08 || IBUSbyte[4] == 0x18 ) ) digitalWrite(11, HIGH); // Нажата previous
else if( IBUSbyte[3] == 0x3B && IBUSbyte[4] == 0x28 ) digitalWrite(11, LOW); // Отпустил previous
else if( IBUSbyte[3] == 0x3B && ( IBUSbyte[4] == 0x80 || IBUSbyte[4] == 0x90 ) ) digitalWrite(12, HIGH); // Нажата dial
else if( IBUSbyte[3] == 0x3B && IBUSbyte[4] == 0xA0 ) digitalWrite(12, LOW); // Отпустил dial
}
if( IBUSbyte[2] == 0xC8 && IBUSbyte[3] == 0x01 ) digitalWrite(13, HIGH); // Нажата R/T
MsTimer2::start();
return true;
}
}
return false;
}
byte CalcXOR( byte IBUSbyte[6] )
{
byte i;
byte checksum = 0;
byte length;
length = IBUSbyte[1] + 1;
for(i = 0; i < length; i++)
{
checksum ^= IBUSbyte[i];
}
return checksum;
}
void ResetPinButton()
{
digitalWrite(8, LOW);
digitalWrite(9, LOW);
digitalWrite(13, LOW);
MsTimer2::stop();
}
void ReadMAfonPin()
{
if( digitalRead(7) == HIGH )
{
delay(2);
if( digitalRead(7) == HIGH ) MafonPin = true;
}
else MafonPin = false;
}
Подключение: сигнал RX c IBUS подключается в Serial1 пины на борту 18tx,19rx (внимание только для Ard Mega для других версий нужно использовать софтовый Serial см ниже)
Работает след образом: D7 настроен на вход, когда на D7 уровень сигнала LOW то кнопки управляют пинами D8-D13 и данные о нажатиях в комп не идут. когда на D7 HIGH то пины молчат и данные о нажатиях отправляются в ПК (как настроить на эти сигналы на нажатия кнопок клавы см в конце поста)
примечание: кнопка R/T управляет D13 не зависимо от сигнала на D7, можно использовать для переключения режимов (например на магнитоле CD/AUX/FM)
Так как многим такие сложности не нужны и большинство использует более компактные версии arduino то решил нарисовать еще один прошивку с использованием библиотеки NewSoftSerial для arduino не имеющих дополнительных Serial портов.
перед прошивкой положить библиотеку NewSoftSerial в arduino-0017\hardware\libraries
Подключение: к D7rx D8tx (сигнал RX с шины подключается к D7)PHP код:#include <NewSoftSerial.h> // програмный Serial для подключения BMW I-BUS
// I-BUS
NewSoftSerial IBUS(7, 8); // пины для подкл I-BUS (7rx,8tx)
int IBUSreceiveByte = 0; // считываем байт с I-BUS
byte IBUSbyte[6] = {0,0,0,0,0,0}; // массив сообещний
void setup()
{
Serial.begin(115200); // открываем порт для передачи в ПК
IBUS.begin(9600); // настройка порта IBUS
}
void loop()
{
ReadIBUSmsg();
}
boolean ReadIBUSmsg()
{
while( IBUS.available() > 0 )
{
for( int i=1; i<6; i++ )
IBUSbyte[i-1] = IBUSbyte[i];
IBUSbyte[5] = IBUS.read();
if( IBUSbyte[0] == 0x50 && IBUSbyte[(IBUSbyte[1]+1)] == CalcXOR(IBUSbyte) )
{
Serial.write(IBUSbyte, 6);
{
if( IBUSbyte[3] == 0x32 && IBUSbyte[4] == 0x11 ); // Нажал +
else if( IBUSbyte[3] == 0x32 && IBUSbyte[4] == 0x10 ) ; // Нажал -
else if( IBUSbyte[3] == 0x3B && ( IBUSbyte[4] == 0x01 || IBUSbyte[4] == 0x11 ) ) ; // Нажата next
else if( IBUSbyte[3] == 0x3B && IBUSbyte[4] == 0x21 ) ; // Отпустил next
else if( IBUSbyte[3] == 0x3B && ( IBUSbyte[4] == 0x08 || IBUSbyte[4] == 0x18 ) ) ; // Нажата previous
else if( IBUSbyte[3] == 0x3B && IBUSbyte[4] == 0x28 ) ; // Отпустил previous
else if( IBUSbyte[3] == 0x3B && ( IBUSbyte[4] == 0x80 || IBUSbyte[4] == 0x90 ) ) ; // Нажата dial
else if( IBUSbyte[3] == 0x3B && IBUSbyte[4] == 0xA0 ) ; // Отпустил dial
else if( IBUSbyte[2] == 0xC8 && IBUSbyte[3] == 0x01 ) ; // Нажата R/T
}
}
}
}
byte CalcXOR( byte IBUSbyte[6] )
{
byte i;
byte checksum = 0;
byte length;
length = IBUSbyte[1] + 1;
for(i = 0; i < length; i++)
{
checksum ^= IBUSbyte[i];
}
return checksum;
}
Работает след образом: При нажатии кнопок данные отправляются в ПК (как настроить на эти сигналы на нажатия кнопок клавы см в конце поста)
Код симулятор посылок с шины дабы не бегать с 5го этажа по морозу на парковку 6 раз чтоб узнать что перепутал Tx и Rxно нужен второй Arduino который будет играть роль шины. D10 настроен на вход, когда на нем уровень HIGH то шлется симулированный сигнал нажатия кнопки руля.
Подключение: 1пин Tx (стандартный порт на всех моделях) работает соответственно на выход и симулирует Rx сигнал от IBUS.PHP код:byte PLUS_DOWN[8] = {0, 0x50, 0x04, 0x68, 0x32, 0x11, 0x1F}; // + press button
byte MINUS_DOWN[8] = {0, 0x50, 0x04, 0x68, 0x32, 0x10, 0x1E}; // - press button
byte NEXT_DOWN[8] = {0, 0x50, 0x04, 0x68, 0x3B, 0x01, 0x06}; // > press button
byte NEXT_HOLD[8] = {0, 0x50, 0x04, 0x68, 0x3B, 0x11, 0x16}; // > hold button
byte NEXT_REL[8] = {0, 0x50, 0x04, 0x68, 0x3B, 0x21, 0x26}; // > release button
byte PREV_DOWN[8] = {0, 0x50, 0x04, 0x68, 0x3B, 0x08, 0x0F}; // < press button
byte PREV_HOLD[8] = {0, 0x50, 0x04, 0x68, 0x3B, 0x18, 0x1F}; // < hold button
byte PREV_REL[8] = {0, 0x50, 0x04, 0x68, 0x3B, 0x28, 0x2F}; // < release button
byte VOICE_DOWN[8] = {0, 0x50, 0x04, 0xC8, 0x3B, 0x80, 0x27}; // voice press button
byte VOICE_HOLD[8] = {0, 0x50, 0x04, 0xC8, 0x3B, 0x90, 0x37}; // voice hold button
byte VOICE_REL[8] = {0, 0x50, 0x04, 0xC8, 0x3B, 0xA0, 0x07}; // voice release button
byte RT_DOWN[8] = {0, 0x50, 0x03, 0xC8, 0x01, 0x9A, 0x80}; // voice release button
int ButtonPin = 10; //кнопка на 10 ноге
void setup()
{
Serial.begin(9600); // открываем порт на скорости 115200 для передачи наружу
pinMode(ButtonPin, INPUT); // Устанавливем 10 пин на вход
}
void loop()
{
if (digitalRead(ButtonPin)==1) {
//Вывод в стандартный порт байты посылки команды VOL+
for (int i=1; i <= 6; i++){ Serial.write(PLUS_DOWN[i]); }
//Задержка 1000 милисекунд 1000 м.с. = 1 секунда
delay(1000);
}
}
для выбора какую команду слать, в этой строке
for (int i=1; i <= 6; i++){ Serial.write(PLUS_DOWN[i]); }
PLUS_DOWN
меняем на то что нужно послать. Например NEXT_DOWN
byte PLUS_DOWN[8] = {0, 0x50, 0x04, 0x68, 0x32, 0x11, 0x1F}; // + press button
byte MINUS_DOWN[8] = {0, 0x50, 0x04, 0x68, 0x32, 0x10, 0x1E}; // - press button
byte NEXT_DOWN[8] = {0, 0x50, 0x04, 0x68, 0x3B, 0x01, 0x06}; // > press button
byte NEXT_HOLD[8] = {0, 0x50, 0x04, 0x68, 0x3B, 0x11, 0x16}; // > hold button
byte NEXT_REL[8] = {0, 0x50, 0x04, 0x68, 0x3B, 0x21, 0x26}; // > release button
byte PREV_DOWN[8] = {0, 0x50, 0x04, 0x68, 0x3B, 0x08, 0x0F}; // < press button
byte PREV_HOLD[8] = {0, 0x50, 0x04, 0x68, 0x3B, 0x18, 0x1F}; // < hold button
byte PREV_REL[8] = {0, 0x50, 0x04, 0x68, 0x3B, 0x28, 0x2F}; // < release button
byte VOICE_DOWN[8] = {0, 0x50, 0x04, 0xC8, 0x3B, 0x80, 0x27}; // voice press button
byte VOICE_HOLD[8] = {0, 0x50, 0x04, 0xC8, 0x3B, 0x90, 0x37}; // voice hold button
byte VOICE_REL[8] = {0, 0x50, 0x04, 0xC8, 0x3B, 0xA0, 0x07}; // voice release button
byte RT_DOWN[8] = {0, 0x50, 0x03, 0xC8, 0x01, 0x9A, 0x80}; // voice
Для сканирования порта (посмотреть что приходит в ПК) используем Terminal.exe данные должны приходить в таком виде
next____________________________
DOWN 50 04 68 3B 01 06
HOLD 50 04 68 3B 11 16
RELISE 50 04 68 3B 21 26
plus____________________________
50 04 68 32 11 1F
minus___________________________
50 04 68 32 10 1E
prev_____________________________
DOWN 50 04 68 3B 08 0F
HOLD 50 04 68 3B 18 1F
RELISE 50 04 68 3B 28 2F
R/T______________________________
50 03 C8 01 9A 80
Voice____________________________
DOWN 50 04 C8 3B 80 27
HOLD 50 04 C8 3B 90 37
RELISE 50 04 C8 3B A0 07
Теперь назначаем на принятый сигнал комбинации клавиатуры. сделать это можно с помощью программы IR Kay написанной Chip`ом для проекта "управление любым IR Пультом"
единственное что файл Config нужно править руками но это не составит труда.
выглядит он внутри примерно так:
<50046832111F>Key1=49 />
<50046832101E>Key1=50 />
прописываем в ручную коды приходящие от нажатий кнопок руля и код нажатия кнопки.
PS: Благодарим kostya740 за помощь в написании прошивки для Mega, Также efimomax за очень полезные советы и примеры, Chip за софт и не человеческое терпение




 
			
			 
					
						 Re: arduino и  I-BUS
 Re: arduino и  I-BUS
				 
					
					
					
						 Ответить с цитированием
  Ответить с цитированием