Multi-m3pi Communication with Wixel

The USB virtual COM port is handled by the usb_com library, so you should look for a feature of that library that tells you when the baud rate has changed. Here is the documentation for that library:
pololu.github.com/wixel-sdk/usb__com_8h.html

The usb_serial app needs to know the virtual baud rate so it can set the baud rate of the UART, so you can look at its source code to see how it does that:
github.com/pololu/wixel-sdk/blo … b_serial.c

If these hints are not enough, let me know.

Yes, dynamic channel changing is possible for any Wixel regardless of whether it is connected to USB or an m3pi; you would just have to figure out how exactly the m3pi sends that instruction to the Wixel.

–David

Thanks, that should give me enough to work with. :slight_smile: Unfortunately, I’m away from home for the next week or so, and I won’t be able to do any work on my robots until I come back. I’ll keep you posted once I return.

Thanks,
Geoff

I’ve succeeded in implementing the dynamic channel changing, although not quite in the way that we discussed. Rather than have the PC set the virtual baud rate, I have implemented a primitive message system, whereby the PC or the m3pi commands the Wixel (via UART or USB messages) to change the channel.

I’ve modifed the WSA’s usbToRadioService() function to look like the following (and the corresponding uartToRadioService() is similar):


while(usbComRxAvailable() && radioComTxAvailable())
{

	//radioComTxSendByte(usbComRxReceiveByte());

	receivedByte = usbComRxReceiveByte();

	// are we in a state which accepts a new channel byte?
	if(acceptChannelByte)
	{
		setRadioChannel(receivedByte);    // changes CHANNR as discussed
		acceptChannelByte = 0;
	}
	else
	{
	
		// change to a state which accepts a new channel
		if(receivedByte == CHANNEL_CHANGE_BYTE)
		{
			acceptChannelByte = 1;
		}
		else	// normal 'message' byte, subtract one and send it away
		{
			radioComTxSendByte(receivedByte - 1);
		}
		
	}

}

Since the channel changing relies on the PC or m3pi to send data serially, wrapper functions were necessary to ensure that the byte for channel-changing (0x00) was not accidentally sent. Wrapper functions increment all regular message bytes by 0x01 (which are then decremented in the WSA before wireless transmission). This means that the value 0xff is not ‘available’ for transmission, but for my purposes this is not a big limitation. Wrapper functions can either clamp or ignore these values.

Thanks again for your help!
Geoff

Well, the channel changing works, but I’m experiencing a problem. My multi-agent project requires that communications between the m3pis and the PC run fairly quickly, but it seems that I have to put quite a long delay (>150ms) into my .NET code after changing the channel on the Wixel attached to my PC, before writing to the serial port for radio transmission. Otherwise, packets are sometimes transmitted on the incorrect channel. The shorter the delay, the greater the chances are of this problem occurring.

By use of the red LED on the Wixel, I’ve determined that the channel change itself occurs quite quickly. I’m not sure what could be necessitating the delay I’ve written into my .NET code. According to the CC2511’s datasheet, the frequency calibration should be on the order of microseconds. Could someone please shed some light on this?

Below is the code I’m using to change the channel of the Wixel.

void setRadioChannel(uint8 channel)
{
	LED_RED(1);

	radioComInit();

	do
	{
		RFST = SIDLE;
	}
	while(MARCSTATE != 0x01);
	
	CHANNR = channel;
	RFST = STX;

	LED_RED(0);
}

Thanks,
Geoff

You’re using radio_link.lib and radio_com.lib at some level, right? You should be sure to wait for all the packets in radio_link’s buffers to finish being sent before calling setRadioChannel. I think maybe the problem is that there are a lot of packets queued up to be sent in radio_link’s buffers, but when your main loop receives the command to change the radio channel it does it immediately without waiting for the queued data to be sent and acknowledged. Perhaps your problem isn’t really solved by delaying after setting the channel, but solved by delaying (in Wixel firmware) before setting the channel?

–David

Done; that worked really nicely. The delay before changing channels is very brief, which is great. Thanks!

The only thing remaining is to clear the TX queue and change to the next requested channel if the TX queue doesn’t empty itself after a certain amount of time has passed (perhaps a robot has been powered down or is unresponsive). I’ll assume that adding the following function to the radio_link library will do the trick:

void radioLinkResetTxQueue()
{
    radioLinkTxInterruptIndex = radioLinkTxMainLoopIndex;
}

Hello, Geoff!

Would you mind posting your complete, working code here in case other people in the community want to do the same thing?

–David

Hi David,

If I recall correctly, this function should be all that is needed (in the radio_link library) to change a Wixel radio’s channel.

void radioLinkChangeChannel(uint8 channel)
{

	// ensure that the radio is in an idle state
	do
	{
		RFST = SIDLE;
	}
	while((MARCSTATE & 0x1f) != 1);

	// force the radio to recalibrate to the given frequency
	CHANNR = channel;

	do
	{
		RFST = STX;
	}
	while((MARCSTATE & 0x1f) != 0x13);

	// reset the sequence bits
	acceptAnySequenceBit = 1;
	rxSequenceBit = 1;
	txSequenceBit = 0;

	// reset TX and RX pointers
	radioLinkRxInterruptIndex = radioLinkRxMainLoopIndex;
	radioLinkTxInterruptIndex = radioLinkTxMainLoopIndex;
	radioLinkTxCurrentPacketTries = 0;

	// start trying to send a reset packet.
	sendingReset = 1;
	radioMacStrobe();

}

How this can be used is demonstrated in the Project Tabletop Multi-Agent Grid Nav project. All source code can be downloaded from here.

Geoff

