Skip to content

Instantly share code, notes, and snippets.

@markfink
Last active August 29, 2015 14:10
Show Gist options
  • Save markfink/85b7f943e0e1c9b0c715 to your computer and use it in GitHub Desktop.
Save markfink/85b7f943e0e1c9b0c715 to your computer and use it in GitHub Desktop.
ardumeter
/*
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