Getting a new development device to turn on an LED is the classic ‘Hello, World’ application: it shows that the core hardware works. That’s what we’re going to do here. You’ll take your Electric Imp Developer Kit and extend it by adding a small red LED, a 330Ωresistor, a small solder-less breadboard and some wiring. Then you’ll use impCentral™ to enter some code which, when run, will turn the light on: your device will announce its presence with a visual “Hello, World!”
The components you need — small red LED, 330Ωresistor, solder-less breadboard and wire — can be bought from many online electronics stores, or a local supplier if you have one nearby. Google or Bing can help you locate a local supplier or an online one.
This is the circuit you’ll make:
When you have assembled your device, power it up so that it connects to the Internet. If you haven’t configured your Developer Kit for Internet access yet, this section will tell you how.
If you’ve just completed the previous section of this guide, you’ll have impCentral open on your computer. If not, load it up now and sign in using the account log-in details you created earlier.
Locate the Connected Product Product and its Test Hardware Development Device Group that you created in the previous section:
impCentral’s code editor will now appear.
You program all imp-enabled devices using a language called Squirrel. This is very similar to C and its many popular derivatives, such as C++, C# and JavaScript. Our Squirrel Programming Guide details the points where Squirrel diverges from these languages, and covers those areas where it offers unique functionality and methodologies. The Electric Imp Developer Center also includes a full Squirrel reference.
All Squirrel programs will need to use at least some of the imp API — the objects and classes that encapsulate your device, its on-board imp, its Internet connection and the device’s own hardware.
For this example, we’ve written the code for you: just copy and paste it into impCentral’s Device Code pane. You can delete any code already there from the previous section.
To run the code, click the Build and Force Restart button. This tells impCentral to check the code’s syntax and then parcel it up for retrieval by your device. It then tells your device to restart. Every time an imp-enabled device connects to the Internet, it checks if there is new or updated code for it to install. If there is, it replaces any code it already has and runs the new program. For your device, the new code is the program you just pasted into impCentral.
This code will now run on your device. You should not only see the LED in the circuit blinking on and off, but also messages like these in impCentral’s log window:
[Status] Device Disconnecting
[Status] Device Booting; 0.73% program storage used
Though very simple, the code illustrates some key aspects of how imp-enabled devices work. As we noted earlier, Squirrel is an object-oriented language. An object is a software construct that combines data (called ‘properties’) with functions (called ‘methods’) that work with that data. We use our first object in the first non-comment line: hardware, which is an object we use to control device hardware connected to the imp. The hardware object has properties for all of the imp’s pins and standard component-communication buses. We use one of the pin properties here: pin9, which represents pin 9 on the breakout board. We know pin9 is a property of hardware because the two are linked by a period:
hardware.pin9
This says ‘get me the pin9 property of the object hardware’. In fact, pin9 is an object too, with properties and methods of its own. One such method is configure(), used to set up the pin’s functionality. So we could write line six this way:
hardware.pin9.configure(DIGITAL_OUT, 0);
This says ‘perform the method configure() of the object pin9, a property of the object hardware’. Writing the relationship between objects, properties and methods this way is called ‘dot syntax’. The brackets after its name tells the device to call (run) that method. configure() takes a value which tells the device how the pin should operate: as a digital output in this case. A second parameter sets the pin’s initial state. All of the possible values you can pass to configure() are listed in the imp API documentation.
This is an example of the device’s pins being used for General Purpose Input/Output (GPIO). A digital output pin can be set (‘written’) with two possible values, 1 and 0 (sometimes called High and Low, respectively). This applies a voltages to the pin: either 3.3V (High) or 0V (Low). That voltage makes the LED glow.
Lines three and nine introduce Squirrel’s <-
operator, which is used to mark a variable as a global and to assign it an initial value. Later assignments use the standard =
operator, as you can see in line 15. The <-
operator is also used to create and add a entry into a ‘table’, a Squirrel data structure comprising pairs of values and the keys used to identify those values. Why the same operator for both these situations? Because Squirrel stores all global variables in its system table.
We create two globals here: state, which records whether the LED is lit or not, and led, which we use to store a reference to the hardware.pin9 object mentioned above. This not only saves typing, but helps keep it clear what pin 9 is connected to and thus what its role is.
Line 21 is also important. It calls the imp API method imp.wakeup() — which we now know means ‘the method wakeup() of object imp’. This method tells the imp to run the function named in the second parameter when the number of seconds specified in the first parameter have elapsed. In this case, we pass the name of the function we’ve just run, blink().
Remember, blink (without the brackets) is a reference to it, but blink() (with the brackets) is an instruction to execute that function now.
This is how program loops are implemented on imp-based devices. Unlike other embedded systems, imps have their own operating system, impOS™, and when your code comes to an end or a pause, this OS has an opportunity to perform essential system tasks, specifically maintaining contact with the impCloud™ and impCentral. If we had used a classic delay loop, such as
local i = 0;
do {
i++
} while (i < 10000);
we would dominate (‘block’) the imp’s single execution thread and prevent impOS from performing its housekeeping functions for the duration of the loop. This should be avoided.
Using a timer to re-activate the program is an example if the Electric Imp Platform’s event-driven programming methodology: code is run only when triggered to do so by an event. If impOS has done its work, and there’s no user code that needs to be run yet, the device can slow down to conserve power, or even go into a sleep state. We’ll explore this event-driven nature further in the next section.
The code you just entered isn’t interactive: you have no way of controlling the LED while the program is running. We’ll implement code to change the state of the LED remotely, via the Internet, in the next section.