comms between many mbeds?

18 Jan 2010 . Edited: 21 Jan 2010

I am developing a project which includes 18 mbed mcu's which I'd prefer to connect via ethernet.  The mbeds and a couple PCs will all share data from various sensors, etc.. via this connection. The network will be private, and have no DHCP, DNS or internet connection.  I plan on using hard coded IP addresses for each device. 

Can anyone suggest a protocol or whatever suported by the mbed to use for this communication?  I'd prefer not to use http.  I'd prefer two way comms between whichever device decides it needs to share something with another device on the network.  It could be #4 telling #12 something one time, or #8 telling #4 something another, or at the same time... 

Any input is welcome, and I appreciate all comments or ideas!!

Thanks

-mark

18 Jan 2010

I'm not too familiar with it, but I think CAN might be better suited for such task.

18 Jan 2010

Thanks for the reply!

I had considered CAN..  I'm not too familiar with it either, with the exception that I'm pretty sure it's used in cars, etc.. for networking mcu's..  My major concern with that would be including the PCs in the loop, I probably could do a serial link via one of the mcu's or something but I'd really...really like it to be an ethernet free exchange sorta thing...  Mainly due to the fact that if this works out, there is the possibility of this network being given an 802.11 link to another network, etc.... 

 

18 Jan 2010

I just read wikipedia's page on CAN... http://en.wikipedia.org/wiki/Controller_area_network

It outlines the major reason I wouldn't be able to use CAN.... as I need all the mcu's to be able to talk and receive on the network simultaniously...

 "If the bus is free, any node may begin to transmit. If two or more nodes begin sending messages at the same time, the message with the more dominant ID (which has more dominant bits, i.e., zeroes) will overwrite other nodes' less dominant IDs, so that eventually (after this arbitration on the ID) only the dominant message remains and is received by all nodes"

18 Jan 2010 . Edited: 18 Jan 2010

I think MBED + Ethernet is a good fit for your task, so you're on the right path. If you use a switch instead of a hub, then multiple MBED's will indeed be able to talk to each other simultaneously over 100M links. You should be able to get away with simple TCP or even UDP sockets and avoid HTTP overhead altogether. If you look into LWIP (used by HTTPServer/Client), you may find an easy way to implement it. I remember Berkeley sockets are available in LWIP. Assign hard-coded IP addresses to each MBED, open listening (in) sockets which will respond by creating an out socket for each requestor, and go from there. I did something like that way back when I did Verilog/PLI co-simulation, not on MBED of course - used Berkeley sockets on Linux, and it worked just fine. I also used threads, but you may be able to get away with a simple event loop if you deal with tasks and latencies appropriately. I would recommend having HTTPServer there anyway for administration interface (mostly for debugging), but it is only to have nice gui into the guts. Good luck!

18 Jan 2010

If you had your 18 mbeds each connected to a port of a switch (This has the advantage of allowing transformerless operation) then the switch will manage the direct connection between mbeds. Then use standard TCP/IP or some other network protocol (so the switch can function properly). TCP/IP has the advantage of ensuring data is received. (although UDP will probably be 100% reliable as you only have 1 switch and 18 mbeds on the network...)

18 Jan 2010

... an 18-plus port switch would be a hard thing to find (and expensive). Would probably be a few 8-port switches linked together. But if those are gigabit switches, there will be virtually no bottleneck.

18 Jan 2010

I just took a look on the internet, getting 3 x 8 port switch is about the same price as 1 x 24 port switch.

18 Jan 2010
Mark x wrote:

It outlines the major reason I wouldn't be able to use CAN.... as I need all the mcu's to be able to talk and receive on the network simultaniously...

 "If the bus is free, any node may begin to transmit. If two or more nodes begin sending messages at the same time, the message with the more dominant ID (which has more dominant bits, i.e., zeroes) will overwrite other nodes' less dominant IDs, so that eventually (after this arbitration on the ID) only the dominant message remains and is received by all nodes"

I think with a little thought you should be able to make it robust... e.g. use ACK messages (which you would need anyway if you use UDP) to make sure a message was received. From what I've read, CAN would have much simpler wiring, no need for routers, and less complex software (no TCP stack).

Another choice might be I2C. You could assign each mbed a separate slave address, place them by default into slave mode, and switch to master mode when transmitting.

18 Jan 2010

Hmm, I've just read a bit more and it seems that for CAN you have to use a transceiver chip, you can't just connect mbeds with wires... that makes things somewhat more complex.

18 Jan 2010

Here's a nice tutorial on CAN and how it differs from Ethernet. Apparently it already includes provisions for acknowledgment:

"CAN provides a number of fault tolerance mechanisms. One is the inclusion of a 2-bit acknowledgment field. During the acknowledgment time after each packet is sent, the transmitter sends a recessive bit while any receivers send a dominant bit. The transmitter can thus determine that at least one node has received the packet. This prevents a disconnected node from continuing its transmission, blissfully ignorant that no one is listening."

18 Jan 2010 . Edited: 18 Jan 2010

Hi Mark,

Without knowing the precise spec and requirements (data rates, etc and like if you dont mind some additional hardware and expense per node), have you considered Zigbee. I have been using the Telegesis ETRX module, which is about £10 from farnell in one-off. Its a simple AT command set, it takes care of ACK and retramission for you and you get the ability to do things like broadcast, unicast and sink cast. Sink cast being the ability for one (or more) nodes to publicise themselves data sinks (presumably to route onto other networks) so that nodes in the mesh can simply "sink cast", without having to get bogged down in the detail.

I should write up the experiments I did some time...


Thanks,

Chris

 

18 Jan 2010 . Edited: 18 Jan 2010

The line drivers for CAN are fairly simple to wire up and cost about 80p each (probably less if you're buying 18), i'd suggest the microchip parts for this task as they come in DIP format which is easier for prototyping. MCP2551 I believe?

As you want to interface a PC, a suggestion use 1 mbed via ethernet to interface to the PC(s) and CAN connection between all the other mbeds, so a master/slave configuration. (Effectively the mbed is behaving like a commercial CAN interface card)

What sort of cable length are you looking at? CAN has range limits.

CAN operates in a token ring configuration, so there's no need for a switch.

Bus speed can be upto 1Mbit

As I assume you want realtime information you may want to consider adding a timestamp to each packet so synchronise the information, the other possible configuration is Time Triggered CAN but this is more complicated to configure.

19 Jan 2010 . Edited: 19 Jan 2010

Wow! Thanks everyone for the replies! 

I bought four 24port gigabit switches sometime ago and can use one of them...  TCP/IP would be my preferred method I think since it's available for the mbed as well as easy to implement on the PCs which will share the network and have to communicate with the mbeds..  CAN with the requirements for extra hardware, cost, and weight as well as the interface to the PC not being native just seems that it will require more development time, etc....   I really appreciate all the input, this is all great information!!  I've seen zigbee, haven't used one but I have worked with aerocomm boads and loved them..  If I haven't missed something, zigbee is all wireless...??  That would remove it from possible use as I need to ensure the connection is reliable and there is no chance for interference, or anything since lives would be at stake..  As well as keeping it as private as possible would be a nice addition.. Along with not having any possible crosstalk between similar networks, etc... 

So, all in all I think I agree that TCP/IP would be great on a single switch..  So in lies my problem..  My programming skills are a little shy of wrapping my whole head around the implementation of LWIP on the mbed..  I've had my 1st mbed for about a week now and have managed to get it to read stuff like gyro data from the wiiMotion+, do some simple filesystem stuff, and just played around a bit..  I love the device, the fact that it's got so many features...  I'm not even sure where to start with the TCP stuff.  I'm writing software for 18 mbeds, and at least two PCs to do all this which is a huge task.. heh..  I'll be writing the software on the PC end that speaks to the mbeds too, so I have a lot of room for whatever..  Would anyone have any advice on where to start?  And thanks for the note that I can hook them all up to the switch with no magnetics!  That helps..my switches don't have POE so it should be a go! And that saves components, cash, weight and time! =) 

