Проблема передачи данных с ANDROID на HC-05+UNO

Kreuzkopf
Offline
Зарегистрирован: 08.04.2021

Здравствуйте. Проблема возникла при передаче данных с ANDROID на ARDUINO UNO (PRO MINI) + HC-05. В телефоне приложение сделано в Инверторе, в нем 3 SLIDER и 1 CANVAS. Слайдеры отсылают свои положения в виде трехзначных чисел от 0 до 100 к примеру.

Код ардуины прост:


uint32_t myTimer = millis();          
int serial_val;                                 

void setup() {

  Serial.begin(9600);    
  Serial.setTimeout(2);

}

void loop() {

  if (Serial.available()) {       

    serial_val = Serial.parseInt();     
    myTimer = millis();                 

    Serial.println (serial_val);

    if (millis() - myTimer > 3000) {                 
      myTimer = millis();                              

   }
  }
}

Проблема 1: В монитор порта приходит мусор вида:

510
-28789
505
490
491
480
442
474
19259
263
385
48
3
542
504

трехзначные значения верные, они показывают скольжение слайдера. Откуда появились большие числа и как с ними можно бороться? Причем от канвас их много больше, чем от слайдера.

Проблема 2: после получения 1400 строк данных все соединение рушиться. Либо дисконнект, либо приложение не реагирует. Опытным путем установлено влияние модуля HC-05. Если его переткнуть приложение размораживается. Можно снова установить соединение. Подозреваю что есть переполнение буфера в каком то месте.

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

А что за глубокомыслие в строках №№ 16 и 20-23?

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

delay() нонче не в тренде. Лучше написать 5-10 лишних строчек, но чтобы этого мерзкого delay() в программе не было!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, это бы я понял. Но эти то строки каким боком к делэю-то?

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

ЕвгенийП пишет:

Ну, это бы я понял. Но эти то строки каким боком к делэю-то?

Дык, похоже, у ТС не получилось :)

Kreuzkopf
Offline
Зарегистрирован: 08.04.2021

На счет millis(); не переживайте, там реализована функция выключения моторов по истечению таймера (я эти моторы из когда убрал, чтоб не отвлекали). Таймер сбрасывается каждый раз, когда приходят данные по серийному порту. Данные приходят от программы телефона, либо от действий слайдера или как минимум по таймеру каждую секунду из этой же программы (если слайдеры не трогают). В общем это для того, если теряется соединение блютус с телефоном, то данные не придут и millis() остановит моторы. Я в этом деле не специалист, как смог придумать так и реализовал. В принципе работает. Отследить разрыв соединения по другому я не смог, в инвенторе не очень получается ковыряться. Спасибо что проявили интерес.

    if (millis() - myTimer > 3000) {                   
      myTimer = millis();                                  
      spin_1.write(min_pwm);                         
      spin_2.write(min_pwm);
      spin_3.write(min_pwm);
      stepper.setSpeed(0);
      stepper.runSpeed();
    }

Вопрос по существу остался. Как бороться с мусором в серийном порту. И правильно ли я понимаю, что мне нужно реализовать очистку буфера ардуины функцией read?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Kreuzkopf пишет:

На счет millis(); не переживайте

Да, мы как-то не очень.

Kreuzkopf пишет:

Как бороться с мусором в серийном порту.

Не слать его туда и читать поаккуратнее. Сейчас, если два числа придут в пределах таймаута, они слипнутся в одно.

Kreuzkopf пишет:

правильно ли я понимаю, что мне нужно реализовать очистку буфера ардуины функцией read?

Никто ведь не знает что Вы туда шлёте, так что ХЗ что там надо очищать. Вы бы поставили слепой дамп всего, что пришло и посмотрели бы что приходит. Глядишь и понятнее было бы.

Kreuzkopf
Offline
Зарегистрирован: 08.04.2021

Я не смог понять какие манипуляции тут подразумеваются:

ЕвгенийП пишет:

слепой дамп всего

Но с некоторым усилием удалось решить проблему номер 1, хотя решал вторую. Вот таким кодом (из соседней ветки этого форума)

char Buff[10];
byte iBuff = 0;

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

