-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve CM160 readings #2418
Improve CM160 readings #2418
Conversation
Added more attributes and total kWh
src/devices/oregon_scientific.c
Outdated
@@ -142,6 +142,26 @@ static unsigned long long cm180i_total(uint8_t const *msg) | |||
return val; | |||
} | |||
|
|||
static unsigned int swap_nibbles(unsigned char byte) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
types should be uint8_t
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved
src/devices/oregon_scientific.c
Outdated
@@ -142,6 +142,26 @@ static unsigned long long cm180i_total(uint8_t const *msg) | |||
return val; | |||
} | |||
|
|||
static unsigned int swap_nibbles(unsigned char byte) { | |||
return (((byte&0xf)<<4) | (byte>>4)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indent is 4 spaces please. Add spaces around operators () << 4
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be resolved
src/devices/oregon_scientific.c
Outdated
return (((byte&0xf)<<4) | (byte>>4)); | ||
} | ||
|
||
static unsigned int cm160_power(uint8_t const *msg) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
remove both cm160_ functions and put the code directly in the block below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolved
src/devices/oregon_scientific.c
Outdated
|
||
static double cm160_total(uint8_t const *msg) | ||
{ | ||
double total = ((uint64_t) swap_nibbles(msg[10]) << 36) | ((uint64_t) swap_nibbles(msg[9]) << 28) | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No space after a cast: (uint64_t)swap_nibbles
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed
src/devices/oregon_scientific.c
Outdated
unsigned short int ipower = (rawAmp /(0.27*230)*1000); | ||
|
||
//channel add from https://github.com/magellannh/rtl-wx/blob/dbaf3924815903c47b230c65841d18b263421854/src/rtl-433fm-decode.c | ||
int channel = msg[0]>>4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can't work. It was 0x2?
and actually is 0
at this point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, grabbed the channel now before manupilation of msg for checksum check.
src/devices/oregon_scientific.c
Outdated
//Alternate formula = (raw_ipower * 0.07) * 230 - https://github.com/cornetp/eagle-owl/blob/master/src/cm160.c | ||
|
||
double raw_total_energy = cm160_total(msg); | ||
double total_kWh = (raw_total_energy * 230 ) / 3600.0 / 1000.0; //Assuming device is running in 230V country |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If kWh = raw * 230 / 3600 / 1000
then J = Ws = raw * 230
, so the unit is Ws
or J
, or actually As = raw
which is strange but plausible.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed, this device measures amps, current and total.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. But then "total_amps" should be "total_ampsec" -- it is energy (A*s) not power (A).
And in data_make below it should be "current_A" (but this is not really A? There is a factor of 0.27?) and "total_As"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added unit A to current and total amps, there should be no need to indicate seconds as "One Ampere is defined as the current that flows with electric charge of one Coulomb per second"
Re: factor .27 ; this is above my pay grade, that's how I found it ;-) ; maybe the formulae can be improved but am not sure how the original author determined it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, it's easy to confuse per second with x seconds ;) You will see kmh and know it's per second, i.e. km/h, but here I really meant As not A/s :)
An "instant flow of electric current" is A
or like you found C/s
. But an "accumulated amount of electric charge" is C
wich is A·s
:)
They are proportional with power and energy (work), i.e. multiply with voltage and you get W
and `Ws (=J) respectively.
In short it's not both "amps", they are very different, the later is "accumulated by time" -- work, the thing you actually pay for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's a very strange thing about those meters. To count energy (or accurately show power) you will need to measure voltage. Pretty sure the device is doing that, the usual chips measure with "True RMS" -- they measure voltage very detailed, i.e. not only the effective ~230 V but the whole sine wave.
The (0.27*230)*1000
is not correctly written, why would you divide by voltage?
The (same factor) of 0.07 * 230
is better, but it's just *16.1
-- a random factor that likely was just estimated (linear regression?)
So maybe it is really just plain *16
-- which is exactly 4 bits, so maybe we are missing those bits?
Then no 230 needed and it would always work, everywhere.
Strange about the energy though, we do need the 230 and the *230/3600/1000
just looks perfect.
But then 3600/230
is also nearly exactly 16! A good guess would be that the field actually is not As
but Wh
already…
Seems all very much more likely than random conversions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you test if current_watts = (current_amps * 16); // are we missing a nibble?
and total_kWh = total_amps / 16.0 / 1000.0; // should (msg[5]&0xf) belong to current_watts actually?
work with accuracy? They seem much more probable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tested, unfortunately, off by a couple of watts which is not consistent with the device's LCD value. Nor am I convinced that the external device sending the 433 signals and clamping onto the power wire is aware of the volts. During setup the volts are captured on the internal LCD device and it is not transmitted to the external clamp as the calculation of watt occur on the internal device.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, it's a contactless current-clamp only. I wasn't aware. Thanks for testing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, it's a contactless current-clamp only. I wasn't aware. Thanks for testing.
I have a second one on another property I will also verify the kWh calc with, I was able to reset it recently so the number is fairly low and visible on the LCD. Then if there's a discrepancy we can chat again.
src/devices/oregon_scientific.c
Outdated
@@ -806,16 +811,46 @@ static int oregon_scientific_v3_decode(r_device *decoder, bitbuffer_t *bitbuffer | |||
return 1; | |||
} | |||
else if ((msg[0] == 0x20) || (msg[0] == 0x21) || (msg[0] == 0x22) || (msg[0] == 0x23) || (msg[0] == 0x24)) { // Owl CM160 Readings | |||
msg[0] = msg[0] & 0x0f; | |||
|
|||
int channel = msg[0]>>4; //let's grab the channel before we manipulate the msg for checksum validation |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But we know (msg[0] == 0x20) || (msg[0] == 0x21) || (msg[0] == 0x22) || (msg[0] == 0x23) || (msg[0] == 0x24)
So msg[0]>>4
must be == 2
, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, was the original code maybe swap_nibbles(msg[0]) >> 4
? Then we'd get 0,1,2,3,4 which sounds like a channel, yes.
Use msg[0] & 0xf
then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Agree and changes accordingly.
src/devices/oregon_scientific.c
Outdated
@@ -142,6 +142,11 @@ static unsigned long long cm180i_total(uint8_t const *msg) | |||
return val; | |||
} | |||
|
|||
static uint8_t swap_nibbles(unsigned char byte) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
other type should also be uint8_t
, we don't use unsigned char
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adjusted.
Thanks for looking into the possible "channel". I always thought that 0x20 to 0x24 are device versions maybe, as the 0x25 is a CM180i and the 0x26 a Owl CM180. |
I have done so much testing and googling the past day. My answer on kWh appears to be a consistent 12% lower then the OWL CM160 LCD, whether I measure for 1 hour or for 10 hours. What do you think about whether I just * 1.12 in the code? I would have like to hear other users of these units on kWh reading. |
Adding in a *1.12 doesn't seem right. It seems like one thing to figure out is how the voltage is being assumed. A 10% variation in line voltage from nominal is not super surprising. |
The OWL CT Clamp is measuring Amp, not Volt. Unfortunately, this is the best calculation I could get to not knowing what the manufacturer is doing internally to convert it to kWh. Just wish there were more consumers of the device that could test and provide input. |
Do you configure a voltage in the device? Is it assuming 125V (US)? something else? Are you trying to use that configured voltage in the decoder? Maybe the extraction of amps is wrong; perhaps use another device to crosscheck? Have you compared the total to the official power meter? |
|
I think this now describes the setup very well. The amp clamp sends "values", the receiver "corrects" these values and displays them. We can compare the radio "values" and what the receiver displays and guess what the correction must be. For the amps power others already found a scale factor of And maybe the suspected Amp/Watt seconds value is really a Amp/Watt hours or Kilo Amp/Watt hours value and the divs are just part of the correction factor anyway? It looked so neat before :/ I think we are getting closer, still I don't like this correction factor guessing the slightest. |
I don't like it either but it also occurs to me that the device is taking two shortcuts that are hacky:
Really RMS current * RMS voltage is not power. Power is the average of current * voltage, which involves paying attention to phase. More complicated meters do this. So, the idea that the meter is displaying something which is A * configured_V * k, where k is some scale factor of 0.85 (very very ish) is not crazy. But if the A matches rtl_433 to display, then the issue isn't in decoding A. My next question is how the time integral of A(t) * V_fixed compares to the device's own display. I still don't understand if kWh displayed on the CM160 is consistent with the utility company's meter. As an example I have an Aeotec Home Energy Meter Gen5 (2 clamps and a single voltage sense) and the integrated power values are within a few percent of the power company's meter. But that's zwave with no decoding guessing. |
Yeah, I don't like it either, but unfortunately don't have more time to spend on this. The CM160 documentation state it may be accurate to 10%, hence I stopped comparing it to the utility reading. I just wanted to ensure that my kWh from the 433 cumulative total is as close as possible to the reading on the LCD console over time. Originally the calculation seemed so perfect and scientific. Thank you to everyone for their input. |
If possible we want a 1 to 1 mapping with the LCD output but if we cant do that then just do as best as possible and document it in the source code. |
Let me get some of the test evidence, I have been running webcam captures for the CM160 LCD console and have been writing the decoded and converted 433 values to a DB. Let me get some data and images and post them here. Maybe someone sees the problem. Unless it is just a factor of unknown from the vendor IP. |
The LCD console most likely only have 16 or 32 bit fixed point math to present the displayed value. I am all for to just leave it with a 1.12 factor. As long as that is better then before. |
Created PR for 1.12 - #2427 If and when someone finds a more correct formula when can always adjust. |
Added more attributes and total kWh
Build and tested on MacOS