Раскодировать текст при передаче через nrf24l01

jakob291
Offline
Зарегистрирован: 06.01.2013

Добрый день.

Когда-то не очень давно дали мне хороший код, помогающий модулям nrf работать в двух режимах. Я успешно его применял, не заморачиваясь насчет букв (передавал температуру цифрами). Потом только буквы. Попытался передавать смешанные сообщения... и нашел проблему. Проблема следующая: это код стационарного (постоянно подключенного к компу) устройства, которое я хочу научить интерпретировать сообщения вида: "tok 20 14" (запрос понятен. требуется температура. температура 20,14 градусов цельсия) наряду с обычными сообщениями, содержащими только текст.

if(radio.available())
{
    char data[128] = "";
    radio.read(data, 128);
    Serial.println("receiving");
    
      for (int i=1;i<128;i++)
      {
        if (data[i] != 0)
        {
        Serial.print(data[i]);
        }
      }
}

чтобы нормально декодировался текст, data[] делаем массивом символов, но при этом цифры интерпретируются как код символов. Чтобы нормально декодировать цифры, делаем data[] массивом байт, при этом текст тоже декодируется как набор байт.

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

Спасибо.

 

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

Во-первых, совершенно не ясно зачем и как вы пытаетесь читать 128 байт, так как максимальный размер передаваемого пакета составляет 32 байта, а то что свыше просто обрезается.
Во-вторых, прочтите что написали и сформулируйте вопрос, потому как совершенно не понятно чего хотите.

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

maksim пишет:

Во-первых, совершенно не ясно зачем и как вы пытаетесь читать 128 байт, так как максимальный размер передаваемого пакета составляет 32 байта, а то что свыше просто обрезается.

32 байта - это что? Длина буфера или определение протокола?

Если длина буфера, то это не является ограничением для длины принимаемого пакета - читайте сколь угодно длинные последовательности. Главное успевайте делать это вовремя.

 

jakob291
Offline
Зарегистрирован: 06.01.2013

Попробую)

128 возникло в ходе экспериментов, про ограничения пакета не знал.

Хочу передать и принять пакет, содержащий и текст и числа, чтобы текст в Serial monitor был текстом, а числа - числами (и с ними можно было бы провести арифметические операции)

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

arr[0]: Unknown command

arr[1]:

arr[2]:

*Получили сообщение о том, что команду система не поняла*

 

arr[0]: Readings correct

arr[1]: 25

arr[2]: 55

*Получили сообщение с текущей температурой*

Все неудобство в том, что radio.write и radio.read пользовательскую структуру не примут

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

Вы бы указали, какими библиотеками пользуетесь.

Судя по именам используемых функций, radio - это, например, не объект класса Nrf24l.

jakob291
Offline
Зарегистрирован: 06.01.2013

Виноват,

#include <SPI.h>
#include <RF24.h>
#include "RF24_config.h"
RF24 radio(9,10);

Код использовал отсюда

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

jakob291 пишет:

Все неудобство в том, что radio.write и radio.read пользовательскую структуру не примут

Почему? А преобразование типов на что?

Да и судя по декларациям

bool read( void* buf, uint8_t len );
bool write( const void* buf, uint8_t len );

функции едят что угодно.

ustas
Offline
Зарегистрирован: 12.03.2012

jakob291 пишет:

Все неудобство в том, что radio.write и radio.read пользовательскую структуру не примут

Неправда - замечательно примет.

radio.write( &sensor, sizeof(sensor) ); 

Это из одного из моих скетчей. Работает превосходно.

sensor - в данном случае как раз является структурой.

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

step962 пишет:

maksim пишет:

Во-первых, совершенно не ясно зачем и как вы пытаетесь читать 128 байт, так как максимальный размер передаваемого пакета составляет 32 байта, а то что свыше просто обрезается.

32 байта - это что? Длина буфера или определение протокола?

Если длина буфера, то это не является ограничением для длины принимаемого пакета - читайте сколь угодно длинные последовательности. Главное успевайте делать это вовремя.

Это и размер буфера и максимальная длинна пакета, а если заглянуть в библиотеку, то:

bool RF24::read( void* buf, uint8_t len )
{
  // Fetch the payload
  read_payload( buf, len );

  // was this the last of the data available?
  return read_register(FIFO_STATUS) & _BV(RX_EMPTY);
}
uint8_t RF24::read_payload(void* buf, uint8_t len)
{
  uint8_t status;
  uint8_t* current = reinterpret_cast<uint8_t*>(buf);

  uint8_t data_len = min(len,payload_size);
  uint8_t blank_len = dynamic_payloads_enabled ? 0 : payload_size - data_len;
  
  //printf("[Reading %u bytes %u blanks]",data_len,blank_len);
  
  csn(LOW);
  status = SPI.transfer( R_RX_PAYLOAD );
  while ( data_len-- )
    *current++ = SPI.transfer(0xff);
  while ( blank_len-- )
    SPI.transfer(0xff);
  csn(HIGH);

  return status;
}

