Iron Library

Hi,

I've been busy lately with the library that I'm hoping will form the foundation of my work with Arduino. It is titled 'Iron', and offers various interfaces for physical computing tasks. The library is based around the concept of devices, encouraging the designer to build code in a fashion that mirrors the physical unit they are creating.

There is a strong theme of performance to the code and, where possible, the lowest-level interfaces are used. For example, direct port manipulation is accomplished with template meta-programming, allowing comfortable labels to be used in place of bit shifts:

// Set pin mode as output. Equivalent to: 'DDRB |= ( 1 << 5 );'
//
setMode< 13, OUTPUT >();

// Set pin 13 high. Equivalent to: 'PORTB |= ( 1 << 5 );'
//
setDigital< 13, HIGH >();

The notion of a device is a cornerstone of the library, gathering variables, communication and inputs & outputs in one place. For example, a camera device might be defined as:

// Define device
//
EN_DEFINE_DEVICE( Camera, "Example camera", 0xB0, 0x7B, 0xA6, 0x43, 5 )

// Define device attributes
//
EN_DEFINE_ATTRIBUTE( Camera, 0, Input, shutter, uint8_t, Low, 2 )
EN_DEFINE_ATTRIBUTE( Camera, 1, Input, zoom, uint16_t, 512, A0 )
EN_DEFINE_ATTRIBUTE( Camera, 2, Internal, model, uint32_t, 2389221, None )
EN_DEFINE_ATTRIBUTE( Camera, 3, Internal, flash, bool, true, None )
EN_DEFINE_ATTRIBUTE( Camera, 4, Output, led, uint8_t, Low, 13 )

Devices are designed to be interacted with from either the CPU or the MCU. Following is an example of how a camera's shutter might be expressed with Arduino:

// Create device, with MCU view
//
Camera< MCU > g_cam;

void setup()
{
// Set up pin modes for any mapped attributes
//
g_cam.setup()
}

void loop()
{
// If shutter button is 'HIGH', begin read of image data
//
if ( g_cam.is< 0, HIGH >() )
{
g_cam.read< Image >( buffer );
}
}

From the CPU side it is possible to scan a bus for devices, selecting units to interface with:

std::vector< Camera< CPU > > devices = scan< Camera >();

for ( auto it = devices.begin(); it != devices.end(); ++it )
{
select( *it ); // Select a device, ready for signals, etc.
deselect( *it ); // Deselect a device
}

There are many more facets yet to explore in the library, but it felt right to release it now. It is licensed under the GPL: you are free to use it as-is, or hack it to pieces as you see fit :slight_smile: Enjoy!

Why not post the library code as an attachment to your post so we don't have to bother with Github?

I don't see any sign of the essential instruction manual.

...R

I'd prefer not to attach code directly as this is a benefit of a repository: centralized access and revision.

There is nothing special in the use of the library, but I will add a "Getting Started" section to the Github page if that helps.

~M

Another syntax to learn. This hardware developer will stick with the IDE for now.

Fair enough. This library is designed to promote a more fluid design of devices, something that is missing with the typical "straight-C" code, IMHO.

In case it is of interest, there are plans to offer a visual programming model as well. This would allow code assembly from a node-based graph, like Fritzing but for software.

~M

engine_develop:
but I will add a "Getting Started" section to the Github page if that helps.

How condescending can you get "if that helps" ...

The worst affliction of Open Source Software is the assumption by developers that documentation is for wimps. If you really think your product is useful write a 20 or 40 page instruction manual. If it is not worth that much trouble to you, how can you expect a user to take any trouble to use it. And without the documentation that's what it will be - trouble.

...R

I'm sorry if you've read tone where there was none. I assure you that I did not mean to condescend, merely offered to add some documentation. I'll be adding some pages to the wiki today to help show setup and usage. Thanks for your suggestion :slight_smile:

~M

Exactly what advantage is there in using this system? The IDE is, after all, easy to use already.

Hi,

Thanks for your questions. The library is not a replacement for the IDE, and can be used in whichever development software you are comfortable with. It can be imported in the same way that you would any of the "standard" libraries (eg. Servo).

The main focus of the library is to provide interfaces that mirror the devices you are creating. Devices can be defined as objects rather than a loose collection of pin numbers and I/O calls. This device paradigm encourages reuse.

Another advantage is the exposure of low-level operations via friendly syntax. For example, port manipulation requires the use of bit shifts and registry names that can be cumbersome to use. Here is a comparison:

PORTB |= ( 1 << 5 ); // pin name by local register group/id

setDigital< 13, HIGH >(); // natural pin name, uses port syntax internally

Looking further afield, there are plans to create a node-based IDE that would work in a similar fashion as Fritzing, but for sketches. This would be optional, of course: you could still use the Arduino IDE.

~M

engine_develop:
setDigital< 13, HIGH >(); // natural pin name, uses port syntax internally

OR
digitalWrite(13, HIGH);

but maybe I have missed something.

...R

Robin2:
OR
digitalWrite(13, HIGH);

but maybe I have missed something.

...R

The setDigital function uses template arguments and are constants. The call generates code similar to writing the port manipulation yourself. Significantly faster than digitalWrite, however the end result is the same. It looks useful.

I use fat16lib's DigitalIO library for this: Fast digital I/O, software I2C, and software SPI libraries - Libraries - Arduino Forum as it includes a nice object orientated approach. Also the template syntax is not needed when using free functions and is closer to the standard Arduino call.

fastDigitalWrite( 13, HIGH );

Hi,

That is correct: templates allow code generation matching the use of registers/ports. This extends to port setup:

DDRB |= ( 1 << 5 );

setMode< 13, OUTPUT >(); // Identical code generated

