Парсинг полученных данных из массива

Здравствуйте. На устройство отправляю команду в HEX и получаю ответ в виде строки 020001С1;00102458v. Мне нужно отобразить её в виде 0010245,48. Использовал практически все функции ардуино что нашёл в интернете, но ничего не помогло. Прошу помощи решить эту задачку.
Вот код:

// Подключаем библиотеки:
#include <Wire.h>               // подключаем библиотеку для работы с шиной I2C
#include <LiquidCrystal_I2C.h>  // подключаем библиотеку для работы с LCD дисплеем

byte message[] = { 0x02, 0x00, 0x01, 0x43, 0x30, 0x72 };  // массив HEX <STX><NUL><SOH>C0r

LiquidCrystal_I2C lcd(0x27, 16, 2);  // параметры подключения I2C дисплея

void setup() {
  Serial.begin(9600);  //установим скорость обмена 9600

  lcd.init();           // иницилизация дисплея
  lcd.backlight();      // включаем подсветку дисплея
  lcd.setCursor(0, 0);  // установим курсор
}
void loop() {
  Serial.write(message, sizeof(message));  // отправляем массив HEX <STX><NUL><SOH>C0r
  delay(70);                               // задержка 70м.сек

  if (Serial.available() > 0) {  // если в буфере приёма есть данные

    lcd.clear();                       // чистим дисплей
    lcd.println(Serial.readString());  // выводим байт данных в виде символа, из последовательного порта на LCD дисплей

    delay(70);  // задержка 70м.сек
  }
}

не видно попыток обработки приёмного буфера и, читать и выводить в цикле, пока в буфере приёмном что-то есть

если это про код, что ниже - то там используется дай бог сотая часть функций ардуино…
И, главное, там нет ни малейшего намека на обратботку полученной строки, как уже заметили выше.

Здравствуйте. Вы правы, Здесь опубликован чистый код без обработки для ознакомления.

мы ознакомились.
Теперь выложите тот, который имеет отношение к вопросу.

3 лайка

Пытаюсь сделать так, но получаю сообщение об ошибке “Compilation error: cannot convert ‘String’ to ‘char*’ for argument ‘1’ to ‘char* strtok(char*, const char*)’”

// Подключаем библиотеки:
#include <Wire.h>               // подключаем библиотеку для работы с шиной I2C
#include <LiquidCrystal_I2C.h>  // подключаем библиотеку для работы с LCD дисплеем
#include <stdio.h>
#include <string.h>

byte message[] = { 0x02, 0x00, 0x01, 0x43, 0x30, 0x72 };  // массив HEX <STX><NUL><SOH>C0r

LiquidCrystal_I2C lcd(0x27, 16, 2);  // параметры подключения I2C дисплея

String data = Serial.readString();
String name;
const char delimiter =";";

void setup() {

  name = strtok(data, delimiter);

  Serial.begin(9600);  //установим скорость обмена 9600

  lcd.init();           // иницилизация дисплея
  lcd.backlight();      // включаем подсветку дисплея
  lcd.setCursor(0, 0);  // установим курсор

 




}
void loop() {
 
  Serial.write(message, sizeof(message));  // отправляем массив HEX <STX><NUL><SOH>C0r
  delay(70);                               // задержка 70м.сек

  if (Serial.available() > 0) {  // если в буфере приёма есть данные

    lcd.clear();                       // чистим дисплей
    lcd.println(data);  // выводим байт данных в виде символа, из последовательного порта на LCD дисплей

    delay(70);  // задержка 70м.сек
  }
}

Пытаюсь

А в этом варианте ошибок нет, но ардуино висит и ничего не отображает

// Подключаем библиотеки:
#include <Wire.h>               // подключаем библиотеку для работы с шиной I2C
#include <LiquidCrystal_I2C.h>  // подключаем библиотеку для работы с LCD дисплеем
#include <stdio.h>
#include <string.h>

byte message[] = { 0x02, 0x00, 0x01, 0x43, 0x30, 0x72 };  // массив HEX <STX><NUL><SOH>C0r

LiquidCrystal_I2C lcd(0x27, 16, 2);  // параметры подключения I2C дисплея

String data = Serial.readString();
const char delimiter = ";";

void setup() {

  Serial.begin(9600);  //установим скорость обмена 9600

  lcd.init();           // иницилизация дисплея
  lcd.backlight();      // включаем подсветку дисплея
  lcd.setCursor(0, 0);  // установим курсор
}
void loop() {

  char str_array[data.length()];
  data.toCharArray(str_array, data.length());
  char token = strtok(str_array, delimiter);

  Serial.write(message, sizeof(message));  // отправляем массив HEX <STX><NUL><SOH>C0r
  delay(700);                              // задержка 70м.сек

  if (Serial.available() > 0) {  // если в буфере приёма есть данные

    lcd.clear();         // чистим дисплей
    lcd.println(token);  // выводим байт данных в виде символа, из последовательного порта на LCD дисплей

    delay(700);  // задержка 70м.сек
  }
}

что у вас в 11 строке? почему вы читаете строчку из Сериала где-то за пределами луп и сетап функций?
И что вы пытаетесь сделать в строчках 24-26? Строку обработать? Да вы же ее не прочитали еще!

Все чтение и обработка строк должны быть внутри цикла

строка 31

1 лайк

Сделал, теперь я получаю один не читабельный столбец из четырёх “_” в начале строки и больше ничего нет.

// Подключаем библиотеки:
#include <Wire.h>               // подключаем библиотеку для работы с шиной I2C
#include <LiquidCrystal_I2C.h>  // подключаем библиотеку для работы с LCD дисплеем
#include <stdio.h>
#include <string.h>

