Locally attached sensors
-
My serial gateway will have something like 16 locally attached sensor to it. So I would like to keep my serial gateway code as clean and simple as possible, hence I would like some input on how to do this.
I will take the energyMeterPulse sketch in the example folder as an example of my idea.
I would like to rewrite the code to have an constructur like this:
EnergyMeter(DIGITAL_INPUT_SENSOR,PULSE_FACTOR ,SLEEP_MODE,MAX_WATT,CHILD_ID,SEND_FREQUENCY)
Then it should have three methods:
Present Start Stop
My serial gateway code will then look clean:
void setup() { // Setup locally attached sensors EnergyMeter powerSensor1 = new EnergyMeter(2,1000,false,10000,12,60000) } void presentation() { // Present locally attached sensors powerSensor1.present } void loop() { // Send locally attached sensor data here powerSensor1.start }
So how can I restructure energyMeterPulse sketch to achieve this? Or how does other handle heaps of locally attached sensor to gateway?
-
Here is my suggestion, which does not quite work, because I dont know how to make the loop inside a class:)
#include "ENERGYMETER.h" //include the declaration for this class #include <SPI.h> #include <MySensor.h> #define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your light sensor. (Only 2 and 3 generates interrupt!) #define PULSE_FACTOR 1000 // Nummber of blinks per KWH of your meeter #define SLEEP_MODE false // Watt-value can only be reported when sleep mode is false. #define MAX_WATT 10000 // Max watt value to report. This filetrs outliers. int DIGITAL_INPUT_SENSOR // Usually the interrupt = pin -2 (on uno/nano anyway) #define CHILD_ID 1 // Id of the sensor child unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. double ppwh = ((double)PULSE_FACTOR)/1000; // Pulses per watt hour boolean pcReceived = false; volatile unsigned long pulseCount = 0; volatile unsigned long lastBlink = 0; volatile unsigned long watt = 0; unsigned long oldPulseCount = 0; unsigned long oldWatt = 0; double oldKwh; unsigned long lastSend; MyMessage wattMsg(CHILD_ID,V_WATT); MyMessage kwhMsg(CHILD_ID,V_KWH); MyMessage pcMsg(CHILD_ID,V_VAR1); const byte LED_PIN = 13; //use the LED @ Arduino pin 13, this should not change so make it const (constant) //<<constructor>> setup the LED, make pin 13 an OUTPUT ENERGYMETER::ENERGYMETER(_DIGITAL_INPUT_SENSOR){ DIGITAL_INPUT_SENSOR = _DIGITAL_INPUT_SENSOR; // Fetch last known pulse count value from gw request(CHILD_ID, V_VAR1); // Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output // If no pullup is used, the reported usage will be too high because of the floating pin pinMode(DIGITAL_INPUT_SENSOR,INPUT_PULLUP); attachInterrupt(INTERRUPT, onPulse, RISING); lastSend=millis(); } //<<destructor>> ENERGYMETER::~ENERGYMETER(){/*nothing to destruct*/} //present it void ENERGYMETER::present(){ // Send the sketch version information to the gateway and Controller sendSketchInfo("Energy Meter", "1.0"); // Register this device as power sensor present(CHILD_ID, S_POWER); } //turn the LED off void ENERGYMETER::start(){ void loop() { unsigned long now = millis(); // Only send values at a maximum frequency or woken up from sleep bool sendTime = now - lastSend > SEND_FREQUENCY; if (pcReceived && (SLEEP_MODE || sendTime)) { // New watt value has been calculated if (!SLEEP_MODE && watt != oldWatt) { // Check that we dont get unresonable large watt value. // could hapen when long wraps or false interrupt triggered if (watt<((unsigned long)MAX_WATT)) { send(wattMsg.set(watt)); // Send watt value to gw } Serial.print("Watt:"); Serial.println(watt); oldWatt = watt; } // Pulse cout has changed if (pulseCount != oldPulseCount) { send(pcMsg.set(pulseCount)); // Send pulse count value to gw double kwh = ((double)pulseCount/((double)PULSE_FACTOR)); oldPulseCount = pulseCount; if (kwh != oldKwh) { send(kwhMsg.set(kwh, 4)); // Send kwh value to gw oldKwh = kwh; } } lastSend = now; } else if (sendTime && !pcReceived) { // No count received. Try requesting it again request(CHILD_ID, V_VAR1); lastSend=now; } if (SLEEP_MODE) { sleep(SEND_FREQUENCY); } } } void receive(const MyMessage &message) { if (message.type==V_VAR1) { pulseCount = oldPulseCount = message.getLong(); Serial.print("Received last pulse count from gw:"); Serial.println(pulseCount); pcReceived = true; } } void onPulse() { if (!SLEEP_MODE) { unsigned long newBlink = micros(); unsigned long interval = newBlink-lastBlink; if (interval<10000L) { // Sometimes we get interrupt on RISING return; } watt = (3600000000.0 /interval) / ppwh; lastBlink = newBlink; } pulseCount++; }
-
I now get this error message, any idea what the problem might be?
In file included from C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:5:0: C:\Users\kim\Documents\Arduino\libraries\MySensors/MySensor.h:285:4: error: #error No forward link or gateway feature activated. This means nowhere to send messages! Pretty pointless. #error No forward link or gateway feature activated. This means nowhere to send messages! Pretty pointless.
Here is my test class:
#include <EnergyMeter.h> EnergyMeter power(1);//initialize an instance of the class void setup(){ power.present(); } void loop(){ power.update();//stay one second on, then a second off }
and here is my EnergyMeter.cpp file :
#include "EnergyMeter.h" //include the declaration for this class #include <SPI.h> #include <MySensor.h> long PULSE_FACTOR // Nummber of blinks per KWH of your meeter boolean SLEEP_MODE // Watt-value can only be reported when sleep mode is false. long MAX_WATT // Max watt value to report. This filetrs outliers. int DIGITAL_INPUT_SENSOR // Usually the interrupt = pin -2 (on uno/nano anyway) int CHILD_ID // Id of the sensor child unsigned long SEND_FREQUENCY double ppwh boolean pcReceived = false; volatile unsigned long pulseCount = 0; volatile unsigned long lastBlink = 0; volatile unsigned long watt = 0; unsigned long oldPulseCount = 0; unsigned long oldWatt = 0; double oldKwh; unsigned long lastSend; //<<constructor>> setup the LED, make pin 13 an OUTPUT EnergyMeter::EnergyMeter(int _CHILD_ID){ CHILD_ID = _CHILD_ID; // Id of the sensor child /* Optional Arguments */ SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. PULSE_FACTOR =1000; // Nummber of blinks per KWH of your meeter SLEEP_MODE = false ; // Watt-value can only be reported when sleep mode is false. MAX_WATT = 10000; // Max watt value to report. This filetrs outliers. DIGITAL_INPUT_SENSOR = 0; // Usually the interrupt = pin -2 (on uno/nano anyway) /*Starting the setup algorithm */ ppwh = ((double)PULSE_FACTOR)/1000; // Pulses per watt hour MyMessage wattMsg(CHILD_ID,V_WATT); MyMessage kwhMsg(CHILD_ID,V_KWH); MyMessage pcMsg(CHILD_ID,V_VAR1); // Fetch last known pulse count value from gw request(CHILD_ID, V_VAR1); // Use the internal pullup to be able to hook up this sketch directly to an energy meter with S0 output // If no pullup is used, the reported usage will be too high because of the floating pin pinMode(DIGITAL_INPUT_SENSOR,INPUT_PULLUP); attachInterrupt(INTERRUPT, onPulse, RISING); lastSend=millis(); } //<<destructor>> EnergyMeter::~EnergyMeter(){/*nothing to destruct*/} //present it void ENERGYMETER::present(){ // Send the sketch version information to the gateway and Controller sendSketchInfo("Energy Meter", "1.0"); // Register this device as power sensor present(CHILD_ID, S_POWER); } //update the reading of the power void ENERGYMETER::update(){ unsigned long now = millis(); // Only send values at a maximum frequency or woken up from sleep bool sendTime = now - lastSend > SEND_FREQUENCY; if (pcReceived && (SLEEP_MODE || sendTime)) { // New watt value has been calculated if (!SLEEP_MODE && watt != oldWatt) { // Check that we dont get unresonable large watt value. // could hapen when long wraps or false interrupt triggered if (watt<((unsigned long)MAX_WATT)) { send(wattMsg.set(watt)); // Send watt value to gw } Serial.print("Watt:"); Serial.println(watt); oldWatt = watt; } // Pulse cout has changed if (pulseCount != oldPulseCount) { send(pcMsg.set(pulseCount)); // Send pulse count value to gw double kwh = ((double)pulseCount/((double)PULSE_FACTOR)); oldPulseCount = pulseCount; if (kwh != oldKwh) { send(kwhMsg.set(kwh, 4)); // Send kwh value to gw oldKwh = kwh; } } lastSend = now; } else if (sendTime && !pcReceived) { // No count received. Try requesting it again request(CHILD_ID, V_VAR1); lastSend=now; } if (SLEEP_MODE) { sleep(SEND_FREQUENCY); } } } void receive(const MyMessage &message) { if (message.type==V_VAR1) { pulseCount = oldPulseCount = message.getLong(); Serial.print("Received last pulse count from gw:"); Serial.println(pulseCount); pcReceived = true; } } void onPulse() { if (!SLEEP_MODE) { unsigned long newBlink = micros(); unsigned long interval = newBlink-lastBlink; if (interval<10000L) { // Sometimes we get interrupt on RISING return; } watt = (3600000000.0 /interval) / ppwh; lastBlink = newBlink; } pulseCount++; }
-
I think you need
#define MY_GATEWAY_SERIAL
-
@mfalkvidd said:
#define MY_GATEWAY_SERIAL
The define method got rid of that error, so then i Should add it to the constructor?
So that the user that creates the node have to decide if the gateway is serial,wifi, or RF, right?
Now I got these errors instead:
Arduino: 1.6.8 (Windows 7), Board: "Arduino Nano, ATmega328" Build options changed, rebuilding all C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:8:1: error: expected initializer before 'boolean' boolean SLEEP_MODE // Watt-value can only be reported when sleep mode is false. ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp: In constructor 'EnergyMeter::EnergyMeter(int)': C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:27:2: error: 'CHILD_ID' was not declared in this scope CHILD_ID = _CHILD_ID; // Id of the sensor child ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:30:2: error: 'SEND_FREQUENCY' was not declared in this scope SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't wnat to spam the gateway. ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:31:2: error: 'PULSE_FACTOR' was not declared in this scope PULSE_FACTOR =1000; // Nummber of blinks per KWH of your meeter ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:32:2: error: 'SLEEP_MODE' was not declared in this scope SLEEP_MODE = false ; // Watt-value can only be reported when sleep mode is false. ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:33:2: error: 'MAX_WATT' was not declared in this scope MAX_WATT = 10000; // Max watt value to report. This filetrs outliers. ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:34:2: error: 'DIGITAL_INPUT_SENSOR' was not declared in this scope DIGITAL_INPUT_SENSOR = 0; // Usually the interrupt = pin -2 (on uno/nano anyway) ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:38:2: error: 'ppwh' was not declared in this scope ppwh = ((double)PULSE_FACTOR)/1000; // Pulses per watt hour ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:51:18: error: 'INTERRUPT' was not declared in this scope attachInterrupt(INTERRUPT, onPulse, RISING); ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:51:29: error: 'onPulse' was not declared in this scope attachInterrupt(INTERRUPT, onPulse, RISING); ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp: At global scope: C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:59:6: error: 'ENERGYMETER' has not been declared void ENERGYMETER::present(){ ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp: In function 'void present()': C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:64:11: error: 'CHILD_ID' was not declared in this scope present(CHILD_ID, S_POWER); ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp: At global scope: C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:69:6: error: 'ENERGYMETER' has not been declared void ENERGYMETER::update(){ ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp: In function 'void update()': C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:73:36: error: 'SEND_FREQUENCY' was not declared in this scope bool sendTime = now - lastSend > SEND_FREQUENCY; ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:74:7: error: 'pcReceived' was not declared in this scope if (pcReceived && (SLEEP_MODE || sendTime)) { ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:74:22: error: 'SLEEP_MODE' was not declared in this scope if (pcReceived && (SLEEP_MODE || sendTime)) { ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:79:32: error: 'MAX_WATT' was not declared in this scope if (watt<((unsigned long)MAX_WATT)) { ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:80:14: error: 'wattMsg' was not declared in this scope send(wattMsg.set(watt)); // Send watt value to gw ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:89:12: error: 'pcMsg' was not declared in this scope send(pcMsg.set(pulseCount)); // Send pulse count value to gw ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:90:49: error: 'PULSE_FACTOR' was not declared in this scope double kwh = ((double)pulseCount/((double)PULSE_FACTOR)); ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:93:14: error: 'kwhMsg' was not declared in this scope send(kwhMsg.set(kwh, 4)); // Send kwh value to gw ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:100:13: error: 'CHILD_ID' was not declared in this scope request(CHILD_ID, V_VAR1); ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:104:7: error: 'SLEEP_MODE' was not declared in this scope if (SLEEP_MODE) { ^ C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp: At global scope: C:\Users\kim\Documents\Arduino\libraries\EnergyMeter\EnergyMeter.cpp:109:1: error: expected declaration before '}' token } ^ exit status 1 Error compiling for board Arduino Nano. This report would have more information with "Show verbose output during compilation" option enabled in File -> Preferences.
-
just for a test, try to make another constructor without any in-arguments and see if thoose errors persist. just to check. ( I might be way off here. did this stuff 12 years ago and just got back into it )
//Henrik
-
@badmannen
I am on to it:)