====== Sending Data from WaveForms SDK to ThingSpeak.com ======
{{ :reference:software:waveforms:waveforms-sdk:thingspeak_cover.png?600 |}}
~~TechArticle~~
===== 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 your WaveForms SDK compatible Digilent Test and Measurement Device up to ThingSpeak and ends with two optional examples.
One example uses the Pmod MIC3 to capture sound, then, from the measurements, the used Test and Measurement Device calculates the noise level. On the respective ThingSpeak channel, the noise level measurements are visualized in four different ways. The other example uses an Analog Discovery board and the Impedance Analyzer to measure the resistance, the reactance and the capacitance of different electronic components, then post the data on a ThingSpeak channel.
For a detailed description on how to run the noise level measurement example on Analog Discovery Pro in Linux mode, check this guide: [[test-and-measurement:analog-discovery-pro-3x50:linux-thingspeak-demo]].
----
===== Inventory =====
== Hardware ==
* A Digilent Test and Measurement device
* [[test-and-measurement:analog-discovery-3:start|Analog Discovery 3]]
* [[test-and-measurement:analog-discovery-pro-3x50:start|Analog Discovery Pro (ADP3450/ADP3250)]]
* [[test-and-measurement:analog-discovery-pro-2230:start|Analog Discovery Pro (ADP2230)]]
* [[test-and-measurement:analog-discovery-studio:start|Analog Discovery Studio]]
* [[test-and-measurement:analog-discovery-2:start|Analog Discovery 2]]
* [[test-and-measurement:analog-discovery:start|Analog Discovery (Legacy)]]
* [[test-and-measurement:digital-discovery:start|Digital Discovery]]
* [[https://digilent.com/shop/pmod-mic3-mems-microphone-with-adjustable-gain/|Pmod MIC3]] - used by the //Noise Pollution Monitoring// example
* [[https://digilent.com/shop/impedance-analyzer-for-analog-discovery/|Impedance Analyzer for Analog Discovery]] - used by the //Impedance Analyzer// example
== Software ==
* [[software:waveforms:waveforms-3:start]]
* [[https://www.python.org/downloads/|Python 3]]
* [[https://code.visualstudio.com/|Visual Studio Code]], or any other editor of your choice
**Note:** //WaveForms can be installed by following the [[software:waveforms:waveforms-3:getting-started-guide]]. By installing WaveForms, WaveForms SDK will be installed, which is needed later in this guide.//
----
===== Configuring a ThingSpeak Channel =====
Go to [[http://thingspeak.com|thingspeak.com]] and sign in or sign up.
{{ :reference:software:waveforms:waveforms-sdk:thingspeak_sign_in.png?600 |}}
In the //Channels// menu select //My Channels// and create a **New Channel**.
{{ :reference:software:waveforms:waveforms-sdk:thinspeak_newchannel.png?600 |}}
Configure the channel settings, name, and fields. The field will be the containers for your data. Configure a field for every data type, you want to store/process.
{{ :reference:software:waveforms:waveforms-sdk:thingspeak_channelset.png?600 |}}
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.
{{ :reference:software:waveforms:waveforms-sdk:thingspeak_keys.png?600 |}}
When uploading data to a ThingSpeak channel, it will be displayed field-by-filed 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.
{{ :reference:software:waveforms:waveforms-sdk:thingspeak_visualization.png?600 |}}
To make your visualizations/data publicly available, go to **Sharing** and select the option you want to set. //"iframe"//-s of certain graphical elements can also be embedded into your webpages.
{{ :reference:software:waveforms:waveforms-sdk:thingspeak_sharing.png?600 |}}
----
===== Examples =====
To see the usage of the ThingSpeak channels in a project, you can try the examples provided in this guide, or you can create your own examples.
--> Noise Pollution Monitoring #
== Hardware Setup ==
In this example, the Pmod MIC3 microphone module will be used with a Digilent Test and Measurement Device, to measure noise level. The Pmod communicates on SPI interface which will be connected to the Test and Measurement Device's digital I/O lines as follows: SS to DIO line 0 (DIO 24 on Digital Discovery), MISO to DIO 1 (DIO 25 on Digital Discovery) and SCK to DIO 2 (DIO 26 on Digital Discovery). Power to the Pmod is also supplied by the used Test and Measurement Device, so the VCC pin of the Pmod should be connected to the positive supply of the device (VIO on Digital Discovery) and the grounds of the two devices come connected together, as shown in the image to the right.
{{ :reference:software:waveforms:waveforms-sdk:thingspeak_wiring_diagram.png?600 |}}
== Software ==
The complete source code can be downloaded from here: {{ :reference:software:waveforms:waveforms-sdk:pmodmic3_to_thingspeak.zip |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 [[test-and-measurement:digital-discovery:controlling-digital-discovery-with-labview:start]], [[test-and-measurement:analog-discovery-2:ad2-motor-debugger:start]], the [[software:waveforms:waveforms-sdk:reference-manual-legacy]] and the examples available in the WaveForms installation directory.
For a demo project with Pmod MIC3, check [[https://projects.digilentinc.com/56469/using-the-pmod-mic3-with-arduino-uno-fc0daa|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()
== Results ==
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 [[https://www.mathworks.com/help/thingspeak/thingspeakread.html|thingSpeakRead()]].
{{ :reference:software:waveforms:waveforms-sdk:thingspeak_process.png?600 |}}
{{ :reference:software:waveforms:waveforms-sdk:thingspeak_result.png?600 |}}
<--
--> Impedance Analyzer #
== Hardware Setup ==
In this example, the Impedance Analyzer will be used, along with an Analog Discovery board, to measure the resistance, the reactance and the capacitance of different electronic components. In this guide the [[https://digilent.com/shop/impedance-analyzer-for-analog-discovery/|Impedance Analyzer for Analog Discovery]] will be used with Analog Discovery 2. If you plan to use the Analog Discovery Studio, or Analog Discovery 2 without the Impedance Analyzer, check this guide for a connection diagram: [[test-and-measurement:guides:waveforms-impedance-analyzer]]. To measure the properties of an electronic component, place it in the terminal block of the Impedance Analyzer board.
{{ :reference:software:waveforms:waveforms-sdk:thingspeak_wiring_diagram_impedance.png?400 |}}
== Software ==
The complete source code can be downloaded from here: {{ :reference:software:waveforms:waveforms-sdk:analogimpedance_thingspeak.zip |AnalogImpedance_ThingSpeak.zip}}. It contains the python script used to control the Impedance Analyzer instrument and to upload the measured data to ThingSpeak.
Discussing in detail the usage of the WaveForms SDK is beyond the scope of this project. For more information about it, check [[test-and-measurement:digital-discovery:controlling-digital-discovery-with-labview:start]], [[test-and-measurement:analog-discovery-2:ad2-motor-debugger:start]], the [[software:waveforms:waveforms-sdk:reference-manual-legacy]] and the examples available in the WaveForms installation directory.
For a demo project with the Impedance Analyzer, check: [[test-and-measurement:guides:waveforms-impedance-analyzer]].
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 Write API key in the address. Before calling any function from the WaveForms SDK, it is necessary to load the dynamic library.
"""
DWF Python Example
Author: Digilent, Inc.
Revision: 2019-10-21
Requires:
Python 2.7, 3
Desciption:
Performs impedance measurements and pushes to ThingSpeak.com
"""
from ctypes import *
from dwfconstants import *
import math
import time
import sys
import numpy
import requests
url = "https://api.thingspeak.com/update?api_key=8C############BU"
if sys.platform.startswith("win"):
dwf = cdll.LoadLibrary("dwf.dll")
elif sys.platform.startswith("darwin"):
dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
else:
dwf = cdll.LoadLibrary("libdwf.so")
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 signaled to the user.
version = create_string_buffer(16)
dwf.FDwfGetVersion(version)
print("DWF Version: "+str(version.value))
hdwf = c_int()
szerr = create_string_buffer(512)
print("Opening first device")
dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
if hdwf.value == hdwfNone.value:
dwf.FDwfGetLastErrorMsg(szerr)
print(str(szerr.value))
print("failed to open device")
quit()
Initializing the Impedance Analyzer instrument, with a reference resistor of 1MΩ (the reference resistor of the Impedance Analyzer board) and discarding one measurement to force starting a new one.
sts = c_byte()
frequnecy = 1e3
reference = 1e6
capacitance = c_double()
resistance = c_double()
reactance = c_double()
print("Reference: "+str(reference)+" Ohm Frequency: "+str(frequnecy/1e3)+" kHz")
dwf.FDwfAnalogImpedanceReset(hdwf)
# 0 = W1-C1-DUT-C2-R-GND, 1 = W1-C1-R-C2-DUT-GND, 8 = AD IA adapter
dwf.FDwfAnalogImpedanceModeSet(hdwf, c_int(8))
dwf.FDwfAnalogImpedanceReferenceSet(hdwf, c_double(
reference)) # reference resistor value in Ohms
dwf.FDwfAnalogImpedanceFrequencySet(
hdwf, c_double(frequnecy)) # frequency in Hertz
dwf.FDwfAnalogImpedanceAmplitudeSet(hdwf, c_double(1))
dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(1)) # start
time.sleep(1)
# ignore last capture, force a new one
dwf.FDwfAnalogImpedanceStatus(hdwf, None)
Measurements are done continuously until Ctrl+C is pressed. The results of the measurements uploaded to the given ThingSpeak channel. If a communication error appears, or the process is interrupted, the used instrument is stopped, and the program finishes.
print("Press Ctrl+C to stop...")
try:
for i in range(1000):
time.sleep(60) # seconds
if dwf.FDwfAnalogImpedanceStatus(hdwf, byref(sts)) == 0:
dwf.FDwfGetLastErrorMsg(szerr)
print(str(szerr.value))
quit()
if sts.value != 2:
print("Measurement not done")
continue
dwf.FDwfAnalogImpedanceStatusMeasure(
hdwf, DwfAnalogImpedanceResistance, byref(resistance))
dwf.FDwfAnalogImpedanceStatusMeasure(
hdwf, DwfAnalogImpedanceReactance, byref(reactance))
dwf.FDwfAnalogImpedanceStatusMeasure(
hdwf, DwfAnalogImpedanceSeriesCapactance, byref(capacitance))
print(str(i)+" Resistance: "+str(resistance.value)+" Ohm Reactance: " +
str(reactance.value/1e6)+" MOhm Capacitance: "+str(capacitance.value*1e12)+" pF")
r = requests.get(url+"&field1="+str(resistance.value)+"&field2=" +
str(reactance.value/1e6)+"&field3="+str(capacitance.value*1e12))
if r.status_code != 200:
print(r)
break
except KeyboardInterrupt: # Ctrl+C
pass
dwf.FDwfAnalogImpedanceConfigure(hdwf, c_int(0)) # stop
dwf.FDwfDeviceClose(hdwf)
== Results ==
The measured resistances, reactances and capacitances are displayed in the console window, as well as uploaded in the cloud. On the ThingSpeak channel the three default plots are displayed for the three data sets in the **Private View** or in the **Public View** tab, depending on the sharing settings of the channel.
{{ :reference:software:waveforms:waveforms-sdk:thingspeak-cmd.png?600 |}}
{{ :reference:software:waveforms:waveforms-sdk:thingspeak-impedance_result.png?600 |}}
<--
----
===== Next Steps =====
Now that data can be transferred between the test and measurement device and ThingSpeak, the script can be modified as needed for your project.
For more information on WaveForms SDK, see its [[software:waveforms:waveforms-sdk:start|Resource Center]].
For technical support, please visit the [[https://forum.digilent.com/forum/8-test-and-measurement/|Test and Measurement]] section of the Digilent Forums.