-
Thank you!
Can you please explain the code? I am a bit confused with all the "pullups" =)
So we set a variable pulledUp to true and counter to zero.
Then every 10s we check.
I am confused with the else part - if we set pulledUp to false during "stuck LED" condition, then the first IF will get executed after 10 seconds, which will cause a reading update?
Should it not be other way around? I am confused =)if (D2.read()) { // LED is off - all ok onCount = 0; pulledUp = FALSE; } else { onCount++; if (onCount>6) { // >60 secs on pulledUp = TRUE; } }
Also, what is the difference between
if (!pulledUp) pinMode(D2,"input_pullup");
in the beginning and
if (!pulledUp) pinMode(D2,"input");
in the end? Or the first one suppose to be true and the last one false?
-
Hello
I thought I had my power meter puck all ready, but after about a week of successful running, I got into a problem that my power meter LED that blinks for every watt, gets stuck with LED always on =(
I have solar power and possibly it causes issues with a meter (have to call my power company).
Anyway... Is it possible to somehow work around the issue with the code?
This is my code to trigger on the light pulse, similar to the example code:pinMode(D2,"input_pullup"); setWatch(function(e) { c.inc(1); pulseTotal++; update(); if (LEDStatus==1){ digitalPulse(LED1,1,1); // show activity } }, D2, { repeat:true, edge:"falling" });
Not sure what I can do to detect that D2 is short for too long and somehow stop draining the battery if it gets stuck for too long. Once the sun sets, it goes back to normal blinking on power use
-
Hi, sorry, just saw your reply.
I got it working OK. Maybe not the best way, but had to work around the things that I do understand and examples I found online =)captive_portal: esp32_ble_tracker: on_ble_service_data_advertise: - mac_address: E9:F5:D3:BB:1C:30 service_uuid: 180F then: - lambda: 'id(PowerMeter_sensor_battery).publish_state(x[0]);' - mac_address: E9:F5:D3:BB:1C:30 service_uuid: "1809" then: - lambda: 'id(PowerMeter_sensor_temperature).publish_state(x[0]);' - mac_address: E9:F5:D3:BB:1C:30 service_uuid: 2A03 then: - lambda: |- std::string b(x.begin(), x.end()); std::string myStr = &b[0]; float num_float = parse_float(myStr).value(); ESP_LOGD("PowerMeter_sensor_instant_power:", "%s", &b[0] ); id(PowerMeter_sensor_instant_power).publish_state(num_float); - mac_address: E9:F5:D3:BB:1C:30 service_uuid: 2A04 then: - lambda: |- std::string b(x.begin(), x.end()); std::string myStr = &b[0]; float num_float = parse_float(myStr).value(); ESP_LOGD("PowerMeter_sensor_pulse_hour:", "%s", &b[0] ); id(PowerMeter_sensor_pulse_hour).publish_state(num_float); - mac_address: E9:F5:D3:BB:1C:30 service_uuid: 2A05 then: - lambda: |- std::string b(x.begin(), x.end()); std::string myStr = &b[0]; float num_float = parse_float(myStr).value(); ESP_LOGD("PowerMeter_sensor_pulse_day:", "%s", &b[0] ); id(PowerMeter_sensor_pulse_day).publish_state(num_float); on_ble_advertise: then: - lambda: |- ESP_LOGD("ble_adv", "New BLE device"); ESP_LOGD("ble_adv", " address: %s", x.address_str().c_str()); ESP_LOGD("ble_adv", " name: %s", x.get_name().c_str()); ESP_LOGD("ble_adv", " RSSI: %i", x.get_rssi()); ESP_LOGD("ble_adv", " Advertised service UUIDs:"); for (auto uuid : x.get_service_uuids()) { ESP_LOGD("ble_adv", " - %s", uuid.to_string().c_str()); } ESP_LOGD("ble_adv", " Advertised service data:"); for (auto data : x.get_service_datas()) { ESP_LOGD("ble_adv", " - %s: (length %i)", data.uuid.to_string().c_str(), data.data.size()); } ESP_LOGD("ble_adv", " Advertised manufacturer data:"); for (auto data : x.get_manufacturer_datas()) { ESP_LOGD("ble_adv", " - %s: (length %i)", data.uuid.to_string().c_str(), data.data.size()); } if(x.get_ibeacon().has_value()) { auto ibeacon = x.get_ibeacon().value(); ESP_LOGD("ble_adv", ibeacon.get_uuid().to_string().c_str()); ESP_LOGD("ble_adv", "Major: %i", ibeacon.get_major()); ESP_LOGD("ble_adv", "Minor: %i", ibeacon.get_minor()); } sensor: - platform: template name: "PowerMeter_sensor_battery" id: PowerMeter_sensor_battery device_class: "battery" unit_of_measurement: "%" - platform: template name: "PowerMeter_sensor_temperature" id: PowerMeter_sensor_temperature device_class: "temperature" unit_of_measurement: "°C" - platform: template name: "PowerMeter_sensor_instant_power" id: PowerMeter_sensor_instant_power unit_of_measurement: "Wh" device_class: "energy" - platform: template name: "PowerMeter_sensor_pulse_hour" id: PowerMeter_sensor_pulse_hour unit_of_measurement: "Wh" device_class: "energy" - platform: template name: "PowerMeter_sensor_pulse_day" id: PowerMeter_sensor_pulse_day unit_of_measurement: "Wh" device_class: "energy"
-
agree but dont want to be sending extra info. Like I don't really care in the evening that meterbox was opened some time during the day. Just means that I would have to add it to every advertisement
Have to look at what happened to my puck - lost connectivity this morning. Only found out in the evening so don't know what happend -
-
Hello
How would I go about calling a function when the level of ambient light changes?
I want to predefine parameters and call a function if its within a certain range.
Does it use much power to do puck.light() checks? If I just do setInterval to 1 second to check the value and if its outside a predefined level call a function - will it impact the battery much? Would prefer a neater way to do it if possible -
would be a bit hard to measure with multimeter if I need to keep it in the dark.
Apart from LDR there is nothing else attached. Are you saying that serial console is enabled by default? Would have thought that it would only be needed when someone connects to the client.
What are your suggestions on saving power? I was planning to leave it as is and when battery runs flat I would just replace with a fresh one and see how long it will last. Maybe then replace with 2x1.5 AA battery pack or just replace with esp32 -
yes, I am. I have pasted the whole code (modified now a bit) here:
http://forum.espruino.com/conversations/366190/#comment16108564Is there a way to test how much power it's using? It's a closed box and I did my best to shield it. It is reading values ok. Signal can hardly get out of the box so had to install esp32 inside it. So dropped the to power to -4
-
no, thats fine as is. Was just confirming to make sure that both don't advertise, taking power.
I know I have been connecting to the puck a number of times to update the code, but its currently sitting around 70% with just about 1 week running.
Already disabled the LED pulsing and trying to make the most out of the battery. See how I go. Have an idea of replacing the CR2030 with 2 AA lithiums -
-
-
is it possible to stop sending advertisements? I have solar, so during the day the power use is zero (mostly). But because it is resending the last read value, I am currently just sending a 0 (zero) value for power every 30 seconds just to clear it. It is not energy efficient, as I am just sending zero all the time until the next pulse is read, which may be in the afternoon - hours later.
I would like to be able to check if last power value was zero and if it was, then stop advertising it.setInterval(function() { power = 0; if (sDate.getMinutes()==0) { update(); } NRF.setAdvertising({ 0x1809 : [E.getTemperature()], 0x180f : [Puck.getBatteryPercentage()], 0x2a03 : [String(power)] }); print("Battery and temp data sent"); }, 30000);
-
Hello
Here is my project. Not sure if I should be posting a code here or in pastebin. Let me know so that I will do it next time =)
Anyway. I have this working by using Puck.js that counts pulses on my smart power meter and transmits them for ESPHome running ESP32 board to pickup and process into HomeAssistant.
At the moment have an issue with with the code (which is reused example code plus few extras) - it is set to keep track of pulses (hourly, daily etc), but it does not reset when the hour is changed over. Which causes incorrect values - it increments what was already there from the previous day =(
Can someone skim through the code and suggest any optimizations and help me with counter resets for daily pulses?function Counter() { this.clear(); } /// Clear the counters back to zero Counter.prototype.clear = function() { this.totals = { count : 0, // Overall count year : new Uint32Array(12), // each month of the year (0..11) week : new Uint32Array(7), // each day of the week (0..6) month : new Uint32Array(31), // each day of the month (0..31) day : new Uint32Array(24), // each hour (0..23) }; this.historyPeriod = 60*60*1000; // 1 hour in milliseconds this.history = new Uint32Array(96); // last 96 hours this.historyTime = 0; this.lastUpdate = new Date.now(); }; Counter.prototype.inc = function(n) { if (n===undefined) n=1; var t = this.totals; var d = new Date(); // Totals by time period t.count+=n; t.year[d.getMonth()]+=n; t.week[d.getDay()]+=n; t.month[d.getDate()-1]+=n; t.day[d.getHours()]+=n; print("Day:"+t.day); print("Month:"+t.month); pulseHour=t.day[d.getHours()]; pulseDay=t.month[d.getDate()-1]; // Rolling history this.historyTime += d.getTime()-this.lastUpdate; this.lastUpdate = d.getTime(); var steps = Math.floor(this.historyTime / this.historyPeriod); if (steps>=0) { this.historyTime -= steps*this.historyPeriod; var h = this.history; h.set(new Uint32Array(h.buffer, 4*steps), 0); h.fill(0, h.length-steps); h[h.length-1]+=n; } }; var c = new Counter(); var pulseTotal = 0; var power = 0; var cTime = Date.now(); var pulseHour = 0; var pulseDay = 0; E.setTimeZone(8); var LEDStatus = 0; // 0 = LED Status off 1 = LED Status on var txpower = 0; //-20, -16, -12, -8, -4, 0, and 4 NRF.setSecurity({display : 1, mitm : 1, bond : 1, passkey : '123456'}); NRF.setTxPower(txpower); //-20, -16, -12, -8, -4, 0, and 4 // Update BLE advertising function update() { var a = new ArrayBuffer(4); var dataV = new DataView(a); var mydate = new Date(); var temp = E.getTemperature(); var batt = E.getBattery(); var dataJSON = {b:batt,t:temp,c:1}; var timeDiff = (Date.now() - cTime); //Number of pulses per wh - found or set on the meter. var ppwh = 1; //1000 pulses/kwh = 1 pulse per wh //Calculate power var totalkWh = pulseTotal/1000; if (pulseHour>0) { power = Math.floor(((60*60*1000) / timeDiff)/ppwh); } cTime=Date.now(); //dataV.setUint32(0, c.totals.day, false/*big endian*/); //print(c.totals.day[mydate.getHours()]); print(mydate.toString()); print("Temperature:"+temp); print("Battery:"+batt); print("Current power use:"+power); print("Total power use:"+totalkWh); print("Pulses this hour:"+pulseHour); print("Pulses this day:"+pulseDay); NRF.setTxPower(txpower); //-20, -16, -12, -8, -4, 0, and 4 NRF.setAdvertising([{ 0x2a03 : [String(power)], 0x2a04 : [String(pulseHour)], 0x2a05 : [String(pulseDay)]}], {interval: 600, showName:false } // name: "PM \xE2\x9A\xA1"} // default is 375 - save a bit of power ); power = 0; } function onInit() { var sDate = new Date(); clearWatch(); D1.write(0); pinMode(D2,"input_pullup"); setWatch(function(e) { c.inc(1); pulseTotal++; update(); if (LEDStatus==1){ digitalPulse(LED1,1,1); // show activity } }, D2, { repeat:true, edge:"falling" }); update(); setInterval(function() { power = 0; if (sDate.getMinutes()==0) { update(); } NRF.setAdvertising({ 0x1809 : [E.getTemperature()], 0x180f : [Puck.getBatteryPercentage()], 0x2a03 : [String(power)] }); print("Battery and temp data sent"); }, 30000); }
-
nRF client shows writeable attributes and name is one of them. I do not know how nRF client connects to change the name (as pairing/bonding is asking for a pin code) without real pairing. But it does and it does it on a device- once changed I can see it changed when I connect from IDE as well as other devices
-
Hi
Have a code that sends BLE advertising like this:NRF.setAdvertising([{ 0x2a03 : [String(power)], 0x2a04 : [String(pulseHour)], 0x180f : [Puck.getBatteryPercentage()]}], {interval: 600} // name: "PM \xE2\x9A\xA1"} // default is 375 - save a bit of power );
The "power" variable is instantaneous power that I display between pulses. But the issue that I have is that when there is a delay between pulses that goes for too long (have solar), it keeps retransmitting the last value.
Is it possible to manipulate it somehow, so that I can put some code in between the interval resends?
Like if time difference between pulses is over 60 seconds, it will set the "power" variable to 0 -
so far I have found that I can only send numbers 0-255 (is that 2 bytes?)
How do I overcome the limitation? Is there a tool to see how many bytes in total are getting sent, so that I know when I am approaching the limit? Also read about using short UUID and not using the name to save on the data.
I guess one option is to rotate the information sending, instead of sending all at once. I saw an example before, but cannot find it -
Hi
I am trying to do a smart power meter pulse counter with the puck.
It all kind of works, until the values get over a certain level. Then it throws all kind of errors and stops sending any data.
This is the setAdvertising code I use:NRF.setAdvertising([{ 0x2a03 : [String(power)], 0x2a04 : [String(pulseHour)], 0x2a05 : [String(pulseDay)], 0x180f : [Puck.getBatteryPercentage()]}], {interval: 600, name: "PM \xE2\x9A\xA1"} );
All of the service data values are integers. Power is instantaneous power which can go to like 5000 and pulseHour and pulseDay can go well over 1000. I tried not using the string, but then it does not store the full value. Not sure where it breaks
-
-
Hi
Would like to secure my puck from connection/writing attempts.
Not sure what others use - would like some input.
Was thinking of either using a PIN code if I wanted to do something like connect/write new code, or making it connectable only when the button is pressed.Tried using this in the onInit function
function onInit() { NRF.setSecurity({display : 1, keyboard : 1, mitm : 1, passkey : '1234'});
but get this error
Running onInit()... BLE Connected, queueing BLE restart for later Uncaught Error: ERR 0x7 (INVALID_PARAM) at line 1 col 72 ...mitm : 1, passkey : '1234'}); ^ in function called from system
Later I moved the NRF.setSecurity({display : 1, keyboard : 1, mitm : 1, passkey : '123456'});
into the main body of the code and added "56", as it requires 6 characted PIN code.
But I can still connect to it and it does not ask for the codeAnd worst part is that now I am not able to connect to it =( It connects and then instantly disconnects
-
Hi everyone
I am trying to find the most efficient way to get data from puck.js to ESPHome.
End goal is to get it into Home Assistant. I have other sensors running off ESPHome (ESP32), so makes sense to re-use it to get the data.
Any tips on the service data format? I am sending battery status of puck plus 3 extra pieces of info -
I have another reading that shows current watts based on time between the pulses.
But I wanted to keep track of the total pulses for the day and actual kW use per hour. But for this I need to know when the current hour or day is overDoes the time sync happen during the code upload? Guess it would break then when doing battery replacement
-
Hi
I have started with this example as a base to modify for my needs:
https://www.espruino.com/Smart+MeterI am measuring time between pulses to calculate current power use. But I also want to keep track of pulses per hour and per day. I am lost at math that is used in the example to modify. I dont need an array to store, as data will be picked up but another device and stored elsewhere.
Can someone point me in the right direction/assist with javascript to detect a day/hour rollover, so that counters can be reset?
Some pseudo-code =)var hourPulses=0 var dayPulses=0 For every pulse if hour > previous hour then hourPulses =0 if day > previous day then dayPulses =0 increment dayPulses increment hourPulses send NRF data loop
Something like that. I just dont know how it will work when moving into a next day.
The example in the link above somehow magically sets it into an array. But I just want one value to be sent for the current hour and day. -
Love your detailed replies!
With an internal resister of "around 13k ohm" that you mentioned - is that in series or parallel?
I know basic electronic concepts, but not really my field, so having a bit of a blank trying to picture it. Will it be like LDR and internal in series, thus making a voltage divider to an analog read pin (in this case between 2 digital pins with one set to 0)?
I was asking about different LDRs as I do not know if the device will be able to register this micro voltage if too high resistance is chosen.
I dont think it will really matter as you have said - I looked at the nRF power estimation and most of the power will be used in tramission of the data
well, it works but trying to understand how it saves power.
Just because we set variable pulledUp to true does not mean that we set pinmode to input_pullup
first line only sets the pinmode to input_pullup if pulledUp is false
so I am trying to understand when does it actually set pinmode, if the condition when everything is ok is setting it to false...