GithubHelp home page GithubHelp logo

openenergymonitor / emontxfirmware Goto Github PK

View Code? Open in Web Editor NEW
153.0 68.0 139.0 1.26 MB

An open-source wireless energy monitoring node

Home Page: https://shop.openenergymonitor.com/emontx-v3-electricity-monitoring-transmitter-unit-433mhz/

Shell 0.20% C++ 99.80%

emontxfirmware's Introduction

emonTx Firmware Examples

Arduino compatible firmware examples (ATmega328) for emonTx Low power wireless energy-monitoring node.

Update: the offical firmware for latest version of emonTx V3 (as shipped via OpenEnergyMonitor online store) has been moved to a dedicated emonTx V3 repository


Part of the openenergymonitor.org project

Purchase Hardware

emonTx V3 Resources:

emonTx V2 Resources:


Licence

The emonTx firmware is released under the GNU GPL V3 license

The documentation is subject to GNU Free Documentation License

The emonTx hardware designs follow the terms of the OSHW (Open-source hardware) Statement of Principles 1.0.

emontxfirmware's People

Contributors

amaury-anciaux avatar aminfiberlin avatar antonytrupe avatar fpalme avatar glynhudson avatar ichilton avatar jonmurphy avatar mrestivill avatar slyremarks avatar trystanlea avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

emontxfirmware's Issues

rwm_init() for RFM12B missing !!!

Hi, when i compile the sketch with RFM12B defined and RFM69CW undefined I get the error...

emonTxV3_4_3Phase_Voltage.cpp.o: In function setup': /opt/arduino/emonTxV3_4_3Phase_Voltage.ino:264: undefined reference torfm_init()'
emonTxV3_4_3Phase_Voltage.cpp.o: In function loop': /opt/arduino/emonTxV3_4_3Phase_Voltage.ino:325: undefined reference torfm_send(unsigned char const*, unsigned char, unsigned char, unsigned char)'
collect2: error: ld returned 1 exit status
Multiple libraries were found for "Ports.h"
Used: /home/mcp/Programming/Arduino/sketchbook/libraries/jeelib
Not used: /home/mcp/Programming/Arduino/sketchbook/libraries/RFu_jeelib
Fehler beim Kompilieren.

We have original ordered EmonTX 3.4 with RFM12B Chip.

RF birate configuration

Hi all.

There has been talk already about lowering the bitrate to improve the communication range. I did it myself and I would like to share a few thoughts, with the hope that we could make that easier for anyone needing it.

How

emonTX / emonTH

On emonTX side, it is pretty simple. Just add a call to rf12_control() with the proper value during initialization.

This is how I did it on emonTX.

And this is how I did it on emonTH. It is just the same, except I also added a few lines to print the bitrate on the serial port at startup, along with the other parameters.

emonBase

Of course, the bitrate needs to be set accordingly on the emonBase. This shows how I did it (see other commits on same branch for other bitrate values). Again, just the same, except the call to rf12_control() appears several times in the code.

Remarks / questions

Before trying to improve the code for integration, I would like to be sure there is a real interest in this. Otherwise, I'll just keep it dirty for myself.

I think it could be added as a parameter in each sketch, just like Node ID and all, without adding too much confusion to the end user. What do you think ?

I'm listing below a few points to be discussed.

emonBase parameter

Instead of hardcoding, we could modify the RFM2Pi code to make the bitrate a parameter that could be set just like the frequency, Node ID, etc. I'm pretty sure it is not so big a deal, although I never went down to it.

This would allow a user to choose the bitrate by only reprogramming the TX and changing the bitrate smoothly on the base. With this, I'd iterate until I find the fastest bitrate with acceptable throughput. Currently, I justed picked the lowest to spare me the hassle of the tests.

Max packet length and bandwidth occupation

According to the RFM12B page , "the library accepts a variable length packet of data, the limit is 66 bytes".

I can't find the source, but I think this 66 limit is based on the max time a single unit should occupy the bandwidth. I don't know exactly how this is calculated, but if the bitrate is lowered, maybe the max length should be decreased.

Should we come up with a way to enforce this ? What are the requirements ?

Is the 66 limit actually enforced ? Does it depend on the bitrate as I suspect ?

User friendly #defines

In my code, I picked the #defines from the jeelib: RF12_DATA_RATE_1 to RF12_DATA_RATE_9.

Those do not contain the bitrate explicitly, as opposed to something like RF12_DATA_RATE_1200. Should we create such explicit #defines?

Where ? In EmonLib ?

Note that maybe the user does not care about the actual value, and picking in [1-9] makes it easier for him.

Minimize runtime code

