Forming data block for sending over IridiumSBD

Hello!

In my software i have a data structure:

struct SEND_DATA_STRUCTURE{
 // ????????? ??????
  byte com_stat ;
  byte id_data;
  double Shirota;
  double Dolgota;
  int kurs_tek;
  int kurs_raschet;
  int napr_vetra;
  int skor_vetra;
  byte parus;
  byte rul;
  byte chasy;
  byte minuty;
  byte RC1;
  byte RC2;
  byte RC3;
  
};

with byte, double, integer data.

I want to send this data over IRIDIUM modem using IridiumSBD library with sendSBDText(const char *message); command.

How i can make a string with my data to sending?
I vant something like this " STD, com_stat, id_data, ...., EOT" - all data from my data structure with STD flag on start, EOL on end and comma (,) separation between different data.

So how i can forming a string to sending and how i can check data length (must be less that 300 bytes )?

Thanks all. Have a nice day.

PS Sorry my bad English

Research the snprintf() function.
It will allow you to format a string from variables and text.

Why would you be planning to use a method that sends text to send binary data?

If the text data is 8 bit, ie signed char

Just put an extra field in your structure as a byte, e.g.

byte null_terminator;

Set this field to zero

Then pass the address of the struct to your send data command

You may need to cast to char *

Use sizeof to determine the size, but it looks smaller than 300 bytes to me

PaulS:
Why would you be planning to use a method that sends text to send binary data?

I want to have "easy to read" data on other end of Iridium link.

So i need a way to convert my binary data to text, then send it.

PaulS:
Why would you be planning to use a method that sends text to send binary data?

It solves the byte sex problem. Big endian sender plus little endian receiver and no agreed network byte ordering isn't a problem in this case.

rogerClark:
If the text data is 8 bit, ie signed char Just put an extra field in your structure as a byte, e.g. byte null_terminator; Set this field to zero Then pass the address of the struct to your send data command

This wouldn't work if one of his data bytes in the struct could be interpreted as NUL.

It solves the byte sex problem.

It does, but there is no way to convert a struct to text. The individual members can be converted, but there is no magic bullet.

PaulS:

It solves the byte sex problem.

It does, but there is no way to convert a struct to text. The individual members can be converted, but there is no magic bullet.

To give an example - any encoding scheme that used the printable ASCII codes for data and the non-printables (codes less than 32) for seperators would work.

@bwat

Re nulls

Yes. My mistake
I realised it would not work after I'd posted it.

How about using uuencode

Or any binary to text

I've just looked at the iridium library that I think it are using, and it has a binary send command.

That command uses the same internal function as the text sending command

So converting your structure to text for transmission seems completely pointless.

However, I think that what the OP has illuded to, is not that they need to send binary over a text only system, but its more likely that they want to send to a system with a different architecture

In which case byte order is not the only issue. Sizes and format of the double type is also likely to be an issue.

I am working on a project that sends a struct from Arduino to a Java based system. I.e android.

I intend to write a java class which process binary data to and from the properties in the class

I presume the machine receiving the iridium data has more CPU power and memory etc than the Arduino so it would make sense to do the processing at the other end

Ok.

You right.

But how i can convert different data types from my structure to single array of bytes and add CRC to end of this array?

Or may be easiest way - send each data by different command?

I don't have a time limit to sending data, but in case of Iridium - "time is money'.

This is from RockSeven site:
"Credits are used each time you transmit. 1 credit is used per 50 characters of message sent or received. 1 credit is also used if you check your mailbox and there are no messages waiting (A mailbox check). "

So if i understand right - 50 characters = 50 bytes.

More bytes - more money to pay.

Ideally i want something like this sequence:
=== on board side

  1. Data from my structure make a array of bytes to send, with separation bytes or bytes sequenses
  2. CRC calculation of array
  3. If possible - simple compression method
  4. Data sending over IRIDIUM

=== on earth side

  1. Geting data to email over Iridium service
  2. Decompression of data and printing log on paper.

Decompresion can be made "by hand" or in Processing.

My project is control system for autonomous sailing boat (yacht) for MICROTRANST competition.
you can read more about thic competition here:
http://www.microtransat.org/

And our team make web site - i think we start it at September....

Thanks all.

Sorry my bad English.

Any C++ CRC would be fine, but keep it small. I googled it and found

http://excamera.com/sphinx/article-crc.html

I took that code and added another function to do a CRC on data instead of a string (I think I got the code right... Please check it yourself);

#include <avr/pgmspace.h>

struct SEND_DATA_STRUCTURE{
 // ????????? ??????
  byte com_stat ;
  byte id_data;
  double Shirota;
  double Dolgota;
  int kurs_tek;
  int kurs_raschet;
  int napr_vetra;
  int skor_vetra;
  byte parus;
  byte rul;
  byte chasy;
  byte minuty;
  byte RC1;
  byte RC2;
  byte RC3;
  
};

struct DATA_AND_CRC
{
struct SEND_DATA_STRUCTURE send_data;
unsigned long crc;
} my_data;

static PROGMEM prog_uint32_t crc_table[16] = {
    0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
    0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
    0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
    0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
};

unsigned long crc_update(unsigned long crc, byte data)
{
    byte tbl_idx;
    tbl_idx = crc ^ (data >> (0 * 4));
    crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
    tbl_idx = crc ^ (data >> (1 * 4));
    crc = pgm_read_dword_near(crc_table + (tbl_idx & 0x0f)) ^ (crc >> 4);
    return crc;
}

unsigned long crc_string(char *s)
{
  unsigned long crc = ~0L;
  while (*s)
    crc = crc_update(crc, *s++);
  crc = ~crc;
  return crc;
}

unsigned long crc_data(byte *data,int len)
{
  unsigned long crc = ~0L;
  while(len-->0)
  {
    crc = crc_update(crc, *data++);
  }
  crc = ~crc;
  return crc;
}

void fake_send(byte *data,int len)
{
  while(len-->0)
  {
     Serial.print(*data++,HEX);
  }
}

void setup()
{
  unsigned long crc;
  Serial.begin(115200);
  
  Serial.println(crc_string("HELLO"), HEX);// Example of existing function
  
  Serial.println(crc_data((byte *)"HELLO",5), HEX);// test my function returns the same result for 5 char string ;-)
  
  Serial.println(sizeof(my_data.send_data), DEC);// get size of struct
  
  


  my_data.send_data.com_stat=1 ;
  my_data.send_data.id_data=2;
  my_data.send_data.Shirota=123.456789;
  my_data.send_data.Dolgota=321.987654;
  my_data.send_data.kurs_tek=3;
  my_data.send_data.kurs_raschet=4;
  my_data.send_data.napr_vetra=5;
  my_data.send_data.skor_vetra=6;
  my_data.send_data.parus=7;
  my_data.send_data.rul=8;
  my_data.send_data.chasy=9;
  my_data.send_data.minuty=10;
  my_data.send_data.RC1=11;
  my_data.send_data.RC2=12;
  my_data.send_data.RC3=13;
  
  
  
  
  
  my_data.crc=crc_data((byte *)&my_data.send_data,sizeof(my_data.send_data));
  Serial.println(sizeof(my_data), DEC);// get size of struct
  fake_send((byte *)&my_data,sizeof(my_data));
}

void loop()
{
}

Edit. Compression is probably not worth it, as the data length is only 29 bytes
You may find compressing it makes it bigger not smaller

Edit.

BTW to decode it, rather than doing it manually, just feed the data to another Arduino and get it to print the contents of the same struct.