Arduino / WiShield v1.0 - Wireless Temp. & Switch Controller

Post here if you are working on a project and need help, or have an idea and need a helping hand on getting it going with Wi-Fi.
Don't worry, if you get it completed, we can move the project to the Complete Wi-Fi forum later.

Arduino / WiShield v1.0 - Wireless Temp. & Switch Controller

Postby cfsapper » Thu Oct 28, 2010 2:34 pm

Hi all!

So here is my project: I am working on a multi-sensor device which is also intended to control solid state relays.
As it stands, I am using TMP102 temperature sensors which report over the I2C protocol to an Arduino Due. w/ WiShield 1.0
The temperature data for two sensors is being sent via POST method to a PHP script on a colocated server.
The remote PHP script stores the incoming data in an SQL database which I then analyze using JpGraph & PHP.
This part is working just fine - I have been collecting temperature data for ~6mo now.

What I am struggling with is the following:

Getting control data from the remote server to control a solid state relay.

What I would like to do is use my SQL database to control the switch states (Boolean function, really).
I have written a PHP script that polls my database and returns the only following:

<switch name>,<switch state> (eg. |1,0)

I am using pipe ( | ) as a sort of index to parse the incoming GET request so that my code knows where to start looking for the actual control data.
I would like to make this scalable so that I could have say, 4 switches, all having their states returned with a single query of the SQL/PHP server.
So I need to somehow include the ability to intelligently parse multiple switch data.

Ie: sw1,1 .. sw2,0 .. sw3,1 .. etc

As it stands, if I make a text file (switch.php) with |1,0 in it, the switch get set to off, similarly if the text file contains only |1,1 the switch is turned on.
When I test my swtich.php using the SQL data, my web browser reports only: |1,0 or |1,1 but the Arduino does not control the switch accordingly.

I was hoping that an experienced coder could have a look at my source (below) and make suggestions / help me along my way.
I think that my problems are in the very last fuction in the code below, however, I am also open to critique of my general methods.

Code: Select all
#include <WiServer.h>
#include <Wire.h>

// Wireless configuration parameters ----------------------------------------
#define WIRELESS_MODE_INFRA   1
#define WIRELESS_MODE_ADHOC   2
unsigned char local_ip[] = {192,168,1,130};                           // 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 = {"apnamehere"};               // max 32 bytes
unsigned char security_type = 2;                           // 0 - open; 1 - WEP; 2 - WPA; 3 - WPA2
const prog_char security_passphrase[] PROGMEM = {"appasswdhere"};   // max 64 characters
prog_uchar wep_keys[] PROGMEM = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,   // 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
            };
unsigned char wireless_mode = WIRELESS_MODE_INFRA;
unsigned char ssid_len;
unsigned char security_passphrase_len;
uint8 ip[] = {111,222,333,444};  // obviously fake values ;)
POSTrequest sendData(ip, 80, "www.servername.here", "/project1/temp.php?", tempData);  // post tempData to server
GETrequest getData(ip, 80, "www.servername.here", "/project1/switch.php");                     // get switch states from server (ie: sw1,1 .. sw2,0 .. etc)

// Temperature sensor parameters --------------------------------------------
int ptrTemp =  0b00000000;              // TMP102 register pointers
int ptrConf =  0b00000001;
int addr0 = 0b1001001;                  // ADD0 pin connection selects one of four possible addresses 1001001 = Vcc, 1001000 = gnd
int addr1 = 0b1001000;
int hightempmark = 0;
int lowtempmark = 100;
float temp0cal = 0;                       // calibration variable for sensor0
float temp1cal = 0;                       // calibration variable for sensor1

// Digital switching parameters ---------------------------------------------
int led = 6;                                  // Indicator LED for sw0 - using PWM via analogWrite(led, 128) to avoid using a resistor
int sw1 = 0;                              // default switch state for sw0 set to off

// Misc. configuration parameters -------------------------------------------
int debug = 1;                            // if set to 1, multiple Serial.print outputs will be made
int ptr = 0, cntr = 0;
int indexFound = 0;
char* dataIn;

// Begin program space --------------------------------------------------------

void setup(){
  serialInit();                         // initialize serial interface & LCD output
  I2Cinit();                            // initialize the I2C network for temperature sensors
  tempCal();                          // cross-calibrate temperature sensor to the same temperature (greatest)
  swInit();                             // initialize digital switching parameters
  wirelessInit();                     // start WiFi connection 
}

void loop(){
  sendData.submit();                    // submit temperature data for sensors using POSTrequest sendData in wireless configuration parameters
  getData.submit();                      // get switch state data using GETrequest getData in wireless configuration parameters
  WiServer.server_task();            // have WiServer actually process the sendData.submit() and getData.submit() routines
}

