Передача пакета данных

9ser
Offline
Зарегистрирован: 18.11.2012

Добрый день

Поскажите как грамотно сфрмровать пакет данных на передатчике???

Есть следующие условия:

- тип датчика << 1 - DS18B20; 2 - DS1990; 3 - DHT; и т.д.        

- порядковый номер датчика << числовое значение от 0 до 9999

- значение датчика << числовое значение от -9999 до 9999

- разделитель << _

Пакет формата :

3-0-23.2_2-0-4

т.е датчик DHT, порядковый номер 0, значение 23.2

      датчик DS1990, порядковый номер 4

Ну как-то так

Заранее спасибо

 

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

А чем Вам предложенный Вами формат не нравится? Разумеется вместо - лучше использовать другой символ, а то отрицательные значения нельзя будет передавать.

com
Offline
Зарегистрирован: 06.09.2013

Serial.println("3-0-23.2_2-0-4"); 

так сойдет?

9ser
Offline
Зарегистрирован: 18.11.2012

kisoft пишет:
А чем Вам предложенный Вами формат не нравится? Разумеется вместо - лучше использовать другой символ, а то отрицательные значения нельзя будет передавать.

Ха  на счет отрицательных значений это надо проверить...

Вот какой функцией записать зачения фатчиков в такой форма на передатчике, а потом обратно разгруппировать на приемнике??? Вот в чем вопрос???

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

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

9ser
Offline
Зарегистрирован: 18.11.2012

билбиотека RF24network

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

Нужно опросить все датчики сформировать пакет даенных  на передатчике =>принять и полученные данные разложить по полочкам тип датчика и его значение

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

RF24 не использовал, но, похоже в ней есть пересылка строк (максимальнуюдлину не знаю), потому есть пара вариантов:

1. Собирать в строку и посылать её

2. Хранить данные в виде структуры и посылать в виде структуры

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

Структура может быть, например, такой:

typedef struct Record
{
  byte sensor_type;
  uint16_t sensor_number;
  int16_t sensor_value;
};

А дальше уже тоже варианты - слать по одной структуре (менее затратный по памяти вариант) или собирать их в общую массу и высылать все в едином массиве структур (памяти займет побольше).

 

9ser
Offline
Зарегистрирован: 18.11.2012

вот это есть даже так

struct payload_t
{
  unsigned int from_node;    //<< Логический адрес, передатчика */
  unsigned int to_node;      //<< Логический адрес, приемника */   
  unsigned int id;           //<< Идентификатор сообщения, увеличивается каждый сообщение */
  unsigned long sensor_data; //<< Тип и значения датчиков. тяжелая часть пакета*/
  unsigned int command;       //<< Команда для управления Клиентом
};

Вопрос как засуть в long sensor_data значения скажеи 3х датчиков???

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

Давайте посчитаем. -9999..9999 - это 14 бит плюс знак, 15 * 3 = 45 бит. 45 бит - это 6 байт.

unsigned long - это 4 байта.

По двум - войдут легко.

 

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011

9ser пишет:

вот это есть даже так

struct payload_t
{
  unsigned int from_node;    //<< Логический адрес, передатчика */
  unsigned int to_node;      //<< Логический адрес, приемника */   
  unsigned int id;           //<< Идентификатор сообщения, увеличивается каждый сообщение */
  unsigned long sensor_data; //<< Тип и значения датчиков. тяжелая часть пакета*/
  unsigned int command;       //<< Команда для управления Клиентом
};

Вопрос как засуть в long sensor_data значения скажеи 3х датчиков???

2 + 2 + 2 + 4 + 2 = 12 bytes

А зачем адреса и команды двухбайтовые делать ?

struct payload_t
{
  byte from_node;    //<< Логический адрес, передатчика */
  byte to_node;      //<< Логический адрес, приемника */   
  byte id;           //<< Идентификатор сообщения, увеличивается каждый сообщение */
  unsigned int sensor_data_1; //<< Тип и значения датчиков. тяжелая часть пакета*/
  unsigned int sensor_data_2;
  unsigned int sensor_data_3;
  byte command;       //<< Команда для управления Клиентом
};

1 + 1 + 1 + 2 + 2 + 2 + 1 =10   и ещё 2 байта в запасе

com
Offline
Зарегистрирован: 06.09.2013

а зачем данные от разных датчиков засовыать в один пакет? это же неудобно...

9ser
Offline
Зарегистрирован: 18.11.2012

com пишет:

а зачем данные от разных датчиков засовыать в один пакет? это же неудобно...

а какие есть варианты?

9ser
Offline
Зарегистрирован: 18.11.2012

trembo пишет:

А зачем адреса и команды двухбайтовые делать ?

struct payload_t
{
  byte from_node;    //<< Логический адрес, передатчика */
  byte to_node;      //<< Логический адрес, приемника */   
  byte id;           //<< Идентификатор сообщения, увеличивается каждый сообщение */
  unsigned int sensor_data_1; //<< Тип и значения датчиков. тяжелая часть пакета*/
  unsigned int sensor_data_2;
  unsigned int sensor_data_3;
  byte command;       //<< Команда для управления Клиентом
};

1 + 1 + 1 + 2 + 2 + 2 + 1 =10   и ещё 2 байта в запасе

вот смотри у меня только на одном передатчике 5 температур, 4 дискретных  входа, 2 управляемых порта + аналоговые данные. А таких передатчиков допустим 5 штук(и не факт, что сигналы будут идентичны) + количествой передатчиков возможно и выростет. У меня список огроменный будет будет

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

9ser пишет:

вот смотри у меня только на одном передатчике 5 температур, 4 дискретных  входа, 2 управляемых порта + аналоговые данные. А таких передатчиков допустим 5 штук(и нефакт что сигналы будут идентичны) + количествой передатчиков возможно и выростет. У меня список огроменный будет будет

задам направляющий вопрос!

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

9ser
Offline
Зарегистрирован: 18.11.2012

какой функцией данные дальше как из пакета unsigned int sensor_data_1 вытащить?

мне же придется ими пользоватся?

 - тип отдельно

 - значение отдельно

Вот коряво попробовал сделать


/*
 Copyright (C) 2012 James Coliz, Jr. <maniacbug@ymail.com>

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 version 2 as published by the Free Software Foundation.
 */

/**
 * Simplest possible example of using RF24Network,
 *
 * RECEIVER NODE
 * Listens for messages from the transmitter and prints them out.
 */

#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

//============================
const int button_1 = 2;
      int flag_1 = digitalRead(button_1);
      int state;
//============================


// nRF24L01(+) radio attached using Getting Started board 
RF24 radio(40,41);

// Network uses that radio
RF24Network network(radio);

// Address of our node
const uint16_t this_node = 0;

// Address of the other node
const uint16_t other_node = 1;

// When did we last send?
unsigned long last_sent;


// How many have we sent already
unsigned long packets_sent;

// Structure of our payload
struct payload_t
{
  unsigned int from_node;     //<< Логический адрес, передатчика 
  unsigned int to_node;       //<< Логический адрес, приемника    
  unsigned int id;            //<< Идентификатор сообщения, увеличивается каждый сообщение 
  unsigned int type;          //<< Тип датчика и порядковый номер ds18B20(1); button(2);
  unsigned int number;        //<< Номер датчика
  unsigned int value;         //<< Pначения датчика
  unsigned int command;       //<< Команда для правления
};
 
void setup(void)
{
  Serial.begin(57600);
  Serial.println("Start RF server");
 
  SPI.begin();
  radio.begin();
  network.begin(/*channel*/ 90, /*node address*/ this_node);
}

void loop(void)
{
  // Pump the network regularly
  network.update();
  button();
  // Is there anything ready for us?
  while ( network.available() )
  {
    // If so, grab it and print it out
    RF24NetworkHeader header;
    payload_t payload;
    network.read(header,&payload,sizeof(payload));
    Serial.print("Server : ");
    Serial.print(payload.to_node);
    Serial.print(" <<=== client : ");
    Serial.println(payload.from_node);
    Serial.print(" counter :  ");
    Serial.println(payload.id);
    
    switch(payload.type)
          {          
          case 1:
              switch(payload.number)
                {
                case 0:
                Serial.print("Ds18b20(1) : ");
                //Serial.print(payload.number);
                Serial.print(" : ");
                Serial.println(payload.value);
                
                case 1:
                Serial.print("Ds18b20(2) : ");
                //Serial.print(payload.number);
                Serial.print(" : ");
                Serial.println(payload.value);
                
                default:
             break;
              }
          break;
          
          case 2:
              Serial.print("button_");
              Serial.print(payload.number);
              Serial.print(" : ");
              Serial.println(payload.value);  
          break;         
   
          default:
             break; 
        }
    
    
  }
}
// vim:ai:cin:sts=2 sw=2 ft=cpp

 

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

чем вас не устраивает? вполне себе вариант.

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

