-
@tve
Re #26 ... you are 110% correct ... but unfortunately ... so am I. When I wrote the original post, the lack of ability to form a connection WAS indeed not being handled by the ESP8266 (Espruino port).Since then, code has been added to the espconn_reconn_cb() via issue #595.
So ... YES ... handling a lack of connection CAN be caught in the espconn_reconn_cb() and YES ... at the time of writing ... handling a lack of connection was NOT being handled (but is now).
-
@Gordon ... In post #24 ... that was a written recap of what I understood in post #21. I am a big one for verbose but less ambiguous wording when it comes to technology discussions. So yes ... #24 was what you said in #21 ...
The absence of anyone having made a fuss in the past is not an indication that we have quality or correctness now. I'm a big fan of shooting for the best we can possibly do. You are the architect of all ... if you don't feel that there is value in this area then it is up to folks who think otherwise to civilly make their cases for change to ensure that you have all the information you need to make the decisions for or against a change. My data point is that on("error"), is desirous ... it isn't vital (yet) ... but would have relative high priority in the networking work items.
I changed the error handler in the ESP8266 port to now detect connection failures and in subsequent sends() requests does now indeed return -1 ...
However ... now I find that causes a problem because I now get:
ERROR: Socket error -1 while sending
On my console ... but worse ... my app ends because of the exception because I am no-longer able to detect when I should trigger a setTimeout() for the next round ... I would have to have an on("error") handler (or the solution you suggested using the timer .... which I respectfully ... simply don't like).
-
If I'm understanding properly ... the callback handler on an http.get() will not be invoked if the original connection request times out. I think I am also understanding that there is no on("error") handler in the current implementation for the object returned by http.get().
If these concepts are true, then we don't have an "elegant" means of detecting that a network request through http.get() has timed out and hence have no way of "handling" such a situation.
The best notion we have right now is firing a timer to go off some time in the future when we could sensibly assume that the connection should have been made ... and in that timer function, check see if the connection did indeed happen (or assume that since the timer fired ... we weren't cancelled) ... and handle there.
I suggest that this is a great opportunity to form a group of us to determine if this is the desired final semantics we want ... and, if not ... figure out what the correct semantics should be, start a design and then make progress towards implementation. My opinion is that I really don't like the "timer" solution as a long term solution and believe that I would like the on("error") handler on the "get()" request.
-
I have found at least two major problems and a mystery :-)
First problem is related to issue #595 which states that there is no network error handling at the ESP8266 level. In English this means that if the ESP8266 detects a network error, it silently ignores this. When working with Thing Speak, we need to assume that Thing Speak may ignore our HTTP GET request ... when that happens, the lack of the ability to form a connection is not handled by the ESP8266 and it keeps the socket open. This means that we start to leak sockets and quickly die. The solution is to detect the failure to form the connection and shutdown the socket.
The second problem is related to the logic of the sample application. It's logic says "Every period, make a GET request to thing speak" ... however that logic doesn't say "At the end of the PREVIOUS GET request, schedule another request to Thingspeak". What this means is that if a request to connect to Thingspeak takes a while, more and more parallel requests could be made until we run out of resources. The solution is to change the logic to use setTimeout at the completion of the last GET request instead of setInterval which keeps sending new GET requests irrespective of whether previous ones completed.
The last note is still a mystery. When we use the Espruino "http.get()" method ... that is an asynchronous call ... it takes a callback function to be invoked when the response from the get request is available ... however ... we have a problem. In ESP8266, all network calls are asynchronous and this includes the formation of the connection request in the first place. What should happen when the "http.get()" request connection fails ... because it will be an asynchronous connection and happen later in the story ... this is going to be tricky.
Again ... I believe that http.get() assumes a synchronous call while ESP8266 network connections are asynchronous. We may be plain stuck here for a while.
-
-
@Erni,
Perfect post and diagnostics ... I for one will start investigating what that means from the very detailed info you have supplied.... later ...
Am now running the same code using my own API key for ThingSpeak ... am watching to see what happens .... -
-
here you go ... a one time special to get you going ... a build of Espruino for ESP8266 with a 9600 baud rate ...
https://github.com/espruino/EspruinoBuilds/tree/master/ESP8266/Special_9600
-
-
@JumJum ... well ... that idea of yours makes perfect sense. Instead of "neopixelWrite" being a static function, maybe we create a class called "NeoPixel" with methods on it like "write" to write a stream of data and "init" to identify the data pin as well as set the T0H, T1H, T0L and T0H values. Then, in principle, any and all devices would work and all we would have to do is publish the working values.
However ... at this point, given that the current neopixelWrite() method seems to be working for the majority of us ... I'm tempted to flag that as "future" and attack some of the higher priority items in Espruino land.
As it is, I'm not sure we ever reached consensus on whether or not to include NeoPixel support in native Espruino (ESP8266 specific or otherwise).
I'm assuming that you yourself are able to drive NeoPixels?
-
I tested with real WS2812s and exactly as you stated, the results were horrible. I examined my own timings and got exactly what y'all measured. The timing diagram for the PL9823s that I was using gives T0H as 0.35us and T1H as 1.36us ... while for real WS2812s ... T0H as 0.35us and T1H as 0.7us.
In the actual timings now ... I have T0H as ~0.4us and T1H as ~0.95us. My tests are showing no errors.
I have uploaded a new firmware ... can I ask y'all to try this build and see if we are getting closer?
-
Thanks for the feedback ... the two 100us long pulses at the start are debug that I put in ... I'll remove them for sure. I have also been testing with PL9823s as opposed to WS2811s or WS2812s. I'll next dig out some WS2812s ... and see if those start to fail. I'm kicking myself for not having tested with those in the first place.
@MarkusGritsch ... everywhere I surf on the Internet I find your name related to these NeoPixel devices. You are certainly the most knowledgeable in that area. Folks like myself are acolytes in your footsteps here. I'll study the article you pointed at in great depth and see if I can't get the timings more accurate. If the WS2812 area for Espruino is something you yourself have particular interest in, I'll be delighted to work with you if you would be interested in getting a build environment for Espruino running at your work area. If not, your comments and timing results are EXTREMELY helpful ... thank you sir.
-
An experimental build is now up at:
https://github.com/espruino/EspruinoBuilds/tree/master/ESP8266
This has the following extra function:
var esp = require("ESP8266"); var pin = new Pin(1); esp.neopixelWrite(pin, [255, 255, 255, 0, 0, 0, 128,128,128]);
The array can be as long as you like but must be multiple of 3 in size. The pin is the Pin id of the pin you are using for the data line. The timing is hard-coded for the neopixel speeds.
@tve ... I like the idea but am not yet seeing how it would work for NeoPixels which appear to be our focus de-jure. At the NeoPixel level we want a pixel to be 3 bytes/pixel ... with 8 bits for red, 8 bits for green and 8 bits for blue. Not yet sure how we would turn that into a digital vector ....
-
@allObjects For each change to Espruino, there is usually a Github "Issue" created where folks can freely chime in with their comments, questions, suggestions and notions ... see for example:
https://github.com/espruino/Espruino/issues/606
Do you think these are useful?
-
-
-
We got permission from the author of MetalPhreak for inclusion of the code in Espruino ... in fact he is happy to change the license in any way ... see the following:
https://github.com/MetalPhreak/ESP8266_SPI_Driver/issues/7
He is a good chap and happy to accommodate as needed.
As for the integration of hardware SPI. The first pass is understanding the architecture of Espruino as it relates to hardware SPI ... we made some notes on this here ... https://github.com/espruino/Espruino/wiki/SPI-Architecture
Then we implemented these architected functions using MetalPhreak that worked out just great.
I don't think anyone is saying that this is the best solution or couldn't be dramatically improved. However it does now gives us a functional base line to start with. I am super keen that we all collaborate with each other ... I'd be delighted to devote time to changing the implementation and design ... but it will be best served by community involvement with you as the leader.
-
One can use NeoPixels with an ESP-1 ...
The first is that although the hardware SPI is not exposed on edge pins, it is still there on the physically exposed ESP8266. In "theory" one could solder on some wires directly to the SMD IC. From my perspective, I'd discount this immediately ... but Ive seen it "talked about" in some forums ... I for one couldn't solder that finely.
The other option would, of course, be the 1 wire solution written in C code that had been mentioned before ... bypassing the use of SPI.
As I was thinking about SPI driven NeoPixels on an ESP8266, we may have distaste for that solution. It strikes me that the hardware SPI will now consume 4 pins for driving the NeoPixel as opposed to the 1 that is strictly needed. SPI has 4 pins:
- MOSI
- MISO
- CLK
- SS
Since we will be driving data down MOSI and ignoring the other 3 pins, that may be considered a waste if users are finding themselves pin constrained. We might also find ourselves getting stuck if users need hardware SPI in addition to NeoPixel driving. For example, if the data describing the colors of the pixels over time were on an SD card which was being read by hardware SPI, we would need to introduce some form of SS to decouple it from MOSI data that it would otherwise detect when communicating with other devices.
- MOSI
-
-
Try the following and see if it makes any difference: