Last active
August 29, 2015 14:10
-
-
Save markfink/85b7f943e0e1c9b0c715 to your computer and use it in GitHub Desktop.
ardumeter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
ardumeter, monitoring temperature and power consumption. | |
features: | |
* collect measurements and forward to emoncms http://emoncms.org/ | |
* reconnect after ethernet connection loss | |
* S0 pulse count for up to 20 electricity meters | |
* use DS128B20 sensor address to bind temperature sensors | |
status LEDs: | |
Startup -> red LED ON | |
Error -> red LED flashes | |
Data -> green LED flashes | |
source: https://gist.github.com/markfink/85b7f943e0e1c9b0c715 | |
(c) 2014 Mark Fink | |
*/ | |
#include <EtherCard.h> // https://github.com/jcw/ethercard | |
#include <PinChangeInt.h> // https://github.com/GreyGnome/PinChangeInt | |
#include <OneWire.h> // http://www.pjrc.com/teensy/td_libs_OneWire.html | |
#include <DallasTemperature.h> // http://download.milesburton.com/Arduino/MaximTemperature/DallasTemperature_LATEST.zip | |
// Status variables to track connected periphery | |
boolean DEBUG, DNS; | |
unsigned long timer = 0; | |
// On-board LED | |
uint8_t greenLED = 5; | |
uint8_t redLED = 6; | |
// Setings for DS128B20 | |
const int TEMPERATURE_PRECISION= 11; // 9 (93.8ms),10 (187.5ms) ,11 (375ms) or 12 (750ms) bits equal to resplution of 0.5C, 0.25C, 0.125C and 0.0625C | |
int temperature_sensor_bus= 7; // one wire bus | |
DeviceAddress temp_in_addr = { 0x28, 0x8F, 0xEF, 0x5C, 0x06, 0x00, 0x00, 0x7E }; | |
DeviceAddress temp_out_addr = { 0x28, 0x6B, 0xDF, 0xDF, 0x02, 0x00, 0x00, 0xC0 }; | |
OneWire oneWire(temperature_sensor_bus); | |
DallasTemperature sensors(&oneWire); | |
// sensor measurements | |
String temp_in; | |
String temp_out; | |
// I connected the S0 bus to A0, A1, A2 pins | |
uint8_t a0 = 0; | |
uint8_t a1 = 0; | |
uint8_t a2 = 0; | |
/* Recommended node ID allocation | |
------------------------------------------------------------------------------------------------------------ | |
-ID- -Node Type- | |
0 - Special allocation in JeeLib RFM12 driver - reserved for OOK use | |
1-4 - Control nodes | |
5-10 - Energy monitoring nodes | |
11-14 --Un-assigned -- | |
15-16 - Base Station & logging nodes | |
17-30 - Environmental sensing nodes (temperature humidity etc.) | |
31 - Special allocation in JeeLib RFM12 driver - Node31 can communicate with nodes on any network group | |
------------------------------------------------------------------------------------------------------------- | |
*/ | |
uint8_t node_id = 10; | |
// ethernet interface mac address, must be unique on the LAN | |
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 }; | |
byte Ethernet::buffer[500]; | |
// set this to the domain name of your hosted emoncms - leave blank if posting to IP address | |
const char website[] PROGMEM = "emoncms.org"; | |
// set if your emoncms installation is in a subdirectory i.e "/emoncms3" | |
char basedir[] = ""; | |
// set your emoncms apikey for write mode | |
char apikey[] = "your api key"; | |
//--------------------------------------------------------------------- | |
// setup sensors | |
//--------------------------------------------------------------------- | |
void setup() | |
{ | |
// setup onboard LEDs | |
pinMode(greenLED, OUTPUT); | |
pinMode(redLED, OUTPUT); | |
digitalWrite(greenLED, HIGH); | |
digitalWrite(redLED, LOW); | |
// setup arduino pins | |
pinMode(A0, INPUT); digitalWrite(A0, LOW); | |
PCintPort::attachInterrupt(A0, &count_a0, FALLING); // add more attachInterrupt code as required | |
pinMode(A1, INPUT); digitalWrite(A1, LOW); | |
PCintPort::attachInterrupt(A1, &count_a1, FALLING); | |
pinMode(A2, INPUT); digitalWrite(A2, LOW); | |
PCintPort::attachInterrupt(A2, &count_a2, FALLING); | |
// setup Serial | |
Serial.begin(9600); | |
if (Serial) { DEBUG = true; } | |
else { DEBUG = false; Serial.end(); } | |
if (DEBUG) { | |
Serial.println(F("ardumeter, monitoring temperature and power consumption.")); | |
Serial.println(F("========================================================")); | |
} | |
// setup DS18B20 | |
sensors.begin(); | |
// check one wire power usage | |
if (sensors.isParasitePowerMode()) { if (DEBUG) { Serial.println(F("Info: One wire bus in parasite power mode.")); }} | |
sensors.setResolution(temp_in_addr, TEMPERATURE_PRECISION); | |
sensors.setResolution(temp_out_addr, TEMPERATURE_PRECISION); | |
delay(1000); | |
// setup Ethernet ENC28J60 | |
if (ether.begin(sizeof Ethernet::buffer, mymac) == 0) | |
if (DEBUG) { Serial.println(F("Error: Failed to access Ethernet controller.")); } | |
if (DEBUG) { Serial.println(F("Setting up DHCP")); } | |
if (!ether.dhcpSetup()) | |
if (DEBUG) { Serial.println(F("Error: DHCP failed.")); } | |
if (DEBUG) { | |
Serial.println(F("Ethernet connection details:")); | |
ether.printIp("My IP: ", ether.myip); | |
ether.printIp("Netmask: ", ether.netmask); | |
ether.printIp("GW IP: ", ether.gwip); | |
ether.printIp("DNS IP: ", ether.dnsip); | |
} | |
// DNS check | |
check_DNS(); | |
delay(1000); | |
digitalWrite(redLED, HIGH); | |
} | |
//--------------------------------------------------------------------- | |
// main loop | |
//--------------------------------------------------------------------- | |
void loop() | |
{ | |
ether.packetLoop(ether.packetReceive()); | |
// 10000 = one post every 10 seconds. | |
// its recommended to keep this figure at 10s or longer, 20, 30s | |
// millis() is set back to 0 every 50 days! | |
if (((millis()-timer)>10000) || (millis() < timer)) { | |
timer = millis(); | |
// issue global request for all connected temperature sensors to return a measurement | |
sensors.requestTemperatures(); | |
temp_in = read_temp_sensor(temp_in_addr); | |
temp_out = read_temp_sensor(temp_out_addr); | |
if (!DNS) { check_DNS(); } | |
if (DNS) { send_ether_json_data(); } | |
// reset counters for next interval | |
a0 = 0; | |
a1 = 0; | |
a2 = 0; | |
} | |
} | |
//--------------------------------------------------------------------- | |
// helper functions | |
//--------------------------------------------------------------------- | |
void blink_LED(uint8_t led) { | |
digitalWrite(led, LOW); | |
delay(300); | |
digitalWrite(led, HIGH); | |
} | |
void check_DNS() { | |
if(ether.dnsLookup(website)) { | |
DNS = true; | |
ether.printIp("SRV: ", ether.hisip); | |
} | |
else { | |
DNS = false; | |
Serial.println(F("Error: DNS failed.")); | |
blink_LED(redLED); | |
} | |
} | |
String read_temp_sensor(DeviceAddress address) { | |
char charVal[10]; // used to convert float values to String | |
float temp = sensors.getTempC(address); | |
if (temp == -127.00) { | |
if (DEBUG) { Serial.println(F("Error: Could not get temperature.")); } | |
blink_LED(redLED); | |
} | |
dtostrf(temp, 4, 2, charVal); | |
return String(charVal); | |
} | |
// S0 pulse counter functions | |
void count_a0() { a0++; }; | |
void count_a1() { a1++; }; | |
void count_a2() { a2++; }; | |
void send_ether_json_data() | |
{ | |
String str; | |
char buf[150]; | |
str = String(basedir) + "/input/post.json?"; | |
str += "apikey=" + String(apikey); | |
str += "&node=" + String(node_id); | |
str += "&json={"; | |
str += "pump:" + String(a0) + ","; | |
str += "heat:" + String(a1) + ","; | |
str += "frost:" + String(a2) + ","; | |
str += "temp_in:" + temp_in + ","; | |
str += "temp_out:" + temp_out; | |
str += "}\0"; // End of json string | |
str.toCharArray(buf, 150); | |
if (DEBUG) {Serial.print(F("Data sent: ")); Serial.println(buf);}; | |
// Send data to the server: | |
ether.browseUrl(PSTR(""), buf, website, 0); | |
blink_LED(greenLED); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment