Sending Data to ThingSpeak.com with Analog Discovery Pro (ADP3450/ADP3250) in Linux Mode

Overview

ThingSpeak, created by MathWorks, is an online platform for collecting, viewing, and analyzing data in the cloud. This guide runs through the steps required to send data captured by the Analog Discovery Pro (ADP3450/ADP3250) up to ThingSpeak and ends with an example, which uses the Pmod MIC3 to capture a sound wave, then, from the measurements, the Analog Discovery Pro calculates the noise level. The noise level measurements are visualized in four different ways on the ThingSpeak channel.

To view examples for uploading data to ThingSpeak with other Test & Measurement devices, or with Analog Discovery Pro in Standard mode, check this guide: Sending Data from WaveForms SDK to ThingSpeak.com.

To take measurements and to upload data to ThingSpeak without the help of a PC, one can use the Analog Discovery Pro (ADP3450/ADP3250) in Linux mode. In this mode, the Test & Measurement device will run the script independently and can accept commands from any connected terminal.

To successfully run this example, you will need the latest Linux version for your device. To update the ADP3450/ADP3250 Linux image, follow this guide: How to Update or Recover Linux Mode on the Analog Discovery Pro (ADP3450/ADP3250).


Inventory

Hardware
Software
  • On PC:
    • Tera Term, or any other terminal emulator of your choice
    • Visual Studio Code, or any other editor of your choice (you can choose to use a text editor on the Analog Discovery Pro instead).
  • On Analog Discovery Pro:
    • WaveForms SDK - preinstalled
    • GNU nano, or any other editor of your choice (you can choose to use a text editor on the PC instead).

Note: WaveForms can be installed by following the WaveForms Getting Started Guide.

Note: In this guide, the Python script will be created and edited on the PC, then copied to an USB drive to move it on the Analog Discovery Pro. If you choose to edit the script directly on your Test & Measurement device, the steps are similar.


Setting Up the Analog Discovery Pro (ADP3450/ADP3250)

The first step is to connect your device to the internet. If you already have internet enabled for Linux mode, just connect the Ethernet cable and skip this step.

Connect the Analog Discovery Pro (ADP3450/ADP3250) to the Internet

The first step is to connect a serial terminal to your device, which will be used later when logging into Linux mode. Make sure that the Analog Discovery Pro is connected to the host computer and powered on.

Find out which serial port the device is connected to and make note of it. For example, if you are running Windows, this will be a COM port listed in the Device Manager.

Note that the serial connection should be established before booting into Linux mode, to ensure that no boot messages are missed.

Open a terminal emulator, such as TeraTerm, and connect to the noted serial port using 115200 Baud, 8 data, 1 stop, and no parity bits.

Note that if the Analog Discovery Pro is connected to immediately after booting, it may take approximately 20 seconds for the login prompt to be presented. If the screen is blank upon successful connection, press Enter on the keyboard and the login prompt should now be displayed.

Open WaveForms. The application will be used to configure the network settings of the device.

If the Device Manager hasn't opened, then select Settings → Device Manager. Make sure your device appears and is selected in the list of devices, boot into Linux Mode if you have not done so already, then click the Network button to open the Network Settings window.


Make sure to check the Apply these settings on Linux boot box.

It is important to note that you can later change these settings from within Linux itself, however, the settings seen here in the Network settings screen will be applied each time the device is rebooted.

To most easily connect to the internet, you should be connected to an access point that provides DHCP, typically a router. Check each of the “obtain automatically” boxes in order to take advantage of this.

Click Apply and Reboot in order to save the changed settings to the device and to reboot it.


You can observe the boot process with the previously-connected serial terminal. When it completes, a login prompt will be seen.

Once the device boots, log in using your username and password. The table below lists the defaults if you are using it for the first time:

Default username: digilent
Default password: digilent

Note that upon login, a “urandom warning” may be printed to the terminal, and can safely be ignored.


Check out the dropdowns below for instructions on setting up an internet connection through the corresponding interfaces:

Ethernet

Plug one end of the ethernet cable into the back of the Analog Discovery Pro and the other end into the router.

Run the ip addr show dev eth0 command, which will print the network information of the ethernet interface. If successfully connected to the local network it should be assigned an IP address, Gateway, etc.

WiFi

Enter superuser mode by running the command sudo su, entering the user's password when asked. On success, the active user should change to 'root'.

Plug the USB WiFi dongle into the bottom left USB port.

In the terminal, run ip l to get a list of network interfaces. In this case, the WiFi interface is `wlx00c0caad6c4b`, the final network interface in the screenshot to the right. Notice that the MAC address is included in the name. Yours will differ.

Create the WIF, WSSID, and WPWD environment variables to be used in the following commands. The WIF is the WiFi interface you found in the last step, while the WSSID and WPWD are the name and password of your WiFi network. This can be done as follows:

WIF=your-interface
WSSID=your-ssid-here
WPWD=your-password-here

Note: If the SSID or WPWD has '!' as a special character, history substitution must first be disabled by running set +H, and can be re-enabled by running set -H after completing this setup.

For a connection that will persist after a system reboot, run the following:

wpa_passphrase "$WSSID" "$WPWD" > /etc/wpa_supplicant/wpa_supplicant-${WIF}.conf
systemctl enable wpa_supplicant@${WIF}.service
systemctl start wpa_supplicant@${WIF}.service

Note that it may take some time for a WiFi connection to be established when rebooting the device, potentially several minutes.

For a connection that will only exist until a reboot, run the following:

wpa_supplicant -B -i $WIF -c <(wpa_passphrase "$WSSID" "$WPWD")

Note that it may take some time for a WiFi connection to be established when rebooting the device, potentially several minutes.



Now boot into Linux mode. If your device already is in Linux mode, just skip this step.

Booting into Linux Mode

Mode selection can be done through WaveForms using the Device Manager. With the Analog Discovery Pro connected to the host computer by Ethernet, open WaveForms. If the Device Manager hasn't opened yet, then click Settings → Device Manager.

Select the Analog Discovery Pro from the device menu, then click the Boot button. The Boot Mode window should open. By default, Standard Mode which allows the user to communicate with the instrumentation device over USB or Ethernet will be selected.

To change to Linux Mode, select Linux, then click “Apply & Reboot”.

At this time, an audible click should be heard and the Analog Discovery Pro will disconnect from WaveForms. About 10-15 seconds should pass before it reconnects. Confirm that the second column next to the Analog Discovery Pro says “ETH:LX”, confirming the mode has successfully been switched.


Configuring a ThingSpeak Channel

Go to thingspeak.com and sign in or sign up.

In the Channels menu select My Channels and create a New Channel.

Configure the channel settings, name, and fields. The field will be the containers for your data. Configure a field for every data type that you want to store/process.

Under API Keys, note the Write API Key that will be needed to push data to the server from the custom application or script. The Read API Key can be used to access stored data.

When uploading data to a ThingSpeak channel, it will be displayed field-by-field on different plots. To modify these default plots, or add other data visualization methods to your channel, you can use the visualization or widget presets, you can modify the MATLAB code of the default plots, or you can write your own code to visualize the data.

To make your visualizations/data publicly available, go to Sharing and select the option you want to set. “iframe” tags can be used to embed graphical elements from ThingSpeak into your webpages.


Script Overview

The complete source code of this project can be downloaded from here: PmodMIC3_to_ThingSpeak.zip. It contains the Python script used to control the Pmod MIC3, to convert the measured data, and to upload the results to ThingSpeak.

Discussing in detail the usage of the WaveForms SDK is beyond the scope of this project. For more information about it, check Controlling Digital Discovery With LabVIEW, Using the Analog Discovery 2 to Debug Different Motor Controllers, the WaveForms SDK Reference Manual, and the examples available in the WaveForms installation directory.

For a demo project with Pmod MIC3, check Using the Pmod MIC3 with Arduino Uno.

At the beginning of the script, the necessary modules are imported, then the address of the ThingSpeak channel is defined. To access your own channel, use your own API key in the address.

DIO lines used to communicate with the Pmod, as well as global variables controlling communication and data processing, are also defined here. Before calling any function from the WaveForms SDK, it is necessary to load the dynamic library.

"""import modules"""
import sys  # This module provides access to some objects used or maintained by the interpreter and to functions that interact strongly with the interpreter
import time  # This module provides various functions to manipulate time values
from ctypes import *  # C data types in Python
import signal    # This module provides mechanisms to use signal handlers
import requests  # Requests HTTP Library
 
# ----------------------------------------------------------------------------------------------------------
 
"""variables for communication with ThingSpeak"""
url = "https://api.thingspeak.com/update?api_key=E**************7"
 
# ----------------------------------------------------------------------------------------------------------
 
"""variables for connections and SPI"""
# define the communication frequency in Hz
spi_frequency = 1e6
# pin used for chip select (DIO 24 on Digital Discovery)
spi_CS = 0
# pin used for master in - slave out (DIO 25 on Digital Discovery)
spi_MISO = 1
# pin used for serial clock (DIO 26 on Digital Discovery)
spi_SCK = 2
# samples to average
AVERAGE = 1000
 
# ----------------------------------------------------------------------------------------------------------
 
"""load the WaveForms SDK"""
if sys.platform.startswith("win"):
    dwf = cdll.LoadLibrary("dwf.dll")  # on Windows
 
elif sys.platform.startswith("darwin"):
    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")  # on macOS
 
else:
    dwf = cdll.LoadLibrary("libdwf.so")  # on Linux

For repeating tasks like resetting and closing the used instruments, displaying error messages, and reading data on SPI, user defined functions are used. Certain keywords and interrupt handlers must also be defined before using them.

"""function to reset all instruments, close the device and quit"""
 
 
def close_device(signum=0, frame=0):
    signum = frame  # dummy
    frame = signum  # dummy
    print("Device disconnected\n")
    dwf.FDwfDigitalSpiReset(hdwf)
    dwf.FDwfDigitalOutReset(hdwf)
    dwf.FDwfDigitalInReset(hdwf)
    dwf.FDwfAnalogIOEnableSet(hdwf, c_int(False))
    dwf.FDwfDeviceClose(hdwf)
    sys.exit()
 
# ----------------------------------------------------------------------------------------------------------
 
 
"""function to display the last error message"""
 
 
def display_error(err_msg="No error"):
    if err_msg == "No error":
        err_msg = create_string_buffer(512)
        dwf.FDwfGetLastErrorMsg(err_msg)
        err_msg = str(err_msg.value)[2:-1]
        if err_msg == "":
            err_msg = "unknown error"
    print("Error: " + err_msg + "\n")
    return err_msg
 
# ----------------------------------------------------------------------------------------------------------
 
 
"""function to read spi data"""
 
 
def spi_read():
    lsb = c_int()
    msb = c_int()
    dwf.FDwfDigitalSpiSelect(hdwf, spi_CS, LOW)  # activate
    time.sleep(.001)  # millisecond
    spi_command = c_int(0)
    dwf.FDwfDigitalSpiWriteRead(hdwf, spi_mode, c_int(8), byref(
        spi_command), c_int(1), byref(lsb), c_int(1))  # read 1 byte
    dwf.FDwfDigitalSpiWriteRead(hdwf, spi_mode, c_int(8), byref(
        spi_command), c_int(1), byref(msb), c_int(1))  # read 1 byte
    time.sleep(.001)  # millisecond
    dwf.FDwfDigitalSpiSelect(hdwf, spi_CS, HIGH)  # deactivate
    return lsb.value | (msb.value << 8)
 
