TAN: Trailer Area Network

Introduction

A friend of mine, Scott Lemon founder and CTO of Wovyn, and I were discussing my travel trailer API and he coined the term, trailer area network or TAN. My TAN is going to be based on WiFi because of the ubiquitous availability of WiFi connected devices including microcontrollers, commercially available connected devices, and mobile phones and tablets. To this network I’ll attach microcontrollers that control trailer subsystems. These subsystems will connect via WiFi to a trailer hub that will expose subsystem functionality through the travel trailer API, see Figure below.

In this figure Internet connectivity is acquired through a mobile hotspot with the help of a cell signal booster. The mobile hotspot allows 15 devices to connect to it. One of the 15 devices will be the TAN Hub. The TAN Hub will create a subnet that subsystems will attach to, there could be many. Communications between the subsystems and the TAN Hub may use various protocols, but the TAN Hub will expose their functionality through a REST based API.

Components

There are three main sets of components that are needed to create the described TAN. For Internet connectivity we need a signal booster and a mobile hotspot. We need a server of sorts to act as the TAN Hub and a WiFi connected microcontroller unit to use in the construction of subsystems.

Internet Connectivity

I have selected the AT&T Unite Explore, also known as the Netgear AC815S, device as my mobile hotspot device. It seems to get good reviews and is reasonably priced. I may experiment with other hotspots in the future.

I acquired a weBoot Drive 4G-M Cell Phone Signal Booster to facilitate the acquisition of cell signals in remote locations. In the future I may experiment with various antenna configurations to increase the usable range.

Trailer Area Network Hub

For the TAN Hub I will use the Corewind WiFiG25 microcontroller module described in my original post describing my trailer API. This module is based on a 400 MHz ARM processor, has ample memory, and built in WiFi and runs the Linux operating system.

I expect to add an API management system to this module and communication systems to enable it to connect to and communicate with trailer subsystems.

Subsystem Controllers

There are many potential trailer subsystems that can be exposed and interacted with through an API. Examples include: leveling jacks, stabilizers, tank levels, battery levels, solar energy generation, awning, pop-outs, security, weather data, etc. Each of these will inevitably require special sensors, actuators, etc., but I am hoping to standardize on the microcontroller modules used to control the subsystems and communicate to the TAN Hub.

I will be experimenting with the ESP 12-F module based on the ESP8266 chip. This is an impressive module featuring a 32 bit MCU, integrated WiFi, tcp/ip stack, 4 MBytes of Flash memory for user programs, and all this for $1.74. It is capable of communicating with other hardware using SPI, I2C, Serial and other low level communication protocols.

These communication channels, as well as the available GPIO lines, will be used to interface these modules to subsystem specialty hardware such as switches, sensors, etc. The integrated WiFi will be used to connect these subsystems to the TAN Hub.

Summary

Future posts will describe various details related to the programming, configuration, and use of the components discussed in this post. There is much to learn, much to do, and a lot of fun to be had.

Docker for Cross Compilation

Given my interests in enterprise computing and embedded systems, I decided to mix the two disciplines and use Docker to create a C development environment to generate Arm executable from my OS X based Mac. This may seem like a stretch, but the traditional way to do this is to fire up a full-blown virtual machine, install Linux, install the gcc based cross compiler, edit code on the host machine, switch to the VM, compile, and iterate.  This is slow and cumbersome, and not nearly as educational or fun!

The first step was to install boot2docker and follow the directions. This provided a simple and clean way to get Docker running on OS X.  Next I created a Dockerfile to create a Docker image FROM Ubuntu, loaded all the required modules and configured the image for cross compilation.  Here is my Dockerfile:

##################################################
# This docker file creates an Arm cross compiler
# platform from Ubunto
##################################################
# Ubunto as base image
FROM ubuntu
MAINTAINER J. Kelly Flanagan, Brigham Young University
# update ubuntu image
RUN apt-get update
# enable 32 bit code to run on 64 bit machine
RUN apt-get -y install lib32z1
# install the gcc tools to enable compilation
RUN apt-get -y install gcc build-essential libncurses5-dev mtd-utils u-boot-tools
# ADD cross compiler tools and unpack in appropriate location
# create destination directory
RUN mkdir /opt/codesourcery/
# ADD source
ADD arm* /opt/codesourcery/
ADD mkubifsimage /bin/
RUN chmod 777 /bin/mkubifsimage
# for interactive use set path
RUN echo ‘PATH=/opt/codesourcery/arm-2011.09/bin:$PATH’ >> /root/.bashrc
# set environment variable so I know I’m in a container
ENV ARM_CROSS_COMPILER TRUE
# create build directory where a volume will be mounted
RUN mkdir -p /tmp/arm_cross_compiler
# End Dockerfile

With this Dockerfile I ran the following build command using docker,

docker build -t ubuntu_arm_crosscompiler .

this resulted in a new Docker image called ubuntu_arm_crosscompiler. This image can be used to create an interactive Docker container by executing,

docker run -i -t ubuntu_arm_crosscompiler

This yields a shell where you can invoke gcc to create Arm object and executable files from source. However, I don’t use it interactively; I invoke it from make so that it appears as if I am compiling from my Mac, but end up with the desired Arm executable file.

As an example let’s assume we have a source directory with a Makefile and a few source files: Makefile, test.c, test.h, and testfunc.c.  The Makefile uses conditionals to determine whether it is executing on the host machine or the Docker container. In the Dockerfile the environment variable ARM_CROSS_COMPILER was set and will exist in any container derived from that image. The contents of the Makefile are included below.

# Name: Makefile
# Purpose: Build Arm executable via Docker based cross compiler
# Author: J. Kelly Flanagan
# Docker specific stuff
DOCKER_ARGS = -v $(PWD):/tmp/arm_cross_compiler -w /tmp/arm_cross_compiler
CC=/opt/codesourcery/arm-2011.09/bin/arm-none-linux-gnueabi-gcc
RM=rm -f
HEADERS = test.h
OBJECTS = test.o testfunc.o
TARGET = test
test: $(OBJECTS)
ifeq ($(ARM_CROSS_COMPILER),TRUE)
            $(CC) -o $@ $^ $(CFLAGS)
else
            @docker run $(DOCKER_ARGS) ubuntu_arm_crosscompiler make $@
endif
%.o: %.c $(HEADERS)
ifeq ($(ARM_CROSS_COMPILER),TRUE)

            $(CC) -c -o $@ $

else
            @docker run $(DOCKER_ARGS) ubuntu_arm_crosscompiler make $@
endif
clean:
            $(RM) $(OBJECTS) $(TARGET)

From the source directory we execute make and the first target (test) is invoked. This target invokes the next that checks to see if the header file or the source files are newer than the corresponding object files. If the object file doesn’t exist or the source file has been modified, the action is taken. The action checks to see if the ARM_CROSS_COMPILER environment variable is set. If it is not then the Docker command is executed. When the Docker container is created from the image it mounts the current working directory and executes the same make command that was invoked on the Mac. However, in the container the environment variable is set and the source file is compiled to an object file using the cross compiler. The make in the container now completes and returns to make on the Mac that then moves on to the next target. This is repeated until all object files have been created or updated at which point a final compilation takes place to link the object files to one executable.

Docker works well in this case because it is efficient enough to be invoked and destroyed quickly enough to not be a major contributor to compile time and it is much more convenient than switching back and forth between my host and a VM. Finally, I can share either the Dockerfile or the image with others, enabling them to easily use my tool chain. I’m definitely adding Docker to my standard set of tools for solving problems.