Pachube and WiShield

Discussion about any of the included sketches (i.e. WebServer), or user-generated applications.

Re: Pachube and WiShield

Postby Daemach » Tue Mar 09, 2010 4:50 pm

First, thank you very much for posting this code. Open source rules :)

I was able to get this working immediately. It seemed to work fine when I had it inside my office but when I put it in one of my out buildings, it's intended final home, the behavior became erratic. Temperatures and light levels are all over the charts but it's in a cold, sealed room in the dark at the moment. The temperature isn't fluctuating like this!

http://www.pachube.com/feeds/6162 ( Look at the data after the second dotted line. The wishield kept losing connection yesterday.)

The first thought I had was that maybe the arduino doesn't apply a voltage to the thermistor until the moment it senses. Perhaps the thermistor needs some time to stabilize. Does that make any sense?

Any other ideas?
Daemach
 
Posts: 4
Joined: Tue Mar 09, 2010 4:39 pm

Re: Pachube and WiShield

Postby Daemach » Wed Mar 10, 2010 3:44 pm

FYI I disconnected the device for programming so the data on pachube is going to be old. Here's a short sample of the temperature datastream (actual temp was around 46-48):

2010-03-09T17:00:00Z,12
2010-03-09T17:15:00Z,48
2010-03-09T17:30:00Z,26
2010-03-09T17:45:00Z,11
2010-03-09T18:00:00Z,42
2010-03-09T18:15:00Z,19
2010-03-09T18:30:00Z,46
2010-03-09T18:45:00Z,31
2010-03-09T19:00:00Z,48
2010-03-09T19:15:00Z,46
2010-03-09T19:30:00Z,12
2010-03-09T19:45:00Z,48
2010-03-09T20:00:00Z,8
2010-03-09T20:15:00Z,18
2010-03-09T20:30:00Z,9
2010-03-09T20:45:00Z,37

I wonder if the code should be rewritten so that the sensors are being sampled (and possibly smoothed) and the timer used just to send the data to pachube. I'm not a good enough coder to make those changes quickly though, so if I'm off base please tell me.
Daemach
 
Posts: 4
Joined: Tue Mar 09, 2010 4:39 pm

Re: Pachube and WiShield

Postby owenschoppe » Thu May 27, 2010 11:08 pm

Greg and ChiefRobot, thank you for all of your help on here. Your code definitely saved me.

I just wanted to share my results. I combined code from Greg and ChiefRobot for a sketch that POSTs and GETs data from Pachube. The CSV data returned is parsed to individual variables. I thought people might appreciate seeing it all in one place.

Code: Select all
/*
* A simple sketch that uses WiServer to PUT (via POST) to Pachube
*
* Sends and receives two variables to Pachube.
* The data received is parsed; storing the CSV values in the appropriate variables.
* Sketch does not make WiFi connection after upload. The ardunio must be reset.
*
* Many thanks to GregEigsti and ChiefRobot for writing most of this code.
*/

//#include <MsTimer2.h>  //For easy and accurate timing. 210bytes

#include <WiServer.h>

//#define maxLength 30

//Wireless configuration defines ----------------------------------------
#define WIRELESS_MODE_INFRA   1
#define WIRELESS_MODE_ADHOC   2

//Wireless configuration parameters ----------------------------------------
unsigned char local_ip[]       = {192,168,1,108};  // IP address of WiShield
unsigned char gateway_ip[]     = {192,168,1,254};     // router or gateway IP address
unsigned char subnet_mask[]    = {255,255,255,0}; // subnet mask for the local network
const prog_char ssid[] PROGMEM = {"2WIRE814"};    // max 32 bytes
unsigned char security_type    = 1;               // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
// WPA/WPA2 passphrase
const prog_char security_passphrase[] PROGMEM = {"xxx"};   // max 64 characters
// WEP 64-bit keys
//Change the length on line 337 in the g2100.c file:   cmd->keyLen = 5;   // Key length: 5 bytes (64-bit WEP); 13 bytes (128-bit WEP)
prog_uchar wep_keys[] PROGMEM = { 0x00, 0x00, 0x00, 0x00, 0x00,   // Key 0 Shortened the keys to match my router settings.
              0x00, 0x00, 0x00, 0x00, 0x00,   // Key 1
              0x00, 0x00, 0x00, 0x00, 0x00,   // Key 2
              0x00, 0x00, 0x00, 0x00, 0x00   // Key 3
            };

// setup the wireless mode
// infrastructure - connect to AP
// adhoc - connect to another WiFi device
unsigned char wireless_mode = WIRELESS_MODE_INFRA;

unsigned char ssid_len;
unsigned char security_passphrase_len;
// End of wireless configuration parameters
//--------------------------------------------------------------

//non WiShield defines
#define DEBUG_PRINT
#define TEMPERATURE_PIN 5
#define LIGHT_PIN       0

//global variables.
boolean inValidPacket;
char recvData[256];
long updateTime = 0;
boolean firstPass = false;
//boolean intTimer;

//Sensor Data Variables:
//--------------------------------------------------------------
int temperature;
int light;

//Incoming Data Variables: Use an appopriate number of variables for your CSV values.
//--------------------------------------------------------------
int var1;
int var2;
//int var3;

//Pachube
//--------------------------------------------------------------
// IP Address for Pachube.com 
uint8 ip[] = {209,40,205,190};
char hostName[] = "www.pachube.com\nX-PachubeApiKey: [YOUR KEY HERE]\nConnection: close";
char url[] = "/api/XXXX.csv?_method=put";

// A request that POSTS data to Pachube
POSTrequest postPachube(ip, 80, hostName, url, feedData);

//char url2[] = "/api/feeds/XXXX.xml"; //For retreiving XML if necessary. Needs a different parser.
char url2[] = "/api/feeds/XXXX.csv";
GETrequest getPachube(ip, 80, hostName, url2);

/*
//MsTimer2 one minute timer ISR
//--------------------------------------------------------------
void timerISR() {
   intTimer = true;
}
*/

//body data function, provides data for the POST command in comma separated values (CSV)
//currently POSTs one value but more can be added by separating with comma (no spaces)
//Your program will not want to use the hardcoded values below, rather it would read the
//sensor(s) and build the data string shown below.
//--------------------------------------------------------------
void feedData()
{
   char buf[16];
   sprintf(buf, "%d,%d", temperature, light);

   WiServer.print(buf);
   
}


// Function that prints data from the server during POSTrequests
//--------------------------------------------------------------
void printData(char* data, int len) {
   // Print the data returned by the server
   // Note that the data is not null-terminated, may be broken up into smaller packets, and
   // includes the HTTP header.

   while (len-- > 0) {
      Serial.print(*(data++));
   }

}

// Function that prints data from the server during GETrequests
//Parsing the data takes three stages:
//1. Data is received in chunks. The last chunk is stored in recvData.
//2. recvData is split into individual lines.
//3. The last line, which always contains the csv data, is split into individual values.
//--------------------------------------------------------------
void printGetData(char* data, int len) {
   //if we are not in the middle of a packet AND we find the OK token
   if(false == inValidPacket && NULL != strstr(data, "HTTP/1.1 200 OK")) {
      //mark that we are in a valid packet
      inValidPacket = true;
      //temporary for debugging purposes
      Serial.println("Data reception has started");
   }

   //if we were in a valid packet AND we get the ending 0 == len call
   //This is executed once after receiving the last chunck of data.
   if(true == inValidPacket && 0 == len) {
      //mark that we are no longer in a valid packet
      inValidPacket = false;

      //grab out the values with something like sscanf()
      parseData();

      //temporary for debugging purposes
      Serial.println("Data reception has ended");
      //Serial.println(data);
     
      //reset firstPass variable for parsing data
      firstPass = true;
   }
   else {
      //insures that the data in recvData is clean and doesn't have leftovers from before
      memset(recvData, 0, 256 * sizeof(char));
      //stash away the last bit of data received
      memcpy(recvData, data, len);
     
#ifdef DEBUG_PRINT //temporary for debugging purposes
      Serial.println("-------- Received a chunk of data: --------");
      Serial.println(recvData);
      //inString = recvData;
      //Serial.println(data);
      //Serial.println("Last chunk of data:");
      //Serial.print("Length: ");
      //Serial.println(len);
      Serial.println("-------- End of Chunk --------");
#endif //DEBUG_PRINT     
   }
}

void setup() {   
   //initialize sensor variables
   temperature = 0;
   light = 0;

   //setup the analog pins as input, probly redundant
   pinMode(TEMPERATURE_PIN, INPUT);
   pinMode(LIGHT_PIN, INPUT);

   // Initialize WiServer (we'll pass NULL for the page serving function since we don't need to serve web pages)
   WiServer.init(NULL);

   // Enable Serial output and ask WiServer to generate log messages (optional)
#ifdef DEBUG_PRINT
   Serial.begin(57600);
   //WiServer.enableVerboseMode(true); //optional
#endif //DEBUG_PRINT

   // Have the printData function called when data is returned by the server during POSTrequests
   //postPachube.setReturnFunc(printData);

   // Have the printGetData function called when data is returned by the server during GETrequests
   getPachube.setReturnFunc(printGetData);

   //set up global state data
   //intTimer = false;
   inValidPacket = false;
   memset(recvData, 0, 256 * sizeof(char));

   //setup the timerISR to be called every minute
   //MsTimer2::set(20000, timerISR); // 60000ms/1min period
   //MsTimer2::start();
}


