-
• #2
Just a guess: do you use
print
orconsole.log
? Maybe this one in the troubleshooting My code works when I'm connected via Bluetooth but stops when I disconnectOr do you use any other library that might contain a
clearWatch
? -
• #3
Thanks. I don't print or log anything on the Puck itself, there's no libs used and the only code that interacts with the Puck from the web page is that shown above. I tried the possible fix from the link, but the issue still persists.
It doesn't always stop working on the first connect from the web page, but usually by the second or third time it's stopped.
-
• #4
Can you post your code for the Puck up since it sounds like you've modified the code on it a bit?
What happens if you use the unmodified original code for the tutorial? Does that work? I'm using it here and it's been running for a month or more just fine.
One thing that could be an issue is you're calling
Puck.eval
twice one after the other. Usually you should nest the calls, so that one is called after the other one completes (because it's asynchronous) but you'll be sendingcurrentkWh
before the first has completed. I seem to recall the Puck library tries to account for this but I can't be 100% sure. -
• #5
Just to add: the setWatch could still be there - you can type
dump()
when connected in the IDE and see if asetWatch
is reported.One option is that you may be getting an error before the watch completes. For example:
var x = 0; setWatch(function() { x++; ... },...);
works fine, but if you'd called
delete x
thenx++
would create an error and stop execution. -
• #6
You're correct that the original code did work without issue. Thanks for the suggestion about nesting
Puck.eval
. I've now implemented that, but the issue has occurred again. Not sure if it's related, but it seemed to stop watching the flashes after I receivedgattserverdisconnected
error (although I haven't noticed that happen before in relation to it stopping working).The current Puck code is as follows:
const years = [] let lastFlashTime = Date.now() let currentkWh = 0 /** * Get the last 2 digits of full year * @param {number} year Year to parse * @return {number} */ function getYear(year) { return parseInt(year.toString().substr(-2)) } /** * Increment count, create new year, month, date, hour as needed */ function increment() { const d = new Date() const hour = d.getHours() const date = d.getDate() const month = d.getMonth() const year = d.getFullYear() // 2-digit year, as number const yr = getYear(year) if (years[yr]) { if (years[yr][month]) { if (years[yr][month][date]) { if (years[yr][month][date][hour]) { years[yr][month][date][hour]++ } else { // No hour in current date years[yr][month][date][hour] = 1 } } else { // No date in current month years[yr][month][date] = new Uint16Array(24) years[yr][month][date][hour] = 1 } } else { // No month in current year years[yr][month] = [] years[yr][month][date] = new Uint16Array(24) years[yr][month][date][hour] = 1 } } else { // Current year not yet created years[yr] = [] years[yr][month] = [] years[yr][month][date] = new Uint16Array(24) years[yr][month][date][hour] = 1 } } /** * Set the current usage in kWh from timings of flashes */ function setCurrentUsage() { const currentTime = Date.now() const diffMs = currentTime - lastFlashTime const diffSec = diffMs / 1000 const kWh = (3600 / diffSec) * 0.001 const decimalPlaces = 2 currentkWh = Number(Math.round(kWh + 'e' + decimalPlaces) + 'e-' + decimalPlaces) lastFlashTime = currentTime } /** * Watch fires an update */ function update() { increment() setCurrentUsage() } /** * Initialization function */ function onInit() { clearWatch() D1.write(0) pinMode(D2, 'input_pullup') setWatch(function (e) { update() digitalPulse(LED1, 1, 1) // Show activity }, D2, { repeat: true, edge: 'falling' }) }
When I type
dump()
into the IDE whilst it's broken, I still see thesetWatch
there, nothing seems out of place.Regarding your comment about an error in
setWatch
, how would I go about catching an error in there? I guess atry/catch
? -
• #9
Hi - that's what you'd expect - so what happens is
dump()
tries to recreate the current state of the interpreter as code. BecauseonInit
has already run, the watch was added already so it creates code for it.So that all looks good. What happens if you're connected via Bluetooth when the LED flashes? Do you get any error messages? You could try putting
digitalPulse
beforeupdate
to see if that helps - because ifupdate
created an error then execution would stop before it got run.... or maybe:
setWatch(function (e) { try { update() digitalPulse(LED2, 1, 1) // Show activity } catch (e) { digitalPulse(LED1, 1, 1) // Show activity console.log(e); } }, D2, { repeat: true, edge: 'falling' })
That'll flash green if it's ok, red if there was an error.
Could you check
E.getBatteryPercentage()
? It just might be your battery is on the way out?gattserverdisconnected
usually happens either if the Puck forces a disconnect (which you're not doing) or if it reboots. -
• #10
It looks like you were right about the battery. Although when I checked, it showed around 50%, every time I checked the percentage varied considerably. It was an old battery, so I changed it for a new one. It's been many days in now and there's not been a single issue with the watch not working.
Many thanks for helping to fix this issue!
-
• #11
Fri 2019.08.09
@Fisu should you be curious, we just wrapped up a discussion on the electrical characteristics, battery life and what to look out for with this exact same battery. Includes datasheet links and explanations:
http://forum.espruino.com/conversations/304667/#comment14851181
-
• #12
Thanks for the link. Some interesting stuff there.
-
• #13
I was so sure it was the battery that's the issue as it was working for 4-5 days without issue. Then last night (still with the new battery) it stopped working again.
So whilst it is broken, when the light on the electric meter flashes, I don't get any light flashing on the Puck (I did implement the try/catch above, but neither the red nor green light flashes). I get no error messages when connected in the IDE. I wondered could it have something to do with the memory slots, but doing
process.memory().free
showed2016
, which I assume is more than enough.Would you happen to have any other ideas what I could try?
-
• #14
Sat 2019.08.10
So that you are not waiting, wondering,
Did you catch this post?
I'm not able to assist as we don't have that type of meter here in the US. However, have you attempted to go back to the original source that Gordon references in #4 and give that a go?
Are you able to restart and continue, e.g. this is only a run time issue after a period of time, or are you forced to reboot/re-upload?
Is it possible there is a counter or something related to the date that reaches an upper limit, then causes an over flow or error? Could placing that section inside a try/catch help in identifying a possible cause to investigate further?
'but doing process.memory().free showed 2016'
Plenty.
'but neither the red nor green light flashes'
Wow, I would expect one or the other, so it appears that
setWatch()
is no longer seeing edges. It would appear that functionupdate()
is stuck in an endless loop. To check, place anotherconsole.log()
outside of the try/catch in #9 with an additional counter, then monitor. Will/may take a few days before halting, as you pointed out. Not sure if this would work, but at that point, is it possible to block copy that #9 on the left-hand console side of the WebIDE and see if pulses can then be detected? e.g. Espruino is still running and the issue IS in theupdate()
function.Try placing a try/catch block(s) inside the update function to see if errors can be trapped, rather than bubbling up and possibly missed.
As a last resort, pepper the entire flow with
console.log()
statements and see which one is last recorded. -
• #15
Many thanks. Plenty of ideas to try there. I'll implement what you suggest and report back what happens when it fails again.
-
• #16
Just spotted this:
Fr L#60 function setCurrentUsage() {
Here is a likely spot. There are two division equations. If the divisor is ever zero, a divide by zero error will be thrown. Place the try/catch just inside this function wrapping all, or create two separate to isolate. Maybe a system call to time is not completing timely.
Is L68 an acceptable practice? (combining a float with string text 'e' to return a number inside round?)
parseFloat() or parseInt()
are required to provide the Math object with a valid number.
orhttps://www.w3schools.com/jsref/jsref_toexponential.asp
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math
"Math is a built-in object that works with the Number type"
Could the const keyword be blocking a later assignment to that corresponding declaration.
Try changing all const to var to test. Not likely, but worth a shot.Add a clearWatch() in every catch to immediately stop execution. Label each with a useful descriptor like a line number. Hopefully there will be enough previous console.log detail prior to the clearWatch() call to review.
Run time debugging is a challenge and can be a real pain, . . . just waiting.
-
• #17
Good catch with the division. I've now added the try/catch to see if the issue is with that.
Regarding L68, I'm not sure it is acceptable practice, but it was a trick I found to round a number to x decimal places. If that is the issue, then the try/catch should catch that, although I've been using the same snippet in other work, so I'd be surprised if that is the issue.
Thanks for the tips, I've updated the Puck code so I'll wait and see what gets logged out.
-
• #18
I think you don't have to format the
currentkWh
on the puck.Just use
toFixed
on the display page. For example:var kwh = 1234.56789; console.log(kwh.toFixed(2)) "1234.57"
Separation of data & display concerns :)
-
• #19
Sun 2019.08.11
You beat me to it
toFixed()
@AkosLukacs, as I was in the process of documenting a discovered anomaly while prepping my response.as a mod to your example will show
>var kwh = 1234.505; >console.log(kwh.toFixed(2)) 1234.50
Is this another anomaly but withtoFixed()
? (re: "The number is rounded if necessary" )https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed
"toFixed() returns a string representation of numObj that does not use exponential notation and has exactly digits digits after the decimal place. The number is rounded if necessary, and the fractional part is padded with zeros if necessary so that it has the specified length."
YES just posted -
• #20
The result of
toFixed
looks like a number, because you console.log it, so there are no parenthesis around the printed value.>var fixed = kwh.toFixed(2); ="1234.50" >typeof fixed ="string"
And yes, looks like some rounding anomaly:
>2134.506.toFixed(2) ="2134.50" >2134.507.toFixed(2) ="2134.51"
-
• #21
Our posts are crossing each other and I hadn't finalized that post. Discovered the difference while ping-ponging between MDN and the WebIDE. Is an interesting subtlety one needs to be aware of. Thanks for confirming.
'so there are no parenthesis ' (double quotes)
May I inquire as to which Espruino version those tests were done? (same 2v04 ?)
Had a thought, could this anomaly be related to the floating point number of digits to right of zero not matching different browsers and node.js output? hmmmm. . . .http://forum.espruino.com/conversations/336605/
test files #1 -
• #22
Yes, you're right, I should just format it on the page. Thanks.
I've recreated and adapted the Smart meter tutorial. What I've noticed is, after I upload the code to the Puck, it watches the flashes correctly and will continue until I connect from the web page. From that moment on, it is as if the watch on the pin is removed. The Puck no longer flashes when the electric meter flashes, and there are no further records of the flashes. The variables stored in the Puck remain and are not reset, it seems it is just the watch method which has an issue after connection from the web page.
I'm not sure how to debug this issue. The only place
clearWatch()
is called is in theonInit()
function on the Puck. The connection code from the web page seems simple, and I cannot see anywhere there that might clear the watch. Any ideas on how I can further debug this issue?Here is the code from the website connection script (I don't call any Puck functions anywhere else apart from here):