Comments: Internet Datalogging With Arduino and XBee WiFi

Pages

Comments 31 comments

  • Hello, i have adjusted this code to meet my requirements but once i plug it all up, the only thing on the serial monitor is: Testing connection it stays there and nothing else happens… I have configured my xbee wifi with X-CTU and it show to be connected with wifi but as soon as i plug it on my arduino xbee sheild, it doesnt connect and i get the Testing Connection messdage only once i upload the code.. when i am programming i put the jumper on the USB and once it has uploaded, i change it to XBEE but it has no effect. any help on this would be helpfull please! heres the code:

    #include <SoftwareSerial.h>
    

    // The Phant library makes creating POSTs super-easy

    include <Phant.h>

    // Time in ms, where we stop waiting for serial data to come in // 2s is usually pretty good. Don’t go under 1000ms (entering // command mode takes about 1s).

    define COMMAND_TIMEOUT 2000 // ms

    // WiFi Network Stuff //

    // Your WiFi network’s SSID (name): String WIFI_SSID = “saqib”; // Your WiFi network’s encryption setting // Set the “encrypt” variable to one of these four characters: // OPEN = 0, WPA_TKIP = 1, WPA2_AES = 2, WEP = 3 enum encryption{NO_SECURITY, WPA_TKIP, WPA2_AES, WEP}; encryption WIFI_EE = WPA2_AES; // Your WiFi network’s passphrase (if necessary). If your network // is open, make this a blank string (passphrase = “”;) String WIFI_PSK = “saqibwifipassword”;

    // Phant Stuff //

    String destIP = “54.86.132.254”; // data.sparkfun.com’s IP address

    // Phant phant(server, publicKey, privateKey); Phant phant(“data.sparkfun.com”, “o85jyKNrXEIK32Gw4byN”, “yzo87X59jEU2DZbEV5N8”); // Phant field string defintions. Make sure these match the // fields you’ve defined in your data stream: const String AirTempField = “AirTemp”; const String CamErrField = “CamErr”; const String CrankErrField = “CrankErr”; const String FuelConField = “FuelCon”; const String FuelPressField = “FuelPress”; const String GearField = “Gear”; const String KPHField = “KPH”; const String LambdaField = “Lambda”; const String MAPKpaField = “MAPKpa”; const String OilPressField = “OilPress”; const String OilTempField = “OilTemp”; const String RPMField = “RPM”; const String TPSField = “TPS”; const String VoltsField = “Volts”; const String WaterTempField = “WaterTemp”;

    //////////////// // XBee Stuff // //////////////// const byte XB_RX = 2; // XBee’s RX (Din) pin const byte XB_TX = 3; // XBee’s TX (Dout) pin // We’ll use “xB” from here-on to send and receive data to it: SoftwareSerial xB(XB_RX, XB_TX); const int XBEE_BAUD = 9600; // Your XBee’s baud (9600 is default)

    //set the baud rate up to match the one on the can bus

    ///////////////////////////// // Input Pin Stuff // ///////////////////////////// int a; int b; int c; int d; int e; int f; int g; int h; int i; int j; int k; int l; int m; int n; int o; //think about adding the CAN bus variables here

    ///////////////////////// // Update Rate Control // ///////////////////////// // Phant limits you to 10 seconds between posts. Use this variable // to limit the update rate (in milliseconds): const unsigned long UPDATE_RATE = 10000; // 10000ms = 10 seconds unsigned long lastUpdate = 0; // Keep track of last update time

    /////////// // Setup // /////////// // In setup() we configure our INPUT PINS, start the XBee and // SERIAL ports, and CONNECT TO THE WIFI NETWORK. void setup() { // Set up sensor pins: // a=0; // b=0; // c=0; // d=0; // e=0; // f=0; // g=0; // h=0; // i=0; // j=0; // k=0; // l=0; // m=0; // n=0; // o=0;

    // Set up serial ports: Serial.begin(9600); // Make sure the XBEE BAUD RATE matches its pre-set value // (defaults to 9600). xB.begin(XBEE_BAUD);

    // Set up WiFi network Serial.println(“Testing network”); // connectWiFi will attempt to connect to the given SSID, using // encryption mode “encrypt”, and the passphrase string given. connectWiFi(WIFI_SSID, WIFI_EE, WIFI_PSK); // Once connected, print out our IP address for a sanity check: Serial.println(“Connected!”); Serial.print(“IP Address: ”); printIP(); Serial.println();

    // setupHTTP() will set up the destination address, port, and // make sure we’re in TCP mode: setupHTTP(destIP);

    // Once everything’s set up, send a data stream to make sure // everything check’s out: Serial.print(“Sending update…”); if (sendData()) Serial.println(“SUCCESS!”); else Serial.println(“Failed :(”); }

    ////////// // Loop // ////////// // loop() constantly checks to see if enough time has lapsed // (controlled by UPDATE_RATE) to allow a new stream of data // to be posted. // Otherwise, to kill time, it’ll print out the sensor values // over the serial port. void loop() { // If current time is UPDATE_RATE milliseconds greater than // the last update rate, send new data. if (millis() > (lastUpdate + UPDATE_RATE)) { Serial.print(“Sending update…”); if (sendData()) Serial.println(“SUCCESS!”); else Serial.println(“Failed :(”); lastUpdate = millis(); } // In the meanwhile, we’ll print data to the serial monitor, // just to let the world know our Arduino is still operational: readSensors(); // Get updated values from sensors Serial.print(millis()); // Timestamp Serial.print(“: ”); Serial.print(a); Serial.print(‘\t’); Serial.print(b); Serial.print(‘\t’); Serial.print©; Serial.print(‘\t’); Serial.print(d); Serial.print(‘\t’); Serial.print(e); Serial.print(‘\t’); Serial.print(f); Serial.print(‘\t’); Serial.print(g); Serial.print(‘\t’); Serial.print(h); Serial.print(‘\t’); Serial.print(i); Serial.print(‘\t’); Serial.print(j); Serial.print(‘\t’); Serial.print(k); Serial.print(‘\t’); Serial.print(l); Serial.print(‘\t’); Serial.print(m); Serial.print(‘\t’); Serial.print(n); Serial.print(‘\t’); Serial.println(o); delay(1000);

    //add the messgae bytes here to display on the serial monitor }

    //////////////// // sendData() // //////////////// // sendData() makes use of the PHANT LIBRARY to send data to the // data.sparkfun.com server. We’ll use phant.add() to add specific // parameter and their values to the param list. Then use // phant.post() to send that data up to the server. int sendData() { xB.flush(); // Flush data so we get fresh stuff in // IMPORTANT PHANT STUFF!!! // First we need to add fields and values to send as parameters // Since we just need to read values from the analog pins, this // can be automized with a for loop: //readSensors(); // Get updated values from sensors. //phant.add(tempField, tempVal); //follow this as shown

    phant.add(AirTempField, a); phant.add(CamErrField, b); phant.add(CrankErrField, c); phant.add(FuelConField, d); phant.add(FuelPressField, e); phant.add(GearField, f); phant.add(KPHField, g); phant.add(LambdaField, h); phant.add(MAPKpaField, i); phant.add(OilPressField, j); phant.add(OilTempField, k); phant.add(RPMField, l); phant.add(TPSField, m); phant.add(VoltsField, n); phant.add(WaterTempField, o);

    // After our PHANT.ADD’s we need to PHANT.POST(). The post needs // to be sent out the XBee. A simple “print” of that post will // take care of it. xB.print(phant.post());

    // Check the response to make sure we receive a “200 OK”. If // we were good little programmers we’d check the content of // the OK response. If we were good little programmers… char response[12]; if (waitForAvailable(12) > 0) { for (int i=0; i<12; i++) { response[i] = xB.read(); } if (memcmp(response, “HTTP/1.1 200”, 12) == 0) return 1; else { Serial.println(response); return 0; // Non-200 response } } else // Otherwise timeout, no response from server return -1; }

    // readSensors() will simply update a handful of global variables // It updates tempVal, lightVal, coVal, and methaneVal void readSensors() { a = a + 1; b = b + 2; c = c + 3; d = d + 4; e = e + 5; f = f + 6; g = g + 7; h = h + 8; i = i + 9; j = j + 10; k = k + 11; l = l + 12; m = m + 13; n = n + 14; o = o + 15;

    }

    /////////////////////////// // XBee WiFi Setup Stuff // /////////////////////////// // setupHTTP() sets three important parameters on the XBee: // 1. Destination IP – This is the IP address of the server // we want to send data to. // 2. Destination Port – We’ll be sending data over port 80. // The standard HTTP port a server listens to. // 3. IP protocol – We’ll be using TCP (instead of default UDP). void setupHTTP(String address) { // Enter command mode, wait till we get there. while (!commandMode(1)) ;

    // Set IP (1 - TCP) command(“ATIP1”, 2); // RESP: OK // Set DL (destination IP address) command(“ATDL” + address, 2); // RESP: OK // Set DE (0x50 - port 80) command(“ATDE50”, 2); // RESP: OK

    commandMode(0); // Exit command mode when done }

    /////////////// // printIP() // /////////////// // Simple function that enters command mode, reads the IP and // prints it to a serial terminal. Then exits command mode. void printIP() { // Wait till we get into command Mode. while (!commandMode(1)) ; // Get rid of any data that may have already been in the // serial receive buffer: xB.flush(); // Send the ATMY command. Should at least respond with // “0.0.0.0\r” (7 characters): command(“ATMY”, 7); // While there are characters to be read, read them and throw // them out to the serial monitor. while (xB.available() > 0) { Serial.write(xB.read()); } // Exit command mode: commandMode(0); }

    // connectWiFi(id, ee, psk) //

    • I hit the same problem. I added some code in the commandMode function:

      waitForAvailable(1);
      Serial.print("... xB.available = "); //debug
      Serial.print(xB.available()); //debug
      Serial.print("\n"); //debug
      if (xB.available() > 0)
      

      And found that xB.available() always returns zero. I’m still trying to troubleshoot that problem but at least I know what’s going on.

  • Would there be a way to implement this with the Lilypad Arduino? Any advice you can provide would be very helpful

  • Hello, total newcomer here! Could I in theory use this tutorial to create my humidity/temperature recording project? Obviously I’d discard the other sensors used here and just add an appropriate humidity sensor (or use a sonsor that does both).

    Could I also download the resulting data, having uploaded it to the cloud, add it to a spreadsheet on my PC and then use that spreadsheet to provide data for a simple visual basic UI?

    Regards, Ben.

  • One year ago, or so, I had no problem with any of the hardware or software in this tutorial. Now, however, it seems that the Xbee cannot connect using the provided software. I get the message: Waiting to connect: CF.

    Two things to note: 1) CF is not one of the status options within connectedWiFi, so where is it coming from? 2) There is no problem with the XBee itself, as I have no problems connecting to my router when I use XCTU.

    Does anyone know what could be going on?

  • Hi. Thanks for the great tutorial!

    My question is: I have an e8266 and I am wondering if I could use it instead of the xbee?

  • Great tutorial.. However, I could not figure out how to post 2 rows for a particular parameter? For example, in the current example, if I have to post two values at a time under the “temp” - one actual and one setpoint, then how do I insert both, rest of the parameters have one value. I tried to give a ‘\n’ before appending the next data, but that didn’t work. Is there a problem with the json parser or something?

  • My project is very similar to the one described in this article, except for one detail. I would be collecting data from a rc car, which means that WiFi from my home would not be available. Is it still possible for me to collect data such speed and battery voltage wirelessly and stream this data to a website? If so, what additional equipment would I need? Thank you very much for your help.

  • OK, let me try another avenue. I can probably write my own code if I could figure out what the phant library does. The Phant phant command obviously concatenates a string containing the website and the public and private keys. Does phant do anything else? Is there a description someplace?

  • Hi, This example does exactly what I have been looking for, but I own an CC3000 rather than an XBee. I’ve managed to work around most issues, but cannot see how to perform the tasks in the setupHTTP. Can anyone tell me how to set the destination ip, the port and the ip protocol on a CC3000?

  • HI all, I have had the same issues as described here when I tried to send data, I have taken the code, tested every different possibilities and solutions and came up with a working piece of code here. Feel free to use it and please comment back to let me know how it performed for you. Make sure you write down your public key and your private key at the beginning of the sketch where it is written in bewteen the “ ” (YOUR PUBLIC KEY HERE and YOUR PRIVATE KEY HERE). Your Xbee needs to be configurated prior to this with X-CTU to be connected on your WiFi already.

    #include <SoftwareSerial.h>
    #include <stdlib.h>
    
    String server = "data.sparkfun.com";
    String publicKey = "YOUR PUBLIC KEY HERE";
    String privateKey = "YOUR PRIVATE KEY HERE";
    #define IP "54.86.132.254" // data.sparkfun.com
    SoftwareSerial xb(2, 3); // RX, TX
    const byte VALUES = 4;
    enum field_labels {SV, BV, CC, OC};
    const String Names[VALUES] = {"&solar_voltage=","&battery_voltage=","&charge_current=","&output_current="};
    float Data[VALUES];
    boolean battery_Charged = true;
    void setup()
    {
      xb.begin(9600);
    }
    
    void loop(){
    
      Data[SV] = analogRead(A0)/1024.00 * 30.00;
      Data[BV] = analogRead(A1)/1024.00 * 30.00;
      Data[CC] = analogRead(A2)/1024.00 * 10.00;
      Data[OC] = analogRead(A2)/1024.00 * 10.00;
    
      char buffer[7];
    
      xb.flush(); // Flush data so we get fresh stuff in
    
      xb.print("GET /input/");
      xb.print(String(publicKey));
      xb.print("?private_key=");
      xb.print(String(privateKey));
    
      for (int j=0; j<VALUES; j++)
      {
      xb.print(Names[j]);
      dtostrf(Data[j], 3, 2, buffer);
        for(int i=0;i<sizeof(buffer);i++)
      {
        xb.print(String(buffer[i]));
      }
    }
    
      xb.print("&battery_charged=");
      xb.print(String(battery_Charged));
    
      xb.println(" HTTP/1.1");
      xb.print("Host: ");
      xb.println(server);
      xb.println("Connection: close");
      xb.println();
      delay(10000);
    }
    
    • I like your simplified code, but I wasn’t able to get it to successfully update my stream on data.sparkfun.com. I know my Xbee is connected to the internet, and I was able to run through the Digi Cloud example and toggle an LED, read a trimpot etc. I’m able to ping my Xbee as well. When I run this code (after updating with my public and private keys) I get … nothing. I tried adding some debug commands and I see that xb.available() always returns 0. Any suggestions for troubleshooting?

      EDIT: I can see the GET /input... showing up on the Serial Terminal part of the dashboard on the Xbee Wifi Cloud Kit Page. So it’s clearly sending the data somewhere … Do I need to change anything more than what is indicated in the setupHTTP() function?

      // Set IP (1 - TCP)
      command("ATIP1", 2); // RESP: OK
      // Set DL (destination IP address)
      command("ATDL" + address, 2); // RESP: OK
      // Set DE (0x50 - port 80)
      command("ATDE50", 2); // RESP: OK
      

      EDIT #2: I needed to set DO to 0x18 using XCTU. The crucial piece of info I was missing was that bit 3 was set to 0, so the contents of DL were not being used. Now I’ve got something working!

  • Hi! I am very new in electronics, just started to wire-up this project. I would like to know the sizes of the capacitor used in this project ..I have read the capacitors tutorial with couple of youTube videos, I haven’t found any formula yet, that will help in capacitor sizing. Thank you.

    • Hi, if you look at the first page there is a wishlist of all the parts used in the tutorial. I don’t believe a capacitor is needed in this tutorial though.

  • Question: Once I have a project setup and logging to the Phant server, can I then build my own website and import that info live to my site to incorporate it into graphs and images? I basically want to have a better visual reference for the data. Or should I just skip the Phant server all together and import the info straight to the webpage? Thanks!

  • Hi guys. I’m new to internet of things, and dont know much. I’m getting this error: Sending update…HTTP/1.0 502ÝìÞ Failed :(

    please help!!!

  • I am having a post issue as well. When looking at the serial output I am getting everything up to “Sending update: Success!!!” followed by “time : sensor info” continuously but nothing gets posted to the web. I modified the sensor info (I only have one sensor) but nothing outside of that. Furthermore the serial data “time: sensor data” being printed is evidence that I didn’t mess that bit up. I’m using a pro mini 3v, an xbee breakout, and an analog uv sensor. TX RX (3,2) and A0 for the sensor. Frustrating…

    EDIT: This is all that’s happening in wireshark. After the ARP request there is no further communication happening.

    DCHP Discover
    DHCP Request
    ARP Who has 192.168.1.1? Tell 192.168.1.5
    

    EDIT 2: I have confirmed that it is not the module, the ability for the module to talk to the Pro Mini 3v, or the module’s ability to connect and post to the internet. I can successfully post serial data to Etherios using the Xbee S6B connected to Software Serial and an FTDI breakout attached to the Pro Mini 3v.

    EDIT 3: Using the default code with no sensors attached and the sensor values manually set to zero for testing purposes this is what I get when I print phant.url(). Note that I’ve also tried the below method of commenting out the lines suggested in setup() below.

    http://data.sparkfun.com/input/PUBLIC_KEY.txt?private_key=PRIVATE_KEY
    

    The phant.url function should produce something like: (as per the README)

    http://data.sparkfun.com/input/PUBLIC_KEY.txt?private_key=PRIVATE_KEY&val1=url&val2=22&val3=0.1234
    

    It appears as though string concatenation isn’t happening as it should in my case. This is what printing phant.post() returns:

    POST /input/PUBLIC_KEY.txt HTTP/1.1
    Host: data.sparkfun.com
    Phant-Private-Key: PRIVATE_KEY
    Connection: close
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 0
    

    Edit 4: I suspect the use of String is causing memory fragmentation. Why not use PROGMEM instead…

    Edit 5 (FINAL): So after days and many hours of netcat, putty, wireshark, and XCTU shenanigans I have learned a lot about the Xbee S6B on firmware 2021. My conclusion is that using Software Serial is not a good recommendation for all µC. On my 8 MHz devices, Software Serial (As of Arduino 1.0.5) is just not reliable which is why the programs haven’t been working. After monitoring the Software Serial from the Pro Mini using an FTDI cable it was clear by the sprinkled garbled characters that this was the issue. If at all possible use Hardware Serial for Xbee communication or any other UART communication and Software Serial for debugging ONLY. I’m thinking I will get a Teensy moving forward as it has a UART interface independent of its USB and fits my 3v requirements. That said, using the Xbee S6B in SPI mode would solve these issues, increase potential throughput, and there is already a library for it xbee-wifi-spi-arduino. The downsides to this approach are that it is more complex, requires knowledge of somewhat complicated networking to achieve even simple tasks, requires more pins, and is more resource intensive.

    To Jimb0: This doesn’t mean there wasn’t an issue using String Objects. That still exists and I recommend using PROGMEM instead like the example I posted.

    As for using the Xbee S6B for simple tasks it can be okay but was designed for much much more. For simple GET or POST use Transparent Mode using the UART interface and simply print an HTTP POST or GET request line by line to the module. I think it is probably best to pre-program the S6B using XCTU for destination IP (Server IP), port number, and wireless configuration instead of trying to do it in the program. Also, remember that the port number is in HEX. (so 80 = 50) As a final note RTFM…the User Manual provided by Digi isn’t terrible.

    Here is a simple bit of “quick and dirty” code I used to test send messages to Pushover using the XBee. (IP 184.154.74.158)

    void setup () {
      Serial.begin(9600);
    }
    
    void loop() {
      delay(4000);
      Serial.println("POST /1/messages.json HTTP/1.1");
      Serial.println("Host: api.pushover.net");
      Serial.println("Connection: close");
      Serial.println("Content-Type: application/x-www-form-urlencoded");
      Serial.println("Content-Length: 85");
      Serial.println("");
      Serial.println("token=APP_TOKEN&user=USER_KEY&message=Test");
    }
    

    I’d like to also note that I had trouble using XCTU’s serial console during my tests (packet send). I almost always got back a 400 Error letting me know the request was bad. The same HTTP POST or GET request however would work when entered over serial using a µC. I’m still not exactly sure why this is. It may be a timing issue. For reference I am using XCTU Version: 6.1.1 Build ID: 20140129-0.

    • It does seem memory-related. We can try taking out as much as possible, until something works.

      Wanna give this example sketch a try? It removes the Phant library, and all of the XBee configuring. All it does it construct an HTTP GET and send it out the XBee. It assumes the XBee is already connected to WiFi, and the destination server/port are already set up (which it should be, if you’ve run the other sketch to configure it).

      It works for me. Posts to this stream (it’s already configured to post there, if you want a stream to test on).

      • Sorry but it still doesn’t work. It prints “Sending update…SUCCESS!” to the serial monitor but that isn’t really true.

        When plugged in all that happens is the device requesting DHCP. There is no activity outside of that sadly. The Pro Mini 3v does appear to now be formulating a valid HTTP GET request but nothing happens when sent to the Xbee. By the way, which firmware are you running on the S6B? I read about an issue with the S6B having trouble passing GET and POST to an MCU. (Could be related?) I’m on firmware 2021. Digi Support

        Edit: Maybe try to code it more like this using PROGMEM The Thing System Xbee WiFi S6B

  • For some reason its not working for me. I cant seem to post the data. “Serial.println(phant.url());” prints out the correct URL, i can copy and past it in to a webbrowser and it works. but Serial.println(phant.post()); does not work.

    • Is the code unmodified (aside from WiFi and Phant settings)? I ran into some issues of memory overrun when I added too much stuff to the sketch, which ended up corrupting contents of the POST.

      • Yes its unmodified, except the SSID, and key informaion. i know its on the network i can ping it…

        • Hmm. I still think it’s memory-related.

          I might have been able to recreate the issue. Are you getting a 502 error printed to the serial monitor (if not, what is being printed to the serial monitor after the post fails?)?

          Try commenting out the connectWiFi(WIFI_SSID, WIFI_EE, WIFI_PSK); and setupHTTP(destIP) lines in the setup() function. We can assume those have been correctly set for your XBee module earlier, so we don’t have to run them every time. If I take those out of the sketch, I get a success.

          • Thanks for your help… I put 2 debut prints, phant.url and phant.post.. Testing network Connected! IP Address: 10.3.0.219

            Sending update…http://data.sparkfun.com/input/My_key.txt?private_key=My_private_key&temp=42.7580&light=508&methane=304&co=216

            POST /input/My_KEY.txt HTTP/1.1 Host: data.sparkfun.com Phant-Private-Key: My_private_key Connection: close Content-Type: application/x-www-form-urlencoded Content-Length: 0

            SUCCESS Frist Test!

  • Hi folks, Here i have an interesting video which helps you to push your data to the sparkfun server using Raspberry Pi. Kindly go through the following link for more details:

    http://blogspot.tenettech.com/?p=3375

  • Hi , My setup is as follows . I have a router , my laptop and the arduino(xbee shield mounted) connected in one network. I am able to ping the router and the xbee and the asoc led on the shield blinks continuously. I upload your code on the arduino The serial monitor only displays Testing Network . What is wrong here ? If i am able to ping my xbee device then the sketch should work too . Also , my network does not have an internet connectivity. Encryption level : No security


If you've found a bug or have other constructive feedback for our tutorial authors, please send us your feedback!