{ 2007 10 07 }
Air Quality Meter
/*
Air Quality meter
Language: Wiring/Arduino (pin numbers defined for Arduino)
Microcontroller is connected to a Lantronix serial-to-ethernet device. This program connects to a HTTP server through the Lantronix module, makes a HTTP GET request for a PHP script, and parses the returned string.
Lantronix device communicates at 9600-8-n-1 non-inverted (true) serial.
Lantronix serial settings:
Baudrate 9600, I/F Mode 4C, Flow 00
Port 10001
Remote IP Addr: --- none ---, Port 00000
Connect Mode : D4
Disconn Mode : 00
Flush Mode : 00
*/
// Defines for the program's status (used for status variable):
#define disconnected 0
#define connecting 1
#define connected 2
#define requesting 3
#define reading 4
#define requestComplete 5
// Defines for I/O pins:
#define connectedLED 2 // indicates when there's a TCP connection
#define requestingLED 3 // indicates a HTTP request has been made
#define readingLED 4 // indicates device is reading HTTP results
#define requestCompleteLED 5 // indicates a successful read
#define programResetLED 6 // indicates reset of Arduino
#define deviceResetPin 7 // resets Lantronix Device
#define meterPin 11 // controls VU meter
// defines for voltmeter:
#define meterMax 130 // max value on the meter
#define meterScale 150 // my meter reads 0 - 150
// variables:
int inByte= -1; // incoming byte from serial RX
char inString[32]; // string for incoming serial data
int stringPos = 0; // string index counter
int status = 0; // Lantronix device's connection status
long lastCompletionTime = 0; // counter for delay after last completion
void setup() {
// set all status LED pins and Lantronix device reset pin:
pinMode(connectedLED, OUTPUT);
pinMode(requestingLED, OUTPUT);
pinMode(requestCompleteLED, OUTPUT);
pinMode(programResetLED, OUTPUT);
pinMode(deviceResetPin, OUTPUT);
pinMode(meterPin, OUTPUT);
// start serial port, 9600 8-N-1:
Serial.begin(9600);
//reset Lantronix device:
resetDevice();
// blink reset LED:
blink(3);
}
void loop() {
stateCheck();
setLEDs();
}
/*
Check the status of the connection and take appropriate action:
/*
void stateCheck() {
switch (status) {
case disconnected:
// attempt to connect to the server:
deviceConnect();
break;
case connecting:
// until you get a C, keep trying to connect:
// read the serial port:
if (Serial.available()) {
inByte = Serial.read();
if (inByte == 'C') { // 'C' in ascii
status = connected;
}
else {
// if you got anything other than a C, try again:
deviceConnect();
}
}
break;
case connected:
// send HTTP GET request for CGI script:
httpRequest();
break;
case requesting:
lookForData();
break;
case reading:
readData();
break;
case requestComplete:
waitForNextRequest();
}
}
/*
Set the indicator LEDs according to the state of the program
/*
void setLEDs() {
/* Except for the disconnected and connecting states,
all the states of the program have corresponding LEDS.
so you can use a for-next loop to set them by
turning them all off except for the one that has
the same number as the current program state:
/*
for (int thisLED = 2; thisLED <= 5; thisLED++) {
if (thisLED == status) {
digitalWrite(thisLED, HIGH);
}
else {
digitalWrite(thisLED, LOW);
}
}
}
/*
Command the Lantronix device to connect to the server
/*
void deviceConnect() {
// fill in your server's numerical address below:
Serial.print("C82.165.199.35/80\n");
status = connecting;
}
/*
Send a HTTP GET request
/*
void httpRequest() {
// make sure you've cleared the last byte
// from the last request:
inByte = -1;
// reset the string position counter:
stringPos = 0;
// Make HTTP GET request. Fill in the path to your version
// of the CGI script:
Serial.print("GET /~myaccount/scraper.php HTTP/1.0\n");
// Fill in your server's name:
Serial.print("HOST:example.com\n\n");
// update the state of the program:
status = requesting;
}
/*
Read the results sent by the server until you get a < character.
/*
void lookForData() {
// wait for bytes from server:
if (Serial.available()) {
inByte = Serial.read();
// If you get a "<", what follows is the air quality index.
// You need to read what follows the <.
if (inByte == '<') {
stringPos = 0;
status = reading;
}
}
}
/*
read the number from the server into an array, terminating with a > character.
/*
void readData() {
if (Serial.available()) {
inByte = Serial.read();
// Keep reading until you get a ">":
if (inByte != '>') {
// save only ASCII numeric characters (ASCII 0 - 9):
if ((inByte >= '0') && (inByte <= '9')){
inString[stringPos] = inByte;
stringPos++;
}
}
// if you get a ">", you've reached the end of the AQI reading:
else {
interpretResults();
}
}
}
/*
convert the input string to an integer.
/*
void interpretResults() {
// convert the string to a numeric value:
int airQuality = atoi(inString);
// set the meter appropriately:
setMeter(airQuality);
lastCompletionTime = millis();
status = requestComplete;
}
/*
scale the number from the request to the meter's range and set the meter.
/*
void setMeter(int desiredValue) {
int airQualityValue = 0;
// if the value won't peg the meter, convert it
// to the meter scale and send it out:
if (desiredValue <= meterScale) {
airQualityValue = (desiredValue * meterMax /meterScale) ;
analogWrite(meterPin, airQualityValue);
}
}
/*
Wait two minutes before initiating a new request.
/*
void waitForNextRequest() {
if (millis() - lastCompletionTime >= 120000) {
// reset Lantronix device before next request:
resetDevice();
status = disconnected;
}
}
/*
Take the Lantronix device's reset pin low to reset it
/*
void resetDevice() {
digitalWrite(deviceResetPin, LOW);
delay(50);
digitalWrite(deviceResetPin, HIGH);
// pause to let Lantronix device boot up:
delay(2000);
}
/*
Blink the reset LED.
/*
void blink(int howManyTimes) {
int i;
for (i=0; i< howManyTimes; i++) {
digitalWrite(programResetLED, HIGH);
delay(200);
digitalWrite(programResetLED, LOW);
delay(200);
}
}