void serialInit(){                           // start up serial console at 9600 baud, and initialize serial LCD
  Serial.begin(9600);
  delay(100); 
  Serial.print(12, BYTE);
  delay(5);
  Serial.print(17, BYTE);
  delay(5);
  Serial.print(22, BYTE);                // screen on, no blink
  delay(5); 
}

void I2Cinit(){                          // start up the I2C interface, setting this host as mater unit
  Wire.begin();                          // join i2c bus (address optional for master)
//  delay(100);
 
  Serial.println();
  Serial.println("Initializing I2C interface...");

  Wire.beginTransmission(addr0);        // select temperature register
  Wire.send(ptrTemp);         
  Wire.endTransmission();
  Wire.beginTransmission(addr1);        // select temperature register
  Wire.send(ptrTemp);         
  Wire.endTransmission();          
 
  Serial.println("DONE!");
  Serial.println();
  Serial.print("Using temperature sensors #1 (");
  Serial.print(addr0, BIN);
  Serial.print(") and #2 (");
  Serial.print(addr1, BIN);
  Serial.println(")");
}

void tempCal(){                          // calibrate the temperature sensors to each other, using the higher value as the reference
  int calCnt=0;
  int calTotal = 50;                     // total number of sensor samplings to be done
  int calDelay = 10;                     // delay between samplings (ms)
  float temp0avg = 0;
  float temp1avg = 0;
  float temp0start = 0;
  float temp1start = 0;
 
  Serial.println();
  Serial.println("Temperature Sensor Calibration In Progress:");
  Serial.println("1%                     50%                    100%");
 
  do {                                   // take calTotal number of readings and find the average sensor values
    Serial.print("|");
    temp0avg = temp0avg + getTemp(0,0);
    temp1avg = temp1avg + getTemp(1,0);
    delay(calDelay);
    calCnt++;
  } while (calCnt < calTotal);

  temp0avg = (temp0avg/calCnt);
  temp1avg = (temp1avg/calCnt);
  if (temp0avg > temp1avg) { temp0cal = temp0avg - temp1avg; }
  if (temp0avg < temp1avg) { temp1cal = temp1avg - temp0avg; }

  temp0start = getTemp(0,temp0cal);
  temp1start = getTemp(1,temp1cal);
 
  Serial.println();
  Serial.println("DONE!");
  Serial.println();
  Serial.print("Initial temperature (sensor 0): ");
  Serial.print(temp0start);
  Serial.print(" calibrated by -");
  Serial.print(temp0cal);
  Serial.print(" with Tavg=");
  Serial.println(temp0avg);
  Serial.print("Initial temperature (sensor 1): ");
  Serial.print(temp1start);
  Serial.print(" calibrated by -");
  Serial.print(temp1cal);
  Serial.print(" with Tavg=");
  Serial.println(temp1avg);
}

void swInit(){                                    // initialize digital switching routines, including testing the On/Off LED
  pinMode(led, OUTPUT);                   // led pin set to 6 in global variables
  pinMode(7, OUTPUT);                      // SW1 output
  pinMode(3, OUTPUT);                      // SW2 output
  digitalWrite(7, LOW);                     // make sure the digital output is low, ie switch off
  digitalWrite(3, LOW);                     // make sure the digital output is low, ie switch off 
  Serial.println();
  Serial.println("Testing digital output...");
  Serial.println("LED On");
  analogWrite(led, 128);
  Serial.print("1..");
  delay(1000);
  Serial.print("2..");
  delay(1000);
  Serial.println("3..");
  delay(1000);
  Serial.println("LED Off");
  analogWrite(led, 0);
}

void wirelessInit(){                                  // initialize the WiFi connection
  Serial.println();
  Serial.println("Initializing wireless connection...");
  int start = millis();                                // time the connection routine

  WiServer.init(NULL);                            // disable the internal web server
  WiServer.enableVerboseMode(false);     // changed to false, do not provide verbose output
  sendData.setReturnFunc(printData);      // setup how the resulting data from the sendData routine is handled
  getData.setReturnFunc(printData2);      // setup how the resulting data from the getData routine is handled

  Serial.println("DONE!"); 
  Serial.print("Connection took: ");          // output the results of the timer
  int stop1 = ((millis() - start)*-1);
  Serial.print(stop1/1000);
  Serial.println(" seconds");
  Serial.println();
}

void printData(char* data, int len){          // how the headers returned from sendData routine are handled
  while (len-- > 0) {
//    Serial.print(*(data++));
  }
  uip_close();  // disconnect from server - was commented out
}

