Labels

Tuesday, May 31, 2016

Weather Station Project #25 - Back to the Drawing Board

Well, it looks like there is a major problem with my assumptions.  Take a look at the following graph:


The red line is the sample from my UV sensor and the green line is the sample from the PWS that has the UV sensor.  As you can see, even though my sensor is recording a similar distribution, it is way out of whack.  This is more due to cloud cover and the fact that my sensor is not looking up.  Also, when I set the sensor up, it was pointed out a window through a screen so there are some artifacts to deal with.  The levels are way off here as well. Originally I was going to setup for a sample over an eight day period but I cut that short to be able to see some data.

What I am thinking here is that I need to put the sensors into a different enclosure, one with a glass window.  Oh yeah, the solar radiation results were even worse:



Anyway, I need to go back and rethink this thing. More later.

Saturday, May 28, 2016

Weather Station Project #23 - Initial Code for the Solar/UV Sensors

I thought I would take the time to put together some code that will be used in the Solar Radiation and UV Sensors.  The objective here is to at least get the sensors tracking and providing data output. I was able to cobble together the sources from the TSL2561 and the SI1145 written by Adafruit along with the source code from the Web Server written by Arduino to get something running.  I decided at the last moment to not use a Raspberry Pi but to stick with the Arduino.  I have an Arduino Uno, an Ethernet Shield, some extensions and the Arduino breadboard with the two sensors on it (see the following picture).



The code is pretty simple and surprisingly the Serial interface doesn't get in the way (it lets me do the web service without needing to have a console display):

#include <Wire.h>
#include <SPI.h>
#include <Ethernet.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_TSL2561_U.h>
#include "Adafruit_SI1145.h"

/*  This sketch is a combination of two sketches from Adafruit
 *  sensorapi for the TSL2561 lux sensor and si1145test for 
 *  the SI1145 UV sensor. The sketch captures the state of the two
 *  sensors every minute, waiting for a json request from the ethernet
 *  port.  It then provides a json string back containing the raw and
 *  computed values of the two sensors.
 *  
 *  Please note that the sketch makes use of the Adafruit Sensor API and
 *  libraries (to make the development simpler).
 *  
 *  Connections (TSL2561)
 *  ===========
 *  Connect SCL to analog 5
 *  Connect SDA to analog 4
 *  Connect VDD to 3.3V DC
 *  Connect GROUND to common ground
 *
 *  I2C Address (TSL2561)
 *  ===========
 *  The address will be different depending on whether you leave
 *  the ADDR pin floating (addr 0x39), or tie it to ground or vcc. 
 *  The default addess is 0x39, which assumes the ADDR pin is floating
 *  (not connected to anything).  If you set the ADDR pin high
 *  or low, use TSL2561_ADDR_HIGH (0x49) or TSL2561_ADDR_LOW
 *  (0x29) respectively.
 *
 */

Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(TSL2561_ADDR_FLOAT, 12345);
Adafruit_SI1145 uv = Adafruit_SI1145();

// Some more globals to store intermediate info into until asked for by the web intfc
float tslLUX;
float uvVIS;
float uvIR;
float uvUVRaw;
float uvUV;

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 0, 42);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

/**************************************************************************
 *    Displays some basic information on this sensor from the unified
 *    sensor API sensor_t type (see Adafruit_Sensor for more information)
 **************************************************************************/
void displayTSL2561Details(void)
{
  sensor_t sensor;
  tsl.getSensor(&sensor);
  Serial.println("------------------------------------");
  Serial.print  ("Sensor:       "); Serial.println(sensor.name);
  Serial.print  ("Driver Ver:   "); Serial.println(sensor.version);
  Serial.print  ("Unique ID:    "); Serial.println(sensor.sensor_id);
  Serial.print  ("Max Value:    "); Serial.print(sensor.max_value); Serial.println(" lux");
  Serial.print  ("Min Value:    "); Serial.print(sensor.min_value); Serial.println(" lux");
  Serial.print  ("Resolution:   "); Serial.print(sensor.resolution); Serial.println(" lux");  
  Serial.println("------------------------------------");
  Serial.println("");
  delay(500);
}

/**************************************************************************
 *    Configures the gain and integration time for the TSL2561
 **************************************************************************/
