Controlling Model Railway with FlashAir - Shared Memory

Contributor: ayase hiro

Latest update: March 2016


Previously I showed how to control a model railway with Arduino using the GPIO of the FlashAir. This time I am using the shared memory of the FlashAir.

On the FlashAir command.cgi is used to read and write shared memory.

The Arduino checks the shared memory and depending on the value of the flags in the shared memory it will sets the PWM output to drive the motor of model railway vehicle through a full-bridge driver.

We can also control the electromagnet at the switch point through a full-bridge driver.

User tutorial with FlashAir


iSDIO with Arduino IDE

First, follow the steps that have been posted on the FlashAir Developers site, so that you can use the iSDIO extended command in Arduino IDE.

ref. Creating the iSDIO extended command

Connecting FlashAir and Arduino

Regarding connection of FlashAir and Arduino, we'll connect the SPI.
This time, we use the Seeed Studio SD Card Shield v4, which is also recommended by the Developers site.

ref. Seeed Studio SD Card Shield v4


FlashAir in Seeed Studio SD Card Shield v4
(the Arduino in the photo, is Arduino MEGA2560 compatible board)


Full circuit diagram

Shared Memory of FlashAir

There is 512 bytes of shared memory at 0x1000~0x11FF that the user can use with command.cgi. The remaining "Reserved for Vendor (01000h〜01FFFh)" areas listed in the memory maps that are posted on the FlashAir Developers site.

ref. Arduino tutorial / Reading of the card status

Memory Map of iSDIO registers (Excerpt from SD Specifications Part E7 iSDIO Simplifed Specification Version 1.10)

Address Name Short Description Type
00000h Command Write Register Port Data Port to write the iSDIO Command Write Data W/O
00001h-001FFh Reserved
00200h Response Data Register Port Data Port to read the iSDIO Command Response Data R/O
00201h-03FFh Reserved
00400h-005FFh Status Register Memory Area for iSDIO Status Register Table2-7
00600h-007FFh Capability Register Memory Area for iSDIO Capability Register R/O
00800h-00FFFh Reserved
01000h-01FFFh Reserved for Vendor
02000h-1FFFFh Reserved

Shared Memory Allocation

Arduino is exchanging data with the FlashAir using a shared memory of FlashAir so we need to consider how to exchange the data in shared memory.
As described above, shared memory of FlashAir is 512 bytes so you can use a lot of data. However, it is not necessary to use lots of data.

The shared memory will exchange the status between the FlashAir and Arduino using an 8-byte string allocation.


Data allocation of shared memory

Address Value Range Data Specification
0x1000〜0x1002 000〜200 Operate the value of 3 bytes address to three digits number, as 0x1000 is the three-digit number, 0x1001 is the two-digit number, 0x1002 is the one-digit number.Running speed to be operated on this data is 000-200.
0x1003 0 / 1 Motor direction.
0: Right. 1: Left.
0x1004 0 / 1 Indicating the value of Switch point(rail open direction).
0:Straight. 1: Branch.
0x1005〜0x1007 unused Preliminary for switch point

Writing FlashAir Shared Memory with command.cgi

From a browser that can connect to the FlashAir, you can write data to shared memory by accessing a URL such as http://flashair/command.cgi?op=131&ADDR=0&LEN=8&DATA=12345678.

Reading FlashAir Shared Memory with command.cgi

From a browser that can connect to the FlashAir, you can write data to shared memory by accessing a URL such as http://flashair/command.cgi?op=130&ADDR=0&LEN=8 ,you can read data to the shared memory. In this example, you can read the data of 8 bytes from the shared memory address 0x1000.

Reading FlashAir Shared Memory with SDIO

Like the following code in the Arduino connected to the FlashAir, you can read the data in the shared memory.

#include <utility/Sd2CardExt.h>
const int chipSelectPin = 4; //Seed Studio SD Card Shield V4 specifies to the pin of No.4.
Sd2CardExt card;
uint8_t buffer_sharedMem[8];

