Comments (7)
Update: I tried renaming the init
function and still get the same error. This is very strange.
from lunijs.
Appears the issue was with the port. I changed as follows and it doesn't repeat the init call. However it doesn't progress past the "open" step of the sequence. Here is the updated DemoHelloAPI.js example, which gets the port automatically. I also commented out the option to skipCapabilities because I found it was not necessary to skip.
// This module exercises the high-level API interface to a DDHello
// Luni device driver running on a remote Arduino under Firmata.
//
// This program is strict-mode throughout.
//
// Doug Johnson, May 2016
const log4js = require("log4js");
const path = require("path");
const thisModule = path.basename(module.filename,".js");
const log = log4js.getLogger(thisModule);
log.setLevel('TRACE');
const API = require("../lib/HelloAPI");
const RDD = API.RDD;
const Sequencer = require("../lib/Sequencer").Sequencer;
const firmata = require("firmata");
const unitName = "Hello:0";
const exitAtEnd = false;
let firmataBoard;
let proxyRDD;
let api;
let seq;
let handle;
// Set up
const init = () => {
firmata.Board.requestPort(function(error, port) {
if (error) {
log.debug(error);
return;
}
//let opts = {skipCapabilities: true};
let opts = {};
firmataBoard = new firmata.Board(port.comName, opts, () => {
log.debug(`Board is ready.`);
proxyRDD = new RDD.RemoteDeviceDriver({board: firmataBoard});
log.debug(`RemoteDeviceDriver is ready.`);
api = new API.HelloAPI({driver : proxyRDD});
log.debug(`HelloAPI is created.`);
seq = new Sequencer(api,["open", "read", "write", "close", "read-continuous"]);
log.debug(`Sequencer is created.`);
seq.on("error", (apiError) => {
log.error(`Error ${RDD.SC[apiError.status].sym} (${apiError.status}) ${RDD.SC[apiError.status].msg}.`);
});
seq.on("done", (apiResult) => {
if (exitAtEnd) {
log.info(`Goodbye.`);
firmataBoard.transport.close();
} else {
log.info(`Steps completed.`);
}
}
);
seq.start(step);
});
});
};
// Everything has been opened and we have a handle by the time this step
// sequence is started. Assuming that each of the following step functions
// will result in one of the events captured above, we will progress through
// the following async steps in order.
let step = [
(apiResult) => {
log.info(`Begin step processing.`);
api.open(unitName,RDD.DAF.FORCE,0);
},
(apiResult) => {
log.info(`Opened ${apiResult.unitName} with handle ${apiResult.handle}.`);
handle = apiResult.handle;
api.getGreeting(handle);
},
(apiResult) => {
log.info(`${unitName} says ${apiResult.data}`);
api.getGreeting(handle);
},
(apiResult) => {
log.info(`${unitName} says ${apiResult.data}`);
api.setGreeting(handle, "blah, blah");
},
(apiResult) => {
log.info(`New greeting has been set.`);
api.getGreeting(handle);
},
(apiResult) => {
log.info(`${unitName} says ${apiResult.data}`);
api.setIntervals(handle,null,1000);
},
(apiResult) => {
log.info(`New intervals have been set.`);
api.getContinuousGreeting(handle);
},
(apiResult) => {
log.info(`Continuous greeting started.`);
if (exitAtEnd) {
api.close(handle);
} else {
api.on("read-continuous", (apiResult) => {
log.info(`${unitName} says ${apiResult.data}`);
});
}
},
(apiResult) => {
if (apiResult.eventType === "close") {
log.info(`Closed handle ${apiResult.handle}. Goodbye.`);
firmataBoard.transport.close();
}
}
];
// Start the engine running
log.info(`Program ${thisModule} is running.`);
init();
from lunijs.
Okay it is working now. I had to remove additional Firmata features and run on a Leonardo rather than Uno (Leonard has an additional 500 bytes of SRAM). It appears that even when the compiler reports a few hundred bytes of available RAM, that memory is actually running out and the application running on the board is freezing. I assume you may be using a lot of dynamic memory allocation in your Luni lib stack? If so I'd recommend changing to static allocation wherever possible so the available memory is more realistic. Use fixed static buffers for Strings and reuse them rather than dynamically allocating, etc.
from lunijs.
To provide additional context on the amount of memory being consumed at run-time, if I compile and upload to an Arduino Uno (excluding the following Firmata features in ConfigurableFirmataDeviceDriver.ino: Servo, I2C, OneWire, Stepper, Serial, Scheduler), the compiler reports the board has 701 bytes of dynamic memory available. If I run DemoHelloAPI.js, memory on the board appears to run out just after the handle is opened. Here's the console output:
[2016-07-09 14:55:33.581] [INFO] DemoHelloAPI - Program DemoHelloAPI is running.
[2016-07-09 14:55:38.144] [DEBUG] DemoHelloAPI - Board is ready.
[2016-07-09 14:55:38.146] [DEBUG] DemoHelloAPI - RemoteDeviceDriver is ready.
[2016-07-09 14:55:38.146] [DEBUG] DemoHelloAPI - HelloAPI is created.
[2016-07-09 14:55:38.147] [DEBUG] DemoHelloAPI - Sequencer is created.
[2016-07-09 14:55:38.147] [INFO] DemoHelloAPI - Begin step processing.
[2016-07-09 14:55:38.147] [TRACE] DeviceAPI - open(Hello:0)
[2016-07-09 14:55:38.162] [TRACE] DeviceAPI - proxy.open(Hello:0) callback invoked for API open().
[2016-07-09 14:55:38.162] [INFO] DemoHelloAPI - Opened Hello:0 with handle 256.
// board appears to be frozen at this point... likely ran out of memory
With a Leonardo, because of the extra 500 bytes of memory I can get past that point and program execution continues successfully. There is either way to much dynamic memory consumed (for a microcontroller at least) or there is a leak somewhere.
from lunijs.
Jeff:
Yes, memory is an issue, and I used dynamic allocation more than is probably a good idea in the long term. I’m hoping to be able to take the time to comb the code for specific issues.
One thing is the way I built the read/write continuous functions. I reserve space in each LogicalUnitInfo object for two complete commands to be repeated. This takes a fair amount of memory.
Another issue is the memory used by compiled but removed modules. When I took those out of the picture entirely, I saved something like 260 bytes of SRAM with no loss of functionality.
There are some things that can go in EEPROM, but at least at first glance, it didn’t look like it would save as much SRAM as I’d hoped.
I am a believer in the role of ‘don’t do premature optimization', so I haven’t worried too much about the issue as long as I could configure something that would run. If the functionality seems useful to you and others, then it’ll definitely be time for a thorough memory improvement review.
The UNO has 2 KB (ATmega328P), and the Leonardo has 2.5 KB (ATmega32u4), so I agree that the extra memory helps. However, it’s only 500 bytes difference, not 500 K (I wish!)
As you say, memory is an issue, and I just got an Uno a few weeks ago specifically to test this configuration. However, my main interest is in being able to write code that handles more functionality on the Arduino side and that does not cause more Firmata protocol pollution as time goes on, so I’ve kind of deferred worrying about low memory devices too much and focussed on the interfaces and capabilities for now.
Thanks for your testing and analysis, it’s much appreciated!
Doug
On Jul 9, 2016, at 3:00 PM, Jeff Hoefs [email protected] wrote:
To provide additional context on the amount of memory being consumed at run-time, if I compile and upload to an Arduino Uno (excluding the following Firmata features in ConfigurableFirmataDeviceDriver.ino: Servo, I2C, OneWire, Stepper, Serial, Scheduler), the compiler reports the board has 701 bytes of dynamic memory available. If I run DemoHelloAPI.js, memory on the board appears to run out just after the handle is opened. Here's the console output:
[2016-07-09 14:55:33.581] [INFO] DemoHelloAPI - Program DemoHelloAPI is running.
[2016-07-09 14:55:38.144] [DEBUG] DemoHelloAPI - Board is ready.
[2016-07-09 14:55:38.146] [DEBUG] DemoHelloAPI - RemoteDeviceDriver is ready.
[2016-07-09 14:55:38.146] [DEBUG] DemoHelloAPI - HelloAPI is created.
[2016-07-09 14:55:38.147] [DEBUG] DemoHelloAPI - Sequencer is created.
[2016-07-09 14:55:38.147] [INFO] DemoHelloAPI - Begin step processing.
[2016-07-09 14:55:38.147] [TRACE] DeviceAPI - open(Hello:0)
[2016-07-09 14:55:38.162] [TRACE] DeviceAPI - proxy.open(Hello:0) callback invoked for API open().
[2016-07-09 14:55:38.162] [INFO] DemoHelloAPI - Opened Hello:0 with handle 256.// board appears to be frozen at this point... likely ran out of memory
With a Leonardo, because of the extra 500k of memory I can get past that point and program execution continues successfully.—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub #2 (comment), or mute the thread https://github.com/notifications/unsubscribe/ABONrNo9QQccfxMFYyjhU29MQp5SRc6Gks5qUBoPgaJpZM4JIsuh.
from lunijs.
My ideal minimum memory target for anything included in ConfigurableFirmata is that it should be able to run on an Arduino Uno (still the most popular Arduino board by far) with the following Firmata features included (basically the same as StandardFirmata): DigitalInputFirmata, DigitalOutputFirmata, AnalogInputFirmata, AnalogOutputFirmata, ServoFirmata, I2CFirmata, FirmataExt.
from lunijs.
Sounds good. I did most of the early development with everything there except I2C and Servo. Will work on getting to your list.
On Jul 9, 2016, at 5:47 PM, Jeff Hoefs [email protected] wrote:
My ideal minimum memory target for anything included in ConfigurableFirmata is that it should be able to run on an Arduino Uno (still the most popular Arduino board by far) with the following Firmata features included (basically the same as StandardFirmata): DigitalInputFirmata, DigitalOutputFirmata, AnalogInputFirmata, AnalogOutputFirmata, ServoFirmata, I2CFirmata, FirmataExt.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or mute the thread.
from lunijs.
Related Issues (2)
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from lunijs.