EtherMega
EtherMega by Freetronics is Arduino Mega 2560 compatible board with onboard Ethernet and Power-over-Ethernet support.
After a lot of research I decided that EtherMega are going to be my primary boards for home automatation, because of their PoE support, compatibiity with Arduino and all its other features ie. I couldn’t find anything better on the market than this.
MQTT Node
I decided to use MQTT as a protocol to communicate between devices at home.
I found MQTT client library for Arduino which, as it turns out, works just fine on EtherMega.
My current thinking is to create bunch of nodes for our home that will have different roles and perform different tasks.
Goal of my first office node project is to measure temperature in my office using DS18B20 (OneWire) sensor
To simplify the project I used “DS18B20 Arduino module” that I bought online.
Node v1 will be an experimental proof-of-concept MQTT client running on EtherMega.
Node v1
I started playing around with EtherMega, using provided examples for ethernet and OneWire, getting a basic webserver done first, then playing with DS18B20 temperature sensor.
After trying out MQTT I added MQTT client into my code and spent couple of more hours of hacking to get the project working the way I want.
I connected DS18B20 Arduino module to 5V, GND and its output to digital pin 7.
I used parts of provided OneWire example code to retrieve temperature in degrees celsius and get MQTT client to publish it to /home/office/temperature/ topic.
Testing
Output of /home/status/ topic after the node starts:
$ mosquitto_sub -t /home/status/
office up
Output of /home/office/temperature/ topic when the node runs:
$ mosquitto_sub -t /home/office/temperature/
21.81
21.81
21.81
21.88
21.88
...
The following is my code for Node v1 (node.ino):
/*
Node (office)
-------------
Node (v1) located in the office does the following:
1) TEMPERATURE - read temperature from DS18B20 module
/home/office/temperature/
*/
#include <SPI.h>
#include <OneWire.h>
#include <Ethernet.h>
#include <PubSubClient.h>
// Networking
// MQTT server
byte server[] = {192,168,2,101};
// MQTT client - this node IP address
byte ip[] = {192,168,2,201};
// MAC address
byte mac[] = {0xFE,0xED,0xDE,0xAD,0xBE,0xEF};
// Temperature (DS18B20) connected to pin 7
OneWire ds(7);
// MQTT message buffer
char message_buff[30];
// MQTT callback
void callback(char* topic, byte* payload, unsigned int length);
// MQTT PubSub client
EthernetClient ethClient;
PubSubClient client(server, 1883, callback, ethClient);
// MQTT callback function
void callback(char* topic, byte* payload, unsigned int length) {
// Convert payload to string
int i = 0;
for(i=0; i<length; i++) {
message_buff[i] = payload[i];
}
message_buff[i] = '\0';
String msg = String(message_buff);
}
// Setup
void setup() {
// Start the node at the IP address
Serial.begin(9600);
Ethernet.begin(mac, ip);
// Start MQTT client,
// let the home know the office is up
if (client.connect("office")) {
client.publish("/home/status/","office up");
}
}
// Loop
void loop() {
// Start MQTT client
client.loop();
// Read current temperature and
// publish it to /home/office/temperature/
float celsius;
char temp[10];
celsius = readTemperature();
dtostrf(celsius,2,2,temp);
if (celsius && celsius != -300.00) {
client.publish("/home/office/temperature/", temp);
}
}
// Temperature reading from DS18B20 module
// Code is from OneWire library example
float readTemperature() {
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius;
// Can I haz an address?
if ( !ds.search(addr)) {
ds.reset_search();
delay(250);
return -300.00;
}
// Is CRC valid?
if (OneWire::crc8(addr, 7) != addr[7]) {
return -200.00;
}
ds.reset();
ds.select(addr);
// Start conversion, with parasite power on at the end
ds.write(0x44, 1);
delay(1000);
// We might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(addr);
// Read Scratchpad
ds.write(0xBE);
// Read 9 bytes
for ( i = 0; i < 9; i++) {
data[i] = ds.read();
}
// Convert the data to actual temperature
// because the result is a 16 bit signed integer, it should
// be stored to an "int16_t" type, which is always 16 bits
// even when compiled on a 32 bit processor.
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
//// default is 12 bit resolution, 750 ms conversion time
}
celsius = (float)raw / 16.0;
return celsius;
}
Comments
comments powered by Disqus