October 30th 2020
By Ajdin Mulaosmanovic, Hardware Design Engineer
The development of almost every modern electronic device begins with the development of a prototype for proof of concept. In many cases, the R&D team has to collect the process variables data before the development of the prototype. For this purpose, data acquisition systems (DAQ) are the best option. Many different commercial data acquisition systems come with dedicated software, and their prices can range from a few dollars to several thousand dollars. However, sometimes during the proof of concept stage, it is necessary to prove that the hardware, which will be an integral part of the future system, can reach the desired performance. This mainly refers to the main system processing unit and accompanying analog signal filter IC's and analog to digital converter IC's, as well as IC's for raw digital value preprocessing. Furthermore, let's mention that many modern electronic systems and subsystems require real-time performance within the process which they control or monitor. There are many examples, especially in process automation, automotive industry, aerospace industry, robotics, etc. Here, we'll briefly show what is needed to make a simple, real-time data acquisition system, where a PC is the master device and a small microcontroller system is a real-time engine.
Simplified block structure
Any microcontroller-based system could've been used to explain the concept that is the topic of this blog, and what we want to show isn't restricted to a specific MCU. It is important to understand the basic mechanics, so let's check what are the main components of a simple microcontroller-based data acquisition system.
Figure 1. Simple Real-time data acquisition system
Figure 1. shows a simplified MCU-based data acquisition system with external or internal Analog To Digital Converter (ADC). Therefore, let's list the necessary parts of the system:
- Analog to Digital Converter
- Microcontroller system (MCU development board)
- UART, I2C, CAN, ... to standard USB converter.
Microcontrollers often have a built-in AD converter convenient for use in a variety of applications. If the application requires ADC with higher performances (resolution or sample rate), then we must select a dedicated external ADC. Let's select a microcontroller system with a built-in ADC. Figure 2. shows the FRDM-K22F microcontroller development board from NXP.
Figure 2. NXP FRDM-K22F development board
The NXP Freedom K22F is an ultra-low-cost development platform for Kinetis K22 MCUs. This board is compatible with the Arduino Rev3 pin layout. Peripherals enable rapid prototyping, including a tri-colored LED and 2 user push-buttons for direct interaction, and connectivity for use with Bluetooth and USB. OpenSDAv2 offers options for serial communication, flash programming, and run-control debugging. The FRDM-K22F is enabled by the Arm Mbed OS platform and supported by Zephyr OS, for developing the Internet of Things with a free, open-source operating system.
Thanks to the K22 microcontroller, we can create a real-time system for the acquisition of analog values from an external sensor, and then through the built-in mechanism for converting the UART interface to standard USB, it is possible to transfer data to a PC. Let’s see below how such a system can be implemented.
Microcontroller system – Firmware, Real-Time Engine, and Shell
Firmware is a software program or set of instructions programmed on a hardware device. It provides the necessary instructions for how the device communicates with the other hardware peripherals. We won’t discuss firmware in detail here, except for a few C functions that are necessary for a better understanding of communication and data collection routines. Real-time performances can be achieved in many different ways. The most basic way is to build the so-called bare-metal application, and there are of course more sophisticated options like the use of real-time operating systems. Firmware applications are typically written in a low-level language like C (rarely in assembly). For the sake of this example, let’s assume that we have a high priority timer interrupt routine which starts the A-to-D conversion every X ms where X is a sampling period. In this example, each 20ms (50Hz) timer initiates analog to digital conversion of an external ADC using SPI communication. In the same manner, the system can initiate the AD conversion of an internal ADC.
Code 1. Timer Handler Routine
Shell controls MCUs by commands via the specified communication peripheral based on the debug console driver. Here it is given a very simple example of how the NXP shell can be used to trigger a routine by simply changing the status of a flag. It will be explained below how the master side of a system can interact with the firmware shell.
Code 2. Shell Command
PC application – Communication and Control under .Net Framework
Let’s discuss the PC side of the system. As usual, we need some sort of a terminal application for our console/PC. For that purpose, a simple terminal emulator (TeraTerm or puTTY) can be used. Any other console-like application which supports the serial port connection can also be used for this purpose. Here we want to present how such an application can be written from scratch using C# language in Visual Studio under the .Net Framework.
Microcontroller development platform (FRDM-K22F) doesn’t have MS Visual C# specific libraries that could utilize virtual serial port, so here we’ll demonstrate how to write and receive data from a device connected to a serial port. Our custom made Application uses an OpenSDA virtual serial port to communicate with the FRDM-K22F. OpenSDA is an open-standard serial and debugger adapter. It bridges serial and debugger communications between a USB host and an embedded target processor as shown in Figure 3.
Figure 3. OpenSDA block structure
OpenSDA features a mass storage device (MSD) bootloader, which provides a quick and easy mechanism for loading different OpenSDA Applications such as flash programmers, run-control debug interfaces, serial-to-USB converters, and more. Open SDA serial-to-USB converter is the most important feature for our custom application since it offers us to see the target processor and development board as a Virtual COM port after we connect the board to the PC. The application uses the SerialPort MS Visual Studio C# class which is a part of the System.IO.Ports namespace which contains classes for controlling serial ports. SerialPort class provides a framework for synchronous and event-driven I/O, access to pin and break states and access to serial driver properties. Here we will briefly demonstrate how to create an instance of the SerialPort class, open SerialPort, write and receive data from a device connected to a serial port in C# and .NET.
To create an instance of a SerialPort class, we simply pass the SerialPort options to the constructor of the class, or we can drag and drop serial port control from MS Visual Studio toolbox into Form, and later change the serial port settings. All options for a serial device can be sent through the constructor of the SerialPort class.
Code 3. Serial Port Settings
To use Serial Port, we need to open it:
Code 4. Serial Port Open
After we open the Serial Port, we can use several methods to send and receive data and most often are:
Code 5. Serial Port Send/Receive methods
There are other methods for different ways of sending or receiving data using a serial port.
Visual Studio IDE offers us an option to build and use Graphical User Interface so we can make a simple form with a connection box. Connection Group Box contains controls behind which SerialPort methods are used to Open (Connect) or Close (Disconnect) the application from Virtual COM Port on which is our microcontroller system connected.
Let’s go through the Connection procedure after we plug in the FRDM board in PC and start the app:
Figure 4. Connection group box
Let’s see what lies beneath Connect and Rescan buttons.
Code 6. Button Connect Click handler routine
Code 7. Button Rescan Click handler routine
The serial protocol is a textual command-response protocol, which means that every time the .NET application sends a command request packet to the microcontroller through the serial port, it should always receive a response packet back. Response packet from the controller, which follows the command request from the application, must contain a termination term used in application to mark the end of the response, for example when application finds out that response message contains term OKrn receiving procedure stops. Figure 5. shows a simplified model of the Serial Protocol.
Figure 5. Serial text protocol
Serial Protocol CmdExe method
Command request and receive procedures are both parts of the Command Execute or CmdExe() method.
Code 8. CmdExe method
Command request as it can be seen from CmdExE() method is a loop that sends command string characters one by one, and at the end adds a new line pair /r/n.
On the microcontroller side, the command request is parsed using NXP Shell which is part of the NXP Software Development Kit (SDK_2.x_FRDM-K22F). If the microcontroller recognizes the received command request it will start executing the routine or shell function related to that command. At the end of each shell response, a termination term must be sent, and that term must correspond with the listed termination term in the application. (receiving procedure)
Code 9. SendStringShell method
In the end, let’s say that all above-listed functions both in firmware (NXP real-time engine, timer, and shell parser) and in the application (SerialPort Open/Close, Send/Receive, etc.) can now be used simultaneously so that the real-time MCU system can send data to the PC application, where those data can be farther processed, displayed or stored. We will leave it to the designers to add routines for exchanging data sets for their application. For more info, feel free to reach out to the author.