Using a USB Memory Stick for Data Logging on Opta™

Learn how to interface an Opta™ device with a USB memory stick for data logging.

Overview

In this tutorial, we will learn how to interface an Opta™ device with a USB memory stick for data logging. Data logging is an essential process in industrial environments, where it is critical to continuously monitor and record vital parameters like temperature, pressure, or flow rates. These parameters are often captured through sensors connected to the input ports of a device like Opta™.

Through this guide, we will show you how to record readings from four analog input ports of an Opta™ device and store the data in a

.txt
file inside a USB memory stick. Additionally, we will use the onboard user button and LEDs of the Opta™ device to start, stop, and indicate the status of the data logging process to the user.

Goals

  • Connect an Opta™ device to a USB memory stick for data logging.
  • Read data from four analog input ports of an Opta™ device and write it to a
    .txt
    file on a USB memory stick.
  • Use the onboard user button of an Opta™ device to start and stop the data logging process.
  • Use the onboard user LEDs of an Opta™ device to indicate the different states of the data logging process to the user.

Hardware and Software Requirements

Hardware Requirements

Software Requirements

Compatible USB Memory Sticks

Any USB-C® memory stick should work with Opta® devices and the

Arduino_UnifiedStorage
library. Additionally, the following USB-C® memory sticks have been officially tested by the Arduino Team and are known to be fully compatible with Opta® devices and the
Arduino_UnifiedStorage
library:

  • Kingston® DataTraveler® 80 M USB-C 256 GB Flash Drive
  • SanDisk® Ultra® Dual Drive USB Type-C 64 GB Flash Drive
  • SanDisk® Ultra® Dual Drive Go USB Type-C 64 GB Flash Drive

All USB memory sticks were formatted with the

FAT32
file system before they were used with an Opta® device and the
Arduino_UnifiedStorage
library. It is recommended to use USB memory sticks with a storage capacity of 256 GB or less. If a memory stick has a storage capacity greater than 256 GB, it is advised to partition it, limiting the accessible storage to 256 GB or less.

USB Memory Sticks and Data Logging

USB memory sticks and Flash drives are essential for data logging purposes in industrial environments. These small, rewritable storage devices equipped with integrated Flash memory and a USB interface are ideal for storing data such as temperature, pressure, and machine performance over time.

Data logging, particularly in industrial environments, is essential for predictive maintenance, process optimization, and quality control. It involves collecting large amounts of data over time, which can be analyzed to identify trends, predict equipment failures and improve operational efficiency.

USB memory sticks and data logging with Opta™ devices
USB memory sticks and data logging with Opta™ devices

To manage the communication between a USB memory stick and Opta™, you will use the

Arduino_UnifiedStorage
library. This library is excellent for working with different types of storage, including the FAT file systems that USB memory sticks often use. The main benefit of this library is that it makes dealing with various storage devices and file systems more straightforward. This is especially important in industrial data logging, where you need reliable and accurate data recording.

The

Arduino_UnifiedStorage
library simplifies how to read and write data to external storage devices, ensuring precise and consistent data logging. You can learn more about this library in the following blog post.

Instructions

Setting Up the Arduino IDE

This tutorial requires the latest version of the Arduino IDE that you can download here. In the Arduino IDE, you need to install the core for Opta™ devices, which can be done by navigating to Tools > Board > Boards Manager or clicking the Boards Manager icon in the left tab of the IDE.

In the Boards Manager tab, search for

opta
and install the latest
Arduino Mbed OS Opta Boards
release.

Installing the Opta™ core in the Arduino IDE
Installing the Opta™ core in the Arduino IDE

You can start now compiling and uploading Arduino sketches to an Opta™ device using the Arduino IDE.

Installing the Required Libraries

This tutorial also requires the latest version of the

Arduino_UnifiedStorage
library installed on the Arduino IDE. This can be done by navigating to Tools > Manage Libraries or clicking the Library Manager icon in the left tab of the IDE. In the Library Manager tab, search for
Arduino_UnifiedStorage
and install the latest version.

Installing libraries in the Arduino IDE
Installing libraries in the Arduino IDE

The

Arduino_UnifiedStorage
library needs some dependencies: the
Arduino_POSIXStorage
, the
Arduino_USBHostMbed5
and the
ArduinoRS485
libraries. The IDE will ask you if you want to install them. Ensure all the mentioned libraries are installed correctly and updated to their latest version.

Note: In case you want to receive and show the debug messages on your computer, you can use a USB to RS-485 converter, such as the converter used by the Arduino Pro Content Team. You can use the Arduino IDE's Serial Monitor to display the messages received in the converter or another serial terminal such as CoolTerm, a simple and cross-platform (Windows, Mac, and Linux) serial port terminal application (no terminal emulation) that is geared towards hobbyists and professionals.

Setting Up the Hardware

  1. Connect a +12-24 VDC power supply to your Opta™ device.

  2. To receive debug messages, which is optional, connect a USB to RS-485 converter to the RS-485 interface of your Opta™ device.

  3. The example sketch logs data from the analog inputs ports

    I1
    ,
    I2
    ,
    I3
    , and
    I4
    of an Opta™ device; connect an analog signal source to these input ports to see real values logs on those pins.

  4. For programming your Opta™ device, connect it to your computer using a USB-A to USB-C® cable.

Hardware setup
Hardware setup

Writing Data to a USB Memory Stick

Open the Arduino IDE and paste and save the following code:

1/**
2 Opta USB data logging example sketch
3 Name: usb_data_logging_opta.ino
4 Purpose: This sketch logs data from four analog inputs of an Opta device
5 into a single line in a file on a USB memory stick. The data logging process starts
6 when the user button is pressed for 3 seconds and stops when the button is
7 pressed again for 3 seconds. A Knight Rider LED pattern is used to indicate
8 the status of USB connection. Once the data logging is done, all the user
9 LEDs blink 10 times.
10
11 @author Arduino PRO Content Team
12 @version 1.1 10/11/23
13*/
14
15#include "Arduino_UnifiedStorage.h"
16
17// Constants for analog input pins and LED pins
18const int analog_pins[] = { A0, A1, A2, A3 };
19const int led_pins[] = { LED_D0, LED_D1, LED_D2, LED_D3 };
20
21// Define constants for voltage, resolution, and divider.
22const float VOLTAGE_MAX = 3.0; // Maximum voltage that can be read
23const float RESOLUTION = 4095.0; // 12-bit resolution
24const float DIVIDER = 0.3; // Voltage divider
25
26// Timing control variables
27unsigned long previousMillis = 0;
28const long interval = 1000;
29
30// Knight Rider LED pattern variables
31int ledDirection = 1;
32int currentLed = 0;
33
34// USB storage and folder instances
35USBStorage usbStorage;
36Folder backupFolder = Folder();
37bool usbIntialized = false;
38volatile bool usbAvailable = false;
39
40/**
41 Function to handle USB connection callback.
42 Sets the USB available flag and removes the connection callback.
43
44 @param none
45 @return none
46*/
47void connectionCallback() {
48 usbAvailable = true;
49 Arduino_UnifiedStorage::debugPrint("- USB device connected!");
50 usbStorage.removeOnConnectCallback();
51}
52
53/**
54 Function to handle USB disconnection callback.
55 Resets the USB available flag and reinstalls the connection callback.
56
57 @param none
58 @return none
59*/
60void disconnectionCallback() {
61 usbAvailable = false;
62 Arduino_UnifiedStorage::debugPrint("- USB device disconnected!");
63 usbStorage.onConnect(connectionCallback);
64}
65
66/**
67 Function to handle Knight Rider LED pattern.
68 Displays a LED sequence on Opta's user LEDs to indicate waiting for USB connection.
69
70 @param none
71 @return none
72*/
73void knightRiderPattern() {
74 for (int i = 0; i < 4; i++) {
75 digitalWrite(led_pins[i], LOW);
76 }
77
78 digitalWrite(led_pins[currentLed], HIGH);
79 delay(100);
80 currentLed += ledDirection;
81
82 if (currentLed == 3) {
83 ledDirection = -1;
84 } else if (currentLed == 0) {
85 ledDirection = 1;
86 }
87}
88
89/**
90 Function to check for a 3-second button press.
91 Used to start or stop the data logging process.
92
93 @param none
94 @return true if button is pressed for 3 seconds, false otherwise
95*/
96bool checkButtonPress() {
97 if (digitalRead(BTN_USER) == LOW) {
98 unsigned long buttonPressTime = millis();
99 while (digitalRead(BTN_USER) == LOW) {}
100 if (millis() - buttonPressTime >= 3000) {
101 Arduino_UnifiedStorage::debugPrint("- Button pressed for 3 seconds!");
102 return true;
103 }
104 }
105 return false;
106}
107
108/**
109 Function to blink all user LEDs a specified number of times.
110 Indicates the start or end of a process like data logging.
111
112 @param times Number of times to blink the LEDs
113 @return none
114*/
115void blinkAllLeds(int times) {
116 for (int i = 0; i < times; i++) {
117 for (int j = 0; j < 4; j++) {
118 digitalWrite(led_pins[j], HIGH);
119 }
120 delay(500);
121 for (int j = 0; j < 4; j++) {
122 digitalWrite(led_pins[j], LOW);
123 }
124 delay(500);
125 }
126}
127
128/**
129 Function to handle the writing of data to USB storage.
130 Manages USB initialization, mounting, and writing of sensor data to file.
131
132 @param none
133 @return none
134*/
135void writeToUSB() {
136 if (usbAvailable && !usbIntialized) {
137 usbStorage.begin();
138 Folder usbRoot = usbStorage.getRootFolder();
139 String folderName = "backup_data";
140 backupFolder = usbRoot.createSubfolder(folderName);
141 Arduino_UnifiedStorage::debugPrint("- Backup folder created: " + backupFolder.getPathAsString());
142 usbStorage.unmount();
143 usbIntialized = true;
144 } else if (usbAvailable && usbIntialized) {
145 if (!usbStorage.isMounted()) {
146 if (usbStorage.begin()) {
147 performUpdate();
148 }
149 } else if (usbStorage.isMounted()) {
150 performUpdate();
151 }
152 }
153}
154
155/**
156 Function to perform data update on USB storage.
157 Writes analog sensor data in a formatted string to a text file.
158
159 @param none
160 @return none
161*/
162void performUpdate() {
163 UFile backupFile = backupFolder.createFile("analog_inputs_data.txt", FileMode::APPEND);
164 unsigned long currentMillis = millis();
165 if (currentMillis - previousMillis >= interval) {
166 previousMillis = currentMillis;
167
168 String buffer = "";
169 for (int i = 0; i < 4; i++) {
170 int value = analogRead(analog_pins[i]);
171
172 // Convert the terminal value to its corresponding voltage.
173 float voltage = value * (VOLTAGE_MAX / RESOLUTION) / DIVIDER;
174 if (i > 0) {
175 buffer += "; ";
176 }
177 buffer += "A" + String(i) + ": " + String(voltage);
178 }
179 buffer += "\n";
180 backupFile.write(buffer);
181 Arduino_UnifiedStorage::debugPrint("- Data written to file: " + buffer);
182 }
183 backupFile.close();
184 usbStorage.unmount();
185 Arduino_UnifiedStorage::debugPrint("- File closed and USB storage unmounted!");
186}
187
188// Board initialization
189void setup() {
190 Serial.begin(115200);
191 Arduino_UnifiedStorage::debuggingModeEnabled = false;
192 analogReadResolution(12);
193
194 usbStorage = USBStorage();
195 usbStorage.onConnect(connectionCallback);
196 usbStorage.onDisconnect(disconnectionCallback);
197
198 for (int i = 0; i < 4; i++) {
199 pinMode(led_pins[i], OUTPUT);
200 digitalWrite(led_pins[i], LOW);
201 }
202
203 pinMode(BTN_USER, INPUT_PULLUP);
204 Arduino_UnifiedStorage::debugPrint("- Setup complete!");
205}
206
207// Main loop
208void loop() {
209 static bool dataLoggingStarted = false;
210
211 if (usbAvailable && !dataLoggingStarted) {
212 knightRiderPattern();
213
214 if (checkButtonPress()) {
215 dataLoggingStarted = true;
216
217 // Turn off all the user LEDs
218 for (int i = 0; i < 4; i++) {
219 pinMode(led_pins[i], OUTPUT);
220 digitalWrite(led_pins[i], LOW);
221 }
222
223 // Turn on LED_D0 for data logging indication
224 digitalWrite(led_pins[0], HIGH);
225 Arduino_UnifiedStorage::debugPrint("- Data logging started!");
226 }
227 } else if (dataLoggingStarted) {
228 writeToUSB();
229
230 // Toggle LED_D0
231 digitalWrite(led_pins[0], digitalRead(led_pins[0]) == LOW);
232
233 if (checkButtonPress()) {
234 dataLoggingStarted = false;
235 Arduino_UnifiedStorage::debugPrint("- Data logging stopped!");
236
237 // Blink all LEDs 10 times to indicate end of data logging
238 blinkAllLeds(10);
239 }
240 }
241}

