Versatile ARM Cortex-M3 system for IoT and M2M (Part I)

By on March 5, 2015

Web site:

Project Summary:

Amptek Technologies has developed a versatile ARM Cortex-M3 single board computer targeted for IoT and M2M applications. The credit-card-sized board, called iCon, comes standard with 802.11b/g/n, Bluetooth 4.0, USB 2.0, CAN, RS-485, and lots of user configurable I/O's for expansion. The system runs on uClinux - a port of Linux for embedded systems with no memory management unit (MMU). In Part I of this 2-part series, we will show you how to use iCon to control a robotic arm with a mobile phone or a tablet. In Part 2, we will show you how to use the CAN-bus to read the tachometer of a 2008 Mitsubishi Outlander.

Full Project:

The robotic arm used in this project is the OWI-535 Robotic Arm Edge.  The arm uses five separated DC motors for its various joint movement.  In addition, there is a LED light on the gripper which can be turned on and off.  A wired controller is used to feed a positive or a negative voltage to each DC motor in order to alter its rotation direction.  In this project, the wired controller is replaced with a relay circuit attached to an iCon.  A mobile phone or a tablet then communicates with the iCon through Wi-Fi and controls the robotic arm wirelessly.

For simplicity reason, we use two SPDT relays to control each DC motor.  The first relay toggles between a positive voltage and a negative voltage.  In this case, the voltage comes from four D-size batteries hidden in the base of the robotic arm.  The second relay toggles between the output from the first relay and an open circuit.  This is to control the start and stop of each movement.  Each relay is controlled by a GPIO pin on the iCon, hence a total of ten GPIO pins for the five DC motors.  An additional relay is installed to control the LED light.

There are total of 64 user configurable GPIO pins at the back of the iCon.  The factory default setting is shown in the iCon Expansion Port Pinout diagram here.  In this project, GPIO0 through GPIO9 are used for controlling the five DC motors.  ADC0 is reconfigured as a GPIO to control the LED light.

To facilitate the remote control over the Wi-Fi network, the iCon firmware package includes a Boa web server.

The iCon firmware package also includes a DDNS client.  Future project could involve creating a DDNS server and control the robotic arm outside the local Wi-Fi network.

Circuit diagram:

The schematic for the DC Motor Control and the Light Control are shown here.


Bill of Materials:

SPDT Relay G5V-1-DC5
Diode 1N4001
Transistor 2N2222A
Resistor 2.2K ohm


By no means these are the only parts suitable for this project.  Any equivalent parts will do the job.


Source code for the iCon can be downloaded directly from

Software & Code Snippets:

In this section, we will show how to control the robotic arm.

The iCon Robotic Arm Demo is wirelessly controlled via a Boa web server. To get a better understanding of how the the robotic arm works, we must first understand the file and folder structure.  For the sake of simplicity we will only focus on two functions of the robotic arm:

  1. Controlling the gripper motor,
  2. Toggling the LED light.

All the other motors are controlled using similar functions.

The gripper code uses standard Linux GPIO toggling to manipulate the motor. Exporting the correct GPIO’s into the kernel is important to ensure the system functions properly.

For example if you wanted to use P[5,10] ( port 5, pin 10)  of the iCon board, the GPIO that you would have to export in your Linux code would be 170. This is done determined by the following formula:

(32 * PORT) + PIN = GPIO

Unlike the LED light which only requires one GPIO to be on or off,  the arm motor requires two GPIO’s. One GPIO to controls the direction of the motor, either forward or backward, and one GPIO to controls the power being on and off.

Before we can start toggling with the GPIO’s we should check and see whether the correct board pins are initialized.

The iomux.c located in the /linux/arch/arm/mach-lpc178x directory of the iCon source code contains all the GPIO configurations for the icon board. There you can add/remove or configure existing GPIO’s depending on your usage.

Two simple cgi examples on how to control the gripper to close and how to turn the LED on is listed below .







Stopping the LED & motors or reversing the direction of the gripper is a matter of changing the GPIO values and creating a new file.

So for instance to be able to control the LED to turn on and off, two separate files would be needed. On the other hand, controlling a motor such as the gripper would require 3 files . One file to stop the gripper from moving in either direction, one to open the gripper and one to close the gripper. This is because when using a button/touch click on a web browser, it encompasses 2 actions: A press and release action. We need a stop application to reset the values of the gripper when no ones touching it and we need an action application to move the gripper in the appropriate direction.