void loop() {
  if (Serial.available() > 0) {
    char c = Serial.read();
    if (c == '#' ) {
      Buff [iBuff] = 0;
      iBuff = 0;
    }
    else {
      Buff [iBuff++] = c;
      Serial.println (Buff);
    }
  }
}

Андройд ставит знак # после каждого значения и Ардуина точно видит конец пакета. Ни какого мусора в порт не поступает. Я думал что Serial.read() будет вычитывать биты из буфера и проблема 2 решится. Но все осталось на месте. Поступает 1400 пакетов и фриз, возможно проблема в HC-05. Есть варианты как это проверить? Какой еще буфер очистить? Слайдер убивает весь процесс за 30 секунд работы, Канвас в два раза быстрее, соответственно.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, если сейчас мусора нет, то ладно, хотя с трудом верится. Ваш код не может не печатать грязи. Разве что, если сильно повезёт, но при малейшем чихе в программе, грязь всё равно появится. В строке 16 Вы добавляете новый символ в Buff, но не ставите после него символ конца строки ('\0'). Если Вам повезёт и там и так ноль, то строка №17 отработает нормально. А вот если там что-то отличное от нуля, то строка №1 это напечатает и вообще будет печатать всё, что там есть, пока 0 не встретит.

Если у Вас # добавляется в конец числа (а не перед числом ставится) то я бы делал так:

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

void loop(void) {
	static char Buff[10];
	static byte bufPtr = 0;
	
	if (Serial.available()) {
		const char c = Serial.read();
		if (c == '#') {
			Buff [bufPtr] = '\0';
			Serial.print("Получено: ");
			Serial.println (Buff);
			bufPtr = 0;
		} else {
			if (bufPtr < sizeof(Buff)) Buff[bufPtr++] = c;
			else Serial.println("Буфер переполнен");
		}
	}
}

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

Kreuzkopf
Offline
Зарегистрирован: 08.04.2021

Очевидно, ваш код работает стабильнее. Все данные приходят как и задумывалось. Надпись "буфер переполнен" ни разу не появилась. Массив отрабатывает. Спасибо.

Я написал такую штуку чтобы видеть все, что поступает

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

void loop() {
  if (Serial.available()) {
    int c = Serial.read();
    Serial.write (c);
  }
}

Но ничего сверхъестественного там нет, только это

388#462#404#465#430#463#444#465#445#465#435#468#428#469#425#468#419#465#413#468#427#

При всех успехах по прежнему останавливается работа устройства после поступления 1400 строк данных. Запустить заново получается сбросив питание с модуля HC-05, саму ардуину трогать не обязательно.

Может выкинуть это блютус и другой поставить?

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Kreuzkopf пишет:

по прежнему останавливается работа устройства после поступления 1400 строк данных. 

Ну, мы же кода не видели, так что ХЗ

Kreuzkopf пишет:

Может выкинуть это блютус и другой поставить?

Может. Я же говорю, ХЗ

Kreuzkopf
Offline
Зарегистрирован: 08.04.2021

ЕвгенийП пишет:

Ну, мы же кода не видели, так что ХЗ

С момента #8 сообщения код сильно не изменился. Несколько моментов добавил для компиляции. Суть осталась.

char Buff[10];                      
int serial_val;                       
byte iBuff = 0;                     

void setup() {

  Serial.begin(9600);
  Serial.setTimeout(2);

void loop() {

  if (Serial.available() > 0) {   
    const char c = Serial.read();       
    if (c == '#') {        
      Buff [iBuff] = '\0';
      iBuff = 0;
    } 
    else (Buff [iBuff++] = c);
    serial_val = atoi (Buff);   
    Serial.println (serial_val);
    
    switch (serial_val) {
      case ...
      ...

Тем временем, опытным путем установлено... кривая работа приложения в устройстве Android (очевидно Inventor накосячил). Если проверить код ардуино с любым приложением  типа "джойстик" из андройд маркета, то никакой остановки и фриза не наблюдается.

Проблема остановки моего приложения отправляется на другую ветку форума, посвященную Inventor.

Можно считать задачу выполненной. Спасибо всем за содействие.