void configureTSL2561(void)
{
  /* You can also manually set the gain or enable auto-gain support */
  // tsl.setGain(TSL2561_GAIN_1X);      /* No gain ... use in bright light to avoid sensor saturation */
  // tsl.setGain(TSL2561_GAIN_16X);     /* 16x gain ... use in low light to boost sensitivity */
  tsl.enableAutoRange(true);            /* Auto-gain ... switches automatically between 1x and 16x */
  
  /* Changing the integration time gives you better sensor resolution (402ms = 16-bit data) */
  // tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_13MS);      /* fast but low resolution */
  // tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_101MS);  /* medium resolution and speed   */
  tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);  /* 16-bit data but slowest conversions */

  /* Update these values depending on what you've set above! */  
  Serial.println("------------------------------------");
  Serial.print  ("Gain:         "); Serial.println("Auto");
  Serial.print  ("Timing:       "); Serial.println("402 ms");
  Serial.println("------------------------------------");
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Serial.println("Light Sensor Test"); Serial.println("");
  
  /* Initialise the sensor */
  if(!tsl.begin())
  {
    /* There was a problem detecting the ADXL345 ... check your connections */
    Serial.print("Ooops, no TSL2561 detected ... Check your wiring or I2C ADDR!");
    while(1);
  }
  
  if (!uv.begin()) {
    Serial.println("Didn't find Si1145");
    while (1);
  }

  /* Display some basic information on this sensor */
  displayTSL2561Details();
  
  /* Setup the sensor gain and integration time */
  configureTSL2561();
  
   // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());

 /* We're ready to go! */
  Serial.println("");
}

void loop() {
  // put your main code here, to run repeatedly:
  /* Get a new sensor event for the lux sensor */ 
  sensors_event_t event;
  tsl.getEvent(&event);

  /* Display the results (light is measured in lux) */
  if (event.light)
  {
    tslLUX = event.light;
    // Serial.print(event.light); Serial.println(" lux");
  }
  else
  {
    /* If event.light = 0 lux the sensor is probably saturated
       and no reliable data could be generated! */
    tslLUX = 0;
    // Serial.println("Sensor overload");
  }

  /* Read the Visible, IR, UV sensor */ 
  // Serial.println("===================");
  uvVIS = uv.readVisible();
  // Serial.print("Vis: "); Serial.println(uvVIS);
  uvIR = uv.readIR();
  // Serial.print("IR: "); Serial.println(uvIR);
  
  // Uncomment if you have an IR LED attached to LED pin!
  //Serial.print("Prox: "); Serial.println(uv.readProx());

  float UVindex;
  uvUVRaw = uv.readUV();
  UVindex = uvUVRaw;
  // the index is multiplied by 100 so to get the
  // integer index, divide by 100!
  UVindex /= 100.0;
  uvUV = UVindex;  
  // Serial.print("UV: ");  Serial.println(UVindex);

  // At this point formulate the latest json message to send back on web query
  Serial.print("{ "); Serial.print("tslLUX"); Serial.print(" : "); Serial.print(tslLUX);
  Serial.print(", "); Serial.print("uvVIS"); Serial.print(" : "); Serial.print(uvVIS);
  Serial.print(", "); Serial.print("uvIR"); Serial.print(" : "); Serial.print(uvIR);
  Serial.print(", "); Serial.print("uvUVRaw"); Serial.print(" : "); Serial.print(uvUVRaw);
  Serial.print(", "); Serial.print("uvUV"); Serial.print(" : "); Serial.print(uvUV);
  Serial.println(" }");

  // listen for incoming clients
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connection: close");  // the connection will be closed after completion of the response
          client.println("Refresh: 5");  // refresh the page automatically every 5 sec
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html>");

          client.print("{ "); client.print("tslLUX"); client.print(" : "); client.print(tslLUX);
          client.print(", "); client.print("uvVIS"); client.print(" : "); client.print(uvVIS);
          client.print(", "); client.print("uvIR"); client.print(" : "); client.print(uvIR);
          client.print(", "); client.print("uvUVRaw"); client.print(" : "); client.print(uvUVRaw);
          client.print(", "); client.print("uvUV"); client.print(" : "); client.print(uvUV);
          client.print(" }");
          client.println("<br />");
          
          client.println("</html>");
          break;
        }
        if (c == '\n') {
          // you're starting a new line
          currentLineIsBlank = true;
        } else if (c != '\r') {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disconnected");
  }
  
  delay(1000);
}

I did check this out by executing a web call to 192.168.0.42 and was greeted with the json message.  I will have to modify this json message later because it doesn't have the quotes around the string values but at least it is working in the short term. I am going to simply put this up in my window at home and sample through a vertical pane of glass.  If the concept is correct, I should be able to get a fairly good set of samples that at least will prove the concept.  I might have some difficulty around sunup and sundown, but it should be close.  I will start with comparing against one site.

So, I need to position the sensors to point out the window so I can start getting some samples to check. That will be followed by some Python code to extract the json message, parse into an Excel comma delimited file, extract the json message from some local websites, parse them into the same Excel file and do this over several days. I am thinking that a five minute sample should be fine. Later I can pull the file in and do a statistical analysis on the data.