void swSet(){                            // should add (int sw) then use "sw" to controll the switch # - ie. make this function scalable
  int sw = 0;                              // place holder, should be global or function passed variable
  if (debug==1){                         // if debugging is set, print this data via serial console
    Serial.print(12, BYTE);
    Serial.println("----------");
    Serial.print(13, BYTE);
    Serial.print("Sw: ");
    Serial.print(sw);
    Serial.print(13, BYTE);
    Serial.print("Onoff: ");
    Serial.print(sw1);                // sw1 is a boolean (global) value for the state of switch 1, controlled by the SQL data
    Serial.print(13, BYTE);
    Serial.print(millis()/1000);
  }
   
  if (sw1==0) {       
  //  Serial.println("Device 0 set to OFF");
    analogWrite(led, 0);                // if the bit is set, turn on the LED
    digiOut(3,0);
  }
  if (sw1==1) {
  //  Serial.println("Device 0 set to ON");
    analogWrite(led, 128);              // if the bit is not set, turn off the LED
    digiOut(3,1);
  }

 
float getTemp(int sensor, float cal){   // poll sensor for temperature and subtract cal from its value and return the result
  int addr = addr0;
  if (sensor == 0) { addr = addr0; }    // sensor #1
  if (sensor == 1) { addr = addr1; }    // sensor #2
 
  Wire.requestFrom(addr, 2);            // request temperature
  byte byte1 = Wire.receive();
  byte byte2 = Wire.receive();   

//  CALCULATING TEMPERATURES
  int tempint = byte1 << 8;                   // shift first byte to high byte in an int
  tempint = tempint | byte2;           // or the second byte into the int
  tempint = tempint >> 4;                   // right shift the int 4 bits per chip doc
  float tempflt = float( tempint ) * .0625; // calculate actual temperature per chip doc

  if (tempflt > hightempmark) {
    hightempmark = tempflt;
  }
  if (tempflt < lowtempmark) {
    lowtempmark = tempflt;
  }
  return tempflt-cal;
}

void tempData(){
  float temp0 = 0, temp1 = 0;
  temp0 = getTemp(0,temp0cal);
  temp1 = getTemp(1,temp1cal);

  if (debug==1){                        // if debugging is set, print this data via serial console
    Serial.println();
    Serial.print("Reporting the following data: ");
    Serial.print("temp0=");
    Serial.print(temp0);
    Serial.print(" & temp1=");
    Serial.print(temp1);
    Serial.println();
  }

  WiServer.print("temp0=");
  WiServer.print(temp0);
  WiServer.print("&temp1=");
  WiServer.print(temp1);
}

void digiOut(int pin, int state){     // unused pins available to control swiches (via SSR, etc)
                                      // unused pins include: 0,1,3,4,5,6,7
  if (state==1) { digitalWrite(pin, HIGH); }
  if (state==0) { digitalWrite(pin, LOW); }
}

void printData2(char* data, int len) {   // how the headers returned from getData routine are handled
  if (len > 0){
    memset(dataIn, ' ', sizeof(dataIn)); // clear dataIn and initialize cleanly for length of data packet
    for (int cntChar=0; cntChar < len; cntChar++) {
      char chrIn = data[cntChar];    // gather data from data variable 1 char at a time
      if (chrIn == '|') {                    // more advanced: if ((chrIn == '|') || (indexFound != 1))
        dataIn[ptr] = chrIn;             // set the first dataIn[0] to the current chrIn, post-increment ptr
        ptr++;
        indexFound = 1;
      } // end of if (chrIn == '|')
      if (indexFound == 1) {
        sscanf(dataIn, "%[^,], %d", sw1); // ignore the switch name for now, just get the state (and hope it works)
        Serial.println(onoff);
      } // end of (indexFound == 1)
    } // end of for (int cntChar=0; cntChar < len; cntChar++)
  } // end of (len > 0)
//  uip_close();  // disconnect from server - this causes data packet loss for some reason, ie. does not finish GET request
}


Edit: Here is a copy of my PHP backend of the switch.php for analyis also:

Code: Select all
<?php
include ("db.php");

$sw = $_GET['sw'];

$today = date("Y-m-d");

if ($dbtable == "") $dbtable = "switches";

mysql_connect($host,$login,$passwd);
@mysql_select_db($dbname) or die( "Unable to connect to database");

$query = "      SELECT *
                FROM switches
        ";

$result = mysql_query($query);

$cnt = 0;
$cnt2 = 0;

while($row = mysql_fetch_row($result))
{
        $switchIn[$cnt] = $row[0];
        $stateIn[$cnt] = $row[1];
        $dateIn[$cnt] = $row[2];
        $cnt++;
}

mysql_free_result($result);

while($cnt2 < $cnt)
{
        $dateInConv[$cnt2] = date("Y-m-d H:i:s",$dateIn[$cnt2]);
        $cnt2++;
}

$cnt3=0;
while($cnt3 < $cnt)
{
        echo "|";
        echo $switchIn[$cnt3];
        echo ",";
        echo $stateIn[$cnt3];
        $cnt3++;
} // example, outputs:   |1,1

?>
cfsapper
 
Posts: 1
Joined: Thu Oct 28, 2010 2:09 pm

Return to Wi-Fi in Progress

Who is online

Users browsing this forum: No registered users and 1 guest

cron