• The code is very simple... what is not in place yet for the engine are the lights in the front and back... (which controlled the piercing eyes when it was part of the human sized robot). The UI is Web retro as well: plain html grey in grey... (suggestion of enhanced look in form of working code are very welcome). Since the robot lived before puck time, wifi was chosen for communication... now, it would probably be BLE... and a nice phone app...

    The electronics is protected form short cuts by the metallic context in a recycled trow-away blister-pack that had packed something else in its previous life. So I could it even call ecologically responsible...

    The power options are:

    • USB 5V Powerbank as used for phones and other USB powered devices, connected to Espruino-Wifi's USB connector.
    • 3 AA Alkaline Cells in a battery holder w/ 3.6...4.5V(as pictured), connected to Espruino-Wifi's GND and VBAT.

    The ULN2003 allows its own - higher 'volted' - supply, which may become an option - either for 6..12V battery or similar supply thru tracks / DC 2-rail. (Currently, the wheels are not isolated against one another (side-ways, so it produces for now a short-cut between the 2-rail DC technique as used. Therefore either the bought stuff runs or the DIY runs...).

    Here the code:

    // robotTrainEngine.js
    // - espruino-wifi EW.1=GND (USB left), 2=VUSB/VBAT, 3=3.3V
    // - SSID:     robot
    // - Password: password
    // - stepper - 28BYJ-48 5V w/ ULN2003APG driver chip (DC) based driver board (DB)
    //   - EW.13,14,15,16 - A4,A5,A6,A7 - green,blue,purple,grey
    //   - DB.1,2,3,4 - IN1,IN2,IN3,IN4 (IN1 left, power right)
    //   - DB.8=DC.8=GND, DB.9=5V=DB.10 - black, white
    //   - DC.9=DB.11 powered 5V w/ DB.11-10 jumper)
    // - power by 5V USB powerbank
    var fastest = 1; // ms per step - (3=safe, 1,2 may be challenging...)
    var lon = false; // logging on
    var pag
    ='<html><head><style>'
    +'td {text-align:center; vertical-align:middle; }'
    +'</style>'
    +'<meta name="viewport" content="width=device-width, initial-scale=1">'
    +'<script>var ifrm;'
    +'function eb(b) { ifrm.src = "/ifrm.html?e=" + b.id; }'
    +'</script>'
    +'</head><body onload="ifrm = document.getElementById(\'ifrm\');">'
    +'<h3>Hello from <i><b>robot</b> train engine!</i></h3>'
    +'<table width="100%"><tr>'
    +'<td><button id="le"  onclick="eb(this)"><br>FRONT LIGHT<br><br></button></td>'
    +'<td><button id="be"  onclick="eb(this)"><br>BOTH LIGHTS<br><br></button></td>'
    +'<td><button id="re"  onclick="eb(this)"><br>BACK LIGHT<br><br></button></td>'
    +'</tr><tr>'
    +'<td><button id="lb"  onclick="eb(this)"><br>FRONT BLINK<br><br></button></td>'
    +'<td><button id="bl"  onclick="eb(this)"><br>BOTH BLINK<br><br></button></td>'
    +'<td><button id="rb"  onclick="eb(this)"><br>BACK BLINK<br><br></button></td>'
    +'</tr></table><table width="100%"><tr>'
    +'<td><button id="s-2" onclick="eb(this)"><br>-f<br><br></butto­n></td>'
    +'<td><button id="s-5" onclick="eb(this)"><br>-m<br><br></butto­n></td>'
    +'<td><button id="s-9" onclick="eb(this)"><br>-s<br><br></butto­n></td>'
    +'<td><button id="s+0" onclick="eb(this)">Engine<br>STOP<br></b­utton></td>'
    +'<td><button id="s+9" onclick="eb(this)"><br>+s<br><br></butto­n></td>'
    +'<td><button id="s+5" onclick="eb(this)"><br>+m<br><br></butto­n></td>'
    +'<td><button id="s+2" onclick="eb(this)"><br>+f<br><br></butto­n></td>'
    +'</tr></table>'
    +'<iframe id="ifrm" width="100%" height="30"></iframe>'
    +'</body></html>'
    ;
    pinMode(LED1,"output");
    pinMode(LED2,"output");
    pinMode(A0,"output");
    pinMode(B0,"output");
    var WebServer = require('WebServer')
      , wifi = require('EspruinoWiFi')
      ;
    function onInit() {
      if (wifi)
        wifi.startAP('robot', {
          authMode:'open', password:'password'
        }, startServer);
      else
        startServer();
    }
    
    function startServer() {
      var ws = new WebServer(
    { port: 80
    , file_system: '/var/www/'
    , memory:
    {'index.html':{'type':'text/html','conte­nt': pag }
    ,'ifrm.html':{'type':'text/html','conten­t':
        '<html><body>e: XX</body></html>' }
    }});
    ws.on('start', function (WebServer) {
      if (lon) console.log('WebServer listening on port ' + WebServer.port); });
    ws.on('request', function (request, response, parsedUrl, WebServer) {
      var e = (parsedUrl.query) ? parsedUrl.query.e : null, v;
      if (lon) console.log('WebServer requested', parsedUrl, response, "e="+e);
      if (e=="le"||e=="be") { v = !digitalRead(LED2);
        digitalWrite(LED2,v); digitalWrite(B0,v); }
      if (e=="re"||e=="be") { v = !digitalRead(LED1);
        digitalWrite(LED1,v); digitalWrite(A0,v); }
      if (e=="lb") { setTimeout(blnkl,50,13); }
      if (e=="bl") { setTimeout(blnkb,50,9); }
      if (e=="rb") { setTimeout(blnkr,50,13); }
      if ((e+" ").substr(0,1)=="s") { var s = Math.round(1 * e.substr(1));
         s=(s<0&&s>-fastest)?-fastest:(s>0&&s<3)?­fastest:s; e="s"+s; r(s); }
      response.dSnd = response.dSnd.replace("XX",e);
    });
    ws.on('error', function (err, WebServer) {
      if (lon) console.log('WebServer error', err); });
    ws.createServer();
    }
    
    function blnkl(c) { var v;
      v = !digitalRead(LED2); digitalWrite(LED2,v); digitalWrite(B0,v);
      if (c) setTimeout(blnkl, 50, c - 1);
    }
    function blnkb(c) { var v;
      v = !digitalRead(LED1); digitalWrite(LED1,v); digitalWrite(A0,v);
      v = !digitalRead(LED2); digitalWrite(LED2,v); digitalWrite(B0,v);
      if (c) setTimeout(blnkb, 50, c - 1);
    }
    function blnkr(c) { var v;
      v = !digitalRead(LED2); digitalWrite(LED2,v); digitalWrite(A0,v);
      if (c) setTimeout(blnkr, 50, c - 1);
    }
    
    // mirror stepper code from http://forum.espruino.com/comments/12055­381/
    // stepper.js
    // stPs stepper pins
    // st   step 0..8
    // stT  step Time in milliseconds [ms]
    // stI  step Interval (from setInterval() and for clearInterval()
    // sts  steps 0001,0011,0010,... pin signals
    // stBW sts - steps Backwards
    // stFW sts - steps Forward
    // dmy  ...because of (cond) ? exprT : exprF needs something to assign to
    var run = false;
    var st = 0;
    var stT = 0;
    var stI = null;
    var sts = null;
    var stSt =  0b0000;
    var stFW = [0b1000,0b1100,0b0100,0b0110,0b0010,0b00­11,0b0001,0b1001];
    var stBW = [0b1001,0b0001,0b0011,0b0010,0b0110,0b01­00,0b1100,0b1000];
    var stPs = [A4,A5,A6,A7];
    
    // setI setInterval(i,stsC) i in [ms] with (optionl) step Change (if not null), 
    // and direction info (string)
    var setI = function(t,stsN,d) {
      if (lon) console.log("t = ",t, d); 
      if (stI) clearInterval(stI);
      if (stsN) sts = stsN;
      run = true;
      stI = setInterval(stp,t);
    };
    
    // stp step
    var stp = function() { digitalWrite(stPs, sts[st = ++st % 8]); };
    
    // _sFW step ForWard
    var _sFW = function(t) {
      if (lon) console.log("FW w/ " + t);
      if (stT > 0) { setI((stT = t),null," ~F");
      } else { if (stT) { st = Math.abs(st - 7); } if (!stI) { st--; } setI((stT = t),stFW," FW"); }
    };
    
    // _sBW step BackWards
    var _sBW = function(t) {
      if (lon) console.log("BW w/ " + t);
      if (stT < 0) { setI(-(stT = t),null," ~B"); 
      } else { if (stT) { st = Math.abs(st - 7); } if (!stI) { st--; } setI(-(stT = t),stBW," BW"); }
    };
    
    // stop
    var stop = function() {
      console.log("stop");
      if (stI) { stI = clearInterval(stI); stI = null; }
      if (lon) console.log(stI);
      run = false;
      digitalWrite(stPs, stSt);
    };
    
    
    // run function - t is stepping interval in [ms]
    var r = function(t) {  
      if (typeof t === "undefined" ) {
        if (stT) {
          if (lon) console.log((stT > 0) ? "F>B" : "B>F");
          r(-stT);
        } else {
          if (lon) console.log("What ?");
        }
      } else { 
        dmy = (t) ? (t>0) ? _sFW(t) : _sBW(t) : stop(); 
      }
    };
    

    1 Attachment

    • robotTrainEngineControlUI.jpg
About

Avatar for allObjects @allObjects started