Hi,
Ive been tinkering away trying to make a sketch to integrate my weather station with OpenEnergyMonitor. The weather station in question is a PeetBros Ultimeter 100 that outputs serial data.
I have found the necessary code to grab the serial data from the station, but am just having trouble with the RF12 components of the code. Im unable to pickup my transmissions on a simple serial base unit, and im not sure how to troubleshoot at which end (Tx or Rx) is causing the problem.
The sketch is very much a draft and im still working on a few things such as my BMP pressure is not correct (negitive values) and I want to have more precision with the temperature.
Im planning on doing a writeup on my build once done.
Any help with these problems, or if anyone can suggest any improvements i could make to my code it would be very much appreciated.
Kind regards,
Mike Christiansen
/*
Code by Mike Christiansen nz.mike.christiansen@gmail.com
for open use, modifacation and sharing. No liability assumed.
Any feedback most appreciated, im only an arduino beginner :)
Code for Openenergymonotor tx device running on a jeenode.
this tx transmits data from a peet bros weather station
(wind speed, direction, averaged speed, outdoor temp, and
wind direction name (from michael p code) along with data
from a BMP085.
Attachments to the jeenode uses the folowing jee ports
Weatherstation serial port, uses arduino pin 6 (rx)
jeenode port 3 dio 5v and gnd through a ttl-rs232 converter
BMP085
Pressure bord, P4
Thanks to these people for there code contrubition.
Michael P from ADS-WS1 yahoo group
*/
//==============================BMP085==============================
// Jeenode - Jeelabs
#include <Ports.h>
#include "PortsBMP085.h"
#include <RF12.h>
#include <avr/sleep.h>
#include <avr/eeprom.h>
PortI2C four (4);
BMP085 psensor (four, 3); // ultra high resolution
MilliTimer timer;
//==================================Openenergymonotor===========================
// http://openenergymonitor.org
//---------------------------------------------------------------------------------------------------
// RF12 settings
//---------------------------------------------------------------------------------------------------
// fixed RF12 settings
#define MYNODE 18
#define network 212 //default network group (can be in the range 1-250). All nodes required to communigate together must be on the same network group
#define freq RF12_915MHZ //Frequency of RF12B module can be RF12_433MHZ, RF12_868MHZ or RF12_915MHZ. You should use the one matching the module you have.
// set the sync mode to 2 if the fuses are still the Arduino default
// mode 3 (full powerdown) can only be used with 258 CK startup fuses
#define RADIO_SYNC_MODE 2
#define COLLECT 0x20 // collect mode, i.e. pass incoming without sending acks
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// CT energy monitor setup definitions
//--------------------------------------------------------------------------------------------------
/*
int inPinI= 3; //I/O analogue 3 = emonTx CT2 channel. Change to analogue 0 for emonTx CT1 chnnel
int numberOfSamples= 1480; //The period (one wavelength) of mains 50Hz is 20ms. Each samples was measured to take 0.188ms. This meas that 106.4 samples/wavelength are possible. 1480 samples takes 280.14ms which is 14 wavelengths.
int Vrms= 230; //UK assumed supply voltage. Tolerance: +10%-6%
int CT_BURDEN_RESISTOR= 56; //value in ohms of burden resistor R3 and R6
int CT_TURNS= 1500; //number of turns in CT sensor. 1500 is the vaue of the efergy CT http://www.efergy.com/Products/efergy-Shop-Accessories/EFERGY/Jackplug-E...
double CAL=1.2477; //*calibration coefficient* IMPORTANT - each monitor must be calibrated. See step 4 http://openenergymonitor.org/emon/node/58
*/
//########################################################################################################################
//Data Structure to be received
//########################################################################################################################
typedef struct {
int ct1; // current transformer 1
int ct2; // current transformer 2
int temp1; // Outdoor temperature 1
int temp2; // BMP085 temperature 2
int temp3; // Server temperature 3
int BMP_pres; // BMP085 Pressure
int emon_wind_speed; // PeetBros wind speed out
int emon_wind_dir; // PeetBros wind direction out
int emon_avg_wind; // PeetBros 5min ave wind speed
int emon_wind_name; // Wind as named below
} Payload;
Payload emontx;
//########################################################################################################################
//=================BELOW FOR SERIAL READ FROM PEET BROS STATION===================
// THANKS TO MICHAEL P FROM ADS-WS1 YAHOO GROUP
#include <NewSoftSerial.h>
// rx tx
NewSoftSerial weather_port1(6,7);
int wind_speed =0; // wind speed in kmh
int wind_dir = 0; // wind dir in degrees
int temp = 0; // Outdoor temp fahrenheit
int tempc = 0; // Outdoor temp celsius
float rain = 0; // not attached in my example
float bar = 0;
int id_temp =0; // not attached in my example
int hum = 0; // not attached in my example
int id_hum = 0; // not attached in my example
int day = 0; // time not used
int minutes = 0; // time not used
float day_rain = 0; // not attached in my example
int avg_wind = 0; // averaged wind speed over 1 minute
byte chrconv(byte);
unsigned int getword(char *);
void get_weather();
char * wind_name(int);
char * getLine();
unsigned int getword(char * ptr)
{
return( chrconv(*(ptr+0)) << 12 | chrconv(*(ptr+1)) << 8 | chrconv(*(ptr+2)) << 4 | chrconv(*(ptr+3)));
}
byte chrconv(byte chr)
{
if (chr < 48 || chr > 70)
return -1;
return (0x40 & chr) ? (9 + (0x0f & chr) ) : (chr - 48);
}
//================="WITHOUT DELAY" CODE FOR WRITING TO RF12b=======================
// using arduino example blink without delay
long previousMillis = 0;
long interval = 10000;
//================================SETUP============================================
void setup(){
//================================BMP085============================
psensor.getCalibData();
//===============================PeetBros============================
Serial.begin(9600);
weather_port1.begin(2400);
//============================Openenergymonotor=========================
//-----------------------------------------
// RFM12B Initialize
//------------------------------------------
rf12_initialize(MYNODE,freq,network); //Initialize RFM12 with settings defined above
rf12_sleep(0); //Put the RFM12 to sleep - Note: This RF12 sleep interupt method might not be 100% repiable. Put RF to sleep: RFM12B module can be kept off while not used – saving roughly 15 mA
//------------------------------------------
Serial.print("Node: ");
Serial.print(MYNODE);
Serial.print(" Freq: ");
Serial.print(freq);
Serial.print(" Network: ");
Serial.println(network);
delay(1000);
//===========================PeetBros=========================================
}
char wLine[100];
char * getLine()
{
char cc=0;
int ii=0;
while(cc != '!')
{
delay(1);
cc = weather_port1.read();
}
wLine[0]='!';
ii=1;
while(1)
{
if(weather_port1.available() > 0)
{
cc = weather_port1.read();
if (ii < 99 and cc != '\n' and cc != '\r' and cc > 31)
{
wLine[ii] = cc;
ii++;
}
else
{
wLine[ii] = '\0';
return &(wLine[0]);
}
}
}
}
void get_weather()
{
// char * ptr = "!!030100D8017402632755030600F0----0006052000360201\0";
char * ptr = getLine();
int num_chars = strlen(ptr);
//Serial.println(ptr);
//Serial.println( num_chars);
if (!ptr or *ptr != '!' or *(ptr+1) != '!')
{
Serial.println("no header");
return;
}
//0000 wind speed [0.1 kph]
wind_speed = (getword(ptr+2) /10.0);
//00D8 wind direction [0-255]
int tWindDir = (getword(ptr+6) * 360)/255;
if ( tWindDir >=0 and tWindDir <=360)
wind_dir = tWindDir;
//0174 current outdoor temp [0.1 deg F]
temp = (getword(ptr+10) /10.0);
// Maths - Temp conversion to degrees C
tempc = ((temp-32)/1.8);
//0263 rain long term total [0.01 inches]
rain = (getword(ptr+14) / 100.0);
//2755 current barometer [0.1 mbar]
bar = (getword(ptr+18) / 10.0) *0.0295301;
//0306 current indoor temp [0.1 deg F]
id_temp = (getword(ptr+22) /10.0);
//---- current outdoor humidity [0.1%]
hum = (getword(ptr+26) / 10.0);
//---- current indoor humidity [0.1%]
id_hum = (getword(ptr+30) / 10.0) ;
//0006 date [day of year, -1]
day = (getword(ptr+34) + 1);
//0520 time [minute of day, 0-1440]
minutes = (getword(ptr+38));
//0036 today's rain total [0.01 inches]
day_rain = (getword(ptr+42) / 100.0);
//0000 1 min wind speed average [0.1 kph]
avg_wind = (getword(ptr+46) / 10.0);
}
char * wind_name(int windir)
{
char * wname[17] = {"", "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"};
float rawDir = float(windir) / 22.5;
int offset = int(rawDir + 1.5);
offset = offset > 16 ? offset- 16 : offset;
return wname[offset];
}
void send_rf12() {
//==================================BMP085===================================
psensor.startMeas(BMP085::TEMP);
delay(16);
int32_t traw = psensor.getResult(BMP085::TEMP);
psensor.startMeas(BMP085::PRES);
delay(32);
int32_t praw = psensor.getResult(BMP085::PRES);
struct { int16_t temp; int32_t pres; } payload;
psensor.calculate(payload.temp, payload.pres);
// this code is not needed for use as remote node, keep it for debugging
//Serial.print("BMP ");
//Serial.print("temp = ");
//Serial.print(payload.temp/10.0);
//Serial.print(' ');
//Serial.print("Pressure = ");
//Serial.println(payload.pres);
//--------------------------------------------------------------------------------------------------
// Create emon payload
//--------------------------------------------------------------------------------------------------
int temp1 = tempc; // Outdoor temperature 1
int temp2 = payload.temp/10.0; // BMP085 temperature 2
int BMP_pres = payload.pres/1; // BMP085 Pressure
int emon_wind_speed = wind_speed; // PeetBros wind speed out
int emon_wind_dir = wind_dir; // PeetBros wind direction out
int emon_avg_wind = avg_wind; // PeetBros 5min ave wind speed
//char emon_wind_name = wind_name(wind_dir); // Wind name
//---------------------------------------------------------------------------------------------------
//Serial print for debug
//---------------------------------------------------------------------------------------------------
delay (10);
Serial.print("temp1: ");
Serial.println(temp1/1.0);
delay(5);
Serial.print("temp2: ");
Serial.println(temp2/1.0);
delay(5);
Serial.print("pres: ");
Serial.println(BMP_pres);
delay(5);
Serial.print("emon_wind_speed: ");
Serial.println(emon_wind_speed);
delay(5);
Serial.print("emon_wind_dir: ");
Serial.println(emon_wind_dir);
delay(5);
Serial.print("emon_avg_wind: ");
Serial.println(emon_avg_wind);
delay(5);
//--------------------------------------------------------------------------------------------------
// Send payload data via RF
//--------------------------------------------------------------------------------------------------
rf12_sleep(-1); //wake up RF module
while (!rf12_canSend())
rf12_recvDone();
rf12_sendStart(rf12_hdr, &emontx, sizeof emontx, RADIO_SYNC_MODE);
rf12_sleep(0); //put RF module to sleep
}
void loop() {
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
//do whatever is in these brackets
send_rf12();
}
get_weather();
String prBuff = String("W Dir:") + wind_name(wind_dir) + String(" W Spd:") + wind_speed;
//Serial.println(prBuff);
prBuff = String("Avg Spd:") + avg_wind + String(" W deg:") + wind_dir;
//Serial.print(prBuff);
//Serial.print ("temp:");
//Serial.println (tempc);
//Serial.print("wind dir:");
//Serial.println(wind_dir);
//Serial.print("wind speed:");
//Serial.print(wind_speed);
//Serial.println("kms");
//Serial.print("avg_wind: ");
//Serial.print(winddir);
//Serial.print(avg_wind);
//Serial.println("kms");
}
Re: Can anyone help with my project. Weather station integration.
If your not using a CT sensor it would be a good idea to remove the energy monitoring code. See here for a barebones RFM12 Tx and Rx code: https://github.com/openenergymonitor/RFM12B_Simple