Can I make web interface for hardware events?

Posted on
  • just found out that this thread is not meant for this type of conversations.. I don't know how to delete the conversation however..

    Hello everyone...
    I am new to this forum, I hope I can add more value here.

    I have a question regarding a project I am working on.
    I am developing a remote controller using an ESP8266 and interfacing with some simple electronics to my hardware I want to control. I want to interface with the user using a webpage obviously.
    In the beginning I started to do the development using the esplorer tool and lua scripting. But that was very not helpful and can't give me all the features I wanted. Then I found this amazing javascript interpreter that may give me what I need. So I have some questions for you guys.

    I want to control a wall-mounted device that controls my AC. The device has some interfacing buttons (power, fan, tempUp and tempDown).
    I want to make the device controlled by the web interface as well as the device interface itself.
    developing the webpage is easy and I could follow the tutorials easily. But is it possible to update the content of the web interface when a button is clicked? I mean if someone turned on the AC, when I go to the webpage I can see the status as "ON" and if someone changed the temperature I can keep track of how many times he clicked the button and update the temp variable in the controller?

    To sum up, I want to make the variables for the webpage controlled by the hardware as well as the user from the PC.

    Thanks

  • BTW I made all the interfacing hardware and I just need to program my 8266.

  • Hi - are you planning on using the ESP8266 alone, or the ESP8266 and an Espruino board?

    I'm not sure the Espruino firmware that runs on the ESP8266 is stable enough to use properly yet - although it is improving all the time. The one that runs on something like the Espruino Pico is pretty good though.

    Right now, if you want the webpage to update automatically (I guess you mean while it's still open?) you'll want to do something like an AJAX request - basically having the website request another small webpage every few seconds.

    Potentially Websockets are an option in the future, but that's some way off.

  • I am trying to use the 8266 alone. It is ok to do some tests with the current firmware..

    No I don't need to update the page while it is still open. I just need to update the variables and once I refresh the page I see the new values

  • @Gordon
    is it possible to make a function that always loops? and whenever the user request the page it can answer with the page as well?

    The keys I am watching are implemented as keypad, and to monitor what key is pressed I need to watch the driving pins and which pin of the sensing pins has changed.. I have the logic and I can simply convert it to code. But is it possible to make an event listener for these changes and serve the web as well?

  • You go down a different route...

    1. Set all driving pins to same state
    2. Set all sensing pins in state with single watch
    3. Single watch triggers a 'complete' scan to multiplex drive/sense the key
    4. Decide valid key (combination press) and perform action based on key
    5. Set all driving pins to same state
    6. Set all sensing pins in state with single watch on opposite edge
    7. Single watch triggers return to original state (1 and 2).

    If you want to have a repeat on holding a key longer than a configurable time, you need to modify 4 a bit and have a logical loop (timout before you check again with a scan), then move on.

    For sure fall NOT into the arduino trap. (Check out the similarly structured approach I took with the touch screen and its application with a UI...).

  • @allObjects I don't think I get that
    take it easy.. I am still so new to the code (in fact I just found about it today). I don't know how the code structure and how it operates ! Though I am experienced with arduino...
    I don't know how the code loops! And how I can make a routine for my logic.. And whether it is possible to serve a web page and watch a hardware concurrently?!

    So can you please elaborate more?

  • Also I think you didn't get the full idea that I am working on..
    The keypad is wired into different circuit that is using it... I need to monitor this key pad and check which button was pressed... to get the idea please see this pseudocode to get the idea:

    The keypad is implemented this way: pin1 & 2 are the driving lines; pins 10 - 12 are sensing lines
          pin 1    pin 2
            |        |
    pin10--pwr------ |----
            |        |
    pin11--tUp-----tDwn--
            |        |
    pin12--fan-------|----
            |        |
    

    to detect which button is clicked I have to do this way:

    while(true){
          if (pin 1 == low){
            if(pin10 == low)
                pwr is clicked;
            else if(pin 11 == low)
                tUp is clicked;
            else if(pin 11 == low)
                fan is clicked;
          }
          else if (pin 2 == low){
            if(pin 11 == low)
                tDwn is clicked;
          }
    }
    
  • NP... I'll take it easy... you being experienced with Arduino: you will find out Espruino is like vacation and fun!

    But in deed: thinking in Espruino IS (a bit - to say at least) different... loop versus event. And because it is event driven, you can do all the things you plan to do.

    To get you going, I suggest you start with the wall device and the part of it that controls your ac... and for development - and teaching - purposes, assume, you are running it for an initial period on connected via USB... and then later, adding the Web server / wifi onto it so you can control it via internet.

    What kind of key pad are you thinking about? How many key are there? Is it multiplexed or is every key (button) just connected to a pin and can operate independent of each other?

    I assume - for simplicity - you have a two buttons - call them tmpUpBtn and tmpDownBtn hat work as their names imply: pressing them once will increase / decrease the desired temperature. The buttons are plain push buttons that on press connect a pin with ground. I also assume, you are using a Pico, some bread board, etc. But let me know what you have and where you plan to go.

    I will start very simple, and over time the things will evolve into more elaborate consturcts and objects that are easy to handle and pass on to any processing you nead, including creating a response to a http request from your browser over your planned wifi access.

    var dbg = true;
    var log = function() { console.log(arguments.join("")); };
    var tmpTarget = 21; // Celsius
    var tmpTargetMax = 30; 
    var tmpTargetMin = 18;
    var tmpAdj = 0.5;
    var tmpUpBtn = A6; // PIN A6 
    var tmpDownBtn = A5; // PIN A5
    var tmpTargetAdj = function(adj) {
      tmpTarget = (
        ((tmpTarget += adj) > tmpTargetMax)
          ? tmpTargetMax
          : (tmpTarget < tmpTargetMin)
            ? tmpTargetMin
            : tmpTarget
      );
      if (dbg) log("target Temp (tmpTarget): ",tmpTarget);
    };
    var initPins = function()  {
      pinMode(tmpUpBtn,"input_pullup");
      pinMode(tmpDownBtn,"input_pullup");
    };
    var tmpBtnsWatch = function() {
      setWatch( function(){ tmpTargetAdj(+tmpAdj); }, tmpUpBtn
        , {repeat: true, edge:"falling", debounce:50 } );
      setWatch( function(){ tmpTargetAdj(-tmpAdj); }, tmpDownBtn
        , {repeat: true, edge:"falling", debounce:50 } );
    };
    function onInit() {
      console.log("onInit");
      initPins();
      tmpBtnsWatch();
      if (dbg) log("target Temp (tmpTarget): ",tmpTarget);
    }
    

    Wire your buttons, connect Espruino, copy, past and upload this script (attached as AC09.js file), and operate your buttons... - I hope not having made typos.

    Your output should show the (adjusted) tmpTarget.


    1 Attachment

  • ...I thought you were using a multiplexed keypad... but to get as quickly as possible to the point of how Espruino works, I wrote the code with simple button. Btw, you can already use your keypad with the above code. You just wire it accordingly:

    1. connect middle row of pad with ground
    2. connect columns to pins

    (btw, I noticed your nice adjustment in the character graphics. Use the Espruino IDE editor to write these character graphics... becaue it has fixed font... and then copy them into the posting text area.)

  • Using your keypad, you can give code below (as well attached) a shot. In your case, the use of pins for driving and sensing a 3x2 = max 6 buttons and using only 4 of the 6 options while consuming 5 GPIO pins is not the most effective use of anyway already sparce resources... to say the least. You may consider an SPI or I2C driven port extender that uses max 3 GPIO pins for 8, 16, 24, 32,... estended pins...

    // Modue for Drive/Sense Multiplexed Keypad
    //
    // - supports any number of driving pins (rows)
    // - supports any number of sensing pins (cols)
    // - has enable(true/false) for controlled actions
    // - callback called w/ button # 0,1,2,3,... and time
    // - optional:
    //   - start disabled vs. default enabled (eval boolean)
    //   - driving high/watch_rising vs. default low/falling
    //   - custom debounce vs. 200[ms] default (and minimum)
    //
    //
    // Note: momentary-on push switches connect rows w/ cols
    //
    // Example: Keypad controlling AC (pins Espruino Pico)
    //
    // \    sense 
    //   \  pins: pin B1   pin B10
    //     \       |        |        
    // drive \     |        |
    // pins:   \   |        |
    //           \ |        |
    // pin B13 ----0:pwr----1:------ pwr on/off(toggle), N/C
    //             |        |
    // pin B14 ----2:tDwn---3:tUp--- target temp down  , up
    //             |        |
    // pin B15 ----4:fan----5:------ fan on/off(toggle), N/C
    //             |        |
    
    var keypadModule = (function(){
    
      var Keypad = function(dps,sps,cb,e,p,d) {
        this.dps = dps;
        this.sps = sps;
        this.cb = cb;
        this.p = p;
        this.d = d;
        this.e = e;
        this.pl = (p === "up") ? 1 : 0;
        this.np = 0;
        this.ws = null;
      }, p = Keypad.prototype;
    
      p.init = function(_this) {
        this.sps.forEach(function(sp,i){
          pinMode(sp,"input_pull" + _this.p);
        });
        this.drive(this);
        this.watch(this);
      };
      p.drive = function(_this){
        this.dps.forEach(function(dp){
          pinMode(dp,"output");
          digitalWrite(dp,1 - _this.p);
        });
      };
      p.watch = function(_this){
        this.ws = [];
        this.sps.forEach(function(sp,i){ var si = i;
          _this.ws.push( setWatch( 
                function(ep){ _this.scan(si,ep.time); }
              , sp
              , { repeat: false
                , edge: (_this.pl) ? "falling" : "rising"
                , debounce: _this.d } ) );
        });
        this.w = true;
      };
      p.scan = function(si,tp) {
        if (dbg) log(tp - this.np);
        this.ws.forEach(function(w,i){ clearWatch(w); });
        if (this.e && (tp > this.np)) {
          this.dps.forEach(function(dp){ pinMode(dp,"input"); });
          var b = -1, di, dl = this.dps.length, dp;
          var sp = this.sps[si], s = 1 - this.pl;
          for (di = 0; di < dl; di++) { 
            if (dbg) log("scan si: ",si," - di: ", di, " - s: ", s); 
            pinMode(dp = this.dps[di],"output");
            if (digitalRead(sp) === s) {
              b = di * this.sps.length + si; dl = 0;
            } pinMode(dp,"input");
          } this.drive(this); this.watch(this);
          this.np = getTime() + (this.d / 100);
          if (b >= 0) { this.cb(b,tp); } 
        } else { this.watch(this); }
      };
    
      p.enable = function(e) { this.e = !!e; };
    
      return ({connect:function(
         drivePins  // array of drive pins 
        ,sensePins  // array of sense pins;
        ,callback   // callback acceptin button # 0,1,2,...
        ,enabled    // optional, default = true
        ,pull       // optional, default = "up"
        ,debounce   // optional, default = 200, min = 200, [ms]
        ){
          var kp = new Keypad(drivePins,sensePins,callback
            , !enabled
            , ((pull === "up") ? pull : (pull === "down") ? pull : "up")
            , (    (isNaN(debounce)
                || ((debounce * 1) < 200)
              ) ? 200 : debounce * 1) );
           kp.init(kp);
           return kp;
      }});
    })();
    
    var dbg = true;
    var log = function() { console.log(arguments.join("")); };
    
    // var keypad = require("KeypadMDS").connect(
    var keypad = keypadModule.connect(
        [B13,B14,B15], [B1,B10], function(btn,tme){ // 0,1,2,3...
          if (dbg) log("" + tme + ": Button # ",btn," pressed: "
              , [ "pwr toggle","N/C"
                , "temp down" ,"temp up"
                , "fan toggle","N/C"
                ][btn] );
      }); 
    

    1 Attachment

  • Verified (and enhanced) code creates this console output:

     1v80 Copyright 2015 G.Williams
    >echo(0);
    =undefined
    949377234.41604518890
    scan si: 0 - di: 0 - s: 0
    949377234.41604518890: Button # 0 pressed: pwr toggle
    4.81315994262
    scan si: 0 - di: 0 - s: 0
    scan si: 0 - di: 1 - s: 0
    949377241.43724060058: Button # 2 pressed: temp down
    -1.82220757007
    2.95375728607
    scan si: 0 - di: 0 - s: 0
    scan si: 0 - di: 1 - s: 0
    scan si: 0 - di: 2 - s: 0
    949377246.60013008117: Button # 4 pressed: fan toggle
    6.82493495941
    scan si: 0 - di: 0 - s: 0
    scan si: 0 - di: 1 - s: 0
    949377255.63546943664: Button # 2 pressed: temp down
    78.17845439910
    scan si: 1 - di: 0 - s: 0
    scan si: 1 - di: 1 - s: 0
    949377336.02310276031: Button # 3 pressed: temp up
    -1.92238414287
    2.93543815612
    scan si: 1 - di: 0 - s: 0
    949377341.16769027709: Button # 1 pressed: N/C
    0.59415245056
    scan si: 1 - di: 0 - s: 0
    scan si: 1 - di: 1 - s: 0
    scan si: 1 - di: 2 - s: 0
    949377343.96973037719: Button # 5 pressed: N/C
    > 
    

    Noteworthy:

    1. Code needed to discard multiple physical and logical press events within the debounce time: happening while pressing temp down and temp up the first time (tp < np, a negative value, this_press_time < nextallowedpress time) - in lines 11. and 25.

    2. Scanning is optimized - and simplified - and so the result: 'first' (lowest) detected pressed button (number) is used. If multi-pressings are not (yet) detected.

    3. Enhancements to think about are:

      • detection of multiple button presses and optionally allow / disallow
      • press and hold button
      • provide press (button down) and release (button up) information in either same or
        separate callbacks.
      • press-'fumblin' (timely overlapping of presses of multiple/different buttons

    4. You can use any number of driving and sensing pins. Using Espruino directly - driving and sensing pins each using a GPIO pin - is 'expensive'. Using some SPI or I2C driven port yields more pins for other things... but requires this extra chip and wiring...

    5. Was a fun exercise - with some serious challenges as every HI / input (and output) UI has.

    6. Useful for marketed and DIY matrix key pads.

    7. Practically module-ready...

  • 'Final', 'moduled' Keypad code is discussed (and available) in Keypad - bought or DIY - controlled directly by Espruino conversation.

  • Not quite sure if I'm helping here, but in answer to your previous questions:

    Yes, you can do a loop - just setInterval(myLoopFunction, time_in_ms_to_call_fn).

    But you probably shouldn't need that - even though it is the obvious thing to do coming from Arduino.

    Espruino is event based, so once you've set up a webserver with a callback function, that function will be called back when a web page is requested. If you set up a KeyPad, that KeyPad's callback function will get called when a key is pressed too.

    Both things will work together just fine without you having to worry -no loop needed.

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Can I make web interface for hardware events?

Posted by Avatar for MosabWadea @MosabWadea

Actions