simple protocol

Go To Last Post
22 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Guys,
I have two avr's communicating quite nicely wirelessly - at the moment I am sending pi through the air, but I want a protocol so that it/I know when the message is complete.
This is my current code (transmission side):

void main(void) 
{	
float pi = 3.141596;

	Initialize(); //initialize IO, UART, SPI, set up nRF24L01 as RX, execute KSA
	uart0_open(); //open UART0
	nrf24l01_initialize_debug(false, 2, false); //initialize the 24L01 to the debug configuration as TX, 1 data byte, and auto-ack disabled
	arc4_initialize_ksa(key, keylen); //execute the KSA

	while(1)
	{	
	send (pi);

	}
}

void send(float number){
unsigned char halfpie[7];
dtostrf(number, sizeof(halfpie), 5, halfpie);
halfpie[sizeof(halfpie) - 1] = '*';
	unsigned char data[2]; //array to hold the encrypted byte and packet count
	data[1] = 0; //initialize packet count
		DelayS(1); //delay 1 second between each letter
		data[1] = 0;
		data[0] = 0;
		int i = 0;
		while (i < sizeof(halfpie)){//(data[0] != '*'){
		data[0] = halfpie[i];//set up data to be sent

		nrf24l01_write_tx_payload(data, 2, true); //transmit encrypted byte and counter
		
		//wait for the packet to be sent
		while(!(nrf24l01_irq_pin_active() && nrf24l01_irq_tx_ds_active()));
		
		nrf24l01_irq_clear_all(); //clear all interrupts in the 24L01
		data[1]++; //increment the packet count
		i++;
		ToggleLED(); //toggle the on-board LED as visual indication that the loop has completed
		DelayMS(10);
		if (data[0] == '*'){
		break;
		}
		}
}

The bit I am stuck with is the dtostrf. I am copying pi into the array halfpie, but I am trying to set the last character to be a * and then leave the while loop when data[0] == *.
It all compiles fine etc, and runs and sends, however I only ever get (repeating) 3.14 on my terminal from the receiving end. Why doesnt it send everything up to and including the *?
I want to use the * receiving end to know when one number ends and the next begins if I send a string of floats...
Have I misunderstood dtostrf? I understand the second last paramter to be the precision after the decimal?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why not encrypt a 16 byte packet or larger? The NRF24L01 can handle a 32 byte packet.

You can just get the chip to auto-ack the packet. If you use a 2-byte CRC with each 32-byte packet of data, you can be 100% sure of successful transmission.

If you don't get an ack, you transmit the packet again. The only problem can be losing the ack from a successful reception. So the receiver needs to check whether you have repeated a block. Just add a 'packet sequence number' as part of the 32-byte data. e.g. one-byte 0..255.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yeah I read that doc on embedded wotsitz, I didnt quite understand the auto-ack feature. is that what the data[1] is all about?
The reason however I wanted the * was because i I am transmitting a load of numbers but as a string, so i needed to know where to break the string back up... But are you saying its better to send floats as floats?
so imagine you wanted to send 0.11111, 2.22222, 3.333 all stored in an array, I was going to send as

0.11111*2.22222*3.333

i.e as a string, then break it up the other end?
Are any of the examples useful to see something like this in action - i.e using the ack to confirm submission?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here's how I'd send 3 floats

float f1,f2,f3;
char *p;

f1=1.234;
f2=5.678e9;
f3=-3.456e-10;

putchar(0xaa); //beginning of 14 byte packet marker
putchar(0x55);
p=&f1;         //addres of f1
putchar(*p++); //send lo byte
putchar(*p++);
putchar(*p++);
putchar(*p++); //send hi byte (put em back together same way)

p=&f2;
putchar(*p++);
putchar(*p++);
putchar(*p++);
putchar(*p++);

p=&f3;
putchar(*p++);
putchar(*p++);
putchar(*p++);
putchar(*p++);
//maybe a checksum here?

Imagecraft compiler user

Last Edited: Mon. Sep 10, 2012 - 02:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can send your data however you want.
e.g. a printable string.
e.g. a fixed number of bytes, ints, longs, floats, ...

A string works by having a terminating NUL.
A 'block' could have a 'size' field.

So a possible 32-byte 'packet-structure' could be:

You can send an arbitrary amount of data by sending N full packets + a part-full packet. You just ignore the 'unused' bytes in the last packet.

Note that you can monitor a keyboard, and send one key per packet or several keys. Since you can achieve 100kB / sec data rate, I doubt if a fast typist will ever be too quick.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So if I send a string made up of all the numbers in an array, do I not need the * (or something) to differentiate one value from the next on receiving end - i.e my original question?

My sensor, transmitting end, receives 10 values stored in an array, and I want to send them all at once, then break it up the other end. Can I read about ack somewhere, if you think thats the best way?
An example based on what you are saying would be really useful, because om obviously not getting something...
We spoke before about confirming a successful send, but I dont remember this ever being mentioned?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Both ends need to know the same size of packet.
Ten floats will be at least 40 bytes, so you would need at least two packets.

Your example projects all 'change ends' and expect the receiver to send the same data back. The transmitter could simply use the auto-ack and be confident that an ACK means everything went ok.

If you are sending 40 bytes and not 40MB, you hardly need worry about throghput or efficiency.

If you use the string values of any float, you probably need at least 14 bytes per float. You can send a magic start message. You can even send the array[number] e.g. 4th member

"array[3]: -1.234567e-12\n"

You can choose any protocol that you like. I suggest that the Enhanced ShockBurst is very reliable. Be prepared to repeat packets when the automatic number of attempts fails. You might transfer 32MB without ever repeating a packet. However you must be prepared for glitches.

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

OK, I think I will look at what your ping example does to decide on the quality of the ping again....

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I am sending pi through the air, but I want a protocol so that it/I know when the message is complete.

Umm--When sending pi, can it ever be complete?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
can it ever be complete?
...PI in the sky? :?

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

js wrote:
...PI in the sky? :?

"I may make you feel but I can't make you think" - Jethro Tull - Thick As A Brick

"void transmigratus(void) {transmigratus();} // recursio infinitus" - larryvc

"It's much more practical to rely on the processing powers of the real debugger, i.e. the one between the keyboard and chair." - JW wek3

"When you arise in the morning think of what a privilege it is to be alive: to breathe, to think, to enjoy, to love." -  Marcus Aurelius

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I bet you saw that in one of those fancy Italian Museums ... like to Uffizi. :lol:

Ross McKenzie ValuSoft Melbourne Australia

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

nice bit of social chat going on....

Quote:

float pi = 3.141596; 


...
David, i wonder if you could adjust one of your main's to send a long string, or an array of floats just so I can see how you would do it and what you mean. Im not exactly sure of the best way to do this, and I think I am doing it wrong as I am sending each character one at a time - by the sounds of things I can send 32 bytes at once...
Thanks

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

there are things which surprise me:

converting a float (4 bytes) into a string (many, say 10 bytes) eats bandwidth and CPU (on one end, one has to code it with lots of divisons/multiplications, and the other end has to decode it with the same CPU burden). If there were (i,e)ndianity issues, I could understand it, but on the same processors?

Perhaps you should send your float as it is (and add , say, an XOR on all its bytes to have some kind of validation : the CPU burden would just be XORing 4 bytes -on both sides : if there is an inconsistency, the receiver might send a NACK, else, it acknowledges).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Floating point formats are standardized, so assuming the AVR compiler actually adheres to the standard, if something different then an AVR needs to interpret the data it should be no problem.

I agree that conversion to ASCII then back again is a waste of resources.

XOR is not going to work reliably with RF, CRC8 is trivial and much better.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

if something different then an AVR needs to interpret the data it should be no problem.

Apart from the issue of endianism of course. But OP has already said this is AVR->AVR so no worries on this occasion.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

@jayjay
for XORs, it was in my mind the easiest way to have some kind of redundancy (I wrote without looking at other people's answers...)
If Monsieur OP wants to send int16_t/int32_t s, too, he might have indianity issues (they are not standardized), but not while communicating between two AVRS.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The NRF24L01+ hardware looks after CRC and integrity of data. The punter just has to choose what data to send from a 'convenience' point of view.

Personally, I am happier with human readable data if efficiency is not critical. 40 bytes of binary data or 500 bytes of ascii strings will take 1ms or 10ms.

How fast can you type?
How fast can you read?

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

David, Can I data[] be of type float, I thought we discussed this a while ago and it needed to be a char - the values, once manipulated coming from my sensor are of type float, so I thought I HAD to send chars?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

nice bit of social chat going on....
Quote:

Code:

float pi = 3.141596;


Oh--an >>approximation<< of pi.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"

Quote:
the values, once manipulated coming from my sensor are of type float, so I thought I HAD to send chars
"
float s occupy 4 bytes, and then can be seen as 4 char s as Bobgardner showed you.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Want me to show how to put em together on the receiver end? Or is it obvious its just the opposite of taking them apart?

Imagecraft compiler user