Skip to main content

Squirrel Application Development Guidelines

Key Techniques To Help You Create Successful Electric Imp Apps

Whether you are embarking on developing your first Electric Imp application, or you are working on the latest of many Squirrel development projects, the following guidelines will help you improve the efficiency and performance of your application, and make it easier to enhance going forward. These guidelines embody the key techniques and methodologies you should employ in order to develop and maintain a successful Electric Imp application.

1. Write Efficient Squirrel

Squirrel is an easy language to learn, but only a full understanding of its operational idiosyncrasies will allow you to optimize your code fully. For example, using blobs rather than arrays to store byte data, arrays rather than tables or tables rather than class instances can, in the right circumstances, reduce your application’s memory footprint and improve its performance. So can choosing how you define ‘global’ variables, and making good use of constants. For a full guide to optimizing your code for efficiency, please see ‘Writing Efficient Squirrel’.

See also ‘Optimizing Squirrel for Speed’

2. Write Clear, Maintainable Squirrel

Electric Imp’s Squirrel Style Guide derives from our many person-years writing Squirrel code that’s easy to read, understand and maintain. All of our sample code and our code libraries adopt the best practices detailed in the guide, and we recommend them for your application code too.

3. Learn What Happens When An imp’s Connection State Changes

Your product’s connectivity is mediated by its on-board imp, so it’s essential to understand how the imp manages its connection to the impCloud™ and how it responds to connection-state changes. These can arise not only from external factors, such as an Internet outage, but also from internal factors, such as errors in your Squirrel code or unexpected values read in from a peripheral. Or you may deliberately choose to go offline because you can conserve power that way. The Network State Diagram details all such circumstances and how the imp responds in each case.

Tip Use libraries such as ConnectionManager and MessageManager to handle connectivity for you.

4. Select Your imp’s Connection Mode Carefully

impOS™ supports two operational modes: ‘simple’, where the imp deals with connectivity loss by hibernating for a fixed period and then attempting to reconnect, and ‘advanced’, in which the imp continues to operate and leaves you, the application designer, to manage the connection. Understanding these two modes is essential to the successful operation of your application. A basic device that doesn’t interact with end-users, or one that is battery powered, may not need to continue operating during connectivity outages, so might adopt the simple mode. However, an imp controlling a continuously updated display should not sleep in these circumstances — select advanced mode in this case. These modes have a direct effect on how the imp behaves across connection-state changed (see above).

Tip Use the imp API method server.setsendtimeoutpolicy() to select the imp’s mode: SUSPEND_ON_ERROR for simple mode, RETURN_ON_ERROR for advanced.

See also ‘How To Run An imp-enabled Device Offline’

5. Take full Advantage Of The Agent

When designing IoT products, it’s easy to focus on the device — the ‘thing’ — but never underestimate the value of the imp-enabled device’s online companion, the agent. Agents have more memory and greater processing power than imp modules, so can be given number crunching tasks to perform: if the device-sent data, or incoming information, needs to be pre-processed in some way, for example. Each agent essentially operates as a web server, so can be written to serve a fully interactive device-control interface in any web browser. That’s in addition to their ability to interact securely with online services on the device’s behalf and shielding it from Internet-routed attacks.

Tip With Electric Imp’s Rocky library, you can easily create powerful agent-hosted web APIs for data retrieval and transmission.

See also ‘How To Use An Agent As A Simple Web UI Server’

6. Ensure Your Code Plays Well With impOS

The imp’s Squirrel application code and impOS execute in a single thread, so tight loops will prevent Squirrel ceding the CPU to impOS. This in turn prevents impOS from performing important tasks such as maintaining connectivity with the agent and managing message flow. Rather than loop using traditional structures such as while(true) { . . . }, use timers that re-call a function embodying the loop code. This not only ensures impOS gets the resources it requires — between the completion of the first pass through the loop and the timer-triggered second pass — but also employs a key and commonly used Electric Imp coding methodology: asynchronous, event-driven programming.