# ----------------------------------------------------------------------------------------------------------
 
 
"""keyboard interrupt handler and keywords"""
signal.signal(signal.SIGINT, close_device)
 
HIGH = c_int(1)
LOW = c_int(0)
DwfDigitalOutIdleZet = c_int(3)

Before using a Test and Measurement Device, it needs to be connected to the host computer. To safely connect it, cases in which the device is used by other software, or is not available from some other reason, should be evited.

"""open the connected T&M device"""
device_count = c_int()
dwf.FDwfEnum(c_int(0), byref(device_count))  # count devices
 
if device_count.value == 0:
    # terminate the program if no devices are connected
    display_error("No connected device detected")
    sys.exit()
 
for device_index in range(device_count.value):
    # get the name of the device
    device_name = create_string_buffer(64)
    dwf.FDwfEnumDeviceName(device_index, device_name)
 
    # connecting the device
    hdwf = c_int()
    dwf.FDwfDeviceOpen(device_index, byref(hdwf))
 
    # check for success
    if hdwf.value != 0:
        break
 
if hdwf.value == 0:
    # terminate the program if the device can't be connected
    display_error()
    sys.exit()
 
# display message
device_name = str(device_name.value)[2:-1]
print(device_name + " is connected\n")

To start communicating with the connected Pmod, it has to be powered. In devices which support this feature, the output voltage of the power supply should be set to 3.3V, as this is the recommended operating voltage of the Pmod. However, a supply voltage of 5V shouldn't damage the Pmod, according to its datasheet.

After the microphone is powered, the SPI interface should be initialized. After setting the communication parameters, a dummy read is performed to start driving the serial clock.

"""start the power supply"""
if device_name == "Digital Discovery" or device_name == "Analog Discovery Pro 3450" or device_name == "Analog Discovery Pro 3250":
    dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(
        0), c_double(3.3))  # set digital voltage to 3.3V
elif device_name == "Analog Discovery 2" or device_name == "Analog Discovery Studio":
    dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(
        0), c_double(True))  # enable positive supply
    dwf.FDwfAnalogIOChannelNodeSet(hdwf, c_int(0), c_int(
        1), c_double(3.3))  # set voltage to 3.3V
elif device_name == "Analog Discovery":
    dwf.FDwfAnalogIOChannelNodeSet(hdwf, 0, 0, 1)  # enable positive supply
else:
    display_error("Can't start the power supply. The device is incompatible.")
    close_device()
dwf.FDwfAnalogIOEnableSet(hdwf, c_int(True))  # master enable
print("Power supply started\n")
time.sleep(5)  # seconds
 
# ----------------------------------------------------------------------------------------------------------
 
"""initialize the spi communication"""
dwf.FDwfDigitalSpiFrequencySet(hdwf, c_double(
    spi_frequency))    # set clock frequency
dwf.FDwfDigitalSpiClockSet(hdwf, spi_SCK)   # SCK pin
dwf.FDwfDigitalSpiDataSet(hdwf, c_int(1), spi_MISO)  # MISO pin
dwf.FDwfDigitalSpiIdleSet(hdwf, c_int(1), DwfDigitalOutIdleZet)  # idle state
spi_mode = c_int(1)  # MOSI/MISO mode
dwf.FDwfDigitalSpiModeSet(hdwf, c_int(0))   # CPOL=0 CPHA=0 mode
dwf.FDwfDigitalSpiOrderSet(hdwf, c_int(1))  # MSB first
dwf.FDwfDigitalSpiSelect(hdwf, spi_CS, HIGH)  # CS pin
 
# dummy read to start driving the channels, clock and data
dwf.FDwfDigitalSpiReadOne(hdwf, c_int(1), c_int(0), c_int(0))
 
print("SPI interface initialized\n")
time.sleep(1)  # seconds

Measurements are done continuously until Ctrl+C is pressed. The results of the measurements are averaged, then converted to dB (this conversion is just an approximation of the true noise level).

