Serial через терминал работает, а через bluetooth нет...

4ort
Offline
Зарегистрирован: 02.06.2012

День добрый!

Пробую связать arduino uno с компом, и такой странный глюк.
Вот тестовый скетч:
 

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

int inSize=0; 						// Переменная которая будет содержать размер буфера
char str[128]; 						// Так как типа string тут нет, будем использовать массив символов

void loop(void) {

  inSize=0; 						// Сбрасываем переменную
  memset(str, '\0', 128); 			// Очищаем массив

  if (Serial.available() > 0)
  {
    delay(200); 					// Ждем, для того, чтобы пришли все данные
    inSize = Serial.available(); 	// Получаем длину строки и записываем ее в переменую
    for (int i = 0; i < inSize; i++)
    {
      str[i] = Serial.read(); 		// Читаем каждый символ, и пишем его в массив
    }

    // Сравнять массив с строкой будем используя функцию strcmp
    if (strcmp(str, "gett1") == 0) 
    {
      Serial.println("command gett1 ok");
    }
    else if (strcmp(str, "gett2") == 0) 
    {
      Serial.println("command gett2 ok");
    }
    else if (strcmp(str, "geth1") == 0)
    {
      Serial.println("command geth1 ok");
    }
    else
    {
      Serial.print("Error command! ");
      for (int i = 0; i < inSize; i++)
      {
        Serial.print(str[i]); 
      }
      Serial.println(); 
    }  
  }
}

Например, посылая команду "gett1" через терминал, я получаю нормальный ответ "command gett1 ok", но отсылая её-же через блютус, получаю ответ "Error command! gett1", то-есть я вижу в конце переданную команду, значит она нормально принялась, но почему-то не распознана.

В чем тут может быть дело?

Блютус модуль обычный, на BC417, работает нормально, простые команды типа цифр передаются и распознаются нормально - а со строковыми такой косяк непонятный...

 

leshak
Offline
Зарегистрирован: 29.09.2011

 Возможно в delay(200);

Может не успевает прийти вся строка целиком. А может наоборот - успевает о блюпупа не хватает размера приемного буффера что-бы вместить всю строку целиком.

Попробуйте выкинуть delay, и, вместо него перед строкой 19 (внутри цикла, перед вычитыванием) добавить

while(!Serial.available()){} ;// ждем прихода следующего символа

Даже если это "Не поможет", IMHO в любом случае так надежней будет чем "магические задержки".

И еще, убедитесь, что когда вы отсылаете строку с компа, вы случайно не добавляете к ней что-то типа \r, \n и т.п.

 

leshak
Offline
Зарегистрирован: 29.09.2011

 И еще, там где вы делаете вывод ошибки. Выведите не каждый принятый символ,  а его код в виде HEX. Я там же выведите покодово ту строку с которой стравниваете (предварительно положите ее в переменную, сравнение тоже делаейте с переменной).

В таком случае в "найди разницу" - будет легче играть.  Например буква c. Русская и латинская. Выглядит одинаково, на клаве в одном месте (запросто перепутать), а пока кодами не выведешь - фиг догадаешься почему одинаковые "на глаз" строки не хотят нормально совпадать ;)

4ort
Offline
Зарегистрирован: 02.06.2012

leshak, спасибо! Действительно, с hex выводом стало видно, что через блютус добавлялись символы 0xD 0xA - по умолчанию в Termite, через который я с блютусом работал, было включено "Append CR+LF" - убрал - теперь нормально работает)

leshak
Offline
Зарегистрирован: 29.09.2011

 А вы попроубйте сей "недуг" в "подвиг" определить :)

Вы в терминалах длинну строки (inSize) руками вводите? Если да, то можно от этого отказатся. Включить добавление CR и определять конец строки по нему (читать в str[i], пока принятый байт не будет равен \r)

4ort
Offline
Зарегистрирован: 02.06.2012

Нет, почему же руками?
Длину строки получаю так - 16-я строка:

inSize = Serial.available();    // Получаем длину строки и записываем ее в переменую

а с добавлением в конец \r надо подумать, как лучше сделать - вообще мне надо получать и отправлять данные с датчиков температуры и влажности, в виде: "команда (set/get)", имя датчика (t1... t5, h1...h3) и значение в диапазоне (-10...+100).
Получается что длина "команда+имя" всегда одинакова, а всё что далее будет значением датчика - получается \r и не нужно.

leshak
Offline
Зарегистрирован: 29.09.2011

4ort пишет:

Нет, почему же руками?
Длину строки получаю так - 16-я строка:

inSize = Serial.available();    // Получаем длину строки и записываем ее в переменую

 

 

Как вы ее получаете - это и по коду видно :), вопрос был в том "как вы ее послаете". Если руками - то можно перейти на "маркер конца строки".

4ort пишет:

а с добавлением в конец \r надо подумать, как лучше сделать - вообще мне надо получать и отправлять данные с датчиков температуры и влажности, в виде: "команда (set/get)", имя датчика (t1... t5, h1...h3) и значение в диапазоне (-10...+100).
Получается что длина "команда+имя" всегда одинакова, а всё что далее будет значением датчика - получается \r и не нужно.

Да. Если длинна команды всегда одна и та же - это упрощает. Можно ее просто зашить в код.

Я бы еще добавил какой-то маркер перед командой. Например звездочку (или три).  Что-бы ардуина четко могла знать когда "команда начала передаватся". Могут же быть помехи, часть байтов - может потерятся.....

Поэтому, в идеале, должно быть

  1. Маркер начала команды. Только после его получения - начинаем читать байты-данные. До этого - все игнорируем.
  2. Таймаут. Если после маркера не пришло нужное количество байт в течении определенного времени- считаем что команды небыло.
  3. В конце (или начале) команды можно передавать контрольную сумму. Что-бы знать принялась команда правильно или вкрались ошибки.

На часть пунктов, конечно можно забить, в зависимости от того "как ведет себя канал".

 

 

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

4ort пишет:

Нет, почему же руками?
Длину строки получаю так - 16-я строка:

inSize = Serial.available();    // Получаем длину строки и записываем ее в переменую

Так вы получаете количество символов, находящихся в приемном буфере на момент исполнения этой команды. А если пришли еще не все пересылаемые символы? А если произошла помеха и один из сиволов не был принят правильно и, соответственно, не загрузился  вбуфер? А если ... еще с десяток причин?

leshak
Offline
Зарегистрирован: 29.09.2011

step962 пишет:

4ort пишет:

Нет, почему же руками?
Длину строки получаю так - 16-я строка:

inSize = Serial.available();    // Получаем длину строки и записываем ее в переменую

Так вы получаете количество символов, находящихся в приемном буфере на момент исполнения этой команды.

А и вправду. Проглядел. Что-то подумал, что первым байтом, со стороны компа, посылается длина строки. Поэтому и спрошал "руками посылаете или нет". А так - да, конечно. Будет работать правильно при удачном положении звезд.