In many applications (and especially in certain courses), it might be important to have a tool to allow you to gather and store data for processing and analysis. Commonly, engineers use what it referred to as a data acquisition (DAQ) system. These DAQ systems allow you to record a range of electrical signals at high rate and precision and are particularly useful in experimental settings.

For this tutorial, we are going to cover an implementation of a simplified DAQ system using your microcontroller from your kit along with some specially written code, allowing you to record signals from your experiments! It should be noted, however, that this implementation is inherently limited in performance due to the hardware we are using. Typically, modern DAQ systems have hardware that enables much faster acquisition rates and better resolution. As such, it is important to ensure that the DAQ characteristics from this implementation will be sufficient to observe the signals you plan on measuring.

Figure 1. Illustration of simple DAQ system with a microcontroller.

The Microcontroller DAQ

We are going to be using your HUZZAH32 Feather board to read one or more analog signals. In order for you to run the scripts necessary to acquire data, you will need to flash the microcontroller using Arduino. You can find the tutorial for flashing Arduino here. In addition you will need to have a Python interpreter that is at least version 3. We recommend that you install Python version 3.6. Once you have those dependencies taken care of, we can start to implement your simple DAQ!

First, use the link below to download the scripts that you will need to run your simple DAQ.

Download the zip file here!

In the zip file, you will have two important scripts. The first script is an Arduino script called i2s_adc.ino, which is what you will use to flash your microcontroller. This script reads up to four analog inputs and sends a continuous stream of data over a serial connection to your PC.

The second script is a Python script called serial_log.py. The purpose of this script is to read incoming data from the microcontroller through the serial port and then save it to a text file for later use.

There are a few ways to control the operation of this simple DAQ, so let’s examine the i2s_adc.ino script to understand how.

// **** DATA ACQUISITION SCRIPT ****

#include <driver/i2s.h>
#include "soc/timer_group_struct.h"
#include "soc/timer_group_reg.h"

// Configure DAQ
// #define HIGH_SPEED_DAQ                  // Uncomment to use high speed DAQ, single input, pin 20 on pinout, ~10kHz
#define MULTI_INPUT_DAQ                 // Uncomment to use multi-input DAQ, multiple inputs,
#define MULTI_INPUT_NUM             (4)         // Number of inputs to read
#define MULTI_INPUT_SAMPLE_RATE     (500.0)      // Hz (1000 Hz Max)

// Setup config settings for I2S
#define I2S_SAMPLE_RATE (60000)
#define ADC_INPUT       (ADC1_CHANNEL_4) // Pin 20

// Setup config for standard ADC
#define ADC_INPUT_PIN1      (32)      // Pin 20 on pinout
#define ADC_INPUT_PIN2      (33)      // Pin 22 on pinout
#define ADC_INPUT_PIN3      (34)      // Pin 7 on pinout
#define ADC_INPUT_PIN4      (36)      // Pin 9 on pinout
#define INPUT_ATTEN         (ADC_0db)      // Attenuation for input

At the top under // Configure DAQ, there are several #define lines that can be used to select between two different operational modes.

The first mode is called HIGH_SPEED_DAQ, and the second mode is called MULTI_INPUT_DAQ. To switch between the modes, simply uncomment the line with the mode you would like to use, and comment out the line with the other mode. Make sure that only one mode is uncommented at a time, or your code will not run correctly.

As the name suggests, the HIGH_SPEED_DAQ mode can be used for applications that require a faster rate of data acquisition. It can run at a frequency of up to ~$10kHz$, which is $10,000$ samples per second. However, this mode only has one input and does not allow for ADC attenuation.

Note: The HIGH_SPEED_DAQ mode will sometimes result in dropped samples and anomalies due to the high speed and uncontrolled sampling rate if the serial protocol for your hardware (i.e. your PC) cannot keep up. If you experience dropped samples, try lowering the baud rate in both “i2s_daq.ino” and “serial_log.py”. Example baud rates to try are $115200$, $250000$, and $500000$.

The second mode, MULTI_INPUT_DAQ, should be used in cases where multiple analog inputs are needed simultaneously. This mode enables up to four different analog inputs to be recorded at a controlled sampling rate of up to $1kHz$. It also allows for ADC attenuation, but be aware that this will affect all signals being read.

Before flashing, make sure that you have connected the analog signals you plan to measure to the correct pins on your microcontroller board.

WARNING: The pins of the ESP32 chip are rated for 3.3V maximum. Exceeding this value may damage the chip.

Once you have configured your i2s_adc.ino script and constructed your circuit, you can flash the script to your microcontroller. After this process completes, your microcontroller will begin streaming data over serial through your USB cable and to your PC!

But how do we read it? That’s where the Python script serial_log.py will come in handy. Before running the script in your terminal, there are a few things to configure. Let’s examine the script.

# **** DATA LOGGER SCRIPT ****

import serial
import time
import struct

fileName = 'ENTER_DATA_FILE_NAME'       # Enter your file name here
serialPort = '/dev/ttyUSB1'             # Change the serial port

ser = serial.Serial(serialPort, 921600, timeout=0)

f = open(fileName+'.txt', 'a')

time.sleep(1)

ser.flush()
ser.readline()

while (1):
    try:
        if ser.in_waiting > 0:
            rx_raw = ser.readline().decode()
            f.write(str(rx_raw))
    except KeyboardInterrupt:
        f.close()
        print("Stop!")
        exit()

Toward the top, there are two lines that should be edited before running this script. Create a file name to save your data into by changing the definition of the variable fileName. The file will be saved to the same directory as this script.

The line directly following the file name defines a variable called serialPort that allows you to input the name of the serial port tied to your microcontroller. Make sure that you have verified the correct serial port before executing.

Now, we are all set! Open the terminal that you use to access your Python interpreter and navigate to the directory where your serial_log.py script is located. Run the following command to execute your the Python script and begin collecting data.

python3 serial_log.py

After one second, you will start recording live data from your microcontroller DAQ into a text file. To stop recording, simply stop execution by pressing CTRL+C in your terminal.

Now, open a file explorer window and navigate to the directory where your serial_log.py script is located. You should see a new text file with the name you selected. This contains all of your data in comma-separated columns. Depending on the settings you selected, there will be between two and five columns of data with the first column always being the time in microseconds. The analog input data is still in code form (12-bit by default) and must be converted into voltage in the range of $0-3.3V$!

As another note, running the serial_log.py script multiple times without changing the file name will write to the same text file and simply append the new data to the old data. If this is not what you want, make sure to create a new file name each time you run it or delete the old text file beforehand!

And that concludes our how-to on implementing a simple microcontroller-based DAQ!

Leave a Comment.