In the hobby maker electronic community there are a plethora of sensor IC’s and modules available online to buy at affordable prices. The source code for these sensors is often released on public sites targeting Arduino development boards which makes it really simple to get the get the base of your next product ready in few days.
Many industrial electronics systems require more powerful features only offered by higher performance SBC’s and high level operating systems. How easy is it to integrate sensor modules with the BCT Beta HMI platform? Is it possible to quickly and reliably port source code targeting Arduino in a high level operation system like Linux or Android?
I’ll show how it is straight forward to use these modules in a high level OS such as Android. Along the way I’ll develop a wrapper to enable rapid integration of Arduino libraires and examples with BCT SBC’s.
Let’s take a look at how simple and elegant the solution can be by doing a practical experiment.
2) The scope of the project.
For the project I’m going to use a BCT Beta HMI platform. I will connect it with a readily available hobby grade sensor module to produce a small prototype of an embedded product. The Grove Gas multi sensor board from Seeed Studio can detect various gasses often released during industrial production. This is interesting to me as BCT manufacture PCB assemblies in house.
I’ll take a look at the source code for the module and integrate it with the BCT Beta software APIs. Implement a gas monitoring application that tracks the values over 24 hours. Give the gas monitoring station a spin by exposing it to some liquid/gas compounds commonly available. Finally look at the pitfalls encountered and suggest further improvements of this project.
3) The hardware
The BCT Beta HMI platform is a great choice for my project as it provides good interconnection with embedded peripherals via an expansion header and the integrated LCD screen can be used for displaying gas sensor values in real time. The Seeed Studio, Grove Multichannel Gas Sensor V2, is available from several online shops and electronic parts distributors.
The design of the module is interesting as it contains 4 similarly constructed MEMS sensors from the same manufacturer, Winsen. Each sensor is sensitive to a different gas or group of gasses: Nitrogen Dioxide (NO2), Ethanol (C2H5OH), Volatile Compounds (VOC) and Carbon Monoxide (CO).
These MEMS sensors change their resistance based on the gas exposure and its concentration. There is an STM MCU on the sensor board, which uses an ADC to read the MEMS’ values and report the measured values to the host system via an I2C interface.
The sensor board is powered from3.06 VDC power rail exposed on the Beta’s expansion header. The I2C wires for Clock and Data are also connected to the same header. See Fig. 1 for the details of the wiring. The colour coding is as follows: Black 0V, Red VCC, Yellow SCL, White SDA.
And that’s the hardware setup, quite trivial. OK, lets’ take a look the source code of the sensor board that comes from the manufacturer.
4) Sensor software libraries and examples
The software library for the sensor board is available on the following github page:(https://github.com/Seeed-Studio/Seeed_Arduino_MultiGas)
The library source code is written in C++ for the Arduino IDE. The Arduino IDE supports many host boards and MCUs, but the code often uses the same Arduino API , therefore the code is portable to other boards with a minimum effort.
Looking at the code (src/Multichannel_Gas_GMXXX.cpp) the library only uses the Arduino API Wire class which seamlessly handles the I2C communication. The github project also has some example source code which exercises the library and the sensors.
The top level source code for Arduino IDE has an .ino file extension called a ‘sketch’. It has to implement 2 fundamental functions: setup() and loop(), which are called from within the platform specific start-up code.
The ‘demo_background.ino’ example code basically sets up a serial console for printing sensor values and initialises the gas sensor library in the setup() function. The loop() function reads the sensor’s values via the Gas library and then prints the result on the serial terminal.
We will need a similar library to interface the sensors to the BCT Beta HMI. Before we start porting the code we need to decide which operating system to use. The Beta line of products featuring ARM technology offer either a Linux based distro (Ubuntu, Buildroot etc.) or Android OS.
Both are suitable for the job. Android’s Java development language may seem like a bad option as it could bring some code portability difficulties. On the flip side, Android is actually a great operating system for embedded development as it supports a mature IDE, debugging capabilities over USB, well documented APIs, modern user interfaces and a plethora of examples available online. BCT already provide a full set of Android API for interfaces the features of our SBC’s not typically available on phones and tablets. For this example, the BCT I2C API will no doubt be very useful.
To implement the Gas module library for Android, I could just port over the existing Arduino library on top of the BCT API, but what if I also wanted to experiment with other I2C based sensors that have the Arduino libraries already written?
Would it better to consider porting the Arduino API to Java (Android’s development language), so that other Arduino libraries and code examples could be integrated with Android apps with less effort?
I think that makes sense and has another advantage. If the ported library code does not work properly in certain situations, I can run the original library on an Arduino hardware and then debug & review the results with outputs generated by my new ‘nearly identical’ library port. Having a line-by-line compatible implementation of the library code gives me some assurance bugs were not introduced during porting to the Java. (Note is that it is a good idea to check whether the original library license is compatible with the rest of your code. A ported library may be considered a fork of the original code and the license conditions will be active.)
The Arduino API Wire class implements the I2C bus and is well documented, therefore the implementa-tion for Android OS was quite simple. I opted to bundle the Arduino API port into a separate library called ‘bctinoapi’which can be found on BCT’s github page.( https://github.com/bluechiptechnology/bctinoapi_demo/tree/main/bctinoapi).
Android code that wants to use the Arduino-like interface in Android projects has to import the ‘bctinolib’ library module along with the BCT API module into the Android Studio project. As it stands, the ‘bctinolib’ code implements a small sub-set of the whole Arduino API, just enough to make the Gas Multisensor module to work. Other API implementations can be added later as needed.
The next step was to port the Gas multi sensor library to Android. Here is the code snippet that illustrates the difference between the finished Android Java code and the original Arduino C++ code.
Yes, there are some minor differences mainly related to coding and naming conventions between the two languages, but overall the implementation matches.
Once the gas library was ported over to the Android’s development environment I was curious to see if the sensor board actually worked, because I did not test it with the original library on an Arduino based dev board. The original example/test code is written in the .ino sketch, so my plan was to execute it, or rather its matching java port, from within the Android Activity.
Could I use the same porting principle I used on the ‘bctinolib’ to the Arduino sketches? Could I reuse most of (if not all) base functions the ino sketch is based upon? It made sense from the compatibility point of view to investigate a solution. I created a thin wrapper called InoCurator, also included in the bctinolib, that is able to execute the ported Arduino sketch and run it independently in its own thread. Here is an example how the InoCurator can be used to launch a ported .ino sketch:
The GasInoSketch is the ported version of the example code provided by the Seeed Studio engineers. As I was in total control of the sketch (via InoCurator), I could modify it and pass some initial parameters to its constructor. Like this:
// Start the InoSketch that communicates with the sensor and samples the gas
// values every 2 seconds.
InoCurator.runSketch(new GasInoSketch(this, 2000));
In the example above I’ve added 2 parameters, the first one instructs the sketch to pass the sensor values back to certain listener (‘this’ means this class instance) and to poll the sensors every 2 seconds.
Let’s take a look at the actual example code and compare the differences.
The java sketch code retains the setup() and loop() functions as they exist in the Arduino sketch. A keen eye will spot the baud rate in the Java’s port is set to 0. That means all prints via Serial class will be redirected to the standard output, therefore traceable via Android’s logging tool. Another change is a slightly modified printout of the results.
And basically that’s it. Complicated? Simple? Beneficial for tapping into Arduino code and libraries handling all sorts of peripherals? I let you decide.
Oh. and BTW. The code just worked on the first go.
Part 2 of this blog documents the development of an Android app to explore the response from the various sensors in more detail.
About Blue Chip Technology
At Blue Chip Technology (BCT) we specialise in design and manufacture of embedded electronics systems, Hardware, Firmware and Applications. Our typical customer will usually have a proof of concept and will work with Blue Chip to engineer what is often a complex collection of circuit boards into a commercialised solution.
The Beta HMI platform offers an opportunity to develop those prototypes with a validated, field proven integrated SBC, LCD and touch platform, saving several design and development iterations. BCT’s in house manufacturing and commitment to full life cycle support offers a unique proposition to dramatically reduce time to market, approvals and start-up costs.