byte message[] = { 0x02, 0x00, 0x01, 0x43, 0x30, 0x72 };  // массив HEX <STX><NUL><SOH>C0r

LiquidCrystal_I2C lcd(0x27, 16, 2);  // параметры подключения I2C дисплея

void setup() {

  Serial.begin(9600);  //установим скорость обмена 9600

  lcd.init();           // иницилизация дисплея
  lcd.backlight();      // включаем подсветку дисплея
  lcd.setCursor(0, 0);  // установим курсор
}
void loop() {

  Serial.write(message, sizeof(message));  // отправляем массив HEX <STX><NUL><SOH>C0r
  delay(700);                              // задержка 70м.сек

  if (Serial.available() > 0) {  // если в буфере приёма есть данные

    String data = Serial.readString();
    char *token;
    const char delimiter = ";";
    char str_array[data.length()];
    data.toCharArray(str_array, data.length());
    token = strtok(str_array, delimiter);

    lcd.clear();         // чистим дисплей
    lcd.print(token);  // выводим байт данных в виде символа, из последовательного порта на LCD дисплей

    delay(700);  // задержка 70м.сек
  } else {
    lcd.clear();  // чистим дисплей
    lcd.print("Not connect!");
  }
}

На Си есть рабочий код. Не могу повторить это в ардуино.

ISR(USART_RXC_vect)
{
        char status;
        char data;
	status=UCSRA;
	data=UDR;
	if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
	{
		if (data ==';')
		{
			rx_wr_index=0;
			read_enable = 1;
 
		}
 
		if((data == 'v')&&(read_enable == 1))
		{
				read_enable = 0;
				lcd_out = 1;				
		}
 
		if (read_enable == 1)
		{
			rx_buffer[rx_wr_index++]=data;
			if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
 
			if (++rx_counter == RX_BUFFER_SIZE)
			{
				rx_counter=0;
				rx_buffer_overflow=1;
			}
 
		}
 
	}	

}

замените свою 34 строку вот на эти две и покажите что получилось

if ( token != NULL) lcd.print(token); 
else lcd.print("Not found!");

и на будущее - всегда проверяйте возвращаемое значение strtok, прежде чем использовать.
И у других функций тоже

2 лайка
// Подключаем библиотеки:
#include <Wire.h>               // подключаем библиотеку для работы с шиной I2C
#include <LiquidCrystal_I2C.h>  // подключаем библиотеку для работы с LCD дисплеем
#include <stdio.h>
#include <string.h>

byte message[] = { 0x02, 0x00, 0x01, 0x43, 0x30, 0x72 };  // массив HEX <STX><NUL><SOH>C0r

LiquidCrystal_I2C lcd(0x27, 16, 2);  // параметры подключения I2C дисплея


char *token;
const char delimiter = ";";


void setup() {

  Serial.begin(9600);  //установим скорость обмена 9600

  lcd.init();           // иницилизация дисплея
  lcd.backlight();      // включаем подсветку дисплея
  lcd.setCursor(0, 0);  // установим курсор
}
void loop() {


  Serial.write(message, sizeof(message));  // отправляем массив HEX <STX><NUL><SOH>C0r
  delay(700);                              // задержка 70м.сек

  if (Serial.available() > 0) {  // если в буфере приёма есть данные
    String data = Serial.readString();
    char str_array[data.length()];
    data.toCharArray(str_array, data.length());
    token = strtok(str_array, delimiter);
    lcd.clear();         // чистим дисплей
    //lcd.println(token);  // выводим байт данных в виде символа, из последовательного порта на LCD дисплей

if ( token != NULL) lcd.print(token); 
else lcd.print("Not found!");

    delay(700);  // задержка 70м.сек
  } else {
    lcd.clear();  // чистим дисплей
    lcd.println("Not connect!");
  }
}

Получаю это.

Это то что прилетает:
Снимок экрана 2022-11-29 203824
Здесь в HEX
Снимок экрана 2022-11-29 203852
Пытаюсь сделать так

Но между 5 и 4 мне ещё нужно точку добавить..

Во-первых, strtok() работает только с текстовыми данными, а у вас первые два байта явно служебные. Если это сообщение какого-то протокола, типа модбас - то его и нужно сначала обработать как модбас, извлечь из него данные - вашу строчку, а уже потом искать в ней какие-то поля.
При такой обработке неплохо еще проверить сообщение на валидность - найти верный заголовок, посчитать контрольную сумму, если есть.

А вы как-то очень по-простому - выдрали символы из пакета и хотите их показывать. Так не надо делать. Завтра у вас строчка чуть поменяется и все это перестанет работать.

В том то и проблема что я без понятия как это сделать. Уже не одну неделю сижу в интернете и ищу описание хоть немного похожего случая. :frowning:

А устройство секретное? Мануал у него есть? В мануале обычно или есть название протокола или описаны правила формирования строки ответа.

Устройство не секретное, но нет мануала и описание протокола.

Можете сделать так, как в найденном вами где-то Си-коде - просто тупо искать в сообщении точку с запятой и после нее извлекать номер.
Но без знания протокола я бы вам не советовал - на этом сообщении сработает, а на следующем - может и нет

Информация по этому коду запроса всегда однотипная, меняются только цифры после ; и до v.
По этому мне нужно “вычистить” её и привести к виду 001024,58

Я так понял, что выводить что-либо вы можете только на LCD экранчик? Или есть возможность вывести в нормальный монитор порта?