The device-centered approach takes care of managing inputs/outputs, setting pin modes and keeping variables within a single object. For example:

EN_DEFINE_DEVICE( MyRobot, "My robot", 0xB0, 0x7B, 0xA6, 0x43, 2 )

EN_DEFINE_ATTRIBUTE( MyRobot, 0, Output, motor, uint16_t, 0, A0 )
EN_DEFINE_ATTRIBUTE( MyRobot, 1, Input, bumperButton, uint8_t, 0, 2 )

MyRobot< MCU > g_robot;

void setup()
{
g_robot.setup(); // Sets all pin modes
}

void loop()
{
g_robot.set< 0 >( 1023 ); // Set motor to full-speed

// If bumper button is pressed, reverse motor
//
if ( g_robot.is< 1, HIGH >() )
{
g_robot.set< 0 >( 0 );
}
}

There is still a long way to go with the library (eg. a proper wiki to help with setup/usage), but I was hoping to get some feedback at this stage. I'll post updates as they come.

~M

At the moment - perhaps due to lack of documentation - I cannot understand what your library has to offer in return for the trouble taken to learn it.

I'm afraid my attitude to libraries is coloured by bad experiences with libraries more than once (and not on Arduino) where I found myself spending too much time trying to figure out how the library was supposed to be used. It would actually have been quicker to do the job without the library (it was not even difficult) and it would (IMHO) have been a better service to the community if the authors of libraries had just taken the trouble to write a tutorial about how to do the job without the library. That way they would have expanded the general level of knowledge rather than encapsulating it in a black box.

That said, there are definitely some useful and usable libraries around. I like the Arduino Servo library - but even that gets into trouble with the SoftwareSerial library.

Edit to add ...
In an effort to be more positive, perhaps I am not the target market. Maybe your product is aimed at people who want to get something to work without needing to know ANY of the C/C++ code that regular Arduino users work with. Such people would not have anything to "unlearn". But, if so, extensive documentation is even more essential.

...R

Thanks for your input Robin2. I agree that along with the advent of open-source software there comes a range of quality and support. I do intend to put together some documentation as the library grows. Some of the interfaces are changing often, which makes documentation a moving target, but then it always is :slight_smile:

For example, I've just pushed some changes to the way a Device is defined. The simpler call now looks like:

// Define device
//
EN_DEFINE_DEVICE(
( Camera, "Example camera device", 0xB0, 0x7B, 0xA6, 0x43 ),
(( Input, shutter, digital_t, Low, 2 ))
(( Input, zoom, analog_t, 512, A0 ))
(( Internal, model, uint32_t, 2389221, None ))
(( Internal, flash, bool, true, None ))
(( Output, led, digital_t, Low, 13 ))
)

I would agree that with some libraries the functionality is more along the lines of convenience, offering little incentive to use them. I'm hoping that Iron acts as a more capable layer, allowing more flexible system design.

Once the graphical IDE is in place many of these concepts will become stronger, offering a graph-based structure (see attached for an example). I hope will lead to a new way of designing hardware code. High hopes, I know... we'll see :slight_smile:

~M

engine_develop:
Some of the interfaces are changing often, which makes documentation a moving target, but then it always is :slight_smile:

I think if I was embarking on a complex project like this I would write the documentation first and ensure the code matches it, rather than have the documentation trailing in arrears. I find writing down the description is very good for clearing my thought process.

Also, may I suggest you write the documentation so it can be understood by the little old lady who maintains the flowers in the local church.

Have fun ...

...R

I agree that documentation can often serve as a useul blueprint. In terms of process I tend to start with small unit tests that describe the core functionality, documenting once the interfaces are settled. I will likely use both Doxygen and a wiki to offer usage and examples.

As an update, I've been looking into the graph IDE lately, finding some good open-source options for the GUI. Attached is a snapshot of a quick layout. The idea would be to represent various functions as nodes, allowing you to plug together a graph that describes your device's logic. I'm planning on compiling the graph and uploading to the MCU, similar to the official IDE.

~M

graph.png

Why should anyone bother with the complex template syntax, when digitalWriteFast() provides the exact same optimization using the same familiar syntax as Arduino?

http://forum.arduino.cc/index.php?topic=46896.0

There is much more functionality planned for Iron than the set/get pin functions, much of which will be seen once the graphing interface is complete. Here is a list of features intended for the IDE:

-Node-based sketch design, allowing functions to be plugged together to form larger, reusable components.
-Node API allowing user-defined functions to be loaded and shared.
-Compilation and upload of translated graph to MCU. Option to export graph to code, ready for use in other IDEs.
-MCU pin diagram, allowing graphical selection of pins to read/write, mode setup.
-Bus interface diagram, with drag and drop operations for serial/I2C/SPI interfaces.

The main focus of the library, and IDE, is to promote an object-based approach to system design. I'm hoping this will offer an exciting alternative to designers.

~M

engine_develop,

I really like your object-oriented approach to defining system parts. However, it would be even better to make the syntax similar to that of the Arduino IDE. That way, it will be easier to learn and more enjoyable for newcomers. Just to let you know, though, you are headed in the right direction with the approach.

@engine_develop

Great stuff! Have you looked at handling variability for a larger number of boards and what happens when scaling to larger systems?

I have recently been playing around with a dependency driven execution model inspired by UML Capsules and Connectors. You can find it in Cosa; https://github.com/mikaelpatel/Cosa/tree/master/cores/cosa/Cosa/UML. There are some example sketches with advanced timing, probing, etc, just to show how easy this becomes in a data dependency driven OOP in C++. https://github.com/mikaelpatel/Cosa/tree/master/examples/UML

Keep up the great work!

Cheers.