EasyTransfer Arduino Library

Posted in Arduino Libraries by Bill
30 May 2011
EasyTransfer Arduino Library

The purpose of this library is to make it easy for the everyday Arduino user working on projects with multiple Arduinos communicating with each other and sharing data. I had many people ask me for the code I used in my PS2X library example that sent PS2 Controller values wirelessly to my SAGAR robot. It got to be tiresome answering the questions and I had an idea to write a library to help the inexperienced with micro controller communications. This is a easy to use and no frills way to send data between two Arduinos.

In most of my own projects I define and write my own NMEA standard communication protocols. This makes communications human readable and easy to debug, but proves wasteful with bandwidth and processing power so it’s not right for every application. Binary communications is much more efficient and versatile, but requires careful handling. This library abstracts the finer points of packetized serial communication away from the user so it easy to use and understand.

To use the library, simple define all the data types you want to share inside a data structure. This keeps all the data stored together in memory.

struct SEND_DATA_STRUCTURE{
  //put your variable definitions here for the data you want to send
  //THIS MUST BE EXACTLY THE SAME ON THE OTHER ARDUINO
  int blinks;
  int pause;
};

When requested, the library will send all the binary data in the structure to another Arduino via serial with a checksum to avoid transfer errors.

void loop(){
  //this is how you access the variables. [name of the group].[variable name]
  mydata.blinks = random(5);
  mydata.pause = random(5);
  //send the data
  ET.sendData();
  delay(10000);
}

The receiving Arduino will verify the checksum, and copy the new data onto a identical structure in it’s memory.

void loop(){
  //check and see if a data packet has come in. 
  if(ET.receiveData()){
    //this is how you access the variables. [name of the group].[variable name]
    //since we have data, we will blink it out. 
    for(int i = mydata.blinks; i>0; i--){
      digitalWrite(13, HIGH);
      delay(mydata.pause * 100);
      digitalWrite(13, LOW);
      delay(mydata.pause * 100);
    }
  }

  delay(2500);
}

It’s important to make sure the structure is the same on both Arduinos for this to work. Now sharing data between Arduinos is easy without having to define and program your own communications protocol and have to worry about syncing or transmit errors. EasyTransfer will do that for you.

Using Structures to hold the data allows for versatile communications by allowing any type and number of data points to be shared, as long as the whole structure is under 255 bytes. You could define int’s, arrays, longs, etc inside the structure and share the data. It’s also possible to create two way communications by defining two sets of structs on each end and creating two objects using the library. I will have an example of that up shortly.

You can download the library and example below. The example requires two Arduino boards to be connected to each other via their Uarts. One will create two random numbers and send the data to the other that will flash out a sequence of flashes based on those numbers. The first one will also flash out the same sequence.

Now it’s easier to pick which Serial port to use; Serial, Serial1, etc. AND support for the NewSoftSerial library for creating software serial ports on any pin. EasyTransfer is for hardware serial, SoftEasyTransfer is for software; each has there own set of examples. There’s also an example for two way communications using the library.

Source Code available on GitHub project pages.

 

Or Direct Download

 

UPDATE

Thanks to Kumy, there’s now an I2C version of EasyTransfer. There’s also an experimental VirtualWire version for use with those cheap low frequency radios. All are in the single download zip file above.

 

To install the Library, open the zip file and transfer the EasyTransfer folder into your Arduino ‘libraries’ folder. Then follow the examples to add the code to your project. If you have any problems or questions, let me know in the Support Forum.

Need Help?

Please use the Support Forum to ask for help. Don’t use the comments below.

 

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

Share

Trackbacks / Pingbacks

  1. Comunicaciones entre Arduino y Skymega | /home/darkomen
  2. Bill Porter ported his EasyTransfer library to VirtualWire for me: Cheap wireless telemetry at last…. » itux.co.za - the Experiments