9ser
Offline
Зарегистрирован: 18.11.2012

я думал над таким видом:

Client_1_ds_0 и значение отдельно

Client_1 - это номер передатчика

ds - тип датчика

0 - его порядковый  номер

а в приемнике уже просто делаем сравнение:

 while ( network.available() )
  {
    RF24NetworkHeader header;
    payload_t payload;
    network.read(header,&payload,sizeof(payload));
    switch(payload.type)
         case Client_ds_0:
         ...

 

ну и понаписать все возможные варианты.

Просто мне охото чтобы пакет был не четко описан , а был универсальным и мне не пришлось добивать новые данные при увеличении киентов

Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

ну так и расписывайте пакет как вам нравится. поместите в него хоть мильен переменных всяких разных.. кто ж вам запрещает?

9ser
Offline
Зарегистрирован: 18.11.2012

Я же говорю НЕПРИЕМЛИМО!!!

Поэтому и хочу формат, шаблон как охото называйте...

чтобы не прописывать миллион клиентов...

struct payload_t
{
  unsigned int from_node; - Логический адрес, передатчика. он может быть допустим от 0 до 99
  unsigned int to_node;     -  Логический адрес, приемника. допустим 0
  unsigned int id;                -  Идентификатор сообщения, увеличивается каждый сообщение 
  unsigned int type;           - Тип датчика и порядковый номер ds18B20(1); button(2); ... (3) .. (4) и т.д. 
  unsigned int number;        //<< Номер датсика
  unsigned int value;         //<< Pначения датчика
  unsigned int command;       //<< Команда для правления
};

 

 
вот гдебы нарыть пример готового пакета и его обработку на приемике????
 
Puhlyaviy
Puhlyaviy аватар
Offline
Зарегистрирован: 22.05.2013

9ser пишет:

вот гдебы нарыть пример готового пакета и его обработку на приемике????

 
у вас желание из области фантастики..
ваши пакеты только для вашего проекта.. и мы можем только гадать что у вас там такого понавешено что требуются какие то необычные универсальные пакеты..
шансы, что вы найдете точно такой же проект с точно таким же железом и уже фунциклирующий, стремятся в бесконечность...
9ser
Offline
Зарегистрирован: 18.11.2012

т.е. формировать пакет и обычной функцией 

switch(...)

выбирать данные сравнвая их?

 

com
Offline
Зарегистрирован: 06.09.2013

пара замечаний

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

2. зачем id сообщения? если пакет получен, то все ок, если потерян - да и бог с ним, не ракету же запускаете. а иначе надо контролировать пропуски, чего-то делать - зачем?

3. в структуре надо делать контроль целостности. по сути, вы считываете из входного потока sizeof(payload) байт, говорите "это - мой пакет" и начинаете его разбирать по частям. а если пакет придет не полный, или начнете считывать с середины? Можно в начале пакета писать какую-то сигнатуру, по ней определять начало пакета и от нее отсчитывать нужное количество байт. а в конце пакета еще контрольную сумму

9ser
Offline
Зарегистрирован: 18.11.2012

Поскажите как и принятого пакета сформировыать переменную согласно таблице и записать в нее переменную?

вот пакет:

struct payload_t
{
  unsigned int from_node;     //<< Логический адрес, передатчика 
  unsigned int to_node;       //<< Логический адрес, приемника    
  unsigned int type;          //<< Тип датчика и порядковый номер command(0); ds18B20(1); button(2); 
  unsigned int number;        //<< Номер датчика
  float value;                //<< Значения датчика
};

Допустим я поличил данные типа:

payload_t (2, 0, 2, 1, 1)

я то знаю что это пакет от Клиента 2, Серверу 0, Button_1, значение 1

Подскажите как после принятоого пакета сформаровалось переменная:

Client_2_but_1 = 1;

 

 

9ser
Offline
Зарегистрирован: 18.11.2012

com пишет:

пара замечаний

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

2. зачем id сообщения? если пакет получен, то все ок, если потерян - да и бог с ним, не ракету же запускаете. а иначе надо контролировать пропуски, чего-то делать - зачем?

3. в структуре надо делать контроль целостности. по сути, вы считываете из входного потока sizeof(payload) байт, говорите "это - мой пакет" и начинаете его разбирать по частям. а если пакет придет не полный, или начнете считывать с середины? Можно в начале пакета писать какую-то сигнатуру, по ней определять начало пакета и от нее отсчитывать нужное количество байт. а в конце пакета еще контрольную сумму

Спасибо заменачания приняты