Once you have written your c code to control the motor, you must then compile the code as a cgi file.  This way we can link it to our Boa web server appropriately. Below is a sample MAKEFILE that you can use to add your robotic arm applications with the proper FLAGS. Be sure to adjust the directories to fit your build.

CFLAGS +=-I/home/amptek/Documents/linux-cortexm-1.11.0/A2F/uclibc_output/usr/include -I/home/amptek/Documents/linux-cortexm-1.11.0/linux/include -mthumb -mcpu=cortex-m3 -Os -g -Wall
LDFLAGS += -mthumb -mcpu=cortex-m3 -Wl,-elf2flt=-s -Wl,-elf2flt=16384 -static

all: stop.cgi light.cgi gripper.cgi 

#cgi functions 
light.cgi: light.c libcgic.a
	$(CC) $(CFLAGS) $(LDFLAGS) -O2 light.c -o light.cgi ${LIBS}
stop.cgi: stop.c libcgic.a
	$(CC) $(CFLAGS) $(LDFLAGS) -O2 stop.c -o stop.cgi ${LIBS}

#gripper Motion
gripper.cgi: gripper.c 
	$(CC) $(CFLAGS) $(LDFLAGS) -O2 gripper.c -o gripper.cgi ${LIBS}

	rm -f *.o *.a stop.cgi gripper_stop.cgi light.cgi
	rm -r $(DESTDIR)

Now that we have an understanding of creating an application to move the robotic arm we need to tell our BOA web server how to use it.

The index.html file contains the boa-webserver interface code that will allow you to physically move the robotic arm through a webpage. For our purposes our index.html file is located in the /A2F/ boa-0.94.14rc21/examples folder of the iCon source code.

Here we will put our html code for our web server to access the applications we made earlier.

Sample index.html

<div style="position: relative; left: 300px; top: 100px;">
<img id="notouch" src="background.jpg" style="position: absolute; top:0px; left:0; z-index:1;"> 
<img id="button" src="arrow-up.jpg" style="position: absolute; top:30px; left:80px; z-index:2;"> 
<img id="button5" src="arrow-down.jpg" style="position: absolute; top:100px; left:80px; z-index:7;">
<button style="position: absolute; top:210px; left:340px; z-index:11;" name="j7" type="button" onclick="stop()">off</button>  
<button style="position: absolute; top:210px; left:300px; z-index:11;" name="j8" type="button" onclick="light()">on</button> 
<script type="text/javascript">

document.getElementById("button").addEventListener("touchstart", touchHandler, false);
document.getElementById("button").addEventListener("touchmove", touchHandler, false);
document.getElementById("button").addEventListener("touchend", touchHandler, false);

document.getElementById("button5").addEventListener("touchstart", touchHandler5, false);
document.getElementById("button5").addEventListener("touchmove", touchHandler5, false);
document.getElementById("button5").addEventListener("touchend", touchHandler5, false);

document.getElementById("notouch").addEventListener("touchstart", touchHandlerb, false);
document.getElementById("notouch").addEventListener("touchmove", touchHandlerb, false);
document.getElementById("notouch").addEventListener("touchend", touchHandlerb, false);