Tip Timers are set using the imp API method imp.wakeup()

See also ‘How To Write imp Loop Structures’ and ‘Event-Driven Programming’

7. Don’t Reinvent The Wheel — Re-Use Library Code

Many operations are common to many or all applications, and Electric Imp is dedicated to providing customers with free-to-use, open source libraries that manage these operations. This includes supporting a diverse array of cloud services; providing middleware to manage core imp tasks, such as device-agent communications, Internet accessible RESTful APIs and device connectivity state management; and drivers for many common hardware components and interconnects, including 1-Wire, Modbus-RTU, environmental sensors, display units, near-field communications and much more. Electric Imp’s selection of libraries is already extensive and we release new integrations, utilities and drivers all the time.

See also cloud services integrations, application programming utilities and hardware drivers

8. Keep The Pin Mux Close By When You’re Working With Peripherals

Each imp module supports many peripherals buses and GPIO, but the imp API objects through which these features are accessed in Squirrel depend on the type of imp you are working with. And not all hardware features are supported on all imps: the imp005 has no ADC or DAC support, for example. Use the Pin Mux pages for each imp to check your chosen imp’s pin and bus nomenclature, and capabilities, especially if you are adapting a design based on a different imp, or you have previously worked with another imp.

Tip Use the imp API methods and imp.environment() to determine during runtime what imp your code is running on and adapt your device initialization routines accordingly.

9. Don’t Mistake ‘Embedded’ For ‘Limited’

Depending on the imp module you have chosen, between 120KB and 1MB of RAM are available for applications. RAM utilization is, of course, heavily dependent on your application, but our experience of working with our customers is that applications RAM is not a limiting factor, and memory related issues are usually a sign of sub-optimal application architectures.

The imp005 executes Squirrel code at the rate of approximately 500,000 lines per second. The imp003 and imp004m will execute approximately half and a third of that rate, respectively. Again, customer experience suggests this is no limitation to delivering highly responsive applications. Particularly heavyweight operations can be moved to the agent, which has much more compute power available to it, but generally this is done more in order to conserve device power than for performance reasons.

Finally, each imp module has access to 256KB of application storage space in Flash. This can hold around 10,000 lines of code (comments are removed from the executable code) and typically more. Again, this is no limit to the delivery of complex, feature-rich applications.

You can view a comparative listing of each imp module’s features here.

10. Know Your Power Story When You’re Working With Batteries

Most imps can operate on very low power — the imp005 is an exception — so are ideally suited to run on battery power. The imp API methods server.disconnect() causes your device not only to disconnect from the server but also to power down WiFi. As such it can be used to reduce power consumption while the device is operating, but putting the device into deep sleep, using imp.deepsleepfor() or imp.deepsleepuntil(), when it doesn’t need to operate reduces the power consumption even further: from hundreds of milliwatts to just six microwatts. Careful understanding of your application’s duty cycle — knowing how little time it needs to awake to take readings; knowing readings can be bundled and sent together, not a reading at a time — can extend your device’s battery life by many months.

See also ‘Designing Battery Powered Applications’

11. Adopt A Unit Testing Methodology

Electric Imp’s impt is a JavaScript tool which helps you write and run ‘unit tests’ to verify that your application’s functions (‘units’) work as expected: for any given a set of inputs, does each function return the proper values and gracefully handle failures? Unit testing provides you with a way of checking that your application’s components can handle unexpected values (for example, that returned by a UART read when there is nothing connected) and to ensure changes you make don’t cause already working devices to crash.

12. Do Joined-Up Debugging

The primary means you can use to debug your application are the imp API methods server.log() and server.error(), but these are not the only tools available to you — and will not help you if you are testing your application’s behavior while disconnected (calling either method will connect the imp if it is deliberately disconnected). imps provide multiple serial buses, allowing you to connect your product to a dedicated logging device with its own UART facilities (such as a Raspberry Pi computer or Arduino board) or to a desktop computer via a 3.3V FTDI serial-to-USB converter.

See also ‘Debugging Disconnected Applications’