To ready this code to run on battery, function onInit() {...} (or E.on("init",function(){...});) has to be added with the appropriate code in the function ...body. Furthermore, all stuff printing on the console with print(...); and console.log(...); has to be removed/commented or - when other display/communication device is available - redirected. If not done so, the code execution will hang and you end up with an executed execution (...wat ever...). For the example at hand it is the line containing print("Found card " + card);.
The expected code looks then something like this:
SPI1.setup({sck:B3, miso:B4, mosi:B5 });
var nfc = require("MFRC522").connect(SPI1, B1/*CS PICO*/);
function onInit() {
setInterval(function() {
nfc.findCards(function(card) {
// print("Found card "+card);
card = JSON.stringify(card);
var leds = [LED1,LED2];
if (card=="[147,239,211,128]") digitalWrite(leds,1);
if (card=="[249,192,235,164]") digitalWrite(leds,2);
});
}, 1000);
}
For testing in connected state, upload the code and invoke onInit()from the console (right-hand side of the IDE)... and the code behaves as expected, and is ready for save().
Because you do not (neccessarily) want to save a running timer... (created by setIntervall()) - and for other reason you will see right away, upload it again without the manual kick-off of onInit(), and enter save() in the right-hand side of the IDE.
World is still perfectly in order: the code works. It is ready for test as saved code running on battery. Btw - as found out later - you do not need the battery to test, you can just plug-in USB again - just for power - and - as expected on power-on (sinse recent version(s)), onInit() and (all functions registered with E.on("init",function(){...}); actually get invoked.
Nothing... just nothing. (wiring... all checked again and again... still nothing).
So I reworked the code a bit before pulling in the source of the module. In the example coe, I did not like all the stuff in the callback, so I changed. I added LED1/LED2.set() at the beginning of the onInit() and ....reset() at the end of it to have an simultaneous flash as indication that onInit() is actually called and completed without hick-up:
SPI1.setup({sck:B3, miso:B4, mosi:B5 });
var nfc = require("MFRC522").connect(SPI1, B1/*CS*/);
var cards =
{ "[30,60,213,228]" : function(){ // flash red LED
LED1.set(); setTimeout("LED1.reset()", 100); }
, "[244,171,74,25]" : function(){ // flash green LED
LED2.set(); setTimeout("LED2.reset()", 100); }
},f;
function onInit(){
LED1.set(); LED2.set();
setInterval(function() {
nfc.findCards(function(card) { // print("Card: " + card);
if ((f = cards[JSON.stringify(card)])) { f(); }
});
}, 300);
LED1.reset(); LED2.reset();
}
As you see in lines 3..8, a cards singleton object is created with the JSON stringified card serial arrays as property names and related (assigned) functions as property values. In other words, when property with name matching the card serial is found in cards, its value - the assigned function - is executed ...as found in line 13 in the callback passed to .findCards(card).
Code works connected well, but still does not work completely after saving and running on battery. The simultaneous flashing of both leds indicate that onInit() runs perfectly - from begin to end - but still no functionality else.
Now is the time to find out why it is not working... I proide only a symmary about how to do that in this post:
(1). insert the following two (three) lines at the top / very beginning of your code:
var MFRC522_MODULE = (function(){ var exports = {}; // placed BEFORE module code
return exports; })(); // placed AFTER module code
(3). Replace the line with ...require("MODULENAME").connect(... with this line:
var nfc = MFRC522_MODULE.connect(SPI1, B1/*CS*/);
(4). Upload / run your code... now you can 'investigate' what is going on in the module... by adding console.log(...) / print(...) statements and way more sophisticated: use the debugger introduced in version 1v80 with break point and single step and variable value inspection...
I had not to go that far to see what is really 'broken': having not the .connect() in onInit() just misses the initialization of the device on re-power-up... (m.init(), m being the newly created and returned RFID reader object).
No point to hold on to the unminified module code... and back to the way things can be done with the require(... and .connect(....
How to do you split .require() from .connect() to make the require(... happen and provide a handle of the module, and invoke .connect(... within onInit() to make the device initialization happen on re-power-up? - Easy"
(1). Have a line for the .require(... just in the original spot( line 2) assigning the module to a module-variable - without the connect(... - and define a variable for what connect(... will return later on.
var MFRC522_MODULE = require("MFRC522"), nfc;
(2). Include in onInit(... a line that makes the connect:
var nfc = MFRC522_MODULE.connect(SPI1, B1/*CS PICO*/);
With the above setup, not just Espruino's timers (created with setInterval(... is recreated/initialized, but also the device...
Comment about what about require(... 'should' return: From the very beginning provision of just a '.connect()' by the 'require()' felt strange to me. Familiar with a context where 'require()' return class object(s) and not just a function that bundles everything up, such as the constructor and (extended / dynamic) initialization that can - and as just demonstrated - have to happen at a different time, I'd rather have modules return classes. The additional advantage is that other items than the intialization can be tied to the class - such as constants - so they can be as well used later. @Gordon then made the change that require can also just return an object - 'class object' or singleton with value and function/method properties - as the export object itself. Before, the module had to put it into the export object as a property and the application had to pull it again out of it (export.clazz = XyzClazz; and var XyzClazz = require("XyzClazz").clazz, respective). Since with modules namespaces can be created, a more advance approach has not to be implemented, such as requireJS requirejs.org JavaScript module loader which was first introduced by dojo dojotoolkit.org and has become the standard for dynamic, asynchronous, module loader (AMD) optimized for use in the Web world / broser/client side.
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.
A story in three pieces ( Intro, Getting there..., Final ):
- Getting there...
To ready this code to run on battery,
function onInit() {...}
(orE.on("init",function(){...});
) has to be added with the appropriate code in the function ...body. Furthermore, all stuff printing on the console withprint(...);
andconsole.log(...);
has to be removed/commented or - when other display/communication device is available - redirected. If not done so, the code execution will hang and you end up with an executed execution (...wat ever...). For the example at hand it is the line containingprint("Found card " + card);
.The expected code looks then something like this:
For testing in connected state, upload the code and invoke
onInit()
from the console (right-hand side of the IDE)... and the code behaves as expected, and is ready forsave()
.Because you do not (neccessarily) want to save a running timer... (created by
setIntervall()
) - and for other reason you will see right away, upload it again without the manual kick-off of onInit(), and entersave()
in the right-hand side of the IDE.Save reports in the console:
World is still perfectly in order: the code works. It is ready for test as saved code running on battery. Btw - as found out later - you do not need the battery to test, you can just plug-in USB again - just for power - and - as expected on power-on (sinse recent version(s)),
onInit()
and (all functions registered withE.on("init",function(){...});
actually get invoked.Nothing... just nothing. (wiring... all checked again and again... still nothing).
So I reworked the code a bit before pulling in the source of the module. In the example coe, I did not like all the stuff in the callback, so I changed. I added
LED1/LED2.set()
at the beginning of the onInit() and....reset()
at the end of it to have an simultaneous flash as indication thatonInit()
is actually called and completed without hick-up:As you see in lines
3..8
, acards
singleton object is created with the JSON stringified card serial arrays as property names and related (assigned) functions as property values. In other words, when property with name matching the card serial is found incards
, its value - the assigned function - is executed ...as found in line13
in the callback passed to.findCards(card)
.Code works connected well, but still does not work completely after saving and running on battery. The simultaneous flashing of both leds indicate that
onInit()
runs perfectly - from begin to end - but still no functionality else.Now is the time to find out why it is not working... I proide only a symmary about how to do that in this post:
(1). insert the following two (three) lines at the top / very beginning of your code:
(2). Pull the non minified nodule from the (MFRC522) module repository on the web at http://www.espruino.com/modules/MFRC522.js - replacing MFRC522 with your module name and and place it in between above mentioned two lines of code.
(3). Replace the line with
...require("MODULENAME").connect(...
with this line:(4). Upload / run your code... now you can 'investigate' what is going on in the module... by adding
console.log(...) / print(...)
statements and way more sophisticated: use the debugger introduced in version 1v80 with break point and single step and variable value inspection...I had not to go that far to see what is really 'broken': having not the
.connect()
inonInit()
just misses the initialization of the device on re-power-up... (m.init()
, m being the newly created and returned RFID reader object).No point to hold on to the unminified module code... and back to the way things can be done with the require(... and .connect(....
How to do you split .require() from .connect() to make the require(... happen and provide a handle of the module, and invoke .connect(... within onInit() to make the device initialization happen on re-power-up? - Easy"
(1). Have a line for the
.require(...
just in the original spot( line 2) assigning the module to a module-variable - without the connect(... - and define a variable for what connect(... will return later on.(2). Include in
onInit(...
a line that makes the connect:With the above setup, not just Espruino's timers (created with setInterval(... is recreated/initialized, but also the device...
Comment about what about
require(...
'should' return: From the very beginning provision of just a '.connect()' by the 'require()' felt strange to me. Familiar with a context where 'require()' return class object(s) and not just a function that bundles everything up, such as the constructor and (extended / dynamic) initialization that can - and as just demonstrated - have to happen at a different time, I'd rather have modules return classes. The additional advantage is that other items than the intialization can be tied to the class - such as constants - so they can be as well used later. @Gordon then made the change that require can also just return an object - 'class object' or singleton with value and function/method properties - as the export object itself. Before, the module had to put it into the export object as a property and the application had to pull it again out of it (export.clazz = XyzClazz;
andvar XyzClazz = require("XyzClazz").clazz
, respective). Since with modules namespaces can be created, a more advance approach has not to be implemented, such as requireJS requirejs.org JavaScript module loader which was first introduced by dojo dojotoolkit.org and has become the standard for dynamic, asynchronous, module loader (AMD) optimized for use in the Web world / broser/client side.