function touchHandlerb(e) {
  if (e.type == "touchstart") {
  } else if (e.type == "touchend" || e.type == "touchcancel") {

function light()

function stop()

/* Gripper up arrow*/
function touchHandler(e) {
  if (e.type == "touchstart") {
  } else if (e.type == "touchend" || e.type == "touchcancel") {
/* Gripper down arrow*/
function touchHandler5(e) {
  if (e.type == "touchstart") {
  } else if (e.type == "touchend" || e.type == "touchcancel") {



The last thing we need to do is put all our files together in the kernel image before we rebuild the kernel.  The Networking.initramfs located in the /projects/networking folder of the iCon source code contains all the files that will be built into the kernal uImage. To be able to use our Boa web server and application code we must make sure that all the directories are imported correctly into this file. Below is a  portion view of the entire file that we require to have a running Boa web server.

dir /etc/boa 0777 0 0
file /etc/boa/boa.conf ${INSTALL_ROOT}/A2F/boa-0.94.14rc21/examples/boa.conf 777 0 0
file /usr/lib/boa ${INSTALL_ROOT}/A2F/boa-0.94.14rc21/src/boa 777 0 0
file /usr/sbin/boa ${INSTALL_ROOT}/A2F/boa-0.94.14rc21/src/boa 777 0 0
file /etc/mime.types ${INSTALL_ROOT}/A2F/boa-0.94.14rc21/mime.types 777 0 0

dir /usr/local 777 0 0
dir /usr/local/lib 777 0 0
dir /usr/local/include 777 0 0
dir /usr/local/boa 777 0 0
file /usr/local/boa/cgi-test.cgi ${INSTALL_ROOT}/A2F/boa-0.94.14rc21/examples/cgi-test.cgi 777 0 0
file /usr/local/boa/cgi-test.cgi ${INSTALL_ROOT}/A2F/boa-0.94.14rc21/examples/nph-test.cgi 777 0 0
file /usr/local/boa/ ${INSTALL_ROOT}/A2F/boa-0.94.14rc21/examples/ 777 0 0

dir /var/log/boa  777 0 0
#Error log 
file /var/log/boa/error_log ${INSTALL_ROOT}/A2F/boa-0.94.14rc21/error_log 777 0 0
#Access log
file /var/log/boa/access_log ${INSTALL_ROOT}/A2F/boa-0.94.14rc21/access_log 777 0 0

dir /var/www 777 0 0
dir /var/www/resources 777 0 0
dir /var/www/resources/js/ 777 0 0
file /var/www/index.html ${INSTALL_ROOT}/A2F/boa-0.94.14rc21/index.html 777 0 0

dir /usr/lib 777 0 0
dir /usr/lib/boa 777 0 0
file /usr/lib/boa/boa_indexer ${INSTALL_ROOT}/A2F/boa-0.94.14rc21/src/boa_indexer 777 0 0

dir /usr/lib/cgi-bin 777 0 0
file /usr/lib/cgi-bin/data.txt ${INSTALL_ROOT}/projects/${SAMPLE}/app/data.txt 755 0 0
file /usr/lib/data.txt ${INSTALL_ROOT}/projects/${SAMPLE}/app/data.txt 755 0 0
file /usr/data.txt ${INSTALL_ROOT}/projects/${SAMPLE}/app/data.txt 755 0 0
file data.txt ${INSTALL_ROOT}/projects/${SAMPLE}/app/data.txt 755 0 0

#CGI CODE-- modify as needed 
file /usr/lib/cgi-bin/light.cgi ${INSTALL_ROOT}/A2F/cgic205/light.cgi 777 0 0
file /usr/lib/cgi-bin/stop.cgi ${INSTALL_ROOT}/A2F/cgic205/stop.cgi 777 0 0

file /usr/lib/cgi-bin/gripper_close.cgi ${INSTALL_ROOT}/A2F/cgic205/gripper_close.cgi 777 0 0
file /usr/lib/cgi-bin/gripper.cgi ${INSTALL_ROOT}/A2F/cgic205/gripper.cgi 777 0 0
file /usr/lib/cgi-bin/gripper_stop.cgi ${INSTALL_ROOT}/A2F/cgic205/gripper_stop.cgi 777 0 0

#HTML Background graphics
file /var/www/arrow-up.jpg ${INSTALL_ROOT}/projects/${SAMPLE}/app/roundgrey/arrow-up.jpg 777 0 0
file /var/www/arrow-down.jpg ${INSTALL_ROOT}/projects/${SAMPLE}/app/roundgrey/arrow-down.jpg 777 0 0
file /var/www/arrow-left.jpg ${INSTALL_ROOT}/projects/${SAMPLE}/app/roundgrey/arrow-left.jpg 777 0 0
file /var/www/arrow-right.jpg ${INSTALL_ROOT}/projects/${SAMPLE}/app/roundgrey/arrow-right.jpg 777 0 0
file /var/www/background.jpg ${INSTALL_ROOT}/projects/${SAMPLE}/app/roundgrey/background.jpg 777 0 0

dir /usr/bin 777 0 0
dir /usr/local/bin 777 0 0


Once the image is rebuilt and the networking is up and running on the iCon board.

Start up the Boa web server with the following command

boa &

To access the web server through a browser all you have to do is type in the ip address of the board. For example

And Voilà! You should be able to connect and control  the robotic arm wirelessly.


One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *