Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: EthernetNetIf mbed
WeatherStationInterface.cpp
- Committer:
- BillEccles
- Date:
- 2012-01-02
- Revision:
- 1:1972c4310a72
- Parent:
- 0:dfbd7dacdf8c
File content as of revision 1:1972c4310a72:
/*
WeatherStationInterface.cpp
An interface for the LaCrosse Technology WS-2010-13 PC Interface.
Copyright (C)2012 William N. Eccles
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be includied in all copies or substiantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECITON WITH
THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "mbed.h"
#include "EthernetNetIf.h"
#include "HTTPClient.h"
#define WAIT_time 0.05
#define D() wait(WAIT_time)
Serial mac(USBTX, USBRX);
Serial ws2010pc(p28, p27); // tx, rx
DigitalOut DTR(p29);
DigitalOut mled0(LED1);
DigitalOut mled1(LED2);
DigitalOut mled2(LED3);
DigitalOut mled3(LED4);
const char *requestDCFtime = "\x01\x30\xCF\x04";
const char *requestData = "\x01\x31\xCE\x04";
const char *requestNextDataset = "\x01\x32\xCD\x04";
const char *requestStatus = "\x01\x35\xCA\x04";
void blink() {
int m0, m1, m2, m3;
m0 = mled0;
m1 = mled1;
m2 = mled2;
m3 = mled3;
mled0 = mled1 = mled2 = mled3 = 0;
mled0 = 1;D();mled1 = 1;D();mled2 = 1;D();mled3 = 1;D();
mled0 = 0;D();mled1 = 0;D();mled2 = 0;D();mled3 = 0;D();D();D();
mled3 = 1;D();mled2 = 1;D();mled1 = 1;D();mled0 = 1;D();
mled3 = 0;D();mled2 = 0;D();mled1 = 0;D();mled0 = 0;D();D();D();
mled0 = m0;
mled1 = m1;
mled2 = m2;
mled3 = m3;
// takes 1s with a delay time of 0.05s
return;
}
int errorHalt( bool L3, bool L2, bool L1, bool L0 ) {
while (1) {
mled3 = L0;
mled2 = L1;
mled1 = L2;
mled0 = L3;
wait(0.5);
mled3 = false;
mled2 = false;
mled1 = false;
mled0 = false;
wait(0.5);
}
return -1;
}
void showLEDs( bool L3, bool L2, bool L1, bool L0 ) {
mled3 = L0;
mled2 = L1;
mled1 = L2;
mled0 = L3;
return;
}
float H( int byte ) {
return (float)(byte >> 4);
}
float HS( int byte ) {
return (float)((byte >> 4) & 0x07);
}
float S( int byte ) {
byte = (byte & 0x0F) >> 3;
return ((byte==1) ? -1.0 : 1.0);
}
float L( int byte ) {
byte = (byte & 0x0F);
return (float)byte;
}
float LS( int byte ) {
byte = (byte & 0x07);
return (float)byte;
}
bool wakeup() {
char aChar;
bool wokeup = false;
// mac.printf("Waking up the WS2010...");
DTR = 1;
wait(0.05);
DTR = 0;
wait(0.05);
while (ws2010pc.readable()) {
aChar = ws2010pc.getc();
if (aChar==3) {
// mac.printf(" and it's awake.\n\r");
wokeup = true;
} else {
// mac.printf(" and it didn't want to wake up, returning a %i instead of a 3.\n\r",aChar);
wokeup = false;
}
}
wait(0.1);
return wokeup;
}
int sendString( char *theString ) {
int index = 0;
while (theString[index]!='\0') {
ws2010pc.putc((char)theString[index++]);
// wait(0.005);
}
return index;
}
int receiveString( char *theString, int numChars, int timeout_ms ) {
int index = 0;
bool done = false;
int LSRValue;
Timer aTimer;
theString[0]='\0';
aTimer.start();
while ((aTimer.read_ms()<=timeout_ms)&&(index<numChars)&&(!done)) {
// LSRValue = LPC_UART2-> LSR;
// if ((LSRValue!=97)&&(LSRValue!=96)) { mac.printf("Receive error? LSR is %i.\n\r",LSRValue); }
if (ws2010pc.readable()) {
theString[index] = ws2010pc.getc();
if (theString[index]==0x03) {
done = true;
}
index++;
theString[index]='\0';
}
}
aTimer.stop();
return index;
}
// MAIN
int main() {
int i, j, dataLength, strippedLength, LSRValue;
int db, dt, spreadraw;
float t1c, t1f, h1, hif, hic;
float tic, tif, hi;
float sp, dir, spread, wc;
float pr;
float rn;
string n1, ni, nwin, nr;
HTTPText txt;
HTTPResult r;
bool error, firstTime, haveData, dataPostedOK;
char theData[1024], strippedData[1024], httpQuery[1024];
EthernetNetIf eth;
HTTPClient http;
EthernetErr ethErr;
IpAddr myIpAddr;
firstTime = true;
// Setup Ethernet
showLEDs( false, false, false, true );
// mac.printf("Setting up Ethernet...\n\r");
ethErr = eth.setup();
if (ethErr) {
// mac.printf("Error %d in setup.\n\r", ethErr);
errorHalt( false, false, false, true );
} else {
// mac.printf("Ethernet setup was successful.\n\r");
}
while (1) {
error = false;
// Setup serial port
showLEDs( false, false, true, false );
// mac.printf("Opening serial port...\n\r");
ws2010pc.baud(9600);
ws2010pc.format(8, Serial::Even, 2);
// Wait six minutes unless this is the first time through this
showLEDs( false, false, true, true );
if (!firstTime) {
DTR = 1;
mac.printf("Sleeping for six minutes... ");
i=6;
while (i>=1) {
mac.printf("%i...",i--);
for (j=0; j<12; j++) {
blink();
wait(4);
}
}
mac.printf("\n\r");
}
firstTime = false;
// Wakeup the 2010
showLEDs( false, true, false, false );
error = !wakeup();
// Ask the 2010 for data until there is no more to be had.
haveData = true;
while (haveData&&(!error)) {
showLEDs( false, true, false, true );
mac.printf("Requesting data.... ");
dataLength = sendString((char *)requestData);
dataLength = receiveString(theData, 128, 500);
mac.printf("Received %i characters.\n\r",dataLength);
if (dataLength<2) {
mac.printf("No data received.\n\r");
haveData=false;
} else if ((theData[0]!=2)||(theData[dataLength-1]!=3)) {
mac.printf("Bad dataset received.\n\r");
haveData = false;
} else if ((theData[1]==1)&&(theData[2]==16)) {
mac.printf("No data available at the moment. Will retry later.\n\r");
haveData = false;
}
if (haveData) {
/*
mac.printf("The raw dataset has %i characters: ",dataLength);
i=0;
while (i<dataLength) {
mac.printf("%02X ",theData[i++]);
}
mac.printf("\n\r");
*/
// We have some data. Now strip out the ENQ escape sequences
strippedLength=0;
for (j=0; j<dataLength; j++) {
if (theData[j]==5) {
strippedData[strippedLength++]=theData[j+1]-16;
j++;
} else {
strippedData[strippedLength++]=theData[j];
}
}
/*
mac.printf("No ENQ dataset has %i characters: ",strippedLength);
i=0;
while (i<strippedLength) {
mac.printf("%02X ",strippedData[i++]);
}
mac.printf("\n\r");
*/
// Get rid of leading STX, and trailing checksum and ETX. (Leave the length as a pad in [0].
for (j=2; j<strippedLength-2; j++) {
strippedData[j-2]=strippedData[j];
}
strippedLength = strippedLength-4;
// Show the user what we have.
/*
mac.printf("SOHless dataset has %i characters: ",strippedLength);
i=0;
while (i<strippedLength) {
mac.printf("%02X ",strippedData[i++]);
}
mac.printf("\n\r");
*/
// Now decode everything.
// dataset ID and time before now (in minutes)
db = strippedData[1]*256+strippedData[0];
dt = strippedData[3]*256+strippedData[2];
// remove the header bytes (note that I'm leaving one byte in strippedData[0] so that the index value lines up with
// the index values of the bytes in the WS-2010 documentation, i.e., L25 will correspond to the low nybble of strippedData[25])
for (j=3; j<=strippedLength; j++) {
strippedData[j-3]=strippedData[j];
}
strippedLength = strippedLength - 3;
/*
mac.printf("Hdrless dataset has %i characters: ",strippedLength);
i=0;
while (i<strippedLength) {
mac.printf("%02X ",strippedData[i++]);
}
mac.printf("\n\r");
*/
// mac.printf("Read dataset id %i from %i minutes ago.\n\r", db, dt);
// reading: temperature 1, humidity 1 and heat index
t1c = (LS(strippedData[2])*10.0+H(strippedData[1])+L(strippedData[1])/10.0)*S(L(strippedData[2]));
t1f = 9.0/5.0*t1c+32.0;
h1 = LS(strippedData[3])*16.0+H(strippedData[2]);
n1 = (S(L(strippedData[3]))==-1) ? "NEW" : "OLD";
if (t1f>70) {
hif = -42.379+2.04901523*t1f+10.14333127*h1-0.22475541*t1f*h1-((6.83783e-3)*t1f*t1f)-((5.481717e-2)*h1*h1)+((1.22874e-3)*t1f*t1f*h1)+((8.5282e-4)*t1f*h1*h1)-((1.99e-6)*t1f*t1f*h1*h1);
hic = (hif-32.0)*5.0/9.0;
} else {
hif = t1f;
hic = t1c;
}
// mac.printf(" T1C:%5.2f T1F:%5.2f H1:%5.2f HIF:%5.2f HIC:%5.2f %s \n\r", t1c, t1f, h1, hif, hic, n1);
// reading: indoor temperature and humidity
tic = (LS(strippedData[29])*10+H(strippedData[28])+L(strippedData[28])/10)*S(L(strippedData[29]));
tif = 9.0/5.0*tic+32;
hi = LS(strippedData[30])*16+H(strippedData[29]);
ni = (S((int)L(strippedData[30]))==-1) ? "NEW" : "OLD";
// mac.printf(" TIC:%3.2f TIF:%3.2f HI:%3.2f %s \n\r", tic, tif, hi, ni);
// reading: wind speed, direction and directional spread, wind chill
sp = (HS(strippedData[24])*100.0+L(strippedData[24])*10.0+H(strippedData[23])+L(strippedData[23])/10.0)*0.6215;
dir = (float)((int)L(strippedData[26])%4)*100.0+H(strippedData[25])*10.0+L(strippedData[25]);
spreadraw = (int)(L(strippedData[26])/4);
switch (spreadraw) {
case 1:
spread = 22.5;
break;
case 2:
spread = 45;
break;
case 3:
spread = 67.5;
break;
default:
spread = 0;
}
nwin = (S((int)H(strippedData[24]))==-1) ? "NEW" : "OLD";
// mac.printf(" SP: %5.2f DIR:%5.2f SPREADRAW:%i SPREAD:%5.2f %s \n\r", sp, dir, spreadraw, spread, nwin);
if ((t1f<=50)&&(sp>3)) {
wc = 35.74+(0.6215*t1f)-(35.75*pow(sp,(float)0.16))+(0.4275*t1f*pow(sp,(float)0.16));
} else {
wc = t1f;
}
// mac.printf(" WC: %5.2f\n\r",wc);
// reading: air pressure
pr = (H(strippedData[27])*100.0+L(strippedData[27])*10.0+H(strippedData[26])+200.0)/33.775;
// mac.printf(" PR: %6.3f\n\r",pr);
// Ah, rain. The see-saw tips, and each tip represents 0.0145636 inches of rain.
rn = (strippedData[22]&0x7F)*256+strippedData[21];
nr = (S((int)H(strippedData[22]))==-1) ? "NEW" : "OLD";
// mac.printf(" RN: %7.1f NR %s\n\r",rn,nr);
// Generate the query string
j = sprintf(httpQuery, "http://www.example.com/yourquery.php?datasetnumber=%06d&timedelta=%06d&t1=%.1f&h1=%.1f&n1=%s&hif=%.1f&hic=%.1f&ti=%.1f&hi=%.1f&ni=%s&sp=%.1f&dir=%.1f&spread=%.1f&nwin=%s&wc=%.1f&pr=%.7f&rn=%.1f&nr=%s",db,dt,t1f,h1,n1,hif,hic,tif,hi,ni,sp,dir,spread,nwin,wc,pr,rn,nr);
// mac.printf("The query is \"%s\"\n\r",httpQuery);
// Now try and post the data. Make sure the response from the server doesn't exceed capacity of the buffer "txt".
showLEDs( false, true, true, false );
r = http.get(httpQuery, &txt);
if(r==HTTP_OK) {
// mac.printf("HTTP result:\"%s\"\n\r", txt.gets());
dataPostedOK = true;
} else {
// mac.printf("HTTP error #%d\n\r", r);
dataPostedOK = false;
}
if (dataPostedOK) {
showLEDs( false, true, true, true );
error = !wakeup();
mac.printf("Requesting next dataset.... ");
dataLength = sendString((char *)requestNextDataset);
dataLength = receiveString(theData, 128, 300);
mac.printf("Received %i characters.\n\r",dataLength);
if (dataLength<2) {
mac.printf("No data received.\n\r");
haveData=false;
error = true;
} else if ((theData[0]!=2)||(theData[dataLength-1]!=3)) {
mac.printf("Bad dataset received.\n\r");
haveData = false;
error = true;
} else if ((theData[1]==1)&&(theData[2]==16)) {
mac.printf("No data available at the moment. Will retry later.\n\r");
haveData = false;
}
}
} // end of "if (haveData)"
}
}
errorHalt( true, true, true, true );
return 0;
}