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></button></td>'
+'<td><button id="s-5" onclick="eb(this)"><br>-m<br><br></button></td>'
+'<td><button id="s-9" onclick="eb(this)"><br>-s<br><br></button></td>'
+'<td><button id="s+0" onclick="eb(this)">Engine<br>STOP<br></button></td>'
+'<td><button id="s+9" onclick="eb(this)"><br>+s<br><br></button></td>'
+'<td><button id="s+5" onclick="eb(this)"><br>+m<br><br></button></td>'
+'<td><button id="s+2" onclick="eb(this)"><br>+f<br><br></button></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','content': pag }
,'ifrm.html':{'type':'text/html','content':
'<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/12055381/
// 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,0b0011,0b0001,0b1001];
var stBW = [0b1001,0b0001,0b0011,0b0010,0b0110,0b0100,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();
}
};
Espruino is a JavaScript interpreter for low-power Microcontrollers. This site is both a support community for Espruino and a place to share what you are working on.
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:
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:
1 Attachment