In my emonTH implementation, I added a few lines to print the bitrate (real bps value) on the serial port for debug/logging. I copied the lines used to print the frequency.

It should be possible to do more work at compile time, thus generating a code slightly smaller and with a few less work to do at runtime. It is a small detail, really. Besides, it is executed in debug mode, nothing critical. But is sounds like good practice, so while we're at it, we may want to give it a thought. It should be just a few preprocessor directives to add (like #if and such).

Any interest in this ?

debug case logic bug prevents unit from printing 0 data properly

Hey! We think we found a bug that is preventing the unit from printing 0 data properly. The following code:
if (ACAC)
{
if ((debug==1) && (!CT_count==0)) Serial.print(emontx.Vrms);
}
if ((debug==1) && (!CT_count==0)) {Serial.println(); delay(20);}

Should read:

if (ACAC)
{
if ((debug==1) Serial.print(emontx.Vrms);
}
if ((debug==1) {Serial.println(); delay(20);}

Please try to repeat the finding (condition: no CT clamps attached) and if you agree I can submit a pull request.

emonTx_Pulse design issues

Hi guys.

Back to pulse counting, I decided to let down my first approach using watchdog and deep sleep mode, to catch up with current OpenEnergyMonitor approach: reporting pulses on a regular interval.

So I checked out emonTx_Pulse.

I believe it can't work as is. And so does the V3 version.

The biggest flaw is the power computation. As it is coded right now, the power is computed only when receiving a pulse. Thus, if no pulse is received for a long time (power = 0), computed power remains equal to last value. This is for the most obvious but I don't think the power should be computed in the emonTx. Well, I may be wrong, this is debatable, but right now, I don't see how it could work. At least it is not obvious.

Also, since RF packets may be lost, I think it is preferable not to reset the counter after sending the value. The count will increase with time, just like on any meter index. It is just the real index, in fact, with an offset. The wrap around may or may not be an issue. With an unsigned long, and depending on the meter index rate (energy per unit), it is possible (and preferable) that the max will never be reached. If needed, maybe send the value as a long int (two ints on RF link). Twice the RF traffic, but if the application requires it, why not. (Regarding this, my code is not that smart: I use long ints but then blindly cast as int before sending. Maybe I shall deal with this.)

Anyway, I wanted to share

  • The fact that current Pulse code seems broken to me.
  • The reflexion about how to do better. There may be several interesting approaches. Maybe there's discussions I should check on the forum.
  • The old code I used which was designed with low consumption in mind (deep sleep, wake on interrupt or watchdog) and seemed to work well but gave me a hard time on post-processing. This was before FIWA and FINA. Maybe things are different now.
  • The few improvements / modifications I made to emonTx_Pule code.

My dev_emonTx_pulse branch holds a few commits that you may find of interest. I tried to commit atomically so that you can pick what you want. I can send a pull request if you want, even cherry-pick a few modifications into a new branch if you don't want everything. It starts with cleanup (safe stuff: comments, unused variable), then actually adds or modifies features.

I added software debouncing and use of internal pull-up resistor on IRQ pin. Those can be easily disabled, so they might as well appear in the code, and be commented if unused. (Maybe such parameters should be all grouped on top of the file as #defines).

dev_pulse_temp branch is the same pulse code with temperature, in the temperature examples directory. The idea is that the gas meter is outside, so I might as well use the Tx to record outside temp as well. Again, I can rework that if you feel like providing this as another example.

My concerns now are:

  • Get the damn Reed switch to catch the meter wheel turn. Used to work in my former house.
  • Post-processing. Get the power. Sounds easy but I'm afraid it is not. I need to read more about FIWA/FINA. It is pretty easy to compute (approximative) power from indexes sampled on a regular basis (or interpolated to a regular basis) when you do it afterwards. But in OpenEnergyMonitor, the post-processing operations are triggered upon sample reception (unless there is another way ?), so it might be more tricky. I dunno. I have a lot to catch up with in Emoncms.

Anyway, feedback welcome on the emontx_Pulse work, when you get the time.

Bye.

emonTx Firmeare all in one

Hello i created this code, ussing shapes of all sample codes:

/*
EmonTx CT123 all in one 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

*/

define FILTERSETTLETIME 5000 // Time (ms) to allow the filters to settle before sending data

const int CT1 = 1; // Set to 0 to disable CT channel 1
const int CT2 = 1; // Set to 0 to disable CT channel 2
const int CT3 = 1; // Set to 0 to disable CT channel 3
const int RealPower = 1; // Set to 0 to disable Real Power calculation, AC imput 9v may be suplied
const int Pulse = 1; // Set to 0 to disable Pulse Sensor
const int TP = 1; // Set to 0 to disable Temp sensors
const int AC = 227.5; // Set AC RMS voltage for RMS power calculate
const int CalCoef = 238.5; // Set calibration coeficient voltage for CT123
const int CTSamplesIrms = 1480; // Set number of samples (wafeform) for calculate RMS
const int CTSamples = 50; // Set number of samples (wafeform) for calculate Real RMS
const int SamTimeOut = 2000; // Set Time Out in ms for calculate samples RMS

const int sensorResolution = 10; // DS18B20 resolution 9,10,11 or 12bit corresponding to (0.5, 0.25, 0.125, 0.0625 degrees C LSB), lower resolution means lower power

define freq RF12_868MHZ // Frequency of RF12B module can be RF12_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 = 100; // emonTx RFM12B wireless network group - 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 <avr/wdt.h>

include <JeeLib.h> // Download JeeLib: http://github.com/jcw/jeelib

ISR(WDT_vect) { Sleepy::watchdogEvent(); } // Attached JeeLib sleep function to Atmega328 watchdog -enables MCU to be put into sleep mode inbetween readings to reduce power consumption

include <OneWire.h>

include <DallasTemperature.h>

include "EmonLib.h"

EnergyMonitor ct1,ct2,ct3; // Create instances for each CT channel

define ONE_WIRE_BUS 4 // Data wire is plugged into port 2 on the Arduino

OneWire oneWire(ONE_WIRE_BUS); // Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
DallasTemperature sensors(&oneWire); // Pass our oneWire reference to Dallas Temperature.
DeviceAddress sensor; // arrays to hold device address

typedef struct { int ct1rp,ct1ap,ct1pf,ct1vr,ct1ir, ct2rp,ct2ap,ct2pf,ct2vr,ct2ir, ct3rp,ct3ap,ct3pf,ct3vr,ct3ir, battery, pulse, power, temp1, temp2; } PayloadTX; // create structure - a neat way of packaging data for RF comms
PayloadTX emontx;

const int LEDpin = 9; // On-board emonTx LED

boolean settled = false;

                                                                    // Pulse counting settings

long pulseCount = 0; // Number of pulses, used to measure energy.
unsigned long pulseTime,lastTime; // Used to measure power.
double power, elapsedWh; // power and energy
int ppwh = 4; // pulses per Wh
unsigned int TPcount = 0;

void setup()
{
Serial.begin(9600);
Serial.println("emonTX CT123 + Pulse + Temp 12");
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);

if (CT1) ct1.currentTX(1, 111.1); // Setup emonTX CT channel (ADC input, calibration)
if (CT2) ct2.currentTX(2, 111.1); // Calibration factor = CT ratio / burden resistance
if (CT3) ct3.currentTX(3, 111.1); // Calibration factor = (100A / 0.05A) / 33 Ohms
if (CT1) ct1.voltageTX(CalCoef, 1.7); // Calibration, phase_shift
if (CT2) ct2.voltageTX(CalCoef, 1.7); // Calibration, phase_shift
if (CT2) ct3.voltageTX(CalCoef, 1.7); // Calibration, phase_shift
if (Pulse) attachInterrupt(1, onPulse, FALLING); // KWH interrupt attached to IRQ 1 = pin3 - hardwired to emonTx pulse jackplug. For connections see: http://openenergymonitor.org/emon/node/208

if (TP) {
pinMode(7,OUTPUT); // DS18B20 power control pin - see jumper setup instructions above
digitalWrite(7,HIGH); // turn on DS18B20
delay(10);
sensors.begin();
if (!sensors.getAddress(sensor, 0)) {
Serial.println("Unable to find temperarture sensors");
} else {
TPcount = sensors.getDeviceCount();
Serial.print("Total Temperature Sensors: ");Serial.println(TPcount);
sensors.setResolution(sensor, sensorResolution);
Serial.print("Temperature Sensor Resolution: ");Serial.println(sensors.getResolution(sensor), DEC);
}
}

rf12_initialize(nodeID, freq, networkGroup); // initialize RFM12B
rf12_sleep(RF12_SLEEP);

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()
{

if (CT1) {
if (RealPower) {
ct1.calcVI(CTSamples,SamTimeOut); // Calculate (No.of wavelengths, time-out) realPower,apparentPower,powerFactor,Vrms,Irms. No.of wavelengths, time-out
emontx.ct1rp = ct1.realPower;
emontx.ct1ap = ct1.apparentPower;
emontx.ct1pf = ct1.powerFactor;
emontx.ct1vr = ct1.Vrms;
emontx.ct1ir = ct1.Irms;
} else {
emontx.ct1rp = 0;
emontx.ct1ap = ct1.calcIrms(CTSamplesIrms) * AC; // Calculate apparentPower ct.calcIrms(number of wavelengths sample)*AC RMS voltage
emontx.ct1pf = 0;
emontx.ct1vr = 0;
emontx.ct1ir = 0;
}

Serial.print("CT1 RealPower: ");Serial.print(emontx.ct1rp);
Serial.print(" ApparentPower: ");Serial.print(emontx.ct1ap);
Serial.print(" PowerFactor: ");Serial.print(emontx.ct1pf);
Serial.print(" Vrms: ");Serial.print(emontx.ct1vr);
Serial.print(" Irms: ");Serial.println(emontx.ct1ir);

}

if (CT2) {
if (RealPower) {
ct2.calcVI(CTSamples,SamTimeOut); // Calculate (No.of wavelengths, time-out) realPower,apparentPower,powerFactor,Vrms,Irms. No.of wavelengths, time-out
emontx.ct2rp = ct2.realPower;
emontx.ct2ap = ct2.apparentPower;
emontx.ct2pf = ct2.powerFactor;
emontx.ct2vr = ct2.Vrms;
emontx.ct2ir = ct2.Irms;
} else {
emontx.ct2rp = 0;
emontx.ct2ap = ct2.calcIrms(CTSamplesIrms) * AC; // Calculate apparentPower ct.calcIrms(number of wavelengths sample)*AC RMS voltage
emontx.ct2pf = 0;
emontx.ct2vr = 0;
emontx.ct2ir = 0;
}

Serial.print("CT2 RealPower: ");Serial.print(emontx.ct2rp);
Serial.print(" ApparentPower: ");Serial.print(emontx.ct2ap);
Serial.print(" PowerFactor: ");Serial.print(emontx.ct2pf);
Serial.print(" Vrms: ");Serial.print(emontx.ct2vr);
Serial.print(" Irms: ");Serial.println(emontx.ct2ir);

}

if (CT3) {
if (RealPower) {
ct3.calcVI(CTSamples,SamTimeOut); // Calculate (No.of wavelengths, time-out) realPower,apparentPower,powerFactor,Vrms,Irms. No.of wavelengths, time-out
emontx.ct3rp = ct3.realPower;
emontx.ct3ap = ct3.apparentPower;
emontx.ct3pf = ct3.powerFactor;
emontx.ct3vr = ct3.Vrms;
emontx.ct3ir = ct3.Irms;
} else {
emontx.ct3rp = 0;
emontx.ct3ap = ct3.calcIrms(CTSamplesIrms) * AC; // Calculate apparentPower ct.calcIrms(number of wavelengths sample)*AC RMS voltage
emontx.ct3pf = 0;
emontx.ct3vr = 0;
emontx.ct3ir = 0;
}

Serial.print("CT3 RealPower: ");Serial.print(emontx.ct3rp);
Serial.print(" ApparentPower: ");Serial.print(emontx.ct3ap);
Serial.print(" PowerFactor: ");Serial.print(emontx.ct3pf);
Serial.print(" Vrms: ");Serial.print(emontx.ct3vr);
Serial.print(" Irms: ");Serial.println(emontx.ct3ir);

}

if ((TP) && (TPcount>0)) {
sensors.requestTemperatures(); // Send the command to get temperatures
float temp1=(sensors.getTempCByIndex(0));
emontx.temp1=(temp1_100);
Serial.print("TP1 Temperature: ");Serial.println(emontx.temp1);
}
if ((TP) && (TPcount>1)) {
sensors.requestTemperatures(); // Send the command to get temperatures
float temp2=(sensors.getTempCByIndex(1));
emontx.temp2=(temp2_100);
Serial.print("TP2 Temperature: ");Serial.println(emontx.temp2);
}

emontx.battery = ct1.readVcc(); // Read emonTx battey (supply voltage)
Serial.print("Battery: "); Serial.println(emontx.battery);

if (Pulse) {
emontx.pulse = pulseCount;
Serial.print("Pulses: "); Serial.println(emontx.pulse);
Serial.print("Power: "); Serial.println(emontx.power);
}

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
{
send_rf_data(); // SEND RF DATA - see emontx_lib
digitalWrite(LEDpin, HIGH); delay(2); digitalWrite(LEDpin, LOW); // Flash LED
pulseCount=0;
emontx.power=0;
emontx_sleep(5); // Sleep or delay in seconds - see emontx_lib
}
}

// The interrupt routine - runs each time a falling edge of a pulse is detected
void onPulse()
{
lastTime = pulseTime; // Used to measure time between pulses.
pulseTime = micros();
pulseCount++; // PulseCounter
emontx.power = int((3600000000.0 / (pulseTime - lastTime))/ppwh); // Calculate power
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.