void setup() {
         if (card.init(SPI_HALF_SPEED, chipSelectPin)) {

boolean iSDIO_sharedMemRead() {
         memset(buffer_sharedMem, 0, 0x08);
         if (!card.readExtMemory(1, 1, 0x1000, 0x08, buffer_sharedMem)) {
    		return false;

First specify SPI_HALF_SPEED and the GPIO pin number of Arduino that connects to the Chip Select pin of the SDcard as the argument to the init function of the card class setup function. Running the code initializes the SD card connection. When the initialization is successful, "OK" will be displayed output to the serial port of the Arduino.

On the Seed Studio SD Card Shield V4 the GPIO pin number to be connected to the Chip Select pin is 4, so we set chipSelectPin variable to 4.

After initialization, when the iSDIO_sharedMemRead function is called from the loop function it will store the data read from the shared memory to the variable buffer_sharedMem. In this code, it reads a data block of 8-bytes from the start address of 0x1000. When you use the data, you can select the variable buffer_sharedMem.

By the way, if you write a single-byte numbers (0-9) in the command.cgi to shared memory, it seems that shared memory will be written in US-ASCII code. For this reason, the number 0 is binary code 0x30 (decimal 48), the number 1 is 0x31 (decimal 49)... number 9 is 0x39 (decimal 57). If you want to read a single-byte numbers as a numeric value, cast to char type and you can convert number characters and numbers. There may be a betterway to handle this, but this is a quick method.

int cmd_buffer;
cmd_buffer = (char)buffer_sharedMem[0] - 48;

Implementation of Operation Screen

Request the above URL when the user presses any button with javaScript in List.htm was set in the FlashAir. The image displaying the operation screen on the Web browser is shown below.

Button Behavior and Roles
STOP Emergency stop button. Such as when the model train derails in order to stop immediately.
DOWN Slow down. Speed -10 at once pressed down.
UP Speed up. Speed +10 at once pressed down.
Left The running direction to the left.
Right The running direction to the right.
SW_L Switch Point( rail open direction ) is to the left.
SW_R Switch Point( rail open direction ) is to the right.
Off Reset all to the initial state.
Clear To reload the screen.
Textarea Behavior and Roles
SPEED_STATE Indicating the running speed. Current running speed is in the 0 to 200.
RESULT To show the URL when HTTP requested.(For debugging)

Operation screen List.htm viewed on iPhone

<script language="javascript" type="text/javascript"> 
//Function: HTTP communication to FlashAir
function flashair_get( param ){
          var request = new XMLHttpRequest();
 "GET", param, false);
           request.send(null);  } 
//Global variable definition
var send_mess = "http://flashair/command.cgi?op=131&ADDR=0&LEN=8&DATA="; 

var run_speed_state = 0;		//To store the running speed as number.
var run_speed_val = "000";	//To store the running speed as string.
var run_lr_val = "0";		//To store the running direction as string.
var run_point_val = "0";		//To store the point open direction as string.

//Function : to change in accordance with the various variables in the command number,
//To request a HTTP request to write to the shared memory of FlashAir.
function isdio_send(cmd){
		case 1:	//Emergency stop run_speed_state to 0, run_speed_val to 0.
			run_speed_state = 0;
			run_speed_val = "000";
			document.getElementById('SPEED_STATE').value = run_speed_state;
			url = send_mess + run_speed_val + run_lr_val + run_point_val + “000”;
		case 20:	 //Point control:Curve (branch ) direction  run_point_val to 1.
		case 21:	//Point control:Linear direction run_point_val to 0.
		case 30:	 //Running direction:Right direction run_lr_val to 0.
		case 31:	//Running direction:Left direction run_lr_val to 1.
		case 4:	 //Running control:speed up run_speed_state to +10, run_speed_val to +10.
			run_speed_state = run_speed_state + 10;
				if(run_speed_state > 200){
					run_speed_state = 200;
			run_speed_val = ( '00' + run_speed_state ).slice( -3 );
			document.getElementById('SPEED_STATE').value = run_speed_state;
			url = send_mess + run_speed_val + run_lr_val + run_point_val + “000”;
		case 5:	 //Running control:Slow down run_speed_state to −10, run_speed_val to −10.
		document.getElementById('RESULT').value = url;

Example of javaScript described in List.htm of operation screen

Implementation of Arduino side

In this case, according to the data allocation of the shared memory shown earlier, Do the processing, such as in the flowchart of FIG.


Flowchart of Arduino side

Let's Get Moving

So, let's hook up the Arduino to the model railway set. First, the output of the full-bridge driver for the PWM output is connected to the line and then the output of the full-bridge driver is connected to the switch point. We are using a Kato Precision Model Railroad set but you can connect an Arduino in the same way to other model railways such as Tommy Tech.

The USB cable is connected to the Arduino as it is the power supply. The iPad connected to the FlashAir in the photo is displaying the operation screen List.htm.


The train operation has been published in this video:

Application examples: Creation of model railway controller

By applying the implementation introduced in this case, we tried to produce a model railroad controller (so-called power pack). The controller, in combination with the Arduino UNO R3 and FlashAir, was capable of controlling the PWM output up to 2 systems, and the switch up to 4. Of course, Arduino and FlashAir is doing the exchange of data through the shared memory. Since increasing the PWM output, The data allocation of shared memory has extended as shown in the figure.


Operation screen List.htm viewed on iPhone

Control screen, has been implemented in javaScript to List.htm in the FlashAir. Not only writes the data in response to the operation in the shared memory of FlashAir, read the data of shared memory regularly, then update the screen.

Therefore, when you connect from a plurality of terminals (Web browser) to FlashAir, the state of operating in either of the terminals will be displayed, reflected in all of the control screen through the shared memory.
In short, it was able to operate by one controller from few persons. Stores the status (state) data in the shared memory, through this, by the control such as in the Arduino, Arduino side does not need to be aware of how to rewrite the Shared memory (for example, from a plurality of terminals). this is the merit of the system using the status (state) data.

Everyone, please try to manufacture the original model railway controller using the FlashAir.


Outside of Power Pack


Inside of Power Pack


List.htm of FlashAir viewed in Web browser


Viewing model railway operations using the model railway controller