Hi there,

I need to write a wixel application that allows one master wixel to talk to several wixels, and them to talk back. I don’t need to talk to several wixels at the same time, and the “slave” wixels do not need to talk to other slave wixels, just to the master.

I am thinking about adding a parameter in the app that would act like an address. Do you think it would be possible to modify the radio link library and the wireless serial app to have the ACK/NACK handshaking system working only when the first incoming bytes match that address. Then I guess I would have to use a byte combination at the end of each frame to clearly state that the transfer is over and that the wixel should not ACK or NACK any incoming data until that data matches its address again.

Or maybe that address could be the serial number of the wixel itself (to avoid any confusion that would be very likey to happen if the address was only only one byte long)?

Does that seem feasible to you?

Thanks a lot for any info you can provide me with!

Hi Kom,

While it should be possible to accomplish what you’re trying to achieve, it would require some pretty heavy modification of the Wixel libraries.

Your approach would also require that you know each of the Wixel’s ID numbers, which could either be simply (a) known in advance and hard-coded, or (b) broadcasted as each Wixel joins the network.

You might be better off using different hardware or relying on the channel-change model described in previous posts. I’ve been making some improvements to that approach recently that might suit your needs, with a little modification. Let me know if you’re interested.

Geoff

Hi Geoff,

Thanks a lot for your reply. I considered moving to another hardware but I want to investigate that wixel “mesh” network idea further. Since I am dealing with a certain amount of RF modules, there is a cost consideration here too. I have been using the wireless serial app with channel change that you provided actually, it works but again, considering the number of modules, there is a delay required for changing the channel that slows down the whole process.

So I started looking into the code, because if I understand correctly, the only thing that makes this communication possible only between 2 wixels is the handshaking/error handling system. Right? In the system I am working on, there is a “master” wixel that is central and will be the only one communicating with the several slave wixels. There is no broadcasting or talking to several wixels at once. All communications are between 2 wixels only, but there has to be more wixels on the network. Therefore, I can imagine a system where each wixel would have an address like 1,2,3 etc (set in the config utility), and each transmission would begin with two fixed bytes that act as a delimiter, and then that address. The radio link library would have to be modified so that the link layer will ignore any received byte if it has not previously received those 3 delimiting bytes. It would only ACK/NAK a packet once it has received these 3 bytes, and therefore knows the master is talking to “him”.

The master could scan each address every once in a while, counting each “alive” wixel in the network.

Do you think there is something I am missing here, that would make this harder than what I can think of?

Thanks!

The description of your plan seems incomplete to me because it doesn’t talk about what the plan will be for the actual radio packets. The Wixel’s radio operates on packets at the lowest level, not individual bytes. The radio_link library uses data, reset, and ackowledgement packets to make a lossless bidirectional communication pipe. You’ll have to think about what changes to those packets are necessary.

–David

Hi David,

Thanks for your reply. Do you think that it would be simpler and equally functional to implement a handshaking protocol on top of the radio queue library?

You could try something like that and probably get it working, but I don’t think it would be ideal because the radio_queue library does not give you much control over the timing of packets. For example, Wixels should acknowledge packets for them as soon as possible after the packet is received. Also, when you need to resend a packet, you would have the overhead of needing to copy the packet contents again.

–David

Hi David,

During my investigations, I browsed the CC2511 datasheet and found an option for packet filtering based on address. There is an address register (“ADDR”) that is supposed, when the PKTCTRL1 register is configured accordingly, to be tested against the “destination address byte” in an incoming frame (if the PKTCTRL has the packet address filtering option enabled, that would be the 2nd byte, after the length byte if I understand correctly). The incoming data is thus filtered depending on that destination address byte.

That actually sounds exactly like what I was trying to do.

Any experience or thoughts on that option?

Thanks again,

Côme

Hello, Côme. I have not tried the address feature of the CC2511 radio, but I have read about it and it seems like a good feature to use. --David

Hi David/Geoff

I am also trying to achieve a similar type of outcome, where as I can use one wixel connected to a PC via USB, to communicate with several other Wixels connected to other devices via UART.

Obviously this will be on a one-to-one basis so the Wixel will need to dynamically change the address to talk to any of the others.

I have read through this post and have been looking at modifying the wireless serial app.

I have dumped in Geoffs complete code that he posted here, including the updated lib file etc.

I then ran this app on the Wixel to try it out.

I communicated between the 2 wixels via ‘HT Comm’. And the wireless conenction worked as expected. i.e. type ‘a’ at one com port and ‘a’ was received at the other, showing that the wireless comms was good.

I assumed that by typing a ‘0’, followed by a new radio channel i.e. ‘6’, that this would change the new channel to channel ‘6’. Instead, it juse sent a ‘6’ accross the radio link.

Is this meant to happen? Have I made the wrong assumption to how this shouuld work? I apologise in advance, as there are a few holes in my C knowledge as I have not had much experience.

Any help would be much appreciated.

Thanks

Hi,

I believe typing a ‘0’ will actually send the character itself, not the value zero. You actually need to send a null byte to indicate that you want a channel change, followed by the numerical value representing the channel (i.e., not the character ‘6’, but the actual byte representing 6, 0x06).

As it is, the channel-changing app might be slightly buggy - I’ve written a simpler version that performs much better than the original. I use it in Project Paw Print, and I can provide you with the source code, if you wish.

Thanks,
Geoff

Ahhh ok. That makes sense.

I have been playing around with it this afternoon and got it to sort of work, but wasn’t ideal.

Yea if you could provide me with the source code that would be really great!

Thanks.

I’ll need you to PM me your email address.

Thanks,
Geoff