-
To fix the out-of-memory error, replace these lines (refering to post #3)
this.watch = setWatch(function(t) { if(ht.watch){ ht.watch = clearWatch(ht.watch); }
with these lines
var w = setWatch(function(t) { clearWatch(w);
It would be better to set the watch only once (as well as some other setup tasks), instead of setting it in every run (as it is done in this .js module).
-
-
In my opinion a bug in the dht11.js software module. You are not the first to have issues, see also:
http://forum.espruino.com/conversations/316733/#comment14104546
I don't have a fix, and no DHT11 to test. -
-
I've now included a test for undefined in my code,it is fixed for me.
Since the source code is the same for all systems I wonder what's going on. Might be a job for a long winter nights to dig into it.Another bug is this one (directly after erase and flash):
>require("Storage").getFree(); =16 >require("Storage").eraseAll(); =undefined >require("Storage").getFree(); =196608
Do you have the same on the ESP8266 4MB build? It doesn't affect the JSON.parse.
-
I flashed the device with "espruino_2v04_esp8266_4mb_combined_4096.bin".
The first command I typed in after connecting is "JSON.parse(undefined)" (no Wifi/no other devices connected).
The ESP8266 is USB-powered, and this works fine with Wifi and a few Neopixels normally (when not using this code).> JSON.parse(undefined) ets Jan 8 2013,rst cause:2, boot mode:(3,7) load 0x40100000, len 2408, room 16 tail 8 chksum 0xe5 load 0x3ffe8000, len 776, room 0 tail 8 chksum 0x84 load 0x3ffe8310, len 632, room 0 tail 8 chksum 0xd8 csum 0xd8 2nd boot version : 1.6 SPI Speed : 80MHz SPI Mode : DIO SPI Flash Size & Map: 32Mbit(1024KB+1024KB) jump to run user1 @ 1000 ãänì{ûo|ällld`c<sd'à'ãd`ãrÛl$þ ____ _ | __|___ ___ ___ _ _|_|___ ___ | __|_ -| . | _| | | | | . | |____|___| _|_| |___|_|_|_|___| |_| espruino.com 2v04 (c) 2019 G.Williams Espruino is Open Source. Our work is supported only by sales of official boards and donations: http://espruino.com/Donate Flash map 4MB:1024/1024, manuf 0xc8 chip 0x4016 >process.memory(); ={ free: 1575, usage: 25, total: 1600, history: 0, gc: 0, gctime: 1.901 } >process.env; ={ VERSION: "2v04", GIT_COMMIT: "3956264e", BOARD: "ESP8266_4MB", FLASH: 0, RAM: 81920, SERIAL: "a020a61c-4bc6", CONSOLE: "Serial1", MODULES: "Flash,Storage,hea" ... "r,crypto,neopixel", EXPTR: 1073643636 } >console.log(process.env.MODULES); Flash,Storage,heatshrink,net,dgram,http,NetworkJS,Wifi,ESP8266,TelnetServer,crypto,neopixel =undefined >require("ESP8266").getState(); ={ sdkVersion: "2.2.1(6ab97e9)", cpuFrequency: 160, freeHeap: 15464, maxCon: 10, flashMap: "4MB:1024/1024", flashKB: 4096, flashChip: "0xc8 0x4016" } >require("Flash").getFree(); =[ { addr: 2097152, length: 1048576 }, { addr: 3145728, length: 262144 }, { addr: 3407872, length: 262144 }, { addr: 3670016, length: 262144 }, { addr: 3932160, length: 241664 } ] >require("Storage").getFree(); =16 >
-
-
I can't see why you would need a LIFO. At startup I'd simply discard all messages that queued up while offline, to keep the device simple.
Regarding security:
- When going with the Google Mini local API http is ok (ESP8266 doesn't support https).
- When connecting to the internet you should verify the identity of the server using https (ESP32 supports https).
- In both cases keep in mind that Espruino has a local telnet and OTA server running in the default firmware, that is nice for development but also a potential security risk during operations in a customer WLAN.
Instead of http/https polling you could use websockets, which are much easier to implement in nodejs/esprunion compared to C++. It's an outgoing http (or https) connection as you're using right now, no firewall change required. The only difference is that you "upgrade" the connection once, and then you can send "messages" instead of http requests. Having a tested solution with polling I wouldn't change it, unless you have to scale up.
- When going with the Google Mini local API http is ok (ESP8266 doesn't support https).
-
Copying your code together this would be the code not working, right?
wifi.on('connected',(details) => { var clearQueuePromise = new Promise((resolve,reject) => { idClearQueue = setInterval(() => { idClearQueue = setInterval(() => { --do http GET until successful--- clearInterval(idClearQueue); resolve("OK"); },2000); }); clearQueuePromise.then((resolve,reject) => { print('clear queue finished'); }); });
And having the exact same promise definition "var clearQueuePromise =" outside of the "wifi.on('connected')" makes it work?
-
What changed from #1 (good temperature readings) to #8 (checksum error)? The length of the raw output changed by one bit. What did you change?
The code in #20 looks non-functional, e.g.
parseInt (d.substr (2.8) 2) +
can't work.I copied in the module as reference, with some notes:
/* Copyright (C) 2014 Spence Konde. See the file LICENSE for copying permission. */ /* This module interfaces with a DHT22 temperature and relative humidity sensor. Usage (any GPIO pin can be used): var dht = require("DHT22").connect(C11); dht.read(function (a) {console.log("Temp is "+a.temp.toString()+" and RH is "+a.rh.toString());}); the return value if no data received: {"temp": -1, "rh": -1, err:true, "checksumError": false} the return value, if some data is received, but the checksum is invalid: {"temp": -1, "rh": -1, err:true, "checksumError": true} */ function DHT22(pin) { this.pin = pin; } DHT22.prototype.read = function (cb, n) { if (!n) n=10; var d = ""; var ht = this; digitalWrite(ht.pin, 0); pinMode(ht.pin,"output"); // force pin state to output // start watching for state change this.watch = setWatch(function(t) { d+=0|(t.time-t.lastTime>0.00005); }, ht.pin, {edge:'falling',repeat:true} ); // raise pulse after 1ms setTimeout(function() {pinMode(ht.pin,'input_pullup');pinMode(ht.pin);},1); // stop looking after 50ms setTimeout(function() { if(ht.watch){ ht.watch = clearWatch(ht.watch); } var cks = parseInt(d.substr(2,8),2)+ parseInt(d.substr(10,8),2)+ parseInt(d.substr(18,8),2)+ parseInt(d.substr(26,8),2); if (cks&&((cks&0xFF)==parseInt(d.substr(34,8),2))) { cb({ raw : d, rh : parseInt(d.substr(2,16),2)*0.1, temp : parseInt(d.substr(19,15),2)*0.2*(0.5-d[18]) }); } else { if (n>1) setTimeout(function() {ht.read(cb,--n);},500); else cb({err:true, checksumError:cks>0, raw:d, temp:-1, rh:-1}); } }, 50); }; exports.connect = function(pin) { return new DHT22(pin); };
From my point of view line 22 is not necessary, or if it is lines 21 and 22 should be swapped.
Line 23 could read// read d based on signal change interval
Lines 27 and 28 could be moved to the end and then rewritten. Since the lines will be only executed once everything is set up there's no need to use a setTimer in this case:
//trigger data transmission pinMode(ht.pin,'input_pullup'); pinMode(ht.pin);
Line 29 could read
// parse the received data d (50ms length)
Line 31 could be changed toclearWatch(ht.watch);
, usingif
is not necessary.
And I'd change line 1 toif (!n) n=1;
because one try should be enough if nothing else was specified.And if your raw data is too long, capturing also the trigger you can add
d = d.substr (1); //remove trigger signal
to the code. I don't have this sensor, so I can't try. -
Parsing a variable of type "undefined" creates an error:
function foo(x, y) { for (var i=0; i<arguments.length; i++) { console.log("i="+i); try { console.log("val="+arguments[i]); } catch (e) { console.log(e);} } } foo(undefined, 1, undefined, 2) i=0 ReferenceError: ReferenceError: "0" is not defined i=1 val=1 i=2 ReferenceError: ReferenceError: "2" is not defined i=3 val=2 =undefined
So there are two bugs: arguments.length is not updated (documented https://www.espruino.com/Reference#l__global_arguments). arguments fails for undefined arguments (not documented).
-
Whatever. For one, foo is not an build-in function so the reference to this part of the specs is not substantial. The linked codeburst.io article states "arguments.length indicates the exact number of arguments which does not depend on the number of parameters in the function definition.".
Maybe your understanding of the spec is correct. But all other JavaScript implementations have a different understanding. Being the only to follow the spec is a bug - from the user point of view. Because it's incompatible with the rest of the world.
-
Yes it's a bug.
arguments.length
is set to the number of arguments if the number of provided arguments is higher (and/or equal) to the number specified arguments in the function definition. But it is not set to the number of arguments if the number of provided arguments is smaller.As workaround define the function without arguments,
arguments.length
will be always correct.function foo(x,y) { console.log("arguments.length=" + arguments.length); //console.log("x=" + x); //console.log("y=" + y); //for ( var i=0; i < arguments.length; i++ ) { // console.log("typeof(arguments["+ i + "])=" + typeof(arguments[i])); // console.log("arguments["+ i + "]=" + arguments[i]); //} } function bar() { console.log("arguments.length=" + arguments.length); } foo(); foo(1); foo(1,2); foo(1,2,3); bar(); bar(1); bar(1,2); bar(1,2,3);
-
The ESP8266 gets warm as well - I didn't try it with NodeMCU but I'm pretty sure it would be cooler, too: The ESP8266 and ESP32 support multiple sleep modes, on Espruino only deepsleep() is implemented (deepsleep stops the processor, WLAN etc. and reboots it to wake up). The other sleep options are not available, and as such the processor is always active. In Micropython you used the sleep() function, no wonder it's using less energy and keeps cooler. If you would implement the Micropython version without sleep() the power consumption and temperature should be equal to the Espruino.
So I wouldn't say it's a bug, but the intended operation for the - obviously limited - builds for ESP8266/ESP32. -
Try to add
trace
to your program, and stop it after 3 runs. trace would print the inner state, and provide some information an what's wrong. I'd guess the module would not clean up everything.
If using line 1 doesn't give any hints try line 2, and finally line 3.console.log(global["\xFF"].timers); //print only timers, short info trace(global["\xFF"].timers); //print only timers, full info trace(); //prints full info
-
I'd propose the fix the code like this, however I didn't touch C for ages.
Line 1: set start = 0 for the first run (cache loading)
Line 23: wait if ccount>(0xFFFFFFFF-1000)
Line 24: set start = ccount, in the range [0 .. (0xFFFFFFFF-1000)]I selected the number 1000 just to show the case, in reality it should correspond to the number of ticks needed to transfer a single bit (tOne + tLow (incl. program overhead)). Maybe 300 is more reasonable.
start = 0; //fast pre-roll tZero = 63; //T0H = 400ns for WS2812B tOne = 121; //T1H = 800ns for WS2812B tLow = 181; //PERIOD = 1200ns for WS2812B ets_intr_lock(); // disable most interrupts while(1) { GPIO_REG_WRITE(GPIO_OUT_W1TS_ADDRESS, pinMask); // Set high uint32_t t; if (pix & mask) t = tOne; else t = tZero; while (_getCycleCount()-start < t) ; // busy-wait (high) GPIO_REG_WRITE(GPIO_OUT_W1TC_ADDRESS, pinMask); // Set low start = _getCycleCount(); while (_getCycleCount()-start < tLow) ; // busy-wait (low) mask = mask>>1; // Next bit if (mask == 0) { // Next byte if (p >= end) break; // at end, we're done pix = *p++; mask = 0x80; } pinMask = _BV(pin); // correct pinMask after pre-roll while (_getCycleCount() > 0xFFFFFC17) ; // ccount overflow handler start = _getCycleCount(); // get start time of this bit } ets_intr_unlock();
-
-
-
-
Flash is ok.
>process.env ={ VERSION: "2v04.6", GIT_COMMIT: "c2087d40", BOARD: "ESP8266_4MB", FLASH: 0, RAM: 81920, SERIAL: "18fe34d1-8934", CONSOLE: "Serial1", MODULES: "Flash,Storage,hea" ... ",ESP8266,neopixel", EXPTR: 1073643644 } > >require("Flash").getFree() =[ { addr: 2097152, length: 1048576 }, { addr: 3145728, length: 262144 }, { addr: 3407872, length: 262144 }, { addr: 3670016, length: 262144 }, { addr: 3932160, length: 241664 } ] >
Restarting the Web IDE and reconnecting the board should fix the serial connection.
-
Diffusion kills brightness. From some distance it's impossible to identify individual LEDs on a 144 LEDs/meter LED strip, saving the diffusor. You've already posted a video - did you try this outside at daylight already?
Handling a baseball impact, I'd say the plexiglass itself should be strong enough, without an extra MDF backplate. I'd prefer a more lightweight build. Milling the MDF is a lot of work, even using a CNC. -
Hi Robin
for me it looks like it'll block the while loop. You said the C could would be sending just a very short pulse instead, it's only a minor bug.
Just to expain my understanding of the code I've attached a simplified JavaScript program emulating the code:
- A while loop that doesn't contain any code itself (just assume it would transmit a bit)
- Said while loop shall complete after 10 ticks (t=10)
- The program would repeat forever (as it was transmitting an infinite number of bits)
The program works fine, until ccount is reset back to 0. At this point the while loop hangs, it never quits. This would crash the ESP8266 (reset triggered by wifi/watchdog).
A fix for the JavaScript program would be to uncomment line 17 ("ccountChk = 255-t-5;", with "t" being the waiting time and "5" being an estimated amount of ticks needed to run the program code itself, with good margin). Since the fix itself takes some time to process it might be ok to change the while loop counter "t" from "10" to "9" (in this example it doesn't makes sense. But in the original code you can reduce the while counter due to the delay introduced by a similar fix).
Anyway, before writing a fix I think it's best to get a common understanding if there's a bug, and what the best fix would be. I wouldn't want to add a speculative fix for a potential bug that isn't fully understood.// //step debugger // //init variables var t="na"; var start="na"; var pc = 0; //program counter var ccount = 0; //a 8 bit ccount implementaton var ccountMax = 255; //a 8 bit ccount implementaton var program = []; //program code, addressed by program counter var ccountChk = 255-10-5; //program code program[0] = "t = 10;"; program[1] = "start = ccount;"; //start=_getCycleCount(); //program[1] = "if (ccount>ccountChk) { pc--; start =-1; } else { start = ccount; };"; program[2] = "if (ccount-start < t) { pc--; } //while(_getCycleCount()-start < t);"; program[3] = "pc=0; //while loop completed, repeat the program (to send next bit)"; //step debugger, executes one line of the program code each call stepDebugger = function() { console.log("A PC=" + pc + ", ccount=" + ccount + ", t=" + t + ", start=" + start + ", program: " + program[pc]); eval(program[pc]); //execute one line of code pc++; //set pc to next line if (pc > program.length) { console.log('program ended'); } ccount++; //increase ccount, reset to zero if it's countMax if (ccount>ccountMax) { ccount=0; } console.log("B PC=" + pc + ", ccount=" + ccount + ", t=" + t); } //automatically call the debugger every 500ms stop = setInterval(stepDebugger, 500); //clearInterval(stop) //the while loop (program[2]) exits every 10 ticks. //bug: once ccount==start=253 the while loop "hangs" forever
- A while loop that doesn't contain any code itself (just assume it would transmit a bit)
One thing you could try to identify the bug in the DHT11.js module: Print the read "raw" value, using your code in #1.
tldr:
I'd assume it's length differs from the length in #3, having one extra bit. And removing this bit would fix the module for the ESP32, and would break it for all other boards having a different timing. A rewrite of the module with the setup of the watch only once at the "connect" would be the best solution, and should fix it for all platforms.