I'd really like to thank everyone for the input and help..  I think I will keep CAN in mind, there's some use for that in another project I'll be undertaking after this one's off and running..  And I am sure I will find a place for zigbee in this project too as there's a  requirement for some wireless comms to a couple devices that do not merit an 802.11 link... I'd love to see the writeup!

-mark

19 Jan 2010

Thanks Igor for the link to the CAN tutorial..  It does have some good info, and outlined another reason I should go with ethernet...  I forgot about the need for sharing video from two camera's on the network, which is part of the 'possible' 802.11 link to another network I mentioned earlier..  =/ 

Does anyone know also, if you use a single switch with multiple devices and some do not have magnetics is that ok if others do?  Does that matter?  Also, with TCP/IP on the mbed....I understand it's not multitasking...so if a packet comes in while the cpu's say..reading a sensor or something...what goes on there?  Is the packet resent by the originator since there was no ack from the busy chip?  I'm showing my ignorance with TCP/IP now too.. ;) 

Thanks again to everyone!!

-mark

19 Jan 2010
Mark x wrote:

 That would remove it from possible use as I need to ensure the connection is reliable and there is no chance for interference, or anything since lives would be at stake..

I don't think you should be using mbeds then, or even LPC processors... From the user manual:

Suitability for use — NXP Semiconductors products are not designed, authorized or warranted to be suitable for use in medical, military, aircraft, space or life support equipment, nor in applications where failure or malfunction of an NXP Semiconductors product can reasonably be expected to result in personal injury, death or severe property or environmental damage. NXP Semiconductors accepts no liability for inclusion and/or use of NXP Semiconductors products in such equipment or applications and therefore such inclusion and/or use is at the customer’s own risk.

19 Jan 2010 . Edited: 19 Jan 2010

Thanks Igor, maybe saying 'lives' would be at stake is a listy hasty...  Maybe livelihoods... ;)  The failure of one or more of the processors would be rather unfortunate, but not catastrophic. Part of the goal is a little redundancy and task sharing.

20 Jan 2010

Ilya I, I've looked into the lwip http servers here... And read a bit on the lwip from http://www.sics.se/~adam/lwip/index.html and http://savannah.nongnu.org/projects/lwip/ .... 

I guess my first stumbling block is tackling the shear mass of the whole suite...  How much is required, and how it's been fitted to the mbed..  Do I have to include all the libraries, do I need all the complexity...  I'd like to find the simplest, smallest working solution I can get and make a tcp or udp connection..  Looking at the pub_iva2k_ethrpc http server has helped me see a little of how it can be tailored..  I'm trying to figure out how to chop the http server out(maybe throw it back in later- a good management interface isn't a bad idea.)...and see if I can just shoot some plain text from the mbed to a PC.. If I can get a hello from the mbed across a switch to a PC, the hard part for me is over and I can get the rest of this going!  So, again I really appreciate the kind words! And I'd LOVE to use the mbed, and would hate to use something like an arduino and a lantronix XPort serial to ethernet..

 

20 Jan 2010 . Edited: 20 Jan 2010

Mark,

I suggest importing the whole HTTPServer/HTTPClient tree (http://mbed.org/projects/cookbook/svn/EMAC/lwip/trunk, import as files) into your project instead of messing with LWIP code directly. HTTPServer/HTTPClient already has LWIP adopted to mbed (thanks to Rolf). There are also examples from LWIP one level up (http://mbed.org/projects/cookbook/svn/EMAC/lwip), so you can get to a lower level instead of higher-level HTTPServer/HTTPClient. So it is a good starting point.

To your question of getting rid of HTTPServer - you can remove all calls to it from main(), but keep the source files in the tree. That way it will stay out of your way. When you need it again - just plug it back in.

--

Ilya

21 Jan 2010

Ok, I got the ethernet magnetics and stuff from fedex today........so I've added the following bits to pub_iva2k_ethsntp - myrpc.cpp and it works great......printing the results to the serial terminal... 

void myrpc::initGyro(int rr) {
    const int add1 = 0xA6;
    char cmd[2];
    cmd[0] = 0xFE;
    cmd[1] = 0x05;
    i2c.write(add1,cmd,2);
    wait (0.1);
}
void myrpc::readGyro(int cycles) {
    char cmd[2];
    const int add2 = 0xA4;
        for (int i=0; i<cycles; i++) {
        int yaw, pitch, roll;
        cmd[0] = 0x00;
        i2c.write(add2,cmd,1);
        wait(0.01);
    
        char data[6];
        i2c.read(add2,data,6);
        wait(0.01);
        yaw = (data[3] - 131);
        pitch = (data[5] - 130);
        roll = (data[4] - 126);
        printf("Yaw:%d Pitch:%d Roll:%d\n",yaw,pitch,roll);
    }
}

I cannot for the life of me figure out how to get that to return to the web browser that requested the rpc call....   I've tried     sprintf(_buffer, "%s", yaw);
    return _buffer;  and a few variations but I get errors...   This isn't my long term solution, but I'm getting my feet wet with the lwip stuff.... =)

 Any advice? 

21 Jan 2010 . Edited: 21 Jan 2010

Mark,

For the RPC to return something back in the HTTPServer, you need to make your function return that value. If that is a string, you need to return char*. See myrpc::echo() in my example pub_iva2k_ethsntp. - echo takes in a string and returns it back, so http call will be:

http://my_mbed_ip/rpc/myrpc1/echo+"Some string to be echoed back"

Note that in my example I changed HTTPRPC.h to handle quoted strings in the URI.

Perhaps you know that, but another thing to note is that returning char* can be tricky - you have to allocate a buffer somehow to make it stay after function returns (if you juct return a local char[] variable, it won't work since it is allocated on stack and deleted upon function return). There are many ways to do it properly, but it is easy to create a memory leak if care is not taken.

Here's a quick fix using statically allocated buffer (I mis-indented my additions to illustrate the changes):

char * myrpc::readGyro(int cycles) {
    char cmd[2];
static char buffer[1024];     // use static keyword to make the buffer persist after function returns
    const int add2 = 0xA4;
buffer[0] = 0;   // init it to an empty string
        for (int i=0; i<cycles; i++) {
        int yaw, pitch, roll;
        cmd[0] = 0x00;
        i2c.write(add2,cmd,1);
        wait(0.01);
    
        char data[6];
        i2c.read(add2,data,6);
        wait(0.01);
        yaw = (data[3] - 131);
        pitch = (data[5] - 130);
        roll = (data[4] - 126);
sprintf(buffer,"Yaw:%d Pitch:%d Roll:%d\n",yaw,pitch,roll);
    }
return buffer; 
}

Of course you have to also change the RPC wrapper to use char* return type.

22 Jan 2010

Excellent!  You'll have to forgive my ignorance there..  ;)  I'm going to have to sit down and do some reading regarding handling those things.. 

I also changed { "readGyro", rpc_method_caller<myrpc, int, &myrpc::readGyro> },    to    { "readGyro", rpc_method_caller<char *, myrpc, int, &myrpc::readGyro> },   which did the trick..  Also, void readGyro(int cycles);    to   char * readGyro(int cycles); ...

Thanks so much for the help..  Now I'm going to sit down, do some reading and more fiddling.. 

This, along with Michael Wei 's recent posting on getting started with ethernet will certainly get me on the right track.  I should be able to figure it out from here.. I hope =)

Thanks Ilya....

and thanks everyone!