так что прочитать более 32 байт не получится. Поэтому просто пишите функии, которые будут
передавать/принимать ваш массив по 32 байта.

jakob291
Offline
Зарегистрирован: 06.01.2013

Ustas, дайте пожалуйста ссылку на код, вроде что-то знакомое, а найти не могу.

ustas
Offline
Зарегистрирован: 12.03.2012

jakob291 пишет:

Ustas, дайте пожалуйста ссылку на код, вроде что-то знакомое, а найти не могу.

http://habrahabr.ru/post/171613/ - тут выкладывал куски кода

jakob291
Offline
Зарегистрирован: 06.01.2013

Спасибо, как выяснилось искал не там)

jakob291
Offline
Зарегистрирован: 06.01.2013

За код спасибо, почти разобрался.

Остался последний вопрос: я задал такую структуру

typedef struct{
char comment[32];
int value1;
int value2;
int value3;

}message;

Она идентична и у приемника и у передатчика.

Для теста задал:

        responce.comment = "I'm online and waiting";
        responce.value1 = 25;
        responce.value2 = 19;
        
        radio.write(&responce, sizeof(responce));

Система ругается:

 incompatible types in assignment of 'const char [23]' to 'char [32]'

Система требует строку определенного размера, к тому же считает ее константой, у меня же строки будут разные по длине. А заменить тип на String не выриант, поскольку по неясным причинам на него плохо реагирует serial.println (искажение кодировки, да и затратная по памяти эта штука)

Что предпринять?

 

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

jakob291 пишет:

 

Для теста задал:

        responce.comment = "I'm online and waiting";
        responce.value1 = 25;
        responce.value2 = 19;
        
        radio.write(&responce, sizeof(responce));

Система ругается:

 incompatible types in assignment of 'const char [23]' to 'char [32]'

Попробуйте первую строчку переписать так:

#include <string.h>
...
...
strcpy(responce.comment,"I'm online and waiting");
ustas
Offline
Зарегистрирован: 12.03.2012

я вот так делаю:

memcpy(&sensor.Comment,(char*)MySensors[ParamID].Note, 16);

 

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

Обе функции суть одно и то же, только в memcpy размер передаваемого пакета указывается явно, а strcpy, предназначенная для обработки строк, копирует любое количество байтов, пока не стретится нулевой (0x00 - стандартный признак конца строки в си).

jakob291
Offline
Зарегистрирован: 06.01.2013

Спасибо, работает.

Правда, нашел еще один косяк:

Передаю, меняю числа

responce.value1 = 25;
response.value2 = 19;

Принимаю и читаю по-всякому.

if(radio.available())
  {
    message sensor;
    
    radio.read(&sensor, sizeof(sensor));
    
    
    Serial.println(sensor.comment);
    Serial.println(int(sensor.value1));
    Serial.println(sensor.value2);
    }

В мониторе стабильные

-4061
-8720
 

Чувствую я, что где-то накосячил, но где? (Если передавать не структурой, а по очереди, то все нормально)

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

Перечитайте сообщения #1 и #8 и посчитайте количество байт вашей структуры.

typedef struct{
char comment[26];
int value1;
int value2;
int value3;

}message;

 

jakob291
Offline
Зарегистрирован: 06.01.2013

Блин) Спасибо.

Привык я к защите от дурака высокоуровневых языков ООП...

jakob291
Offline
Зарегистрирован: 06.01.2013

И снова я со своими глупостями.

А нет ли более изящного способа передать "смесь". Например, имеем

char ch[] = "temp";
int num = 25;
....
radio.write(mixture, sizeof(mixture));

и со стороны приемника

char commands[32] = "";
radio.read(&commands, 32);
...
Serial.println(инфа в виде букв и цифр)

Помогите вставить нужные преобразования вместо многоточий. Либо поменять что-то еще. Вариант со структурой тоже катит, но мне так или иначе требуется преобразование. Основное условие: в порту нужна строка вида "temp25" одним махом, ее будем парсить более высокоразвитой программой

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

Ну тогда уж не 

radio.write(mixture, sizeof(mixture));

а

radio.write(sizeof(mixture), mixture);

Ибо зачем нужна информация о длине пакета уже после его передачи? Мертвому припарка...

jakob291
Offline
Зарегистрирован: 06.01.2013

Не, библиотеку, реализовывающую функцию radio, не я писал, там именно такой порядок параметров. Дальше он может и в обратном порядке передавать, это мы не знаем (да нам и не важно)

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

Из библиотеки:

 bool write( const void* buf, uint8_t len );

Скорее всего step962 что-то не так понял.
 

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

Да, принял приведенные строчки за псевдокод и предположил, что речь идет о формировании пакета для передачи... А это было обращение к конкретной библиотечной функции.