Page 4 of 16
Re: MySensors - Gateway to Domoticz
Posted: Sunday 22 March 2015 15:33
by gizmocuz
ThinkPad wrote:I think i am already seeing that. Connected 'MYSController' to the Ethernet gateway i made, and i see the application constantly scrolling, only thing it displays is:
RECV REQ VAR1
Nice, looking forward to it! Let us know if we can help in any way
Below the new code, it also uses the eprom memory to load/save the pulsecount, which is much better then requesting this from the host software (domoticz),
in case its down for whatever reason
A new beta is building at the moment (will take at least 15 minutes), please let us know if you got it working !
Code: Select all
//
// Use this sensor to measure volume and flow of your house watermeter.
// You need to set the correct pulsefactor of your meter (pulses per m3).
// The sensor starts by reading the pulse count reading from the eprom.
// Reports both volume and flow back to gateway.
//
// Unfortunately millis() won't increment when the Arduino is in
// sleepmode. So we cannot make this sensor sleep if we also want
// to calculate/report flow.
//
#include <SPI.h>
#include <MySensor.h>
#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!)
#define PULSE_FACTOR 1000 // Nummber of blinks per m3 of your meter (One rotation/liter)
#define SLEEP_MODE false // flowvalue can only be reported when sleep mode is false.
#define MAX_FLOW 40 // Max flow (l/min) value to report. This filters outliers.
#define CHILD_ID 1 // Id of the sensor child
unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't want to spam the gateway.
#define EPROM_PULSECOUNT_1_STATE 1
#define EPROM_PULSECOUNT_2_STATE 2
#define EPROM_PULSECOUNT_3_STATE 3
#define EPROM_PULSECOUNT_4_STATE 4
MySensor gw;
MyMessage flowMsg(CHILD_ID,V_FLOW);
MyMessage volumeMsg(CHILD_ID,V_VOLUME);
double ppl = ((double)PULSE_FACTOR)/1000; // Pulses per liter
volatile unsigned long pulseCount = 0;
volatile unsigned long lastBlink = 0;
volatile double flow = 0;
boolean pcReceived = false;
unsigned long oldPulseCount = 0;
unsigned long newBlink = 0;
double oldflow = 0;
double volume;
double oldvolume;
unsigned long lastSend;
unsigned long lastPulse;
unsigned long currentTime;
boolean metric;
void setup()
{
gw.begin();
// Send the sketch version information to the gateway and Controller
gw.sendSketchInfo("Water Meter", "1.1");
// Register this device as Waterflow sensor
gw.present(CHILD_ID, S_WATER);
//Retreive our last pulse count value from the eprom
pulseCount = oldPulseCount = LoadLastPulseCount();
lastSend = millis();
attachInterrupt(1, onPulse, RISING);
}
void loop()
{
gw.process();
currentTime = millis();
// Only send values at a maximum frequency or woken up from sleep
bool sendTime = (currentTime - lastSend) > SEND_FREQUENCY;
if (SLEEP_MODE || sendTime)
{
lastSend=currentTime;
if (!SLEEP_MODE && flow != oldflow) {
oldflow = flow;
//Serial.print("l/min:");
//Serial.println(flow);
// Check that we dont get unresonable large flow value.
// could hapen when long wraps or false interrupt triggered
if (flow<((unsigned long)MAX_FLOW)) {
gw.send(flowMsg.set(flow, 2)); // Send flow value to gw
}
}
// No Pulse count in 2min
if(currentTime - lastPulse > 120000){
flow = 0;
}
// Pulse count has changed
if (pulseCount != oldPulseCount) {
oldPulseCount = pulseCount;
SaveLastPulseCount(pulseCount);
//Serial.print("pulsecount:");
//Serial.println(pulseCount);
double volume = ((double)pulseCount/((double)PULSE_FACTOR));
if (volume != oldvolume) {
//Serial.print("volume:");
//Serial.println(volume, 3);
gw.send(volumeMsg.set(volume, 3)); // Send volume value to gw
oldvolume = volume;
}
}
}
if (SLEEP_MODE) {
gw.sleep(SEND_FREQUENCY);
}
}
unsigned long LoadLastPulseCount()
{
int PCount_1=gw.loadState(EPROM_PULSECOUNT_1_STATE);
int PCount_2=gw.loadState(EPROM_PULSECOUNT_2_STATE);
int PCount_3=gw.loadState(EPROM_PULSECOUNT_3_STATE);
int PCount_4=gw.loadState(EPROM_PULSECOUNT_4_STATE);
//check if valid
if ((PCount_1==0xFF)&&(PCount_2==0xFF)&&(PCount_3==0xFF)&&(PCount_4==0xFF))
return 0;//never saved before
unsigned long PulseCount=(PCount_1<<24)|(PCount_2<<16)|(PCount_3<<8)|PCount_4;
//Serial.print("Last Pulsecount: ");
//Serial.println(PulseCount);
return PulseCount;
}
void SaveLastPulseCount(unsigned long PulseCount)
{
int PCount_1=(PulseCount&0xFF000000)>>24;
int PCount_2=(PulseCount&0xFF0000)>>16;
int PCount_3=(PulseCount&0xFF00)>>8;
int PCount_4=PulseCount&0xFF;
gw.saveState(EPROM_PULSECOUNT_1_STATE, PCount_1);
gw.saveState(EPROM_PULSECOUNT_2_STATE, PCount_2);
gw.saveState(EPROM_PULSECOUNT_3_STATE, PCount_3);
gw.saveState(EPROM_PULSECOUNT_4_STATE, PCount_4);
}
void onPulse()
{
if (!SLEEP_MODE)
{
unsigned long newBlink = micros();
unsigned long interval = newBlink-lastBlink;
if (interval!=0)
{
lastPulse = millis();
if (interval<500000L) {
// Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min)
return;
}
flow = (60000000.0 /interval) / ppl;
}
lastBlink = newBlink;
}
pulseCount++;
}
Re: MySensors - Gateway to Domoticz
Posted: Sunday 22 March 2015 15:43
by ThinkPad
That's really awesome! I just flashed your new code onto my TCRT5000 node... will try it when the beta is ready (and if i can get a solid signal of the rotating needle in my watermeter).
By the way, doesn't storing the pulsecount in EEPROM wear out the memory fast? Not sure how tough the EEPROM of the Arduino is, and how often you store this value... but something to keep in mind...
Re: MySensors - Gateway to Domoticz
Posted: Sunday 22 March 2015 15:47
by gizmocuz
ThinkPad wrote:That's really awesome! I just flashed your new code onto my TCRT5000 node... will try it when the beta is ready (and if i can get a solid signal of the rotating needle in my watermeter).
By the way, doesn't storing the pulsecount in EEPROM wear out the memory fast? Not sure how tough the EEPROM of the Arduino is, and how often you store this value... but something to keep in mind...
In your P1 Smart meter has also an eprom i suppose ?
and it is only written when the pulse counter changes, and then only each 20 seconds during changing
so not many writes
It would be interesting to know if someone knows how many times you can write it...
... and there are many memory locations, at the moment only the first 4 are used, so 'when' you have a problem, shift it to the next 4
Re: MySensors - Gateway to Domoticz
Posted: Sunday 22 March 2015 15:48
by gizmocuz
Could you let me know if you get it working ? I am interested in this too ! (and i had a TCRT5000 here)
If its working, can you post a photo of your water meter (the reading part), and a photo where you placed the sensor?
Re: MySensors - Gateway to Domoticz
Posted: Sunday 22 March 2015 15:54
by ThinkPad
That's true, but the code in a smart meter is probably better optimized to not wearout the EEPROM than a random Arduino sketch i think
But i will try it
And my setup is not an ideal example project, i live in a flat and my meter is not from the watercompany. The water usage of the whole flat is measured somewhere in the basement, and this usage is compared to the meters in each appartment. My watermeter is also very old (1986 or so). See pictures here:
http://gathering.tweakers.net/forum/lis ... es/1596066
But i already found this setup:
http://www.domoticz.com/forum/viewtopic ... =20#p29758 Maybe you can use that to create a measuring setup for your meter?
Re: MySensors - Gateway to Domoticz
Posted: Sunday 22 March 2015 15:57
by gizmocuz
EEProm is EEProm, and i bet that on every change it will store it's counters, and there are many
Re: MySensors - Gateway to Domoticz
Posted: Sunday 22 March 2015 16:12
by ThinkPad
Your Arduino sketch is working
. Also a 'RFXmeter' device popped up under 'Devices' after i updated Domoticz to v2.2330. I have now connected a photodiode module to the node instead of the TCRT5000 module, and placed that on my smartmeter (which, apart from the P1-port also has a blinking LED). I am now waiting for a while to see if it updates correctly.
So i think the watermeter is good, now only the personal struggle begins to get the TCRT5000 measure the meter correctly
.
Will try to align the sensor when the dishwasser is running or so
But good job so far! Really great that you could implement this so fast! I think this watermeter sketch you made can also be used for kWh and gas i think? Idea is the same, count the pulses and send it to Domoticz? Although the EEPROM part is maybe a bit tricky, as with the kWh-meter you will get a loooooooooooooot of pulses on a day.
Re: MySensors - Gateway to Domoticz
Posted: Sunday 22 March 2015 17:57
by gizmocuz
Just got a message that the EEPROM can have 100.000 write cycles, so this is not a good option !
Will have to rebuild domoticz/sketch to support the value/var request option
http://playground.arduino.cc/Code/EEPROM-Flash
Re: MySensors - Gateway to Domoticz
Posted: Sunday 22 March 2015 19:47
by gizmocuz
New code for the water sensor (new beta is building)
Code: Select all
//
// Use this sensor to measure volume and flow of your house watermeter.
// You need to set the correct pulsefactor of your meter (pulses per m3).
// The sensor starts by reading the pulse count reading from the eprom.
// Reports both volume and flow back to gateway.
//
// Unfortunately millis() won't increment when the Arduino is in
// sleepmode. So we cannot make this sensor sleep if we also want
// to calculate/report flow.
//
#include <SPI.h>
#include <MySensor.h>
#define DIGITAL_INPUT_SENSOR 3 // The digital input you attached your sensor. (Only 2 and 3 generates interrupt!)
#define SENSOR_INTERRUPT DIGITAL_INPUT_SENSOR-2 // Usually the interrupt = pin -2 (on uno/nano anyway)
#define PULSE_FACTOR 1000 // Nummber of blinks per m3 of your meter (One rotation/liter)
#define SLEEP_MODE false // flowvalue can only be reported when sleep mode is false.
#define MAX_FLOW 40 // Max flow (l/min) value to report. This filters outliers.
#define CHILD_ID 1 // Id of the sensor child
unsigned long SEND_FREQUENCY = 20000; // Minimum time between send (in milliseconds). We don't want to spam the gateway.
unsigned long UPDATE_EEPROM_FREQUENCY = 60*600000; //Update pulse counter to eprom (each hour)
#define EPROM_PULSECOUNT_1_STATE 1
#define EPROM_PULSECOUNT_2_STATE 2
#define EPROM_PULSECOUNT_3_STATE 3
#define EPROM_PULSECOUNT_4_STATE 4
MySensor gw;
MyMessage flowMsg(CHILD_ID,V_FLOW);
MyMessage volumeMsg(CHILD_ID,V_VOLUME);
MyMessage lastCounterMsg(CHILD_ID,V_VAR1);
double ppl = ((double)PULSE_FACTOR)/1000; // Pulses per liter
volatile unsigned long pulseCount = 0;
volatile unsigned long lastBlink = 0;
volatile double flow = 0;
boolean pcReceived = false;
unsigned long oldPulseCount = 0;
unsigned long newBlink = 0;
double oldflow = 0;
double volume;
double oldvolume;
unsigned long lastSend;
unsigned long lastEEpromUpdate;
unsigned long lastPulse;
boolean metric;
void setup()
{
gw.begin(incomingMessage);
// Send the sketch version information to the gateway and Controller
gw.sendSketchInfo("Water Meter", "1.1");
// Register this device as Waterflow sensor
gw.present(CHILD_ID, S_WATER);
//Retreive our last pulse count value from the eprom
pulseCount = oldPulseCount = LoadLastPulseCount();
// Fetch last known pulse count value from gw
gw.request(CHILD_ID, V_VAR1);
lastSend = lastEEpromUpdate = millis();
attachInterrupt(SENSOR_INTERRUPT, onPulse, RISING);
}
void loop()
{
gw.process();
unsigned long currentTime = millis();
// Only send values at a maximum frequency or woken up from sleep
bool sendTime = (currentTime - lastSend) > SEND_FREQUENCY;
if (SLEEP_MODE || sendTime)
{
lastSend=currentTime;
if (!pcReceived) {
//Last Pulsecount not yet received from controller, request it again
gw.request(CHILD_ID, V_VAR1);
}
if (!SLEEP_MODE && flow != oldflow) {
oldflow = flow;
Serial.print("l/min:");
Serial.println(flow);
// Check that we dont get unresonable large flow value.
// could hapen when long wraps or false interrupt triggered
if (flow<((unsigned long)MAX_FLOW)) {
gw.send(flowMsg.set(flow, 2)); // Send flow value to gw
}
}
// No Pulse count in 2min
if(currentTime - lastPulse > 120000){
flow = 0;
}
// Pulse count has changed
if (pulseCount != oldPulseCount) {
oldPulseCount = pulseCount;
if (currentTime - lastEEpromUpdate > UPDATE_EEPROM_FREQUENCY) {
lastEEpromUpdate=currentTime;
SaveLastPulseCount(pulseCount);
}
gw.send(lastCounterMsg.set(pulseCount)); // Send volumevalue to gw VAR1
Serial.print("pulsecount:");
Serial.println(pulseCount);
double volume = ((double)pulseCount/((double)PULSE_FACTOR));
if (volume != oldvolume) {
Serial.print("volume:");
Serial.println(volume, 3);
gw.send(volumeMsg.set(volume, 3)); // Send volume value to gw
oldvolume = volume;
}
}
}
if (SLEEP_MODE) {
gw.sleep(SEND_FREQUENCY);
}
}
void incomingMessage(const MyMessage &message) {
if (message.type==V_VAR1) {
unsigned long gwPulseCount=message.getLong();
if (gwPulseCount>pulseCount) {
pulseCount = oldPulseCount = gwPulseCount;
Serial.print("Received last pulse count from gw:");
Serial.println(pulseCount);
}
pcReceived = true;
}
}
unsigned long LoadLastPulseCount()
{
int PCount_1=gw.loadState(EPROM_PULSECOUNT_1_STATE);
int PCount_2=gw.loadState(EPROM_PULSECOUNT_2_STATE);
int PCount_3=gw.loadState(EPROM_PULSECOUNT_3_STATE);
int PCount_4=gw.loadState(EPROM_PULSECOUNT_4_STATE);
//check if valid
if ((PCount_1==0xFF)&&(PCount_2==0xFF)&&(PCount_3==0xFF)&&(PCount_4==0xFF))
return 0;//never saved before
unsigned long PulseCount=(PCount_1<<24)|(PCount_2<<16)|(PCount_3<<8)|PCount_4;
//Serial.print("Last Pulsecount: ");
//Serial.println(PulseCount);
return PulseCount;
}
void SaveLastPulseCount(unsigned long PulseCount)
{
int PCount_1=(PulseCount&0xFF000000)>>24;
int PCount_2=(PulseCount&0xFF0000)>>16;
int PCount_3=(PulseCount&0xFF00)>>8;
int PCount_4=PulseCount&0xFF;
gw.saveState(EPROM_PULSECOUNT_1_STATE, PCount_1);
gw.saveState(EPROM_PULSECOUNT_2_STATE, PCount_2);
gw.saveState(EPROM_PULSECOUNT_3_STATE, PCount_3);
gw.saveState(EPROM_PULSECOUNT_4_STATE, PCount_4);
}
void onPulse()
{
if (!SLEEP_MODE)
{
unsigned long newBlink = micros();
unsigned long interval = newBlink-lastBlink;
if (interval!=0)
{
lastPulse = millis();
if (interval<500000L) {
// Sometimes we get interrupt on RISING, 500000 = 0.5sek debounce ( max 120 l/min)
return;
}
flow = (60000000.0 /interval) / ppl;
}
lastBlink = newBlink;
}
pulseCount++;
}
MySensors - Gateway to Domoticz
Posted: Sunday 22 March 2015 19:59
by hansrune
Sorry. Should have read the sketch and your updates in MySensorsBase.* more thoroughly first ... This looks great. Thanks!
Isn't this what gw.request() is intended for in MySensors API ? Being able to fully rely on receiving a response may not always be possible, though. Anyway , being able to do a gw.request() in the sketch init is useful to enable updates of the value/settings in EEPROM. In that way, a corrected sensor value can be fed from Domoticz by means of a sketch reset.
Re: MySensors - Gateway to Domoticz
Posted: Sunday 22 March 2015 20:41
by ThinkPad
Nice, i will try the updated sketch and beta tomorrow. Will also look if i can get it attached to my watermeter this time.
Don't want to do it now, don't have any water usage now, and running the tap for half an hour while trying to adjust the sensor seems a bit of a waste for me
Better do it tomorrow when the dishwasher / washing machine is running :p
Re: MySensors - Gateway to Domoticz
Posted: Monday 23 March 2015 9:28
by gizmocuz
bjornhallberg wrote:Any way to get the battery readings to work? I only have the voltage divider (and code) on some of my sensor nodes but it seems the data is getting mixed up when read by Domoticz? I.e. sensors are getting the battery readings of other sensors. Sensors that never report a value get a value anyway.
Fantastic to finally have MySensors and Domoticz working together btw!
I assumed then when a 'node' reports a battery level, this is for all sensors received from it.
Re: MySensors - Gateway to Domoticz
Posted: Monday 23 March 2015 9:35
by gizmocuz
BluesBro wrote:Does Domoticz support the IR-sensor?
It showes up in the log but not show up in the list of available devices.
Not at the moment, because i do not understand the example sketch.
In MySensors there is a variable called 'V_IR_RECEIVE'
But this is not used to send the IR code to the gw (domoticz) instead it is sending V_VAR1 messages, which i think does not make sense
Then there is an option to send IR messages from the gw, to the node, there is a variable for this V_IR_SEND,
this is also not used in the example sketch
So not sure how to implement this.
I could implement the V_IR_SEND/V_IR_RECEIVE calls, but there has to be a standard first
Re: MySensors - Gateway to Domoticz
Posted: Monday 23 March 2015 9:47
by gizmocuz
BluesBro wrote:I found the error.
Domoticz add 1 zero on every reading. 10 lux in the arduino log is 100 in domoticz. And domoticz readings dont go higher than 1000 lux.
This is because i thought (and i could be wrong) the Lux value was send as a percentage.
0=0 lux, 100%=1000Lux
for example this sketch is using percentage (LightSensor Example):
http://www.mysensors.org/build/light
and the sketch underneath it (LightLuxSensor Example) uses the actual value
so whats the standard ? At the moment i have implemented it as percentage, if you convert your value in the range of 0-100% then it should work.
Re: MySensors - Gateway to Domoticz
Posted: Monday 23 March 2015 16:27
by ThinkPad
Just did a short try with the TCRT5000 to measure my
watermeter but as i expected, it is really hard to align it. The gauges are so small.... (I am aiming at the most left one, the 0,001 one).
Also i need to create a better mounting system, now one mm makes the difference for the LED to go on/off. I saw a nice mounting system here:
http://www.domoticz.com/forum/viewtopic ... 1103#p6746
made by a hose clamp around the meter and a metal L-profile.
P.S. I now know that on my module the green LED (=detection) is on the whole time, and turns off when something passes by.
Re: MySensors - Gateway to Domoticz
Posted: Monday 23 March 2015 23:04
by ThinkPad
Ok, i think i got the sensor aligned correctly now. Will let it run for a day and see if it produces some realistic values.
I can't find out how to reset the counter in Domoticz to zero... All the fiddling around has created a huuuuuge water consumption. I want to start from zero now when it is mounted.
I tried setting the value to zero with the JSON url from the wiki:
http://www.domoticz.com/wiki/Domoticz_A ... 7s#Counter but i think because the value is saved in the Arduino it updates it back to the old value again.
How to start fresh??
Re: MySensors - Gateway to Domoticz
Posted: Tuesday 24 March 2015 10:14
by AWI
ThinkPad wrote:
How to start fresh??
Erase the EEPROM?
Code: Select all
/*
*
* This sketch clears user EEPROM (MySensors)
* load and run for > 20 secs
*
*/
#include <MySensor.h>
#include <SPI.h>
void setup()
{
for (int i=0;i<256;i++) {
gw.saveState(i, 0xff);
}
}
void loop()
{
// Nothing to do here...
}
Re: MySensors - Gateway to Domoticz
Posted: Tuesday 24 March 2015 10:42
by AWI
gizmocuz wrote:
and the sketch underneath it (LightLuxSensor Example) uses the actual value
so whats the standard ? At the moment i have implemented it as percentage, if you convert your value in the range of 0-100% then it should work.
Standard should be to report in Lux. The only % value is V_DIMMER. I have reported it in the MySensors forum.
Great to see the implementation growing.
! Update 24-3-2015 11:03, response on MySensors forum:
Agree, this is a "bug". The problem with the current V_* is that it contains no unit information. A backward compatible solution for this for the 1.6 release would be to introduce a V_LIGHT_LEVEL_LUX. Not pretty but it solves the problem without breaking anything.
Re: MySensors - Gateway to Domoticz
Posted: Tuesday 24 March 2015 10:56
by A1AD
gizmocuz wrote:Just got a message that the EEPROM can have 100.000 write cycles, so this is not a good option !
Will have to rebuild domoticz/sketch to support the value/var request option
http://playground.arduino.cc/Code/EEPROM-Flash
Just change the save to eeprom interval a bit? I am writing every 2 hours my water/elektra/gas values.
Re: MySensors - Gateway to Domoticz
Posted: Tuesday 24 March 2015 10:58
by gizmocuz
Thats an option, for the watermeter there is some new code here:
http://www.mysensors.org/build/pulse_water
It now relies on the V_VAR1, but start counting the pulses immediately, they will be added as soon at the gw sends the last value