Avatar for allObjects


Member since Jul 2014 • Last active Oct 2018

Espruino makes IoT as easy as 123!

Most recent activity

  • in ESP8266
    Avatar for allObjects

    ooops... checking the pin vs serial would have helped... ;/

    @Gordon, w/ your input, I conclude that second example is either not working or tricks the observer that it works only half the times, is it?

    Adding a counter and log its value would - when working - only log every other time?

  • in ESP8266
    Avatar for allObjects

    The first code example surprise me a bit by what it should do...

    For ten seconds, every five (5) milliseconds it logs "foo ". On the 1000th time, something after five (5) seconds, it turns the pin on.

    The hanging to me means that something with the buffers goes hi wire, because of all the logging...

    What is the reason for the loop? ...are you trying to reinstate Arduino on an event driven system?

    The second piece of code does it 100 times slower: every 500 milliseconds, it does log something... and the rest of the time it is sleeping. Less than a percent - probably 1/2 a percent as busy as the first code...

    Could it be that the system crashes and reboots?... I would be surprised...

    PS: ...not Espruino hangs, but ESP8266 Wifi stack puts an end to this...?

  • in JavaScript
    Avatar for allObjects

    @Coder2012, very interesting and good to know. Actually I was looking for something like that for similar purposes, like driving multiple chains of RGB LED strings and RGB LED cubes:

    Gsap is designed for the browser as it transitions elements in the DOM but can also transition values on objects you create yourself, therefore you're not restricted to just DOM objects or the window object in the browser.

    May be taking gsap apart and use only the pieces that are needed, could be a starting point. From other experiences though I know that pretty quickly Espruino runs out of steam... and a minimum setup is more in the realm of recent model of Raspberry Pi, even though some stuff can be 'native-d down into Espruino guts' using compiled. Most likely, you will end up writing it natively and add it to the Espruino firmware with control-APIs for the JS side, like GPUs in an end point device have APIs exposed thru the Browser w/ JavaScript language binding (for feeding data and commands and ('source') code).

  • in JavaScript
    Avatar for allObjects

    There is information available about using node.js / npm modules. After all, Espruino follows the node.js style of handling modules. Second one is very insightful conversation with explanations from @Gordon.

    Not directly related, but interesting to know is that the Web IDE can run as a node.js application on any device that can run a node.js... for example, raspberry pi:


  • in JavaScript
    Avatar for allObjects

    The https://www.npmjs.com/package/gsap documentation in its very first sentence says:

    GSAP is a JavaScript library for creating high-performance animations that work *** in every major browser ***.

    The code runs in the browser and the node.js / Web server. Even though Espruino (-Wifi) can work as a a Web server, it is not a node.js server.

    If you implement a Web server on your Espruino-Wifi - based on https://www.espruino.com/WebServer - and implement the pulling of files according to the http(s) request request urls from the SD card, you may get something working (in your browser). You have to used the SD card because Espruno's memory is just to small to keep all the files in memory. Espruino is then the server for the resources the browser needs. Even if you get node.js basics server-side - on Espruino-Wifi - going, it just lacks the resources...

    It would be help full to explain what you want to achieve from a birds point of view.

  • in Pico / Wifi / Original Espruino
    Avatar for allObjects

    Even though the original board has way more GPIOs, I'm a proponent of using PICO. First, it has more - double - RAM / variables - 50% more flash, and is slightly faster, smaller foot print, and does not have the specialized prototype area, that - most of the time does anyway not cater to the specific needs you have - AND, may be the most helpful thing - the ports are all 5V tolerant.

    Should you really run out of GPIOs, there are easy ways to mend that: adding serially driven shift registers or port expanders.

    The issue that 8 pins are on 0.05" pitch is not really an issue because you can choose my or @Gordons approach to make all pins friendly to breadboard and 0.1" pitch: Breadboard friendly PICO (There are other options as well: shims from @Gordon and breakout boards fromn @DrAzzy).

  • in Other Boards
    Avatar for allObjects

    In regard to the sister blog entry about LoRa Gateway Antenna Upgrade:

    I'm surprised that the aerials are horizontal and the significant length difference between them and the wip.

    For regular 1/4 wave length ground plane antennas with standard impedance - 50R - the (four) aerials point about 45 degrees down and wip and aerials have about the same length. See M0UKD's 1/4 Wave Ground Plane Antenna Calculator.

    Do the supplier(s) of your upgrade antenna and the gateway mention:

    • Impedance?
    • Typical wave propagation pattern?
    • Low loss coax?
    • Placements of antenna and gateway?
  • in Other Boards
    Avatar for allObjects

    Without being to familiar with the detail - and going a bit on a limb - I try to answer the difference between

    returning cb; vs return cb(d);

    From variable name, I assume, it is a callback. It is for sure a function, because otherwise cb(d) would have given you an error.

    In JavaScript everything is an object... and a function, like cb, is also an object and can be passed around by reference as argument, assigned to a variable, returned as an object, etc. In the first case - return cb; - function object is returned and something else will invoke it... just as you would hand over an Icemaker vs. handing over Ice it has made, so someone else can push the button and make it make ice at their time and convenience.

    JavaScript syntax defines that a function reference (function name) followed by opening and closing parenthesis it to be invoked. In other words, cb(d) invokes the callback function with passing the d(ata) argument. With the return, you return what the callback function returns... which usually is undefined, because there is nothing around that could 'catch' what it returns.

    Typical with callbacks is that their invocation has to be deferred, because the parameter(s) that have to be passed on invocation are not available yet with the right values, and therefore the callback is handed to the next processing stage, to finally end up at the point AND time where the arguments are ready / populated with the right values and the callback can be invoked.

  • in Puck.js, Pixl.js and MDBT42
    Avatar for allObjects

    ...something like that: a RENDERER singleton for rendering on a display of a particular X and Y size panes - (full) pages and pop-ups w/ display nodes/items - in various styles:

    var panes =                      // declaration of your pages/popups w/ content 
    { start:                         // a page  (covers all of display)
      { id: "start", no: 0, title: "Start Page", s: 0 // s-tyle obj
      , nodes:                       // node displays label or property value
        [ { id: "s01", x:  0, y:  0, w: 30, h: 20,  
          , l: "ip:" , s:  0         // label "ip:" in default s-tyle
        , { id: "s02", x: 35, y:  0, w: 30, h: 20, 
          , p: "ip"  , s:  0         // property "ip" in model obj (see: MVC pattern)
    , msg:                           // a pop-up pane (covers area of display)
      { id: "msg", no: 0, title: "Message", s: 0, x:  20, y:  20, w: 80, h: 28,
      , nodes:
        [ { id: "m01", x:  0, y:  0, w: 30, h: 20,  
          , l: "message:"            // label "message:"
        , { id: "m02", x: 35, y:  0, w: 30, h: 20, 
          , p: "msg"                 // property "msg" in model object
    var styles = // indexed 0,1,... define font, -size and colors
    [ { font: "...", size: 9, fg: [1,1,1], bg: [0,0,0] } // 0: default
    ];                           // f(ore)g(round) and b(ack)g(round) color 
    var RENDERER =               // Singleton (google it)
    { g: null, d: null           // graphics and display objects
    , X: 0, Y: 0                 // display size, set in init()           
    , ps: null                   // p(ane)s set in init()
    , ss: null                   // s(tyle)s set in inbit() 
    , cpid: null                 // current p(ane) id, for optimization
    , cs: -1                     // current style (index0, for optimization
    , doPane: function(pid) {    // render pane w/ p(ane)id
        if (pid != this.cpid) this._initP(pid); // initP(ane) if not current
        this.ps[this.cpid = pid].nodes.forEach(function(n){ // for each node in pane
          this._doN(n,0); });    // render node w/ node object w/o clear-first
        return this; }
    , doNode: function(nid) {    // render node w/ n(ode) id
        // code here... if node found on other than current pane, doPane(),
        //              else do node w/ node object w/ clear-first: this._doN(n,1);
        return this; }
    , _doN: function(n,c) {      // render node w/ n(node) object and c(lear-first, truthy)
        // code here... change style if other than current, remember new current style
        return this; }
    , _initP: function(pid) {    // init - clear w/ style bg and put title
        var p = this.ps[pid];
        if (p.p) { // page (no frame around)
          /* page init code here... if title present, set title bar and title */ }
        else { // pop-up (do frame around)
          /* popup init code here... if title present, set title bar and title */ }
        return this; }
    , _clear: function(x,y,x2,y2,s,b) { // s(tyle index), b(order, truthy) for pop-up
        // code here... consider b(border) and adjust x,y,x2,y2 accordingly
        // remember cs - c(urrent) s(tyle) - for optimiztion
        return this; }
    , getN(nid) { var n;         // get n(ode) by n(ode) id; returns node object n
        // code here...
        return n; }
    , setS(sx) { if (sx !== this.cs) { var s = this.ss[this.cs = sx]; // set stile
        // set style from s code here ... font / font-size / fore / background colors 
        } return this; }
    , init: function(g,d,X,Y,panes,styles) { var p, xo, yo; // p(ane) // init and optimize
        this.g=g, this.d=d, this.X=X; this.Y=Y, this.ps=panes; this.ss=styles;
        for (pid in panes) { p = panes[pid]; // for each pane w/ p(ane) id in panes
          if (p.p = (p["x"] === undefined)) { // page - set x,y,x2,y2 & offset for nodes
            p.x = xo = 0; p.y = 0; p.x2 = this.X-1; p.y2 = this.Y-1; }
          else { // pop-up - set x,y,x2,y2 & offset for nodes pop-up adjusted
            p.x2 = (xo = p.x)+p.w-1; p.y2 = (yo = p.y)+p.h-1; }
          p.nodes.forEach(function(n){                   // for each n(ode) in pane:
              n.p = p; n.x = n.x+xo; n.y = n.y+yo;       // - set pane & adjust x, y      
              n.x2 = n.x+ n.w-1; n.y2 = n.y+n.h-1; }); } // - extend for fill_Rect
        return this; }   
    // other application code here...
    function onInit() {
      // other init code here...
      // get graphics object g and display object d setup
      // other init code here...

    Still a good amount of coding work left, but that's how I would get started.

    The panes and styles definitions use real objects that use more variable space than other constructs, such as arrays... If you see fit, you can make them plain array objects and use the index as the variable name. I do that in my ui stuff. This then changes some of the condition coding, because 'existence' of a value has to be defined differently: length check of array, or if a place holder for the value has to be there to not mess up the indices, a application specific 'undefined' / 'absent' indicator value has to be defined, 0, -1, null, etc. and the test has to consider this 'absent' indicator definition. *Note: X and Y may be retrieved from g(raphics) or d(isplay) object and need then not to be passed... and same applies for either g(raphics) or d(isplay) object.

    If the display has no immediate / transparent update when writing to the Espruino Graphics object - in other words when a .flip() is required - the RENDERER needs to get a .flip() method.

  • in ESP32
    Avatar for allObjects

    It is known that at startup of the wireless connection a power calibration happens that creates that spike. You though still need a supply that can support more than 100% of your average power consumption in order to get your cap charged (quickly enough) for the next spike. ESP8266 already needed such a cap when running on the 3.3V of a PICO - see attached pic (as part of this past conversation.