void loop() {
   if(millis() >= updateTime) {
      //time inverval has passed
      updateTime += 30000;
      //intTimer = false;
     
      //For now just increment the variables. In the future connect them to actual sensors.
      temperature++;
      light++;
      //temperature = convertTemp(analogRead(TEMPERATURE_PIN));
      //light = 1024 - analogRead(LIGHT_PIN);
     
#ifdef DEBUG_PRINT
      Serial.println("===== Timer Fired =====");
      Serial.print("Temp: ");
      Serial.print(temperature, DEC);
      Serial.print("F, Light: ");
      Serial.println(light, DEC);
#endif //DEBUG_PRINT

      //submit tasks for WiServer
      postPachube.submit();
      getPachube.submit();   
   }

   // Run WiServer
   WiServer.server_task();

   delay(10);
}

//Function that parses the last chunk of data received.---------------------------------
void parseData() {
  const char *ptr = recvData;
  char field [ 64 ];
     int n;
     int x;
  //steps through the recvData saving the last line in 'field' and the number of characters read in 'n'.
  while ( sscanf(ptr, "%64[^\n]%n", field, &n) == 1 )
     {
       
#ifdef DEBUG_PRINT       
        //printf("field = \"%s\"\n", field);
        //Serial.print ("Field = ");
        //Serial.println(field);
#endif //DEBUG_PRINT

        ptr += n; /* advance the pointer by the number of characters read */ 
        if ( *ptr != '\n' )
          {
             break; /* didn't find an expected delimiter, done? */
          }
        while ( *ptr == '\n' )
          {
            ++ptr; /* skip the delimiter */
          }
     }

//Store each comma separated value (CSV) in the associated variable
//To use more variable just follow the pattern.
//sscanf looks for comma separated integers (%d , %d). For longer numbers or floats use a different data type.
//Don't forget to change the data type of your variables to match.
//---------------------------

  sscanf(field, "%d,%d" , &var1, &var2  );
  //sscanf(field, "%d,%d,%d," , &var1, &var2, &var3 );

#ifdef DEBUG_PRINT
  Serial.print ("Var1 = ");  //print results
  Serial.println(var1);
  Serial.print ("Var2 = ");
  Serial.println(var2);
  //Serial.print ("Var3 = ");
  //Serial.println(var3);
#endif //DEBUG_PRINT

}

/*
http://www.arduino.cc/playground/ComponentLib/Thermistor2

(Ground) ---- (10k-Resistor) -------|------- (Thermistor) ---- (+5v)
                                    |
                               Analog Pin 0
*/
/*
int convertTemp(int value)
{
   double temp;
   temp = log(((10240000 / value) - 10000));
   temp = 1 / (0.001129148 + (0.000234125 * temp) + (0.0000000876741 * temp * temp * temp));
   temp = temp - 273.15;            // Convert Kelvin to Celcius
   temp = (temp * 9.0) / 5.0 + 32.0; // Convert Celcius to Fahrenheit
   return (int)temp;
}
*/
/*
http://www.libelium.com/squidbee/index.php?title=Adding_a_light_sensor

(Ground) ---- (Light Sensor) -------|------- (1k-Resistor) ---- (+5v)
                                    |
                               Analog Pin 0
*/


The output looks something like this:

===== Timer Fired =====
Temp: 47F, Light: 47
Data reception has started
-------- Received a chunk of data: --------
HTTP/1.1 200 OK
Server: nginx/0.6.34
Date: Fri, 28 May 2010 06:02:44 GMT
Content-Type: text/plain; charset=utf-8
Connection: close
Last-Modified: Fri, 28 May 2
-------- End of Chunk --------
-------- Received a chunk of data: --------
010 06:02:13 GMT
X-Runtime: 5
Cache-Control: private, max-age=0, must-revalidate
Content-Length: 5
Set-Cookie: _pachube_app_session=ef383e1ba7d4a0e50a14578fc488
-------- End of Chunk --------
-------- Received a chunk of data: --------
f36f; path=/; expires=Fri, 28 May 2010 07:02:43 GMT; HttpOnly
Vary: Accept-Encoding
Vary: Accept-Encoding

46,46
-------- End of Chunk --------
Var1 = 46
Var2 = 46
Data reception has ended
owenschoppe
 
Posts: 1
Joined: Thu May 27, 2010 10:45 pm

Re: Pachube and WiShield

Postby GregEigsti » Fri May 28, 2010 12:38 am

Nice, thanks for sharing! Whats the link to your Pachube feed? :D

Greg
Check out the wiki!
uIP Stack Docs
Compatible Access Point List
WiShield user contrib branch - DNS, DHCP, AP Scanning, bug fixes, etc.
SlackLab.org - My geek projects blog.
User avatar
GregEigsti
 
Posts: 955
Joined: Sun Aug 02, 2009 5:23 pm
Location: Sammamish WA USA (near Seattle)

Re: Pachube and WiShield

Postby mengineer » Mon May 31, 2010 8:38 pm

I just remembered I got a email from Pachube a little bit ago and wanted to make sure that everyone else did so they have the new IP for POST/PUT, and so people starting out don't try to use an example on here and get no where I know how much of a headache it could be . Here's the important part of the message:
* IP address change
-------------------
Following our recent migration and redesign the IP address for Pachube.com has changed to: 173.203.98.29. Any devices publishing to Pachube or retrieving from Pachube that are not able to do DNS lookups (Arduino users we're looking at you!) will need to update their IP address configuration before June 30, 2010 - we have a forwarding system in place until then. Please see http://community.pachube.com/node/429 for further info on these changes.
"Every day's a new adventure, you gotta take what you can!"
mengineer
 
Posts: 19
Joined: Mon Apr 12, 2010 8:49 pm
Location: Buffalo, NY

Re: Pachube and WiShield

Postby seacritter » Tue Jul 06, 2010 1:34 pm

Okay... I'm posting 3 datastreams to Pachube, but getting "?" for my last 2. It is in my sprintf statement... either my variables are wrong of my format is wrong. But, I'm banging my head against the screen missing something simple.
My pachube page is at http://www.pachube.com/feeds/8654.

My code is here:
Code: Select all
/*
    * A simple sketch that uses WiServer to PUT (via POST) to Pachube
    */

    #include <WiServer.h>
    #include <MsTimer2.h>
    #include <math.h>

    //Wireless configuration defines ----------------------------------------
    #define WIRELESS_MODE_INFRA   1
    #define WIRELESS_MODE_ADHOC   2

    //Wireless configuration parameters ----------------------------------------
    unsigned char local_ip[]       = {192,168,1,102};  // IP address of WiShield
    unsigned char gateway_ip[]     = {192,168,1,1};     // router or gateway IP address
    unsigned char subnet_mask[]    = {255,255,255,0}; // subnet mask for the local network
    const prog_char ssid[] PROGMEM = {"SSID"};    // max 32 bytes
    unsigned char security_type    = 0;               // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
    // WPA/WPA2 passphrase
    const prog_char security_passphrase[] PROGMEM = {"password"};   // max 64 characters
    // WEP 128-bit keys
    prog_uchar wep_keys[] PROGMEM = {
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Key 0
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Key 1
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Key 2
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Key 3
    // setup the wireless mode
    // infrastructure - connect to AP
    // adhoc - connect to another WiFi device
    unsigned char wireless_mode = WIRELESS_MODE_INFRA;
    unsigned char ssid_len;
    unsigned char security_passphrase_len;
    // End of wireless configuration parameters ----------------------------------------

    //non WiShield defines
    #define DEBUG_PRINT
    #define ZeroPercentVoltage 0.8;

    //global state data
    float val = 0;
    float RH = 0;
    float max_voltage = 3.27;
    float voltage = 4.92;
    int pin = 0; // analog pin
    int tempc = 0,tempf=0; // temperature variables
    int samples[8]; // variables to make a better precision
    int maxi = -100,mini = 100; // to start max/min temperature
    int i;
    float Vin;
    float P;
    boolean intTimer;

    // IP Address for Pachube.com
    uint8 ip[] = {173,203,98,29};
    char hostName[] = "www.pachube.com\nX-PachubeApiKey:my key\nConnection: close";
    char url[] = "/api/feeds/8654.csv?_method=put";
    // A request that POSTS data to Pachube
    POSTrequest postPachube(ip, 80, hostName, url, feedData);


    //MsTimer2 one minute timer ISR
    void timerISR() {
       intTimer = true;
    }

    // Function that prints data from the server
    void printData(char* data, int len) {
       // Print the data returned by the server
       // Note that the data is not null-terminated, may be broken up into smaller packets, and
       // includes the HTTP header.
    #ifdef DEBUG_PRINT
       while (len-- > 0) {
          Serial.print(*(data++));
       }
    #endif //DEBUG_PRINT
    }

    //body data function, provides data for the POST command in comma separated values (CSV)
    //currently POSTs one value but more can be added by separating with comma (no spaces)
    //Your program will not want to use the hardcoded values below, rather it would read the
    //sensor(s) and build the data string shown below.
    void feedData()
    {
       char buf[16];
       sprintf(buf, "%d,%.2f,%.2f", tempf, Vin, RH);
       WiServer.print(buf);
    }

    void setup()
    {   

       // Initialize WiServer (we'll pass NULL for the page serving function since we don't need to serve web pages)
       WiServer.init(NULL);

       // Enable Serial output and ask WiServer to generate log messages (optional)
    #ifdef DEBUG_PRINT
       Serial.begin(9600);
       //WiServer.enableVerboseMode(true);
    #endif //DEBUG_PRINT

       // Have the processData function called when data is returned by the server
       postPachube.setReturnFunc(printData);

       //set up global state data
       intTimer = false;

       //setup the timerISR to be called every minute
       MsTimer2::set(60000, timerISR); // 60000ms/1min period
       MsTimer2::start();
    }

    void loop()
    {
     
       //--------------------------------------------------------------------------------------------
       //handle the timer overflow
       //--------------------------------------------------------------------------------------------
       if(true == intTimer) {
          //one minute has passed
          intTimer = false;
     
// temp section using an LM35 DZ
for(i = 0;i<=7;i++){ // gets 8 samples of temperature
samples[i] = (voltage * analogRead(pin) * 100.0) / 1024.0;
tempc = tempc + samples[i];
delay(500);
}

tempc = tempc/8.0; // better precision
tempf = (tempc * 9)/ 5 + 32; // converts to fahrenheit

//barometric section using an MPX4115 A
Vin = (5.0/1024.0) * analogRead(2);
Vin = Vin + 0.054;                  // Offset Adjustment
P=((Vin/5.0)+0.095)/0.009;
Vin = (P * 0.2952999);

//humidity section using a Honeywell HIH-4030
  val = analogRead(5);
  delay(500);
  max_voltage = (3.27-(0.006706*(tempc,DEC))) ; // The max voltage value drops down 0.006705882 for each degree C over 0C. The voltage at 0C is 3.27 (corrected for zero precent voltage)
  RH = ((((val/1023)*5)-0.8)/max_voltage)*100;
 
    #ifdef DEBUG_PRINT
          Serial.print("===== intTimer fired: temperature = ");
          Serial.print(tempf, DEC);  //print the temperature
          Serial.print(", barometric pressure = ");
          Serial.print(Vin , DEC);   // print the pressure
          Serial.print(", relative humidity = ");
          Serial.println(RH , DEC); //print the humidity
    #endif //DEBUG_PRINT
          postPachube.submit();   
       }

       // Run WiServer
       WiServer.server_task();

       delay(10);
    }


My debug results are here:
Code: Select all
===== intTimer fired: temperature = 82, barometric pressure = 30.0022659301, relative humidity = 43.6915321350
HTTP/1.1 200 OK
Server: nginx/0.6.35
Date: Tue, 06 Jul 2010 20:30:59 GMT
Content-Type: text/plain; charset=utf-8
Connection: close
X-Runtime: 31
Content-Length: 1
Set-Cookie: _pachube_app_session=77400294dbfc188ecf416c531b4fb069; path=/; expires=Tue, 06 Jul 2010 20:50:59 GMT; HttpOnly
Cache-Control: private, max-age=0, must-revalidate
Vary: Accept-Encoding


Any suggestions???
User avatar
seacritter
 
Posts: 45
Joined: Fri May 28, 2010 10:42 am
Location: Today? Near Philly...

Re: Pachube and WiShield

Postby seacritter » Tue Jul 06, 2010 7:01 pm

Okay...

In this version, sprintf doesn't do floats... The work around is a little ugly, but IT WORKS!!!

example of some butt ugly code:
Code: Select all
    /*
    * A simple sketch that uses WiServer to PUT (via POST) to Pachube
    */

    #include <WiServer.h>
    #include <MsTimer2.h>
    #include <math.h>

    //Wireless configuration defines ----------------------------------------
    #define WIRELESS_MODE_INFRA   1
    #define WIRELESS_MODE_ADHOC   2

    //Wireless configuration parameters ----------------------------------------
    unsigned char local_ip[]       = {192,168,1,102};  // IP address of WiShield
    unsigned char gateway_ip[]     = {192,168,1,1};     // router or gateway IP address
    unsigned char subnet_mask[]    = {255,255,255,0}; // subnet mask for the local network
    const prog_char ssid[] PROGMEM = {"SSID"};    // max 32 bytes
    unsigned char security_type    = 0;               // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
    // WPA/WPA2 passphrase
    const prog_char security_passphrase[] PROGMEM = {"password"};   // max 64 characters
    // WEP 128-bit keys
    prog_uchar wep_keys[] PROGMEM = {
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Key 0
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Key 1
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // Key 2
       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; // Key 3
    // setup the wireless mode
    // infrastructure - connect to AP
    // adhoc - connect to another WiFi device
    unsigned char wireless_mode = WIRELESS_MODE_INFRA;
    unsigned char ssid_len;
    unsigned char security_passphrase_len;
    // End of wireless configuration parameters ----------------------------------------

    //non WiShield defines
    #define DEBUG_PRINT
    #define ZeroPercentVoltage 0.8;

    //global state data
    float val = 0;
    float RH = 0;
    float max_voltage = 3.27;
    float voltage = 4.92;
    int pin = 0; // analog pin
    int tempc = 0,tempf=0; // temperature variables
    int samples[8]; // variables to make a better precision
    int maxi = -100,mini = 100; // to start max/min temperature
    int i;
    int b1;
    int b2;
    int h1;
    int h2;
    float Vin;
    float P;
    boolean intTimer;

    // IP Address for Pachube.com
    uint8 ip[] = {173,203,98,29};
    char hostName[] = "www.pachube.com\nX-PachubeApiKey:my key\nConnection: close";
    char url[] = "/api/feeds/8654.csv?_method=put";
    // A request that POSTS data to Pachube
    POSTrequest postPachube(ip, 80, hostName, url, feedData);


    //MsTimer2 one minute timer ISR
    void timerISR() {
       intTimer = true;
    }

    // Function that prints data from the server
    void printData(char* data, int len) {
       // Print the data returned by the server
       // Note that the data is not null-terminated, may be broken up into smaller packets, and
       // includes the HTTP header.
    #ifdef DEBUG_PRINT
       while (len-- > 0) {
          Serial.print(*(data++));
       }
    #endif //DEBUG_PRINT
    }

    //body data function, provides data for the POST command in comma separated values (CSV)
    //currently POSTs one value but more can be added by separating with comma (no spaces)
    //Your program will not want to use the hardcoded values below, rather it would read the
    //sensor(s) and build the data string shown below.
    void feedData()
    {
       char buf[32];
       sprintf(buf,"%d,%d.%02d,%d.%02d",tempf,b1,b2,h1,h2);
       WiServer.print(buf);
    }

    void setup()
    {   

       // Initialize WiServer (we'll pass NULL for the page serving function since we don't need to serve web pages)
       WiServer.init(NULL);

       // Enable Serial output and ask WiServer to generate log messages (optional)
    #ifdef DEBUG_PRINT
       Serial.begin(9600);
       //WiServer.enableVerboseMode(true);
    #endif //DEBUG_PRINT

       // Have the processData function called when data is returned by the server
       postPachube.setReturnFunc(printData);

       //set up global state data
       intTimer = false;

       //setup the timerISR to be called every minute
       MsTimer2::set(30000, timerISR); // 60000ms/1min period
       MsTimer2::start();
    }

    void loop()
    {
     
       //--------------------------------------------------------------------------------------------
       //handle the timer overflow
       //--------------------------------------------------------------------------------------------
       if(true == intTimer) {
          //one minute has passed
          intTimer = false;
     
// temp section using an LM35 DZ
tempc = 0;
for(i = 0;i<=7;i++){ // gets 8 samples of temperature
samples[i] = (voltage * analogRead(pin) * 100.0) / 1024.0;
tempc = tempc + samples[i];
delay(500);
}

tempc = tempc/8.0; // better precision
tempf = (tempc * 9)/ 5 + 32; // converts to fahrenheit

//barometric section using an MPX4115 A
// ((((((0.0048828125 * analogRead(2))+0.054)/5.0)+0.095)/0.009)*0.2952999)
Vin = (5.0/1024.0) * analogRead(2);
Vin = Vin + 0.054;                  // Offset Adjustment
P=((Vin/5.0)+0.095)/0.009;
Vin = (P * 0.2952999);
b1 = Vin;
float f2 = Vin - b1;
b2 = trunc(f2 * 100);

//humidity section using a Honeywell HIH-4030
  val = analogRead(5);
  delay(500);
  max_voltage = (3.27-(0.006706*(tempc,DEC))) ; // The max voltage value drops down 0.006705882 for each degree C over 0C. The voltage at 0C is 3.27 (corrected for zero precent voltage)
  RH = ((((val/1023)*5)-0.8)/max_voltage)*100;
  h1 = RH;
  float fh2 = RH - h1;
  h2 = trunc(fh2 * 100);
 
    #ifdef DEBUG_PRINT
          Serial.print("===== intTimer fired: temperature = ");
          Serial.print(tempf, DEC);  //print the temperature
          Serial.print(", barometric pressure = ");
          Serial.print(Vin , DEC);   // print the pressure
          Serial.print(", relative humidity = ");
          Serial.println(RH , DEC); //print the humidity
    #endif //DEBUG_PRINT
          postPachube.submit();   
       }

       // Run WiServer
       WiServer.server_task();

       delay(10);
    }


Elvis has left the building!!! :lol:
User avatar
seacritter
 
Posts: 45
Joined: Fri May 28, 2010 10:42 am
Location: Today? Near Philly...

Re: Pachube and WiShield

Postby GregEigsti » Wed Jul 07, 2010 5:14 am

Glad you found it; take a look at dtostrf(...) to convert floats...

Greg
Check out the wiki!
uIP Stack Docs
Compatible Access Point List
WiShield user contrib branch - DNS, DHCP, AP Scanning, bug fixes, etc.
SlackLab.org - My geek projects blog.
User avatar
GregEigsti
 
Posts: 955
Joined: Sun Aug 02, 2009 5:23 pm
Location: Sammamish WA USA (near Seattle)

Re: Pachube and WiShield

Postby seacritter » Wed Jul 07, 2010 5:19 am

I'm kinda learning as I go along... I will take a look at it...
User avatar
seacritter
 
Posts: 45
Joined: Fri May 28, 2010 10:42 am
Location: Today? Near Philly...

Re: Pachube and WiShield

Postby seacritter » Sat Jul 10, 2010 8:48 am

Things are getting larger as I add more sensors...

I've bumped into a problem with the pachube sketch and using attachInterrupt . As soon as I enable attachInterrupt, the sketch stops posting to Pachube. It still gives me values. Is there something that doesn't get along with the sketch?

My new code:
Code: Select all
//non WiShield defines
    #define DEBUG_PRINT
    #define ZeroPercentVoltage 0.8;
    #define uint  unsigned int
    #define ulong unsigned long

    #define PIN_ANEMOMETER  2     // Digital 2
    #define PIN_VANE        4     // Analog 4

// How often we want to calculate wind speed or direction
    #define MSECS_CALC_WIND_SPEED 5000
    #define MSECS_CALC_WIND_DIR   5000

//global state data
    float val = 0;
    float RH = 0;
    float max_voltage = 3.27;
    float voltage = 4.92;
    int pin = 0; // analog pin
    int tempc = 0,tempf=0; // temperature variables
    int samples[8]; // variables to make a better precision
    int maxi = -100,mini = 100; // to start max/min temperature
    int i;
    int b1;
    int b2;
    int h1;
    int h2;
    int y1;
    int y2;
    byte x;
    int numBuckettip;
    char winddir;
    int windspeed;
    float Vin;
    float P;
    boolean intTimer;
    volatile int numRevsAnemometer = 0; // Incremented in the interrupt
    ulong nextCalcSpeed;                // When we next calc the wind speed
    ulong nextCalcDir;                  // When we next calc the direction
    ulong time;                         // Millis() at each start of loop().

// ADC readings:
    #define NUMDIRS 8
    ulong   adc[NUMDIRS] = {26, 45, 77, 118, 161, 196, 220, 256};

// These directions match 1-for-1 with the values in adc, but
// will have to be adjusted as noted above. Modify 'dirOffset'
// to which direction is 'away' (it's West here).
    char *strVals[NUMDIRS] = {"W","NW","N","SW","NE","S","SE","E"};
    byte dirOffset=0;

// IP Address for Pachube.com
    uint8 ip[] = {173,203,98,29};
    char hostName[] = "www.pachube.com\nX-PachubeApiKey:my key\nConnection: close";
    char url[] = "/api/feeds/8654.csv?_method=put";

// A request that POSTS data to Pachube
    POSTrequest postPachube(ip, 80, hostName, url, feedData);

//MsTimer2 one minute timer ISR
    void timerISR() {
       intTimer = true;
    }

// Function that prints data from the server
    void printData(char* data, int len) {
// Print the data returned by the server
// Note that the data is not null-terminated, may be broken up into smaller packets, and
// includes the HTTP header.
    #ifdef DEBUG_PRINT
       while (len-- > 0) {
          Serial.print(*(data++));
       }
    #endif //DEBUG_PRINT
    }

//body data function, provides data for the POST command in comma separated values (CSV)
//currently POSTs one value but more can be added by separating with comma (no spaces)
//Your program will not want to use the hardcoded values below, rather it would read the
//sensor(s) and build the data string shown below.
    void feedData()
    {
       char buf[32];
       sprintf(buf,"%d,%d.%02d,%d.%02d,%d.%d,%s",tempf,b1,b2,h1,h2,y1,y2,(strVals[x]));
       WiServer.print(buf);
    }

    void setup()
    {   

// Initialize WiServer (we'll pass NULL for the page serving function since we don't need to serve web pages)
       WiServer.init(NULL);

// Enable Serial output and ask WiServer to generate log messages (optional)
    #ifdef DEBUG_PRINT
       Serial.begin(9600);
    pinMode(PIN_ANEMOMETER, INPUT);
    digitalWrite(PIN_ANEMOMETER, HIGH);
//    attachInterrupt(0, countAnemometer, FALLING);
    nextCalcSpeed = millis() + MSECS_CALC_WIND_SPEED;
    nextCalcDir   = millis() + MSECS_CALC_WIND_DIR;

//WiServer.enableVerboseMode(true);
    #endif //DEBUG_PRINT

// Have the processData function called when data is returned by the server
       postPachube.setReturnFunc(printData);

//set up global state data
       intTimer = false;

//setup the timerISR to be called every minute
       MsTimer2::set(30000, timerISR); // 60000ms/1min period
       MsTimer2::start();
    }

//=======================================================
// Main loop.
//=======================================================
    void loop()
    {
     
//--------------------------------------------------------------------------------------------
//handle the timer overflow
//--------------------------------------------------------------------------------------------
       if(true == intTimer) {
          //one minute has passed
          intTimer = false;
     
// temp section using an LM35 DZ
    tempc = 0;
    for(i = 0;i<=7;i++){ // gets 8 samples of temperature
    samples[i] = (voltage * analogRead(pin) * 100.0) / 1024.0;
    tempc = tempc + samples[i];
    delay(500);
}
    tempc = tempc/8.0; // better precision
    tempf = (tempc * 9)/ 5 + 32; // converts to fahrenheit
   
//Wind direction and speed
   time = millis();

   if (time >= nextCalcSpeed) {
      calcWindSpeed();
      nextCalcSpeed = time + MSECS_CALC_WIND_SPEED;
   }
   if (time >= nextCalcDir) {
      calcWindDir();
      nextCalcDir = time + MSECS_CALC_WIND_DIR;
   }

//barometric section using an MPX4115 A
    Vin = (5.0/1024.0) * analogRead(2);
    Vin = Vin + 0.054;                  // Offset Adjustment
    P=((Vin/5.0)+0.095)/0.009;
    Vin = (P * 0.2952999);
    b1 = Vin;
    float f2 = Vin - b1;
    b2 = trunc(f2 * 100);

//humidity section using a Honeywell HIH-4030
    val = analogRead(5);
    delay(500);
    max_voltage = (3.27-(0.006706*(tempc,DEC))) ; // The max voltage value drops down 0.006705882 for each degree C over 0C. The voltage at 0C is 3.27 (corrected for zero precent voltage)
    RH = ((((val/1023)*5)-0.8)/max_voltage)*100;
    h1 = RH;
    float fh2 = RH - h1;
    h2 = trunc(fh2 * 100);
 
    #ifdef DEBUG_PRINT
          Serial.print("===== intTimer fired: temperature = ");
          Serial.print(tempf, DEC);  //print the temperature
          Serial.print(", barometric pressure = ");
          Serial.print(Vin , DEC);   // print the pressure
          Serial.print(", relative humidity = ");
          Serial.println(RH , DEC); //print the humidity
    #endif //DEBUG_PRINT
          postPachube.submit();   
       }

// Run WiServer
       WiServer.server_task();

       delay(10);
    }
//=======================================================
// Interrupt handler for anemometer. Called each time the reed
// switch triggers (one revolution).
//=======================================================
void countAnemometer() {
   numRevsAnemometer++;
}

//=======================================================
// Find vane direction.
//=======================================================
void calcWindDir() {
   int wval;
   byte x, reading;

   wval = analogRead(PIN_VANE);
   wval >>=2;                        // Shift to 255 range
   reading = wval;

   // Look the reading up in directions table. Find the first value
   // that's >= to what we got.
   for (x=0; x<NUMDIRS; x++) {
      if (adc[x] >= reading)
         break;
   }
   Serial.println(reading, DEC);
   x = (x + dirOffset) % 8;   // Adjust for orientation
   Serial.print("  Dir: ");
   Serial.println(strVals[x]);
//   winddir = (strVals[x]);
}

//=======================================================
// Calculate the wind speed, and display it (or log it, whatever).
// 1 rev/sec = 1.492 mph
//=======================================================
void calcWindSpeed() {
   int y, iSpeed;
   // This will produce mph * 10
   // (didn't calc right when done as one statement)
   long speed = 14920;
   speed *= numRevsAnemometer;
   speed /= MSECS_CALC_WIND_SPEED;
   iSpeed = speed;         // Need this for formatting below

   Serial.print("Wind speed: ");
   y1 = iSpeed / 10;
   Serial.print(y1);
   Serial.print('.');
   y2 = iSpeed % 10;
   Serial.print(y2);
//   windspeed = iSpeed / 10;

   numRevsAnemometer = 0;        // Reset counter
}
User avatar
seacritter
 
Posts: 45
Joined: Fri May 28, 2010 10:42 am
Location: Today? Near Philly...

PreviousNext

Return to Sketches and Applications

Who is online

Users browsing this forum: No registered users and 1 guest

cron