Embedded system architecture

There are many ways to configure an embedded system. Many companies offer custom PCs with a range of I/O interfaces, aimed generally at medium to large-scale applications where the costs of these systems are small compared to the overall cost. For smaller systems, these costs become significant, particularly where controllers are needed at a large number of individual locations.

A number of low-cost computer systems exist, many of which were conceived for educational purposes, to teach computing skills to both children and to adults. They provide some or all of the features of a regular PC but at a very much lower cost. Two of the best-known are the Raspberry PI and the Arduino.

Raspberry PI

The Raspberry PI is a “real” computer, with a specification similar to that of smartphones. It costs about £35.

The board is about the size of a credit card, with a 1.4GHz quad-core ARM Cortex CPU, a graphics processor, 1GB RAM, Ethernet, WiFi, Bluetooth, HDMI,  4 USB ports and an SD card socket. You can choose from a number of operating systems to run on it but the usual is a Linux variant called Raspbian. Along the top of the board you can see 2 rows of I/O pins, which are what makes it suitable for use as a controller in an industrial environment as well as in education, for which it was originally designed. Programming is usually done in Python or C/C++ and a wide range of software libraries are available.

Arduino UNO

The Arduino is another small circuit board, but with a low-power microcontroller instead of a ‘proper’ microcomputer. The UNO is one of several variants of the basic design and costs £20 or less.

This board is 68.6 mm × 53.3 mm and has the microcontroller in a socket (so it can be replaced if damaged), a USB socket and 2 rows of I/O connections that include both hardware and software UARTs (serial ports). These connections are brought out as two rows of sockets, one row each side of the board, and a wide range of extension boards (called “shields”) are available to extend the functionality of the unit. Each one plugs into the board below it and carries the pins through to another row of sockets, allowing several shields to be stacked. The Arduino has no operating system and is programmed directly in C. Memory is limited as the device normally only has a single job to do.

PI vs UNO

Superficially it may seem that the PI is a far better choice than the UNO, given the similarity in cost. It’s a much more powerful device with a wider range of I/O. However, it runs Linux, which – like all popular operating systems – was not designed for real-time applications. When you are dealing with real-world systems, accurate timing is often important and it’s not acceptable to have to wait while the operating system switches between multiple tasks, flushes the cache or checks for updates.

The UNO is much better at handling the needs of real-time processing, as the only program that runs is the one you put in yourself. The low cost of these devices means you can give each one a specific job to do without having to consider the interactions between multiple processes. The board has a lower power consumption than the PI and can be run from a 9V battery or a solar charger.

For many applications, a good solution is to combine both technologies. A Raspberry PI makes a good central controller and can even host a web server that allows the system to be accessed from anywhere. Where a display is needed it can be hosted on the PI itself or on any connected browser. The actual low-level I/O can then be delegated to one or more Arduinos connected to the relevant points of the system under control using the I2C bus protocol.

System Configuration

A typical system configuration uses a PC or laptop as a remote management terminal, connected by WiFi to the system being managed, as shown here:

In this configuration the Raspberry PI runs a small web server and connects to up to 128 Arduinos using the I2C bus. The webserver can be connected to by any number of client PCs and will usually run software that authorises specific users to view the system status or control it.

Because the Arduino has rather limited capabilities but is very inexpensive, it’s best to allocate a specific function to a specific Arduino. So for example, a single Arduino might control a group of digital inputs or outputs, an LCD display, an analog sensor or some other specialised hardware. A wide range of devices can be connected and there is a large pool of software already written to make the job simpler.

Software

The software for this system is in 3 parts. The Arduino programs are written in C; they are usually quite short and frequently contain standard library elements. They can mostly be tested in isolation from the rest of the system, using the very efficient development system freely available.

On the Raspberry PI the code is written in Python. The web server is a standard plug-in library module, as is the I2C bus interface. What remains is code to marshall data and pass it in one direction or the other, plus special functions like user validation.

At the PC, a web browser runs the management interface, and this is most likely to be JavaScript code. There are many options available here, depending on factors such as whether the system is to be part of a company website. The logic of the part of the system involving the PI and Arduinos can be written in standard JavaScript.

EasyCoder

We also offer EasyCoder; a high-level English-like scripting language written in JavaScript and designed to write browser code more quickly and easily. EasyCoder enables the logic of your control system to be expressed in terms of the physical entities involved rather than as computer abstractions. There are significant advantages in following this approach, primarily that the code can often be written by domain experts (the people who own and manage the physical system) as well as by experienced JavaScript programmers. This helps speed development, reduces the likelihood of errors and makes the system more maintainable in the longer term.

A demo script

As a simple example, here’s a script that draws an angular position indicator and 3 buttons. The position indicator simulates the continuous motion of a shaft encoder connected to an Arduino, while the buttons react to clicks and in a real environment cause pins on the Arduino to go high or low.

Below is the script that creates the graphic above. It’s actually HTML code, mostly a preformatted section that holds the actual text of the script. At the top is the container that will hold the graphic. In a real system the commands that interface to the Arduino will operate, but in this demo the pointer is controlled by a continous loop.

<div id="ec-container" style="width: 256px; height: 320px; border: 1px solid black;"></div>
 
<pre id="easycoder-script" style="display: none;">
! Embedded demo

  script EmbeddedDemo
  div Container
  svg Stage
  circle Dial
  circle Blob1
  circle Blob2
  rect Button
  line Line
  variable Width
  variable B
  variable A
  variable R
  variable X
  variable Y
  variable Red
  variable Yellow
  variable Green

  attach Container to `ec-container`

  if mobile
  begin
    put the width of Container into Width
  end
  else
  begin
    put 256 into Width
    set style `width` of Container to Width cat `px`
  end

  create Stage in Container

  set the elements of Button to 3

  put 100 into R

  create Dial in Stage
    style `cx:128;cy:120;r:` cat R cat `;fill:ivory;stroke:blue;stroke-width:5`

  create Line in Stage
    style `x1:128;x2:128;y1:120;y2:20;stroke:rgb(100,50,0);stroke-width:3`

  create Blob1 in Stage
    style `cx:128;cy:120;r:10;fill:rgb(100,50,0`

  create Blob2 in Stage
    style `cx:128;cy:20;r:10;fill:rgb(100,50,0`

  index Button to 0
  create Button in Stage
    style `x:40;y:250;width:50;height:50;fill:#800000;stroke:#808000;stroke-width:3`

  index Button to 1
  create Button in Stage
    style `x:103;y:250;width:50;height:50;fill:#808000;stroke:#808000;stroke-width:3`

  index Button to 2
  create Button in Stage
    style `x:166;y:250;width:50;height:50;fill:#008000;stroke:#808000;stroke-width:3`

  clear Red
  clear Yellow
  clear Green

  on click Button
  begin
    put the index of Button into B
    if B is 0
    begin
      if Red
      begin
         set attribute `fill` of Button to `#800000`
         clear Red
      end
      else
      begin
         set attribute `fill` of Button to `#ff0000`
         set Red
      end
    end
    else if B is 1
    begin
      if Yellow
      begin
         set attribute `fill` of Button to `#808000`
         clear Yellow
      end
      else
      begin
         set attribute `fill` of Button to `#ffff00`
         set Yellow
      end
    end
    else if B is 2
    begin
      if Green
      begin
         set attribute `fill` of Button to `#008000`
         clear Green
      end
      else
      begin
         set attribute `fill` of Button to `#00ff00`
         set Green
      end
    end
  end

  wait 3
! This section only works if a real system is connected
! It reads the shaft encoder at regular intervals
  while true
  begin
    wait 30 ticks
    get Position
    multiply Position by 360 giving A
    divide A by 64
    if A is greater than 360 take 360 from A
    if A is less than 0 add 360 to A
    gosub to SetPointer
  end

! This section is just for the demo
! It's a continuous loop that rotates the pointer through 360 degrees
Loop:
  put 0 into A
  while A is less than 360
  begin
    gosub to SetPointer
    wait 1 tick
    add 1 to A
  end
  go to Loop

SetPointer:
  put 128 into X
  add sin A radius R to X
  put 120 into Y
  take cos A radius R from Y
  set attribute `x2` of Line to X
  set attribute `y2` of Line to Y
  move Blob2 to X Y
  return