вот скетч эмулятора котла BMW. Просто загрузить скетч в голую ардуино, воткнуть в комп и выбрать в WTT ком-порт этой ардуины. После чего выбрать в WTT котел Thermo Top C/Z BMW. и можно диагностировать эмулятор ))
byte otv00[]= {0xC8, 0x38, 0x71, 0x03, 0x01, 0x01, 0x01, 0x0A, 0x16, 0x01, 0xD9, 0x17, 0x01};
byte otv08[]= {0x02, 0x0D, 0x01};
byte otv0401[]= {0x01, 0x07, 0x08, 0x09, 0x18, 0x50};
byte otv0402[]= {0x02, 0x0D, 0x08, 0x06, 0x08, 0x40};
byte otv0403[]= {0x03, 0x02, 0x04, 0x25, 0x01, 0x01};
byte otv0404[]= {0x00};
byte otv05[]= {};
byte otv0B[]= {0x10, 0x3D, 0xff, 0x00, 0x00, 0x50, 0x01, 0x80, 0x2C};
byte otv9402[]= {0x10};
void sendMessage(const byte *command, const size_t size)
{
const byte siZe = size+5;
byte Mes[siZe];
byte Checksum = 0;
for(byte i=0; i<siZe; i++) {
if (i==0) Mes[i] = 0x6B;
if (i==1) Mes[i] = size+3;
if (i==2) Mes[i] = 0x3F;
if (i==3) Mes[i] = 0xA0;
if (i==4) {for (byte t=0; t<size; t++ ) {Mes[i]=command[t]; Checksum^=Mes[i] ;Serial.write (Mes[i]); i++;}}
if (i!=siZe-1) Checksum^=Mes[i];
else Mes[i] = Checksum;
Serial.write (Mes[i]);
}
}
void setup()
{
pinMode (0, INPUT);
}
void loop() {
static uint32_t prev = 0 ;
static bool timer = 0 ;
static bool inita = 0 ;
if (!timer && !inita) {
static bool lasta = 0;
if (!digitalRead(0) && lasta){timer =1 ; prev= millis(); }
lasta = digitalRead(0);
}
if (timer && millis() - prev>290) {prev = millis(); timer=0; inita = 1; Serial.begin (9600, SERIAL_8E1); }
static byte header = 0; // состояние заголовка
static byte message_size = 0; // размер тела принимаемого сообщения, кол-во байт
static byte j = 2; // инкремент
static byte n = 2;
const byte bufsize = 140; // размер буфера принятого сообщения
static byte buf [bufsize] = {0}; // буфер принятого сообщения
static byte checksum = 0; // контрольная сумма входящего сообщения
static uint32_t prevRESETheader=0; // таймер сброса заголовка если в момент приёма сообщения данные оборвались
static bool RESETheader_timer = 0; // таймер сброса заголовка если в момент приёма сообщения данные оборвались
if (inita){
if (Serial.available())
{
// первый старт байт
if (header == 0){buf[0]=Serial.read(); delayMicroseconds(250); Serial.write (buf[0]);
if (buf[0]==0x4F || buf[0]==0x3F){header = 1; RESETheader_timer=1; prevRESETheader = millis(); }
else {header = 0; RESETheader_timer=0;}
}
// длина сообщения
else if (header == 1 ){buf[1]=Serial.read(); delayMicroseconds(250); Serial.write (buf[1]); message_size = buf[1]; if (message_size > bufsize) message_size = bufsize; header = 4;j=2;n=2;checksum = 0;}
// пишем тело сообщения
else if (header == 4 && j< message_size+n) {
buf[j] = Serial.read(); delayMicroseconds(250); Serial.write (buf[j]);
if (j<message_size+n-1) checksum^= buf[j]; // подсчёт КС
if (j==message_size+n-1) header = 5;
j++;}
} // end of Serial.available()
// сообщение приняли, действуем
if (header == 5) {
for(byte i = 0; i<n; i++) checksum^=buf[i]; // прибавляем к контрольной сумме старт байты
// если контрольная сумма верна:
if ( checksum == buf[message_size+n-1]) {
if (buf[2]==0x6B){
if (buf[3]==0x00) {sendMessage(otv00, sizeof (otv00));}
else if (buf[3]==0x08) {sendMessage(otv08, sizeof (otv08));}
else if (buf[3]==0x04 && buf[4]==0x01) {sendMessage(otv0401, sizeof (otv0401));}
else if (buf[3]==0x04 && buf[4]==0x02) {sendMessage(otv0402, sizeof (otv0402));}
else if (buf[3]==0x04 && buf[4]==0x03) {sendMessage(otv0403, sizeof (otv0403));}
else if (buf[3]==0x04 && buf[4]==0x04) {sendMessage(otv0404, sizeof (otv0404));}
else if (buf[3]==0x0B) {sendMessage(otv0B, sizeof (otv0B));}
else if (buf[3]==0x05) {sendMessage(otv05, sizeof (otv05));}
else if (buf[3]==0x94 && buf[4]==0x02) {sendMessage(otv9402, sizeof (otv9402));}
}
}
message_size = 0; header=0; RESETheader_timer=0; j=2; checksum = 0;
}
}
}
А вот и само
описание протокола котла BMW
или вот