To upload the example sketch, click the Verify button to compile and check for errors; then click the Upload button to program the device with the sketch.

Installing libraries in the Arduino IDE
Installing libraries in the Arduino IDE

After uploading the example sketch, you can test it by connecting a compatible USB-C® memory stick. The example sketch logs data from the analog inputs ports

I1
,
I2
,
I3
, and
I4
. Connect an analog signal source to these input ports to test this functionality.

Hardware setup
Hardware setup

The example code from above shows how to interface an Opta™ device with a USB memory stick for storing data from four analog inputs into a single line in a file on a USB memory stick. Here's a brief overview of the example sketch functionality:

  • Connecting the USB memory stick: Once a USB memory stick is connected to an Opta™ device, the device enters into "waiting mode" indicated by a dynamic "Knight Rider" LED pattern with the onboard user LEDs.

  • Starting the process: The data logging process begins by pressing and holding the user button on an Opta™ device for three seconds and then releasing it. This action automatically starts logging data. Data from four analog inputs of the Opta™ device are recorded in a structured format onto the USB memory stick. During this process,

    LED_D0
    blinks to indicate active data logging.

  • Stopping data logging: The process stops by pressing and holding the user button for another three seconds and then releasing it. The device stops recording data and signals completion by flashing all user LEDs ten times.

Here is a step-by-step breakdown of the code tested:

Import libraries:

  • The sketch starts by importing the
    Arduino_UnifiedStorage
    library, which is essential for managing the USB memory stick and file system.

Variables and instances definition:

  • The sketch establishes instances for handling the USB memory stick and the file system. Arrays are defined to store the analog input pin numbers (
    analog_pins
    ) and the onboard user LED numbers (
    led_pins
    ).
  • Variables for managing time (
    previousMillis
    and
    interval
    ) are used to track data logging intervals without relying on the built-in
    delay()
    function.
  • The "Knight Rider" LED pattern is controlled by
    ledDirection
    and
    currentLed
    variables, sequentially illuminating the user LEDs on the Opta™ device.

The

setup()
function:

  • The sketch initializes the Opta™ device, setting the analog-to-digital converter resolution and preparing the onboard user LEDs.
  • The sketch also establishes connection handlers for the USB memory stick using the
    connectionCallback()
    and
    disconnectionCallback()
    functions.

The main

loop()
function:

  • The sketch monitors the onboard user button for a three-second pressing, holding, and then releasing it to initiate or stop the data logging process.
  • When data logging is started,
    LED_D0
    is illuminated as an indication of the process. The "Knight Rider" LED pattern is displayed while the device waits for a USB memory stick connection.
  • The
    writeToUSB()
    function manages the data writing process to the USB memory stick, including initialization and updating data to the USB memory stick through the
    performUpdate()
    function.
  • Analog input data is formatted and written to a file named
    analog_inputs_data.txt
    on the USB memory stick.
  • When the data logging is completed (indicated by pressing the user button for three seconds again), the sketch stops writing data to the USB memory stick.
  • The sketch shows the end of the data logging process by blinking all the onboard user LEDs ten times.

Optional: Debugging with

debugPrint
statements via Opta's RS-485 interface.

  • The
    debugPrint
    functions provide essential feedback throughout the sketch, aiding in monitoring and troubleshooting. The function can be turned on or off by setting the
    Arduino_UnifiedStorage::debuggingModeEnabled()
    function to
    true
    or
    false
    .
  • These statements output important information via your Opta™ device's onboard RS-485 serial interface, including status updates during USB memory stick connection and file operation results.

Conclusion

In this tutorial, you have learned how to interface an Opta™ device with a USB memory stick, read analog input data, and store it on the USB memory stick. Additionally, you have understood how to use the onboard user LEDs to display status information to the user. With these skills, you can explore more complex projects, such as implementing advanced data logging and analysis for various sensors with Opta™ devices.

Suggest changes

The content on docs.arduino.cc is facilitated through a public GitHub repository. If you see anything wrong, you can edit this page here.

License

The Arduino documentation is licensed under the Creative Commons Attribution-Share Alike 4.0 license.