Warning: count(): Parameter must be an array or an object that implements Countable in /homepages/46/d285670699/htdocs/bill/wp-includes/comment.php on line 879
  1. 443 Comments.

    • ConstantinNo Gravatar says:

      Hi Bill,

      I am still enjoying easy-transfer between the two atmels on my PCB… they are pushing the data at 1Mbit/s, and it seems to work great.

      I have a question regarding the use of EasyTransfer on Arduinos with multiple serial ports or those that want to use softserial to add more serial ports. In particular, I am thinking of using a quasi-spi approach, where the master Atmel alerts an outlying Atmel that there is a request for data, and that the outlying Atmel then send the data to the master via Serial (better range and all that than SPI).

      However, that might only work with all outlying Atmels sending either the same data packages or redefining the RECEIVE_DATA_STRUCTURE command on the fly. Is the latter permissible? That is, can I change the expected structure within the loop() section of the Arduino IDE as needed or does it have to be static?

      • BillNo Gravatar says:

        I wouldn’t redefine the Structure but just create multiple objects of the library with the same serial port and different structures. Since the master knows which slave is going to send information, it calls the corresponding ET instance’s RX function. Also note that if something messes up, the wrong ET instance is called and the expected and received packet are different sizes; the library will drop the received packet instead of corrupting memory. IF they are the same size, then memory may get corrupted.

        I flirted with the idea of adding features to be able to label (address) transmissions so the RX Arduino would know which structure to dump the data too. It sounds like you are the first person that might find that useful.

        • ConstantinNo Gravatar says:

          Hi Bill and thanks for the quick reply!

          I apologize in advance and I guess my background as a ME / mfg guy is showing itself… in a concrete 2-device example, do you mean the following type setup?

          …ET init, etc. … followed by

          struct RECEIVE_DATA_STRUCTURE{
          double realPower,apparentPower,Vrms,Irms;
          };

          RECEIVE_DATA_STRUCTURE PowerData;

          struct RECEIVE_DATA_STRUCTURE{
          long pulse_counts;
          float temperature;
          };

          RECEIVE_DATA_STRUCTURE Pod1Data;

          … followed by the setup() and loop()?

      • RichardNo Gravatar says:

        Can I see a copy of your code?
        I have one way transfer working but two way transfer is not. thanks,
        Rick

    • sandeepNo Gravatar says:

      Hi Bill,

      I’m looking to have communications between two arduinos (Unos) with sensor data coming from the 2nd arduino displayed on a laptop connected to the 1st arduino. The 1st arduino would also send control data to the 2nd one to control some motors there.

      Is it possible to use the SoftEasyTransfer for 2-way communications to implement this as I understand that I won’t be able to use the tx/rx pins as well as USB on the 1st Arduino.

      Also what sort of range would I get using this method between two arduinos?
      I’m looking to eventually extend communication to 25m-50m using cable.

      Many thanks from a new Arduino user.

      • BillNo Gravatar says:

        sandeep,

        What is the purpose of the Arduino connected to the computer? IF it’s just relaying information, why not get rid of it and just connect the laptop to the remote arduino via a long cable?

        If it’s doing something else important, yes you could use the software version of the library to do 2way communications.

        Range is a function of the type of connection between the arduinos, my library won’t help or hinder that. 25-50m should be ok if you use a slow serial speed, like 9600 or 4800.

        • sandeepNo Gravatar says:

          Bill, thanks for the quick reply.
          The Arduino connected to the computer is getting used with a PS2 controller using your excellent library.
          Eventually I would get rid of the computer and use an LCD screen with the Arduino.
          I am going to use the low 9600 rate and look into using RS-485 if it does not work well enough.

          Thank you for your help!

    • richNo Gravatar says:

      do you really need twisted pair? You would only need it for long runs right?

      • BillNo Gravatar says:

        RS-485 is differential signalling. That alone doesn’t buy you much noise rejection unless it’s used over twisted pair. Twisting the wires together makes sure any interference is ‘felt’ equally by both wires and can be rejected by the receiving diff amp as common mode noise. If you don’t use twisted pair, you don’t gain much advantage by using RS-485.

    • DaveNo Gravatar says:

      Great library! It’s helping us out on a project where we’re trying to deliver new content to a micro-SD card on one Arduino from another.

      We’re doing about 1kB/s (~ two 512-byte blocks per second), but that seems …slow. With the above talk about getting 1Mbit/s, we’re wondering if you’ve done speed tests with the library? How fast _can_ it go?

      • BillNo Gravatar says:

        Hi Dave,

        Well, the fastest the serial port can go is 115200 b/s or 14.4KB/s (that’s Bytes). My library only puts on 4 extra bytes in overhead and maximum payload size is 255 bytes, so you could send about 55 transfers a second with a full 255 byte payload. Problem is the single core AVR chips have other things to do like write to SD cards or prepare and verify sent and received packets via my library. So limitations I can’t account for reduce that number further. Arduino 1.0 changed serial function to non-blocking, so while the serial port is sending information your program can be doing something else. It used to be that the program would stop while serial was sending. So that change helps improve speed, but I don’t have any figures on by how much. Your limiting factor is how long my library takes to wrap and unwrap the data, and what other stuff the Arduino is doing.

        Physically it still communicates at 115200 b/s which is why it’s important to discuss that speed when it comes to wire lengths and stuff, but practically the Arduino can’t keep up with a constant data stream that fast and do other things at the same time.

    • ConstantinNo Gravatar says:

      Allow to disagree a little. I have two Arduinos communicating amongst themselves at 1Mbit per second. It made a 1% daq rate acquisition difference with the 022 version of the IDE, now it’s likely lower since the serial port no longer hogs the CPU like it used to.

      Other forum participants have used putty and similar terminal programs to also communicate at 250kbit/s and higher. The issue as I see it twofold. For one, sticking to baud rates that are not zero error per the atmel datasheet is a mistake. That is, with a 16Mhz or 8MHz or even 20MHz clock, data rates that are not 250kbaud, 125kbaud, 500kbaud, or 1Mbit/s will result in errors due to the mismatch between the processor speed and the baud rate.

      I am sure that there are good reasons to stick to the baud rates first popularized by analog phone couplers for lower speeds where data rate errors are not present. A lot of legacy hardware is built around those speeds. At the same time, these traditional speeds are a hindrance when it comes to matching the CPU speeds they selected for the arduino hardware.

      But the IDE also does not allow the user to set speeds independently – all you get is a limited pull-down menu. I understand the need for simplicity and all that but why not allow users to change the pull down menu options via entries in preferences.txt or whatnot (grumble).

      • BillNo Gravatar says:

        Ok, so you are going outside the ‘standard’ Arduino baud rates up to the 16 MHZ AVR’s max at 1 Mb/s. I had forgotten the 250k, 500k, and 1m are actually acceptable 0 error rate speeds.

    • […] en el Arduino Playground, he encontrado la libreria EasyTransfer. Que facilita el trabajo a la hora de mandar información por el puerto serie. Trae un ejemplo muy […]

    • PeterNo Gravatar says:

      Thanks, I really love this library.

      I have it working with two XBees, but want to lower the cost, as the application I am testing only requires one way comms.

      Can I use the 433Mhz transmitters.receiver pair from Sparkfun?

      Peter

      • BillNo Gravatar says:

        Peter,

        Those 433Mhz radios require different signalling to operate. They shouldn’t be attached to a uart, and have funky rules like there must be a equal amount of 0s and 1s transmitted. There’s already a library to use those radios like they should be used. But you could adapt my Easy Transfer library to use the Virtual Wire library.

        I haven’t though of writing a spin off version for those radios using the virtual wire library, but if I find time I’ll consider writing one.

        • peterNo Gravatar says:

          I have seen Virtualwire, but I am absolutely lost on how to implement it as easily as yours.
          You’re method of assigning a list variables and sending across the wire is just genius!

          One example where I am using it is – I build a small PCB with two analog joysticks, 6 buttons on it attached to an Atmega8 running Arduino.

          The UART is broken out and attached to the uart on the robot.

          I set values like mydata.XVAL, mydata.YVAL, mydata.Throttle and mydata.BUTTON1 etc in ET.

          Then the Atmega on the Robot need only interpret those like the buttons was onboard…

          Easiest way ever… Replaced the serial cable with two XBees and bob’s my uncle. But as I only have two XBees and need to move them to a new project, I would forever be indebted if you would create an EasyTransferVirtualwire library!

          Peter

    • DaveNo Gravatar says:

      We’ve got 10cm wires connecting two Arduino UNO units, and we’ve successfully cranked up the rate to just over 500,000 baud, which is, well, approximately 4X faster than the 115,200 we were using.

      We’ll try parameters around Constantin’s suggestions later.

    • […] at last….  Uncategorized  Add comments Feb 012012   I have been using EasyTransfer from Billporter.info for a while now.  A big requirement for me, has lately been to replace the […]

    • DDeaNo Gravatar says:

      Hi Bill,

      I have been using your library for a while now and i have just started a project that will be using an attin4313.

      I tried to upload the TX Example (changing the pin from 13 to 7) but i get no blinks.

      What modifications need to be made to get this working on the attiny chips?

      Thanks
      DDea

      • BillNo Gravatar says:

        DDea, the library depends on the Serial or SoftSerial libraries to function. Can you verify the serial is working by sending and receiving a single character from the Attiny without using my library first?

    • DDeaNo Gravatar says:

      Hi Bill,

      The Attiny Serial works fine!!

      I think I may have figured it out. SRAM on the attiny is rather small so i made this addition to your library’s EasyTransfer.h.

      #if defined( __AVR_ATtinyX313__ )
      uint8_t rx_array[64];//RX packet parsing buffer
      #else
      uint8_t rx_array[255]; //RX packet parsing buffer
      #endif

      I usd 64 as it was the first setting i chase that did not hang.

      Thanks

      • BillNo Gravatar says:

        Seeing as the ATtiny only has 250 bytes of Ram, that would explain it. In retro-spec it seems silly I’m not using dynamic memory allocation based off the size of the data struct, but I don’t have any experience with that.

      • BillNo Gravatar says:

        DDea, newest version has dynamic memory allocation now which conserves RAM. As long as your struct size doesn’t get too large, the library won’t crash the ATtiny, or any AVR for that matter. Click the download link to get the newest version.

    • Daniel EgbertNo Gravatar says:

      Bill,

      I am new to arduino’s and xbee’s and I am trying to use your easy transfer library for my college senior project. I have a DFR robotshop rover communicating with an UNO via xbee series one. I need the rover to pass analog values to control a pan/tilt setup and I am also using it to pass char’s to run a switch statement to drive the robot. I can get the pan/tilt or the robot driving with your library, but cannot get them both to work together running at the same time. The servo’s go nuts and the robot barely drives( the tracks are jittery). I am running a baud rate of 9600.

      I see you can only transmit 255 bytes at a time. I made sure my char’s for the switch were 1 byte instead of analog values from the potentiometer.

      Do I need to make another struct to pass the data?

      Do I need to up my baud rate to solve my problems?

    • Jerry IsdaleNo Gravatar says:

      I’m enjoying your EasyTransfer library. I currently have it running from one host arduino reading various input devices to five Teensy arduino clone boards each controlling an LED strand based on structure sent via EasyTransfer. Oh yeah, a 6th Teensy is reading the data and displaying it on a small TFT display.

      My issue is with adding a second EasyTransfer line. This one is intended to live on the host and receive data from a Vocalizer arduino (which has a microphone. I was hoping to have it do a bit of fft/spectrum processing so the LED strips could display power across spectrum bands.

      Unfortunately when I start the second EasyTransfer object (audioEZXfer.begin(…)) the arduino freaks and goes into an infinite reboot… it restarts the setup() gets a bit in and the restarts.

      Have you tried having two EasyTransfers in same arduino?
      Not send/receive on one, but send on one, receive on different object.

      I’m going to bypass this for now, ’cause the job needs to be done wednesday – done being defined by what is complete. But I intend to come back to it and would like to have this feature working.

      I’ll try and work up a small example/test rig and upload it.

      Thanks

      • Jerry IsdaleNo Gravatar says:

        ok. I really hate intermittent problems. I moved things around (physically) and then the app started working again. Grrr. If I can reproduce it again, I’ll let you know.

        • BillNo Gravatar says:

          So it’s working now? To answer your question, I have tried creating two ET objects in one sketch. The 2-way example creates two objects, one is receiving, one is sending. In fact the 2way example sounds like exactly what you are trying to do.

          I just added dynamic memory allocation for the parsing buffer, so it worries me you are having issues. If the RAM is near full when ET.begin() asks for more ram to create a parsing buffer, it may cause the crash. Using dynamic memory is risky, but it is more efficient with RAM then defining the buffer during compile time.

          Let me know if it’s still causing you grief and I’ll see if we kind find the problem.

    • RickNo Gravatar says:

      Or, the Arduino liked that spot better? lol

    • ConstantinNo Gravatar says:

      Hi Bill,

      Quick (I hope!) question… does the EasyTransfer library allow the checksum results to be used to poll for a data packet re-transmission in case the first signal has an invalid checksum?

      I’d think that would be a pretty nifty feature, i.e. to have the option for the two Arduinos to acknowledge that the transmission has been successful. I gather I can probably do that with your RX TX example, but I don’t recall a error trigger in there calling for a re-transmit in case of a garbled transmission.

      Would this be easy to do?

      • BillNo Gravatar says:

        The library itself does not and I chose to do it that way so the channel of data going the opposite way would be clear for whatever the enduser wants to do with it; either for another instance of an ET library or other communications.

        It would be easy for the enduser to write their own retransmit. On the receiving end: if(ET.receiveData()) Serial.print(“A”); and on the transmitting end have it send data, wait a bit then look for an A coming back. If no A comes back send again.

        I may add it to a future version as a feature you can turn on, but it would not be much different then what I just described.

        • ConstantinNo Gravatar says:

          Bill,

          As usual, you are right. It’s best to leave it up to the user to determine how many re-transmits should be attempted, etc. My boards are hopefully completed soon, then the great RS485 experiment will begin!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.