Last active
August 29, 2015 14:16
-
-
Save analogic/88b41891b4279e8ba67b to your computer and use it in GitHub Desktop.
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
#include <OneWire.h> | |
#include <EtherCard.h> | |
#include <avr/wdt.h> | |
// milliseconds to wait for data send | |
#define REQUEST_RATE 60000 | |
// ethernet module RST pin | |
#define ETHERNET_RST 6 | |
// arduino RST pin | |
#define ARDUINO_RST 4 | |
// do you want debug through Serial? | |
#define SERIAL true | |
// ethernet interface mac address, must be unique on the LAN | |
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 }; | |
static byte myip[] = { 192,168,88,111 }; | |
static byte mygw[] = { 192,168,88,1 }; | |
static byte mydns[] = { 8,8,8,8 }; | |
static byte mask[] = { 255,255,255,0 }; | |
// we will test every minut DNS(restart if unavailable) | |
// and send data to that host | |
const char website[] PROGMEM = "your.server.com"; | |
// we need to send request right after start | |
static long timer = -REQUEST_RATE; | |
OneWire ds(3); | |
byte Ethernet::buffer[500]; | |
BufferFiller bfill; | |
char zxc[7]; | |
byte addr[8]; // temp sensor address | |
uint8_t errata; | |
void setup () { | |
// http://weblog.jos.ph/development/arduino-reset-hack/ | |
digitalWrite(ARDUINO_RST, HIGH); //We need to set it HIGH immediately on boot | |
pinMode(ARDUINO_RST,OUTPUT); //We can declare it an output ONLY AFTER it's HIGH | |
// if there is watchdog running stop it! | |
wdt_disable(); | |
// Starting watchdog with 8s timeout | |
wdt_enable(WDTO_8S); | |
#if SERIAL | |
// starting Serial debug | |
Serial.begin(9600); | |
debugln('Hello world!'); | |
#endif | |
// Starting ethernet | |
// will keep restarting whole arduino while it got started properly | |
while(restartEthernet()) { | |
digitalWrite(ARDUINO_RST, LOW); // Force restart | |
} | |
// Find temp sensor, some attempts can fail so we will run it until | |
// address with proper CRC is found | |
while(restartDS18B20()) { | |
digitalWrite(ARDUINO_RST, LOW); // Force restart | |
} | |
} | |
bool restartEthernet() { | |
debugln(F("Restarting ethernet")); | |
pinMode(ETHERNET_RST, OUTPUT); | |
digitalWrite(ETHERNET_RST, HIGH); | |
delay(200); | |
// ENC28J60 resets on holding RST pin LOW | |
digitalWrite(ETHERNET_RST, LOW); | |
delay(200); | |
digitalWrite(ETHERNET_RST, HIGH); | |
delay(200); | |
ether.doBIST(); | |
debugln(F("...done")); | |
errata = ether.begin(sizeof Ethernet::buffer, mymac); | |
if (errata == 0) { | |
debugln(F("Failed to access Ethernet controller")); | |
return 1; | |
} | |
Serial.println(errata); | |
debugln(F("Ethernet begin() success")); | |
debugln(F("Setting static IP")); | |
ether.staticSetup(myip, mygw, mydns, mask); | |
// dynamic/static setup can sometimes take long time | |
// so we rather get another 8s to DNS resolve test | |
wdt_reset(); | |
#if SERIAL | |
debugln(F("...done")); | |
ether.printIp("IP: ", ether.myip); | |
ether.printIp("GW: ", ether.gwip); | |
ether.printIp("DNS: ", ether.dnsip); | |
#endif | |
if (!ether.dnsLookup(website)) { | |
debugln(F("Failed to resolve domain name via DNS")); | |
return 1; | |
} | |
#if SERIAL | |
ether.printIp("SRV: ", ether.hisip); | |
#endif | |
wdt_reset(); | |
debugln(F("...OK")); | |
return 0; | |
} | |
bool restartDS18B20() { | |
debugln(F("Searching temp sensor")); | |
byte i; | |
ds.reset_search(); | |
if ( !ds.search(addr)) { | |
debugln(F("No more addresses.")); | |
ds.reset_search(); | |
return 1; | |
} | |
debug(F("ROM =")); | |
for( i = 0; i < 8; i++) { | |
debug(F(" ")); | |
debug(addr[i], HEX); | |
} | |
debugln(); | |
debugln(F("CRC check")); | |
if (OneWire::crc8(addr, 7) != addr[7]) { | |
debugln(F("CRC is not valid!")); | |
return 1; | |
} | |
debugln(F("...OK")); | |
return 0; | |
} | |
static void response (byte status, word off, word len) | |
{ | |
debugln(F(">>>")); | |
Ethernet::buffer[off+300] = 0; | |
debugln((const char*) Ethernet::buffer + off); | |
debugln(F("...")); | |
} | |
void loop () | |
{ | |
ether.packetLoop(ether.packetReceive()); | |
if (millis() > timer + REQUEST_RATE) { | |
timer = millis(); | |
delay(500); | |
if (!ether.dnsLookup(website)) { | |
debugln(F("Failed to resolve domain name via DNS, forcing restart")); | |
digitalWrite(ARDUINO_RST, LOW); // Force restart | |
} | |
char data[50]; | |
sprintf(data, "?temp=%s&uptime=%ld", dtostrf(temperature(),3,2,zxc), timer/1000); | |
debug(F("<<< REQ ")); | |
debugln(data); | |
wdt_reset(); | |
ether.browseUrl(PSTR("/therm.php"), data, website, response); | |
} | |
if(timer > 86400000) { | |
digitalWrite(ARDUINO_RST, LOW); // Force restart | |
} | |
wdt_reset(); | |
} | |
float temperature() | |
{ | |
byte i; | |
byte present = 0; | |
byte data[12]; | |
float celsius, fahrenheit; | |
ds.reset(); | |
ds.select(addr); | |
ds.write(0x44, 1); // start conversion, with parasite power on at the end | |
delay(1000); // maybe 750ms is enough, maybe not | |
// we might do a ds.depower() here, but the reset will take care of it. | |
present = ds.reset(); | |
ds.select(addr); | |
ds.write(0xBE); // Read Scratchpad | |
debug(F(" Data = ")); | |
debug(present, HEX); | |
debug(F(" ")); | |
for ( i = 0; i < 9; i++) { // we need 9 bytes | |
data[i] = ds.read(); | |
debug(data[i], HEX); | |
debug(F(" ")); | |
} | |
debug(F(" CRC=")); | |
debug(OneWire::crc8(data, 8), HEX); | |
debugln(); | |
// 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]; | |
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; | |
fahrenheit = celsius * 1.8 + 32.0; | |
debug(F(" Temperature = ")); | |
debug(celsius); | |
debugln(F(" Celsius")); | |
return celsius; | |
} | |
/********************* DEBUG SUGAR ****************************/ | |
void debug(const __FlashStringHelper *ifsh) { | |
#if SERIAL | |
Serial.print(ifsh); | |
#endif | |
} | |
void debug(const char *message) { | |
#if SERIAL | |
Serial.print(message); | |
#endif | |
} | |
void debug(int num) { | |
#if SERIAL | |
Serial.print(num); | |
#endif | |
} | |
void debug(uint8_t b, int s) { | |
#if SERIAL | |
Serial.print(b, s); | |
#endif | |
} | |
void debugln(const __FlashStringHelper *ifsh) { | |
#if SERIAL | |
Serial.println(ifsh); | |
#endif | |
} | |
void debugln(const char *message) { | |
#if SERIAL | |
Serial.println(message); | |
#endif | |
} | |
void debugln(int num) { | |
#if SERIAL | |
Serial.println(num); | |
#endif | |
} | |
void debugln() { | |
#if SERIAL | |
Serial.println(); | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment