Skip to content
Browse files

Added a test sketch with no watchdog and no serial printing

  • Loading branch information...
1 parent fdda60d commit 91561efc68feed8c7491ad2b64a21a0a49567aa5 Trystan committed Jan 25, 2012
Showing with 334 additions and 0 deletions.
  1. +243 −0 NanodeRF_dev/NanodeRF_dev.ino
  2. +51 −0 NanodeRF_dev/decode_reply.ino
  3. +40 −0 NanodeRF_dev/dhcp_dns.ino
View
243 NanodeRF_dev/NanodeRF_dev.ino
@@ -0,0 +1,243 @@
+/* _ _
+ | | | |
+ ___ _ __ ___ ___ _ __ | |__ __ _ ___ ___ _ __ __ _ _ __ ___ __| | ___
+ / _ \ '_ ` _ \ / _ \| '_ \| '_ \ / _` / __|/ _ \ | '_ \ / _` | '_ \ / _ \ / _` |/ _ \
+| __/ | | | | | (_) | | | | |_) | (_| \__ \ __/ _ | | | | (_| | | | | (_) | (_| | __/
+ \___|_| |_| |_|\___/|_| |_|_.__/ \__,_|___/\___| (_) |_| |_|\__,_|_| |_|\___/ \__,_|\___|
+
+*/
+//--------------------------------------------------------------------------------------
+// Relay's data recieved by emontx up to emoncms
+// Relay's data recieved by emonglcd up to emoncms
+// Decodes reply from server to set software real time clock
+// Relay's time data to emonglcd - and any other listening nodes.
+// Looks for 'ok' reply from http request to verify data reached emoncms
+
+// emonBase Documentation: http://openenergymonitor.org/emon/emonbase
+
+// Authors: Trystan Lea and Glyn Hudson
+// Part of the: openenergymonitor.org project
+// Licenced under GNU GPL V3
+//http://openenergymonitor.org/emon/license
+
+// EtherCard Library by Jean-Claude Wippler and Andrew Lindsay
+// JeeLib Library by Jean-Claude Wippler
+//--------------------------------------------------------------------------------------
+
+#include <Wire.h>
+#include <RTClib.h>
+RTC_Millis RTC;
+
+#include <JeeLib.h> //https://github.com/jcw/jeelib
+
+#define MYNODE 15
+#define freq RF12_433MHZ // frequency
+#define group 210 // network group
+
+//---------------------------------------------------
+// Data structures for transfering data between units
+//---------------------------------------------------
+typedef struct { int power, battery; } PayloadTX;
+PayloadTX emontx;
+
+typedef struct { int temperature; } PayloadGLCD;
+PayloadGLCD emonglcd;
+
+typedef struct { int hour, mins, sec; } PayloadBase;
+PayloadBase emonbase;
+//---------------------------------------------------
+
+//---------------------------------------------------------------------
+// The PacketBuffer class is used to generate the json string that is send via ethernet - JeeLabs
+//---------------------------------------------------------------------
+class PacketBuffer : public Print {
+public:
+ PacketBuffer () : fill (0) {}
+ const char* buffer() { return buf; }
+ byte length() { return fill; }
+ void reset()
+ {
+ memset(buf,NULL,sizeof(buf));
+ fill = 0;
+ }
+ virtual size_t write (uint8_t ch)
+ { if (fill < sizeof buf) buf[fill++] = ch; }
+ byte fill;
+ char buf[150];
+ private:
+};
+PacketBuffer str;
+
+//--------------------------------------------------------------------------
+// Ethernet
+//--------------------------------------------------------------------------
+#include <EtherCard.h> //https://github.com/jcw/ethercard
+
+// ethernet interface mac address, must be unique on the LAN
+static byte mymac[] = { 0x44,0x29,0x49,0x21,0x30,0x31 };
+
+//IP address of remote sever, only needed when posting to a server that has not got a dns domain name (staticIP e.g local server)
+byte Ethernet::buffer[700];
+static uint32_t timer;
+
+//Domain name of remote webserver - leave blank if posting to IP address
+char website[] PROGMEM = "vis.openenergymonitor.org";
+//static byte hisip[] = { 213,138,101,177 }; // un-comment for posting to static IP server (no domain name)
+
+const int redLED = 6; // NanodeRF RED indicator LED
+const int greenLED = 5; // NanodeRF GREEN indicator LED
+
+int ethernet_error = 0; // Etherent (controller/DHCP) error flag
+int rf_error = 0; // RF error flag - high when no data received
+int ethernet_requests = 0; // count ethernet requests without reply
+
+int emonglcd_rx = 0; // Used to indicate that emonglcd data is available
+int data_ready=0; // Used to signal that emontx data is ready to be sent
+unsigned long last_rf; // Used to check for regular emontx data - otherwise error
+
+char line_buf[50]; // Used to store line of http reply header
+
+//**********************************************************************************************************************
+// SETUP
+//**********************************************************************************************************************
+void setup () {
+
+ //Nanode RF LED indictor setup - green flashing means good - red on for a long time means bad!
+ //High means off since NanodeRF tri-state buffer inverts signal
+ pinMode(redLED, OUTPUT); digitalWrite(redLED,LOW);
+ pinMode(greenLED, OUTPUT); digitalWrite(greenLED,LOW);
+ delay(100); digitalWrite(redLED,HIGH); // turn off redLED
+
+ if (ether.begin(sizeof Ethernet::buffer, mymac) == 0) {
+ ethernet_error = 1;
+ }
+
+ rf12_initialize(MYNODE, freq,group);
+ last_rf = millis()-40000; // setting lastRF back 40s is useful as it forces the ethernet code to run straight away
+
+ digitalWrite(greenLED,HIGH); // Green LED off - indicate that setup has finished
+}
+
+//**********************************************************************************************************************
+// LOOP
+//**********************************************************************************************************************
+void loop () {
+
+ dhcp_dns(); // handle dhcp and dns setup - see dhcp_dns tab
+
+ // Display error states on status LED
+ if (ethernet_error==1 || rf_error==1 || ethernet_requests > 0) digitalWrite(redLED,LOW);
+ else digitalWrite(redLED,HIGH);
+
+ //-----------------------------------------------------------------------------------------------------------------
+ // 1) On RF recieve
+ //-----------------------------------------------------------------------------------------------------------------
+ if (rf12_recvDone()){
+ if (rf12_crc == 0 && (rf12_hdr & RF12_HDR_CTL) == 0)
+ {
+ int node_id = (rf12_hdr & 0x1F);
+
+ if (node_id == 10) // EMONTX
+ {
+ emontx = *(PayloadTX*) rf12_data; // get emontx data
+ last_rf = millis(); // reset lastRF timer
+
+ delay(50); // make sure serial printing finished
+
+ // JSON creation: JSON sent are of the format: {key1:value1,key2:value2} and so on
+
+ str.reset(); // Reset json string
+ str.print("{rf_fail:0"); // RF recieved so no failure
+ str.print(",power:"); str.print(emontx.power); // Add power reading
+ str.print(",battery:"); str.print(emontx.battery); // Add emontx battery voltage reading
+
+ data_ready = 1; // data is ready
+ rf_error = 0;
+ }
+
+ if (node_id == 20) // EMONGLCD
+ {
+ emonglcd = *(PayloadGLCD*) rf12_data; // get emonglcd data
+ emonglcd_rx = 1;
+ }
+ }
+ }
+
+ //-----------------------------------------------------------------------------------------------------------------
+ // 2) If no data is recieved from rf12 module the server is updated every 30s with RFfail = 1 indicator for debugging
+ //-----------------------------------------------------------------------------------------------------------------
+ if ((millis()-last_rf)>30000)
+ {
+ last_rf = millis(); // reset lastRF timer
+ str.reset(); // reset json string
+ str.print("{rf_fail:1"); // No RF received in 30 seconds so send failure
+ data_ready = 1; // Ok, data is ready
+ rf_error=1;
+ }
+
+
+ //-----------------------------------------------------------------------------------------------------------------
+ // 3) Send data via ethernet
+ //-----------------------------------------------------------------------------------------------------------------
+ ether.packetLoop(ether.packetReceive());
+
+ if (data_ready) {
+
+ // include temperature data from emonglcd if it has been recieved
+ if (emonglcd_rx) {
+ str.print(",temperature:");
+ str.print(emonglcd.temperature/100.0);
+ emonglcd_rx = 0;
+ }
+
+ str.print("}\0"); // End of json string
+
+ // Example of posting to emoncms v3 demo account goto http://vis.openenergymonitor.org/emoncms3
+ // and login with sandbox:sandbox
+ // To point to your account just enter your WRITE APIKEY
+ ethernet_requests ++;
+ ether.browseUrl(PSTR("/emoncms3/api/post.json?apikey=2d177d7311daf401d054948ce29efe74&json="),str.buf, website, my_callback);
+ data_ready =0;
+ }
+}
+//**********************************************************************************************************************
+
+//-----------------------------------------------------------------------------------
+// Ethernet callback
+// recieve reply and decode
+//-----------------------------------------------------------------------------------
+static void my_callback (byte status, word off, word len) {
+
+ get_header_line(2,off); // Get the date and time from the header
+
+ // Decode date time string to get integers for hour, min, sec, day
+ // We just search for the characters and hope they are in the right place
+ char val[1];
+ val[0] = line_buf[23]; val[1] = line_buf[24];
+ int hour = atoi(val);
+ val[0] = line_buf[26]; val[1] = line_buf[27];
+ int mins = atoi(val);
+ val[0] = line_buf[29]; val[1] = line_buf[30];
+ int sec = atoi(val);
+ val[0] = line_buf[11]; val[1] = line_buf[12];
+ int day = atoi(val);
+
+ RTC.adjust(DateTime(2012, 1, day, hour, mins, sec));
+
+ DateTime now = RTC.now();
+ emonbase.hour = now.hour();
+ emonbase.mins = now.minute();
+ emonbase.sec = now.second();
+
+ //-----------------------------------------------------------------------------
+
+ delay(100);
+
+ // Send time data
+ int i = 0; while (!rf12_canSend() && i<10) {rf12_recvDone(); i++;} // if can send - exit if it gets stuck, as it seems too
+ rf12_sendStart(0, &emonbase, sizeof emonbase); // send payload
+ rf12_sendWait(0);
+
+ get_reply_data(off);
+ if (strcmp(line_buf,"ok")) {ethernet_requests = 0; ethernet_error = 0;} // check for ok reply from emoncms to verify data post request
+}
View
51 NanodeRF_dev/decode_reply.ino
@@ -0,0 +1,51 @@
+int get_header_line(int line,word off)
+{
+ memset(line_buf,NULL,sizeof(line_buf));
+ if (off != 0)
+ {
+ uint16_t pos = off;
+ int line_num = 0;
+ int line_pos = 0;
+
+ while (Ethernet::buffer[pos])
+ {
+ if (Ethernet::buffer[pos]=='\n')
+ {
+ line_num++; line_buf[line_pos] = '\0';
+ line_pos = 0;
+ if (line_num == line) return 1;
+ }
+ else
+ {
+ if (line_pos<49) {line_buf[line_pos] = Ethernet::buffer[pos]; line_pos++;}
+ }
+ pos++;
+ }
+ }
+ return 0;
+}
+
+int get_reply_data(word off)
+{
+ memset(line_buf,NULL,sizeof(line_buf));
+ if (off != 0)
+ {
+ uint16_t pos = off;
+ int line_num = 0;
+ int line_pos = 0;
+
+ // Skip over header until data part is found
+ while (Ethernet::buffer[pos]) {
+ if (Ethernet::buffer[pos-1]=='\n' && Ethernet::buffer[pos]=='\r') break;
+ pos++;
+ }
+ pos+=4;
+ while (Ethernet::buffer[pos])
+ {
+ if (line_pos<49) {line_buf[line_pos] = Ethernet::buffer[pos]; line_pos++;} else break;
+ pos++;
+ }
+ line_buf[line_pos] = '\0';
+ }
+ return 0;
+}
View
40 NanodeRF_dev/dhcp_dns.ino
@@ -0,0 +1,40 @@
+int dhcp_status = 0;
+int dns_status = 0;
+
+void dhcp_dns()
+{
+ //-----------------------------------------------------------------------------------
+ // Get DHCP address
+ // Putting DHCP setup and DNS lookup in the main loop allows for:
+ // powering nanode before ethernet is connected
+ //-----------------------------------------------------------------------------------
+ if (ether.dhcpExpired()) dhcp_status = 0; // if dhcp expired start request for new lease by changing status
+
+ if (!dhcp_status){
+ dhcp_status = ether.dhcpSetup(); // DHCP setup
+
+ if (dhcp_status){ // on success print out ip's
+ ether.printIp("IP: ", ether.myip);
+ ether.printIp("GW: ", ether.gwip);
+
+ static byte dnsip[] = {8,8,8,8};
+ ether.copyIp(ether.dnsip, dnsip);
+ ether.printIp("DNS: ", ether.dnsip);
+ //ether.copyIp(ether.hisip, hisip); // un-comment for posting to static IP server (no domain name)
+ //dns_status = 1; // un-comment for posting to static IP server (no domain name)
+ } else { ethernet_error = 1; }
+ }
+
+ //-----------------------------------------------------------------------------------
+ // Get server address via DNS
+ //-----------------------------------------------------------------------------------
+ if (dhcp_status && !dns_status){
+
+ dns_status = ether.dnsLookup(website); // Attempt DNS lookup
+
+ if (dns_status){
+ ether.printIp("SRV: ", ether.hisip); // server ip
+ } else { ethernet_error = 1; }
+ }
+
+}

0 comments on commit 91561ef

Please sign in to comment.
Something went wrong with that request. Please try again.