Send 1 byte as fast as possible

I have an app where I need to send one byte from one wixel as fast as possible to the receiving wixel.
Using IO Repeater is too slow obviously.

Basically I need to mirror 1 bit fast as possible around 200 pulses per sec. (almost pwm)

I have tried using radioQueueRxSendPacket() / radioQueueTxSendPacket(),
but I get strange values in the packets buffer[] when I look at the bytes I send.
It seems to be random data in my packet from time to time.

I assume using the radioComTxSendByte() / radioComRxReceiveByte() is what I am after since it sends one byte at a time.
I get compile errors like the radio_link.lib isn’t linked. “Global not declared” etc…
I double checked the my mk file and it’s in there.
I’ve included radio_com.h in my code.

What is the proper way to declare, so I can use these functions?

What is the best way to TX/RX one bit or byte to another wixel as fast as possible?

Thanks

James

Hello, James.

The receiving Wixel will occasionally miss some packets; how do you want your application to behave in that case? Is it OK if the occasional pulse is missed altogether?

I think the way I would approach this problem is have the transmitting Wixel just constantly sending packets as fast as it can. Most of our radio libraries have delays in them to give the other parties a chance to send data, but you can look at the test_radio_signal_tx and test_radio_signal_rx example apps to see how you would send packets as fast as possible. The test_radio_signal_tx app sends packets in bursts, but you should be able to easily modify it so that it is just constantly sending packets.

Sending a packet from a Wixel takes around ~600-1000 microseconds, and it sounds like the period of your signal is 5000 microseconds, so this is definitely pushing the limits of the what the Wixel can do. If you tell me the big picture of what you are trying to accomplish, I might be able to suggest another way to do it that is more likely to work.

If you want help with your compiling or linking errors, please post your code, your options.mk file, and all the error messages.

Edit: Looking at the test_radio_signal_tx app, I now realize it could be a little bit faster if it didn’t go through the frequency synthesizer calibration state every time it transmits a packet.

-David

I need to take a steel wheels rotation count (ir sensor) and send that wirelessly 20 ft.
The wheel gets to about 200 rps max give or take a few counts.

Well, if you have some embedded C programming experience, you could probably set up the transmitting Wixel to count the pulses itself, storing the result in a 32-bit integer. Then just send that count to the other Wixel using whatever kind of radio library you want, like radio_queue. There would be no need for particularly fast radio communication.

–David

Thanks, David for the fast replies. Very Refreshing!

That was my first idea, to just get the counts-per-sec on one side and send to the other.
Which is a bit more code I thought, than trying to just send the HL value.

Since I saw that the radio can send fast uart/spi data streams I knew I could get the HL signal over via a single packet.
But its looking more like I need to do some processing on the one side first to get my latency down so the Wxl can keep up?

When I ran the IO Extender that worked perfectly for what I was after, but too slow.
So I came to the forums looking for some code hoping to find someone doing a single byte transfer over and over.

I do have lots of experiance with Emb. C and PIC’s. I am actually using a PIC on the RX side integrated with the wixel.

When I get home this afternoon i’ll gather up my code and post what I am doing.
Perhaps it works and I just have some call or code bug that prevents the packet from containg the TX value properly.

That’s the idea. It’s hard for me to say for sure that you need to do it, but it seems like that approach is more likely to work, especially if you don’t want to miss any pulses.

The closest thing I know of is the test_radio_signal_tx app I mentioned earlier.

–David

Here’s my TX code:

#include <cc2511_map.h>
#include <board.h>
#include <usb_com.h>
#include <usb.h>
#include <radio_queue.h>
#include <radio_link.h>

uint8 XDATA * txPacket;


void updateLeds()
{
     usbShowStatusWithGreenLed();
}

void TX_Byte()
{  
     // Check to see if there is a radio TX buffer available.
     txPacket = radioQueueTxCurrentPacket();    

    // Byte 0 is the length so set to one byte packet.
    txPacket[0] = 1;
		
	if (P0_0==0)
	{
	 txPacket[1] = 0;	 
	 LED_RED(0); 		// OFF
	}else if (P0_0==1)
	{
	 txPacket[1] = 1;
	 LED_RED(1); 		// ON
	}	
	radioQueueTxSendPacket();		// Transmit Packet
    
}


void main(void)
{
    systemInit();   
    usbInit();
    radioQueueInit();
    P0DIR = (1<<0);			// Set Pin Direction <INPUT>
    LED_RED(0); 			// OFF

    while(1)
    {
    
    updateLeds();
    boardService();
    usbComService();
	
	TX_Byte();  	
       
    }


}

Here’s my RX code:

#include <cc2511_map.h>
#include <board.h>
#include <usb.h>
#include <usb_com.h>
#include <radio_queue.h>
#include <radio_link.h>

uint8 XDATA * rxPacket;
uint8  rx_byte;

void updateLeds()
{         
     usbShowStatusWithGreenLed();
}

void RX_Byte()
{       				
    rxPacket = radioQueueRxCurrentPacket(); 
    radioQueueRxDoneWithPacket();	
	 
	if (rxPacket[1]==0)
	{
	 LED_RED(0); // OFF	
	 P0_0 = 0;	
	}else if (rxPacket[1]==1)
	{
	 LED_RED(1); // ON	
	 P0_0 = 1;
	}
		          
}

void main(void)
{
    systemInit();   
    usbInit();
    radioQueueInit();   
    LED_RED(1);	// ON
	
    P0DIR |= (1<<0);	// Set Pin Direction <OUTPUT>
    P0_0 = 1;			// Set Pin HI
	
    while(1)
    {
    
    updateLeds();
    boardService();
    usbComService();
	
    RX_Byte();  		
       
    }


}

The way you wrote your code, you are not taking into account that sometimes the radioQueue will not have any free TX buffer space available for sending more bytes, and also you are not taking into account that sometimes radioQueue will not have a received packet to hand to you. For example, when the Wixel just starts up it hasn’t had time to receive a packet yet, so you can’t get any data out of radio_queue at that point. In general, your main loop will run way faster than the time it takes to send or receive a packet.

You should check the radio_queue documentation and be sure to correctly handle the cases when radioQueueTxCurrentPacket() or radioQueueRxCurrentPacket() return 0.

–David

void TX_Byte()
{  
    // radio TX buffer available?
    txPacket = radioQueueTxCurrentPacket();
	
	if (txPacket != 0){	 
	
		// Byte 0 is the length of packet (1 byte)
		txPacket[0] = 1;
		
		if (P0_0==0)
		{
		txPacket[1] = 0;	 
		LED_RED(0); 		// OFF
		}else if (P0_0==1)
		{
		txPacket[1] = 1;
		LED_RED(1); 		// ON
		}	
		
	radioQueueTxSendPacket();		// Transmit Packet
    }
  
}



void RX_Byte()
{       				
    rxPacket = radioQueueRxCurrentPacket(); 
	radioQueueRxDoneWithPacket();	
	if (rxPacket != 0)
		{	
		if (rxPacket[1]==0)
		{
		LED_RED(0); // OFF	
		P0_0 = 0;	
		}else if (rxPacket[1]==1)
		{
		LED_RED(1); // ON	
		P0_0 = 1;
		}
	}
}

Still random data in packet[1].
Sometimes it = 0 at the correct time.
Even if I turn the wheel slow or try a 1 or 2 rps its not correct.
I am powering on one (TX) and then the other (RX) to prevent the startup issue.

I also just wrote a loop to send one byte in packet [1] every sec.
Made it simple, but it is like every packet[1] is a random number from 0-255.

This is confusing as I just want to send one byte, even slow its not the byte I am putting in [1].

Another thing you are doing wrong is that you are calling radioQueueRxDoneWithPacket too soon, and you are calling it even if there is no current RX packet, which is invalid. Please see the documentation of that function for more information.

–David

I reread the doc several times again, relooked at all the examples again, moved the donewithrxpacket only once a rxpacket >0 inside the if statements etc.
Still no joy, its still a random # and now my rx led isn’t blinking like before once a packet came in.

What would you suggest I do for this code to at least make it send a single packet that is the correct byte besides just go look at the apps/examples and hack and cludge them?

I’m not asking you to do my code mind you, I just can’t seem to get just a single packet let alone all 16.

This is obvioulsy simple stuff as others are getting valid packet data thru.
I must be missing some simple step or placement of a call still.

Well,
After many hours of trial and error tonight (hackathon):
It sends the single packet [1] byte now no problem 99% time.

I just reset everything and started over, recreated it all again from scratch(major redo).
Not sure what the issue was at all, lib not linked, call missing, call outta place, sdk not installed right but no matter now I can move on.

Looks like the timing is not an issue so far and it’s TX-RX’n the packet fast enough no glitch.
I’ll test real-world on the flywheel this weekend.

Great, I’m glad you got things working. By the way, the radio_queue library has a built-in delay between transmitting packets to give the other party a chance to talk, so if you do need it to be a bit faster you can try to decrease or remove that delay.

–David

Works like a charm, its fast enough for 200rps.
I also created another program that just sends the integer and its fine too.
So with that success I bought 4 more. :wink:

I need to do something similar, sending a byte of data taken from I/O pins configured as inputs and duplicating them on another wixel, like the I/O repeater but as fast as possible. So I’m also hopeful the test_radio_signal_tx AND rx will serve as a good starting point, and yes I see where there are timing loops I could alter or remove. However, as the transmit side will be battery driven, and will not need to continuously send data, I’d like to be able to lower supply current when there is no change. So most likely I’ll want to sample my input pins rapidly and defer transmitting unless I see that there has actually been a state change, or if the input pins can be configured as edge triggered interrupt lines than I won’t have to sample constantly.

But either way, would regulating the transmit periods save any significant battery drain? And, if there is a delay associated with going from a standby (or receive I guess) mode into transmit mode, would that cause me to be right back to the slower response of the I/O repeater?

Finally, if there is no such delay but the standby current is still higher than I’d like, the next step in low battery drain would be to put the wixel MCU into low power sleep mode, perhaps when there have been no state changes in 1/2 hour or so. Of course I’d need a low power external circuit to sense ANY state change and generate a wake-up pulse for the wixel. I do understand that in a scheme like that the initial state change that caused the wake up might be lost, and I suspect that the wake up process would add some delay before a transmission could occur anyway, right? Even so, it could serve as a convenient 'auto off" feature, since I’m already sure I’ll forget to turn off power when I’m not using this project. :slight_smile:

Yes, it would. The Wixel draws a few tens of milliamps while transmitting and it can go down to just a few microamps while it is sleeping. You can see the CC2511F32 datasheet to get more specific numbers and also:

Yes, there could be a delay of several hundred microseconds. The biggest factor is when you choose to calibrate the radio’s frequency synthesizer. It might be possible to calibrate the frequency synthesizer before going to sleep so you don’t have to do that step when you wake up, but I’m not sure. More information about the radio’s state machine and the delays between different states is in the CC2511F32 datasheet.

–David

It works grand for this application, much faster than the IO-Repeater.
I am just using the standard calls and doing 2 bytes now in a loop fast as can go no overhead removed all calls to usbcom and board etc use a jumper to get to bootloader now.
I added another byte for a int value split into a two bytes since 255 rps wasn’t enough resolution so its a uint16 now recombined on the RX side.

Its solid for this app.
It just works and is what I expect to see after programming it. lol