The result of the conversion is pushed to the ThingSpeak channel. If a communication error appears, or the process is interrupted, the used instruments are reset, and the program finishes.

"""measure and send data to ThingSpeak"""
print("Measuring and uploading data. Press ctrl+c to stop...\n")
 
while True:
    try:
        # receive initial data
        level = 0
 
        # average data
        for index in range(AVERAGE):
            level += (spi_read() / 10) / AVERAGE
 
        # calculate noise level
        db = 729.0532027 - level * 0.4239354122 + \
            pow(level, 2) * 0.8875384813 * 1e-4 - \
            pow(level, 3) * 0.6195715088 * 1e-8
 
        # send data and check for errors
        send_state = requests.get(url+"&field1="+str(db))
        if send_state.status_code != 200:
            display_error("Can't communicate with ThingSpeak")
            close_device()
    except KeyboardInterrupt:  # exit if Ctrl+C is pressed
        break
 
# ----------------------------------------------------------------------------------------------------------
 
"""reset and close the device"""
close_device()

Hardware Setup

The Pmod MIC3 communicates on a SPI interface which will be connected to the Analog Discovery Pro's digital I/O lines as follows: SS to DIO line 0, MISO to DIO 1 and SCK to DIO 2. Power to the Pmod is also supplied by the Test and Measurement device used, so the VCC pin of the Pmod should be connected to the VIO pin on Analog Discovery Pro, and the grounds of the two devices should be connected together, as shown in the image to the right.

Prepare a FAT/FAT32 USB drive (while this is the default format for many USB drives, you may need to format it). Copy the Python script (PmodMIC3_to_Thingspeak.py) to the USB drive's root directory. You can also use your own Python script as well, just copy it to the root directory of the USB drive. Plug the USB drive into the back of the Analog Discovery Pro.


Running the Script and Results

To command the ADP3450/ADP3250, you will have to connect to it through a terminal. To do so, you will need a terminal emulator program, like Tera Term, PuTTY for Windows, or Serial WiFi Terminal for Android (the Analog Discovery Pro can now be controlled from any device connected to the internet).

Tera Term will be used in this guide, but the steps are similar for each of the mentioned programs.

Open WaveForms and open the Device Manager from the Settings menu, then select your device and open its Network Settings by clicking on the Network button. Note the IP address assigned to your device and close WaveForms.

Open the terminal emulator and establish a new Secure Shell (SSH) connection to the Analog Discovery Pro's IP address. You can leave every other setting as default. When required, enter the user name and the password:

user name: digilent
password: digilent

You should have now a connected terminal.


As the Python script uses the requests module to communicate with ThingSpeak, this module should be installed first, along with Python 3, by entering the following command into the terminal:

sudo apt-get install python3-requests

When required, enter the sudo password:

sudo password: digilent

Check the drive letter and partition number of the USB drive by entering the following command:

sudo fdisk -l

It should look like /dev/sd<drive letter><partition number>. This guide will use /dev/sda1 in its text and images, but this may differ with your device. Care must be taken to match the drive letter and partition number of your USB drive.

Make the drive contents accessible by entering the command:

sudo mount /dev/sda1 /mnt

And then:

cd /mnt

You can start the Python script by entering the command below, where PmodMIC3_to_Thingspeak.py is the name of the script file.

sudo python3 ./PmodMIC3_to_Thingspeak.py

The indicators can be added from the channel's Private/Public View, with the Add Visualization, Add Widget, MATLAB Analysis, or MATLAB Visualization buttons.

The measured noise levels can be plotted against time or displayed on a gauge widget. A histogram of the measured values can also be displayed, along with a virtual LED, to indicate dangerous noise levels. One important MATLAB function to use in data processing is thingSpeakRead().


Next Steps

Now that data can be transferred between the Analog Discovery Pro and ThingSpeak, the script can be modified as needed for your project.

For more information on WaveForms SDK, see its Resource Center.

For technical support, please visit the Test and Measurement section of the Digilent Forums.