/* EmonTx CT123 + Voltage example An example sketch for the emontx module for CT only electricity monitoring. Part of the openenergymonitor.org project Licence: GNU GPL V3 Authors: Glyn Hudson, Trystan Lea Builds upon JeeLabs RF12 library and Arduino emonTx documentation: http://openenergymonitor.org/emon/modules/emontx/ emonTx firmware code explination: http://openenergymonitor.org/emon/modules/emontx/firmware emonTx calibration instructions: http://openenergymonitor.org/emon/modules/emontx/firmware/calibration THIS SKETCH REQUIRES: Libraries in the standard arduino libraries folder: - JeeLib https://github.com/jcw/jeelib - EmonLib https://github.com/openenergymonitor/EmonLib.git Other files in project directory (should appear in the arduino tabs above) - emontx_lib.ino slave control for 3-phase added by Martin Roberts 14/10/12 */ #define FVCAL 237 // default is 234.26 #define FICAL 111.5 // default 111.1 #define FPHASE 1 // default 1.7 #define FILTERSETTLETIME 5000 // Time (ms) to allow the filters to settle before sending data //CT 1 is always enabled const int CT2 = 1; // Set to 1 to enable CT channel 2 const int CT3 = 0; // Set to 1 to enable CT channel 3 #define freq RF12_433MHZ // Frequency of RF12B module can be RF12_433MHZ, RF12_868MHZ or RF12_915MHZ. You should use the one matching the module you have.433MHZ, RF12_868MHZ or RF12_915MHZ. You should use the one matching the module you have. const int nodeID = 10; // emonTx RFM12B node ID const int networkGroup = 210; // emonTx RFM12B wireless network group - needs to be same as emonBase and emonGLCD needs to be same as emonBase and emonGLCD const int UNO = 1; // Set to 0 if your not using the UNO bootloader (i.e using Duemilanove) - All Atmega's shipped from OpenEnergyMonitor come with Arduino Uno bootloader #include // the UNO bootloader #include // Download JeeLib: http://github.com/jcw/jeelib ISR(WDT_vect) { Sleepy::watchdogEvent(); } #include "EmonLib.h" EnergyMonitor ct1,ct2,ct3; // Create instances for each CT channel #include typedef struct { int power1, power2, power3, Vrms; } PayloadTX; // neat way of packaging data for RF comms PayloadTX emontx[3]; const int LEDpin = 9; // On-board emonTx LED boolean settled = false; void setup() { Serial.begin(9600); Serial.println("emonTX CT123 Voltage example"); Serial.println("OpenEnergyMonitor.org"); Serial.print("Node: "); Serial.print(nodeID); Serial.print(" Freq: "); if (freq == RF12_433MHZ) Serial.print("433Mhz"); if (freq == RF12_868MHZ) Serial.print("868Mhz"); if (freq == RF12_915MHZ) Serial.print("915Mhz"); Serial.print(" Network: "); Serial.println(networkGroup); ct1.voltageTX(FVCAL, FPHASE); // ct.voltageTX(calibration, phase_shift) - make sure to select correct calibration for AC-AC adapter http://openenergymonitor.org/emon/modules/emontx/firmware/calibration ct1.currentTX(1, FICAL); // Setup emonTX CT channel (channel (1,2 or 3), calibration) // CT Calibration factor = CT ratio / burden resistance ct2.voltageTX(FVCAL, FPHASE); // CT Calibration factor = (100A / 0.05A) x 18 Ohms ct2.currentTX(2, FICAL); ct3.voltageTX(FVCAL, FPHASE); ct3.currentTX(3, FICAL); rf12_initialize(nodeID, freq, networkGroup); // initialize RF //rf12_control(0xc657); // approx. 3.918kps, i.e. 10000/29(1+0x57) kps rf12_sleep(RF12_SLEEP); Wire.begin(); // join i2c bus (address optional for master) pinMode(LEDpin, OUTPUT); // Setup indicator LED digitalWrite(LEDpin, HIGH); if (UNO) wdt_enable(WDTO_8S); // Enable anti crash (restart) watchdog if UNO bootloader is selected. Watchdog does not work with duemilanove bootloader // Restarts emonTx if sketch hangs for more than 8s } void loop() { pokeSlave(2); // start slave on phase 2 pokeSlave(3); // start slave on phase 3 ct1.calcVI(20,2000); // Calculate all. No.of crossings, time-out emontx[0].power1 = ct1.realPower; Serial.print(emontx[0].power1); emontx[0].Vrms = ct1.Vrms*100; // AC Mains rms voltage if (CT2) { ct2.calcVI(20,2000); //ct.calcVI(number of crossings to sample, time out (ms) if no waveform is detected) emontx[0].power2 = ct2.realPower; Serial.print("\t"); Serial.print(emontx[0].power2); //Serial.print("\t"); Serial.print(ct2.Irms); //Serial.print("\t"); Serial.print(ct2.powerFactor); } if (CT3) { ct3.calcVI(20,2000); emontx[0].power3 = ct3.realPower; Serial.print("\t"); Serial.print(emontx[0].power3); } Serial.print("\t"); Serial.print(ct1.Vrms); Serial.println(); delay(100); // because millis() returns to zero after 50 days ! if (!settled && millis() > FILTERSETTLETIME) settled = true; if (settled) // send data only after filters have settled { readSlave(2); // get data for phase 2 readSlave(3); // get data for phase 3 delay(100); // send_rf_data corrupts any pending Serial.prints so wait until they finish - need to find out why send_rf_data(); // *SEND RF DATA* - see emontx_lib digitalWrite(LEDpin, HIGH); delay(2); digitalWrite(LEDpin, LOW); // flash LED emontx_sleep(5); // sleep or delay in seconds - see emontx_lib } else if (UNO) wdt_reset(); } void pokeSlave(byte phase) { //Serial.print("Poking slave "); //Serial.println(phase,DEC); Wire.beginTransmission(phase); // transmit to device slave Wire.write(0x5a); // send any data Wire.endTransmission(); // stop transmitting } void readSlave(byte phase) { byte *p; int i; if((phase<2)||(phase>3)) return; p=(byte *)(&emontx[phase-1]); //Serial.print("Reading from slave "); //Serial.println(phase,DEC); Wire.requestFrom(phase, sizeof emontx[0]); // request data from slave device i=0; while(Wire.available()) // slave may send less than requested { p[i++] = Wire.read(); } }