Ком-порт, отправка полного буфера

werxes
Offline
Зарегистрирован: 24.06.2013

Такой вопрос, хочу подцепить Ардуино к мозгу своей машине, по RS232. Протокол описан.

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

Прснифил КОМ порт, вот что я нашел:

Виндовая программа отправляет команду одной(!!!) строкой, пример команды 0х20, 0х05, 0х00, 0х10, 0хСВ

Вот как выглядит ЛОГ видовой программы(пробовал даже свою написать, тоже все работает, использую функцию WINAPI WriteFile)

 

То есть записть в Serial, одит одной стракой.

А вот код пршифки
 

byte cmd[5]={0x20,0x05,0x00,0x10,0xCB};


void setup() {               
  Serial.begin(9600);
}

void loop() {

  Serial.write(cmd,5);
  int bytesSent = Serial.write(cmd,sizeof(cmd));

}

И вот что я имею в ЛОГе

Капнул в HardwareSerial.cpp, заметил что все Serial.Write(DATA, size), Serial.Print(DATA), наследуют функцию Serial.Write(CHAR), то есть получается действительно что Ардуино отправляет по байту.

Можно это как-то исправить? Может есть примеры использовать IO.h от AVR, и работать с прерываниями?

step962
Offline
Зарегистрирован: 23.05.2011

werxes пишет:

Капнул в HardwareSerial.cpp, заметил что все Serial.Write(DATA, size), Serial.Print(DATA), наследуют функцию Serial.Write(CHAR), то есть получается действительно что Ардуино отправляет по байту.

Можно это как-то исправить? Может есть примеры использовать IO.h от AVR, и работать с прерываниями?

Любое устройство отправляет информацию в Serial по байту. Более того - обмен по последовательному каналу осуществляется побитово. Деление на строки осуществляется отправкой спец. символов.

Поэтому изучайте дальше протокол - где-то вы от него все-таки отклоняетесь.

maksim
Offline
Зарегистрирован: 12.02.2012

И вашей программой и ардуиной и всегда и везде отправляется по одному 'байту. Потому что это UART. А вот то что ваша программа и ЭБУ считает признаком конца команды из лога не видно. Но так как в коде видно, что вы ничего не отправляете лишнего, то можно предположить, что концом команды является переданный 'байт - 8 бит, 1 стоповый бит, без проверки четности. А значит нужно выявить а с какими же параметрами 'байт не является признаком конца команды.

'байт - в данном случае от 5 до 9 бит.

http://arduino.cc/en/Serial/Begin

например предположим что это 8 бит, 2 стоп, без пч:

byte cmd[5] = {0x20,0x05,0x00,0x10,0xCB};

void setup() 
{               
  Serial.begin(9600);
}

void loop() 
{
  Serial.begin(9600, SERIAL_8N2); // передаем 4байта команды с двумя стоповыми битами
  Serial.write(cmd, 4);
  Serial.begin(9600, SERIAL_8N1); // и последний байт с одним
  Serial.write(cmd[4]);
  delay(1000);
}

Это было первое предположение. 

Второе мое предположение - задействованы не только линии RX и TX, и признаком начала/конца команды может служить например вывод DTR.

werxes
Offline
Зарегистрирован: 24.06.2013

Дали пищю для размышления!!!

maksim пишет:

Второе мое предположение - задействованы не только линии RX и TX, и признаком начала/конца команды может служить например вывод DTR.

Теоретически это очень возможно, так как у меня собраны 2 виртуальные КОМ порта(null modem).

На одном конце слушает программа эмулятор

На другом конце 2 варианта:

    1) Другая Вин апликуха - с которой все работает

    2) Ардуино, и ту я эмулирую через Протеус.

А возможно потому что, в виртуальный КОМ портах может эмулироваться все линий(не только RX и TX), конечно если же эти линий используются в Вин программах. Это я про штудирую, в своих Вин программах, так как я использую сторонние классы.

Но есть сомнения по этому поваду, так как на боевой среде, то есть ВинАпликуха -> КОМ -> K-line(который работает только 3 проводах(RX,TX,GND)) - все работает.

Максим, можете более детально объяснить по поводу первого пункта

Как сделать отладку, какие параметры менять???

Доп инфа: Вот что выдает моя видовая апликуха:

Line:   1: BYTES:  1:  20
Line:   2: BYTES:  4:  050010CB
Line:   3: BYTES:  1:  20
Line:   4: BYTES:  4:  050010CB
Line:   5: BYTES:  1:  20
Line:   6: BYTES:  4:  050010CB

То есть, после первого байта(0х20) - конец строки. Потом в след идут еще 4 байта.

maksim
Offline
Зарегистрирован: 12.02.2012

  Это откуда?

Line:   1: BYTES:  1:  20
Line:   2: BYTES:  4:  050010CB
Line:   3: BYTES:  1:  20
Line:   4: BYTES:  4:  050010CB
Line:   5: BYTES:  1:  20
Line:   6: BYTES:  4:  050010CB

werxes
Offline
Зарегистрирован: 24.06.2013

 

Вот как раз то что словил Снифер:

 

werxes
Offline
Зарегистрирован: 24.06.2013

Вот схема:

WinApp -> COM2 <----NULLMODEM ----> COM3 -> Arduino

 

Это лог со стороны Win программы, то есть как Win програма принала команду.

werxes
Offline
Зарегистрирован: 24.06.2013

Жалко что в этом Снифере не видно что является конец строки. Понятно что это может быть не байт а параметры ком порта.

Хотя при коннекте вроде как видны некие параметры, попробую сделать  лог и сравнить.

А если у Вас есть идеи дайте знать.

__Alexander
Offline
Зарегистрирован: 24.10.2012

та не должно там быть признака конца строки (0x20 это ващето пробел). ее концом является контрольная сумма (наверное). скорее всего это определено таймаутами снифера. я бы забил, и проверял бы конкретно на авто. как и делал в свое время.

werxes
Offline
Зарегистрирован: 24.06.2013

Лог подключения Ардуино

http://astromoldova.com/arduino/conect_Arduino.png

 

 

 

Лог подключения Win програмы

http://astromoldova.com/arduino/conect_Windows.png

 

не очень удобно для сравнения, но гляньте плиз. Можето что бросеться в глаза.

 

Алексдр, в том то и дело что не работает. Я отправляю эту команду 5 байт(20, 05, 00, 10, СБ), и в ответ получаю этуже строку, видимо это некий эхо.

 

 

werxes
Offline
Зарегистрирован: 24.06.2013

Есть еще одно объяснение, почему не зарабатало на боевой среде.

Машина работает на К-лайн сигналах, я спаял самую просту схему КОМ <-> Kline переходник, а вот с КОМ я брал RX и TX и в Arduino Mega в Serial1. Если переходник рабочий, а он рабочий, виндовая програма подключаеться и работает, то значит на КОМ напряжение +/- 12В, а я его в Ардуино... страно что плата не сгорела.....

maksim
Offline
Зарегистрирован: 12.02.2012

Это не еще одно, а самое первое почему не заработало. RS-232 это не есть UART TTL.

werxes
Offline
Зарегистрирован: 24.06.2013

Закажу себе такую штуку, потом отпишусь!

В любом случае спасибо, за помощь!

__Alexander
Offline
Зарегистрирован: 24.10.2012

а переходник на какой мс сделан? и в к-лайн, как не удивительно, но эхо должно быть, т.к. прием/передача происходит на одной линии.

werxes
Offline
Зарегистрирован: 24.06.2013

Да там 2 транзистора и пару резисторов.

Вот схема:

__Alexander
Offline
Зарегистрирован: 24.10.2012

этот работающий 100%. сам собирал.  для подключения к ардуине достаточно R3 подтянуть к 5В, а не к 12. ща применяю для этих целей l9637, что и вам рекомендую.

werxes
Offline
Зарегистрирован: 24.06.2013

Сейчас l9637, у меня нет. Но обезательно приобрету!

Просто запитаь от 5В?

Или как на схеме:

 

__Alexander
Offline
Зарегистрирован: 24.10.2012

yes. только проверте теперь порты, может уже спалили и придется на другие вешать.

werxes
Offline
Зарегистрирован: 24.06.2013

Так просто запиать от 5 вольт, или пере-паять схему?

__Alexander
Offline
Зарегистрирован: 24.10.2012

на схеме вы правильно указали. R3 на 5В.

werxes
Offline
Зарегистрирован: 24.06.2013

Понял спасибо!

werxes
Offline
Зарегистрирован: 24.06.2013

А вот такую МС не прбовали, по идее ничего не надо кроме нее

 

__Alexander
Offline
Зарегистрирован: 24.10.2012

пробовал. это тоже самое что 9637, только уже достать проблематично.

maksim
Offline
Зарегистрирован: 12.02.2012

Не будет работать эта схема просто так

ибо еще раз повторюсь:

maksim пишет:

RS-232 это не есть UART TTL.

Потому как у RS-232 логическая 1 это -12 вольт (-5вольт) и логический 0 это +12 вольт (+5вольт), в то время как у UART TTL логическая 1 это +5 вольт (+3,3вольт) и логический 0 это 0 вольт.

Тоесть сигналы надо еще инвертировать, что бы эта схема заработала.

werxes
Offline
Зарегистрирован: 24.06.2013

Я перепаивать эту схему не буду, так как она рабочая, просто вот спаяю переходник RS232 - TTL

Например такая пойдайдет???

maksim
Offline
Зарегистрирован: 12.02.2012

На этой схеме как то криво питание подключается, если эквивалентна этой то пойдет

 

__Alexander
Offline
Зарегистрирован: 24.10.2012

для отладки на ПК и на ардуине, лучше (и безопаснее) иметь два разных адаптера. Тот что на МАХ232 и транзисторах применить к ПК. А для ардуино использовать тоже распространенную схему

и так ее переделать под ардуино

1533лн1 это буржуйская 74HC04. Транзистор можно из первой схемы BC945.

werxes
Offline
Зарегистрирован: 24.06.2013

Парни, спаял вот такой переходник:

Работает только отправка данных, с Ардуино(Tx), а вот Rx нет. Скорее я спалил когда втыкал прям из машины в Ардуино(там же +/- 12В), но может что то не до паял(хотя перепровелил несколько раз).

Вопрос: Можно ли проверить этот переходник на Tx0 и Rx0, выводы есть, но походу этиже выводы используються и в USB.

Ардуино прошиваеться, да и проверял простой прошивкой типа эхо.

 

maksim
Offline
Зарегистрирован: 12.02.2012

Если дуина шьется значит ничего вы не спалили. А как вы определили что Rx не работает? Проверить преобразователь просто, замкните в разъеме DB-9 (СОМ-порт) 2 и 3 выводы и проверяете - что отправляете должно возвращаться.

werxes
Offline
Зарегистрирован: 24.06.2013

Значит на выше указоной схеме(RS232 <-> TTL) замыкаю на RS232, пин 2 с 3.

Прошиваю следющей прошивкой:

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

byte cmd[2]={0x20,0x05};
byte buffer[2];
unsigned int cnt = 0;

void setup() {               
  Serial1.begin(9600);
  lcd.begin(16, 2);
}

void loop() {
  cnt = 0;
  Serial1.write(cmd,sizeof(cmd));

  cnt = Serial1.available();

  for (int i=0; i < cnt; i++){
       buffer[i] = Serial1.read();
  }
 
  lcd.setCursor(0,0);
  // Вывод количество принятых байтов
  lcd.print(cnt);

  lcd.setCursor(10,0);
  // Вывод первого байта
  lcd.print(buffer[0],HEX);

  delay(300);
 }

На дисплее должно получить 2 значения, количество принятых байтов(2), и значение первого принятого байта(20). Правильно, ничего я не напутал?

PS: проверял аналогичной прошивкой, переменная cnt(количество принятых байтов) = 0. Хотя снифер показывал что компьютер отправлял данные.

werxes
Offline
Зарегистрирован: 24.06.2013

Сразу и отчитываюсь, Arduino + переходник(TTL-RS232) рабочий, то есть Rx и Tx рабочии.

Буду дальше проверять почему при общений с компютером не работает прием данных с компютера(Rx).

werxes
Offline
Зарегистрирован: 24.06.2013

Как на схеме я подтянул к Компютеру только Rx, Tx и GND.  Вот как у меня

 

Но может нужно замкнуть и другие контакты как NULL Modem кабеле?

???

__Alexander
Offline
Зарегистрирован: 24.10.2012

ниче больше не надо. попробуйте без ардуины замкнуть 2 и 3 на этом кабеле. эхо есть?

werxes
Offline
Зарегистрирован: 24.06.2013

Не люблю задавать глупые вопросы, но вот что у меня:

Эксперемент 1:

Arduino + Переходник, замкнул Rx c Tx - работает. Вот код:

#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
byte cmd[1] = {0x71};
byte buffer[1] = {0x10}; // заплнил какимто значением
unsigned int cnt = 0;
int inByte = 0;
	 
void setup() {              
  Serial1.begin(9600);
  lcd.begin(16, 2);
}
	 
void loop() {

  Serial1.write(cmd,1); // просто отправляем данные

  int cnt = Serial1.available(); // получем данные
  
  for (int i=0; i<cnt; i++){
    buffer[i] = Serial1.read(); //считываем с буфера
  }
  
  lcd.setCursor(0,0);
  lcd.print(buffer[0],HEX); //если данные получили то вывод 71, если ничего то 10.
  
  delay(500);

}

Эксперемент 2:

Отдельно врубил Нулл Кабель, замкнул Rx(3) c Tx(2), запустил Putty - и все работает(то есть текст который вбиваю в окно пути сразу и выводиться в окно).

 

Эксперемент 3:

А вот Ардуино ---> переходник ---> PC, нет. С этожей прошивкой, просто в Putty вбиваю тест, ардуино молчит, хотя окно заполняется данными с Ардуино.

 

Бред сивой кобылы!

maksim
Offline
Зарегистрирован: 12.02.2012

А если PC  --->  переходник и замкнуть RX и TX TTL - то есть те выводы что вы к дуине подключаете, то эхо в Putty возвращается?

werxes
Offline
Зарегистрирован: 24.06.2013

НЕТ.

Питание дал на микруху(+5 и GND), от тогоже ардуино, но только те выводы которые должны быть в дуине, из переходника - замкнул. Эхо нет. Скорее я что-то не до паял, либо что-то пережег.

 

werxes
Offline
Зарегистрирован: 24.06.2013

Парни, извините что вас дергал напрастно.

Не допаял землю к одной ножке, поэтому шло только в одну сторону. Сейчас все работает.

И на машине проверил, тоже все работает, довлен как слон!

Скоро будет собственый бортовой компютер для Хонды!

Сейчас пока пишу для двух срочного мониторчика, планирую заказать 2.8 TFT, с ним кто-то работал? Процесор адушки осилит графику?

__Alexander
Offline
Зарегистрирован: 24.10.2012

работали. но не расскажу. )

werxes
Offline
Зарегистрирован: 24.06.2013

Да, лучше один раз увидеть чем 100 раз услышать, спасибо за фотки. Главное что адушка может общяться с мозгами машины, дальше дело техники!

werxes
Offline
Зарегистрирован: 24.06.2013

Александр вопрос скорее Вам, так как у Вас есть опыт в этих делах.

Имеется глюк, скажем ECU машины принимает 3 команды. Так вот если в Скетче, работаю только с одной командой то все ок, как только пытаюсь в цикле запустить 2 команды, чухню получаю.

Пример, есть 3 команды
1. 20,05,00,10,CB   Ответ, 24 байта, тут есть ответ: обороты, скорость
2. 20,05,10,10,BB   Ответ, 24 байта, Температура, лямнда
3. 20,05,10,10,AB   Ответ, 24 байта, время впрыска

Так вот если запрашиваю только одну команду, причем любую(!, из трех) то все работает.

Вот код:


#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


const unsigned int BUFFER_SIZE = 5;
byte cmd_01[CMD_SIZE]={0x20,0x05,0x00,0x10,0xCB}; //ECU Команда 01
byte cmd_02[CMD_SIZE]={0x20,0x05,0x10,0x10,0xBB}; //ECU Команда 02

unsigned int pause = 300; // пауза междо запросами, вообще не знаю нужно ли.

const unsigned int BUFFER_SIZE = 24; //Ответ обычно 24 байт
byte buffer_01[BUFFER_SIZE];   // Буфер чтения команды 01
byte buffer_02[BUFFER_SIZE];   // Буфер чтения команды 02

unsigned int cnt = 0;

unsigned int rpm = 0;
double volt = 0;

void setup() {               
  Serial1.begin(9600);
  lcd.begin(16, 2);

}

void loop() {
/*
  cnt = 0;
  Serial1.write(cmd_01,CMD_SIZE);      // Отправка команды 01
  cnt = Serial1.available();           // cnt должен быть 24
  for (int i=0; i < cnt; i++){
       buffer_01[i] = Serial1.read();  //заполняем  буфер1
  }
  delay(pause);
*/
  
  cnt = 0; 
  Serial1.write(cmd_02,CMD_SIZE);      // Отправка команды 0й
  cnt = Serial1.available();           // cnt должен быть 24
  for (int i=0; i < cnt; i++){
       buffer_02[i] = Serial1.read();  //заполняем  буфер2
  }
  delay(pause);


//  rpm = 1875000/((int)buffer_01[7] *256 + (int)buffer_01[8]+1); // формула оборотов
  volt = (int)buffer_02[14]/10.45;                              // формула напряжения



  lcd.clear(); 
/*
  lcd.setCursor(0,0);  
  lcd.print(rpm);              // вывод оборотов
*/
  lcd.setCursor(0,1);  
  lcd.print(volt);             // вывод напряжения


}

Так вот если раскоментировать, то ничего не будет работать.

Есть 2 подозрения, что:

1. надо утсновть некий специальный режим COM порта, на адушке

2. может не првельно я читаю, то есть возможно надо делать еще дополнительные проверки, при чтение COM порта, а ля http://forum.arduino.cc/index.php?PHPSESSID=mkbcr82vkf4tfhqrgujsq8je02&topic=45166.30

ПС: линк на описания протокола: http://hondamotor.ru/board/index.php?showtopic=114012

Есть какие либо идеи?

 

werxes
Offline
Зарегистрирован: 24.06.2013

Решил, добавил дополнительные проверки для получение данных.

werxes
Offline
Зарегистрирован: 24.06.2013

гыгыгы http://www.youtube.com/watch?v=kxEJLju9P7U&feature=youtu.be

 

За местный диалект извиняйте!