We make measurements every day. The objective in any
measurement is to answer a question. So we take measurements to establish the
value or the tendency of some variable, the results of which are
specifically targeted to answer our question. However, for an engineer,
measurements provide data that needs to be processed
analyzed, interpreted, and decided upon. Moreover, measurements are a
significant part of control and automation systems. Without precise
measurements the control algorithms might suffer and would not fulfill their
goal.
Objectives
The overall objective of this class is to give students
a basic level of knowledge and understanding of measurements and their
applications in engineering practice.
This introductory lab has several teaching objectives
such as: a) introducing students to interface a pc computer with an analog
transducer; b) acquire data as voltage measurements; c) showing simple
programming concepts for measurements; c) learn to plot data in real time;
and d) introducing the statistical analysis for accuracy and explaining potential outliers of acquired
data. This lab has several sections of increasing difficulty from simple to
comple.
Introduction to Arduino Software
Arduino boards are one of the most cost efficiently ways
to perform engineering measurements since they interface analog sensors to
your computer or embedded measurements systems that you might use in an
automation environment. This following video is a tutorial that shows how to
connect to an Arduino Uno board to your pc, to install the Arduino software,
and upload Standard Firmata library that will give control of the board so
that we can program the board in Python. This is currently the easiest and
direct way to communicate with an Arduino through a programming language
other than C.
Right now, the Arduino board is ready to receive commands
from the Python environment. One thing to remember is the serial com port
number that your computer has allocated to the Arduino.
Python Installation and Modules Installation from Script
Thus, to acquire data from the Arduino board, Python
uses the pyfirmata module, which is a library of functions that converts
python code to C, in other words it is a python wrapper for Arduino firmata
protocol. It includes the serial communication, i.e. pyserial, that you
might have been used before.
This library gives us the ability to perform experiments and measurements
for whatever process or project we work on. Through serial communication
ports, such as USB ports, we are able to acquire data from sensors and
control our experimental devices in real time. Like all Python
libraries, pyfirmata is a module that compiles every time that we run our
code and so, it will optimize to run real fast, as opposed to an
"interpreted" software (MATLAB-like) that is compiled once for all time.
The next video shows how we can install Python, in case
that you do not already have it installed on your computer. The video also
shows how to install pyfirmata directly from a python script, without the
need of using a command prompt. This procedure applies for any other python
library that we will use during our measurements and data analysis as long
as we are running a Windows 10.
If you run on an older Windows operating system then
the following code will work well to install any python package directly
from the script.
try:
from pyfirmata import Arduino, util
except:
import pip
pip.main(['install','pyfirmata'])
from pyfirmata import Arduino, util
Sometimes the procedure that was presented above might
not work on your computer. If that is the case, then you can use the
command prompt and the pip function of python to install all the libraries that
were created for pip-installation. The next video takes you step by step
through this simple procedure.
This first example shows how easy it is to acquire data
and control electronics with Python while using an Arduino board. To keep
it simple for a start, we use a circuit having only an LED and a resistor,
other than the Arduino Uno board that is connected to the computer.
We turn the LED on and off and we measure the voltage drop as we do this.
The data is then plotted in real time and then we save this raw data in
a comma separated file ('.csv') for further use and analysis.
The next diagram shows how we need to wire the LED
and the resistor with the Arduino Uno board. To blink (actuate) the LED
we use a digital pin, for example pin 13, and to measure the voltage drop
on the LED we simply connect an analog pin, say pin A0, as a junction
between the LED and the resistor. A resistor is needed to protect the
LED since the 5 volts generated from digital pin 13 will burn it
relatively fast. A minimum value of 100 Ω will be enough to protect it.
If you are not familiar with the makeup of an electronic
breadboard, then the next image might be helpful.
As this is the first lab, let's program the measurements
in a gradual progression of difficulty,starting from simple tasks toward more
complex code of continuous measurements, plotting data in real time, and
saving it when we are done. If you connected the above LED circuit, then we
carry out a first set of voltage measurements by turning on and off the LED.
This whole procedure is presented in the following video.
This is the Python code that was used in the video to
interface Arduino board, turn on and off the LED, measure voltage and print
its value in the IDLE shell. Please copy and paste it in your python file
to run it.
# File: Lab1a_Measure_OneSetOfValues.py
# Written by George Bunget during Measurements Class, EGR 390, at MSU
# -------------------- Goal -------------------------------------
# Introduction to Arduino communication via python. Procedure: turn on/off a LED
# and get voltage measurements
##------------- Outline of this short code (pseudocode) -----------------
## 1) Import needed libraries such as pyfirmata, time, and numpy
## 2) Connect to the board and set pins for measurement (reading)
## * Need to power the LED so we can collect its voltage drop
## 3) Turn on the LED and get the voltage
## 4) Turn off the LED and get the voltage
## 1) Import needed libraries such as pyfirmata, time, and numpy
##================================================
from pyfirmata import Arduino, util
import time
import numpy as np
## 2) Connect to the board and set pins for measurement (reading)
##===============================================
board = Arduino('COM3')# tell python that our Arduino is connected to the serial port COM3
# COM3 is for my laptop configuration. Your's might be different
# Now, we use util to start an iterator that allows us to read from the board
iterator = util.Iterator(board)
iterator.start()
time.sleep(1.0)# wait 1 sec. Sometimes this helps to give time for communication
#in order to get an actual value and not get 'None' value
## 3) Turn on the LED & Measure Voltage Drop
##================================================
LED = board.get_pin('d:13:o')# assign the digital pin 13 as an output to power the LED
LED.write(1)# write a digital 1 meaning 5V to pin 13
Measured = board.get_pin('a:0:i')# assign the analog pin 0 as an input to
## measure the voltage drop on the LED
time.sleep(0.05)# wait 50 milisec. Sometimes this helps to give time for communication
#in order to get an actual value and not get 'None' value
# If you get a 'None' value increase the pause time
# This is very useful as the Arduino is runs much slower than your computer
Measured_Voltage = Measured.read()# measure the voltage on LED.
#It's a scaled value between 0 and 1
Voltage = Measured_Voltage*5.0 # convert scaled value, i.e. 0 to 1, to actual voltage
print('First value = ',Voltage)
# 4) Turn off the LED & Measure Voltage Drop
#=====================================================
LED.write(0)# write a digital 0 meaning 0V to pin 13
time.sleep(0.1)# wait 100 milisec. to give more time to the board to prepare the
# second reading for us. The computer is much faster
Measured_Voltage = Measured.read()# measure the voltage on LED
Voltage = Measured_Voltage*5.0
print('Second Value = ',Voltage)
Now we want to improve the previous code to run
continuously and take measurements. For this it is recommendable to save
the previous file with a different name, say Lab1b_Measure_Continuously.py.
We will make several modifications as explained in the next video and shown
in the next code snippet. In the end, please copy the following code
and run it on your computer. Do not forget to adjust the COM port value for
your machine.
# File: Lab1b_Measure_Continuously.py
# Written by George Bunget during Measurements Class, EGR 390, at MSU
# -------------------- Goal -------------------------------------
#Adjust the previous code, Lab1a_Measure_OneSetOfValues.py to continuously
# measure the voltage drop on the LED while we continuously turn it on & off.
##------------- Outline of this short code (pseudocode) -----------------
## 1) Import needed libraries such as pyfirmata, time, and numpy
## 2) Connect to the board and set pins for measurement (reading)
## * Need to power the LED so we can collect its voltage drop
## 3) Continuously turn on and off the LED while we measure voltage
## 1) Import needed libraries such as pyfirmata, time, and numpy
##========================================================
from pyfirmata import Arduino, util
import time
import numpy as np
## 2) Connect to the board and set pins for measurement (reading)
##======================================================
board = Arduino('COM3')
# Now, we use util to start an iterator that allows us to read from the board
iterator = util.Iterator(board)
iterator.start()
time.sleep(1.0)# wait 1 sec. Sometimes this helps to give time for communication
#in order to get an actual value and not get 'None' value
# Define the pins that we access
LED = board.get_pin('d:13:o')# assign the digital pin 13 as an output
Measured = board.get_pin('a:0:i')# assign the analog pin 0 as an input to
## measure the voltage drop on the LED
# 3) Continuously turn on and off the LED while we measure voltage
##=======================================================
# For this we create an infinte Loop to run continuously
while(True):
LED.write(1)# write a digital 1 meaning 5V to pin 13
time.sleep(1)# keep it on for 1 second
Measured_Voltage = Measured.read()# measure the voltage on LED
Voltage = Measured_Voltage*5.0
print('First value = ',Voltage)
LED.write(0)# write a digital 0 meaning 0V to pin 13
time.sleep(1)# keep it off for a second
Measured_Voltage = Measured.read()# measure the voltage on LED
Voltage = Measured_Voltage*5.0
print('Second Value = ',Voltage)
Engineers need to plot the measured data in real time so
they can see that what they are doing is good and otherwise correct their
measurement setup if is needed. Thus, plotting data in real time is very
useful during the design stage of a measurement setup. Sometimes, it can
also be useful for any user of the measurement setup. In the next video we
we define a function called "Figure" that we grab the measured data and
plot it after each measurement iteration. We still turn the LED on and off
and keep measuring its voltage drop. To plot our data in python, we need
two more libraries: matplotlib and drawnow. If you do not have these
libraries installed on your computer please watch the video presented
above in the subsection "Install Libraries with Pip on Command Prompt".
The next code snippet is organized as the pseudo-code outline. Please
copy the following code and run it on your computer.
# File: Lab1c_Measure_Continuously_AndPlot.py
# Written by George Bunget during Measurements Class, EGR 390, at Murray State University
# -------------------- Goal -------------------------------------
#Adjust the previous code, Lab1b__Measure_Continuously.py to plot data in
#real time while we continuously measure the voltage drop on the LED that we
#continuously turn it on & off to simulate an automation process.
##------------- Outline of this short code (pseudocode) -----------------
## 1) Import needed libraries such as pyfirmata, time, and numpy
## 2) Connect to the board and set pins for measurement (reading)
## * Need to power the LED so we can collect its voltage drop
## 3) Define a function in python that will plot our measured data in
## real time
## 4) Continuously turn on and off the LED while we measure voltage
## and then plot it after each iterative measurement
#-----------------------------------------------------------------------
## 1) Import needed libraries such as pyfirmata, time, and numpy, etc.
##==========================================================
from pyfirmata import Arduino, util
import time
import numpy as np
import matplotlib.pyplot as plt #import plotting library
from drawnow import * # import all functions within the drawnow library.
## 2) Connect to the board and set pins for measurement (reading)
##==========================================================
board = Arduino('COM3')
# Now, we use util to start an iterator that allows us to read from the board
iterator = util.Iterator(board)
iterator.start()
time.sleep(1.0)# wait 1 sec. Sometimes this helps to give time for communication
#in order to get an actual value and not get 'None' value
# Define the pins that we access
LED = board.get_pin('d:13:o')# assign the digital pin 13 as an output
Measured = board.get_pin('a:0:i')# assign the analog pin 0 as an input to
## measure the voltage drop on the LED
## 3) Define a function in python that will plot our measured data in real time
##============================================================
def Figure():
plt.plot(Time,VoltageArray, 'bo-', markersize=5) # we plot with blue color and round markers for each
# data point
plt.xlabel('Time, [s]')
plt.ylabel('Voltage, [V]')
plt.grid(color='gray', linestyle=':', linewidth=0.5)
# -------------------- Prepare Plotting in Real Time ----------------------------
VoltageArray = [] # create empty array that will fill in with every new data point
Time = [] # create an empty array for time axis
## 4) Continuously turn on and off the LED while we measure voltage
## and then plot it after each iterative measurement
##============================================================
time0 = time.time() # get the time when you start running this file
# Create an infinte Loop to run continuously
while(True):
LED.write(1)# write a digital 1 meaning 5V to pin 13
time.sleep(0.05)# wait 1 sec. Sometimes this helps to give time for communication
#in order to get an actual value and not get 'None' value
Measured_Voltage = Measured.read()# measure the voltage on LED
instance = time.time() # get the time of the measured voltage
Abs_time = instance-time0 # calculate an absolute value of time with 0 when we
# pressed the Run button of Python
Voltage = np.multiply(Measured_Voltage,5)# convert to actual volts
VoltageArray.append(Voltage) # Load distance point in our DataArray
Time.append(Abs_time) # insert the absolute time value into the Time array
print('First value = ',Voltage)
LED.write(0)# write a digital 0 meaning 0V to pin 13
time.sleep(0.05)# wait 1 sec. Sometimes this helps to give time for communication
#in order to get an actual value and not get 'None' value
Measured_Voltage = Measured.read()# measure the voltage on LED
instance = time.time() # get the time of the measured voltage
Abs_time = instance-time0 # calculate an absolute value of time with 0 when we
# pressed the Run button of Python
Voltage = Measured_Voltage*5.0
VoltageArray.append(Voltage) # Load distance point in our DataArray
Time.append(Abs_time) # insert the absolute time value into the Time array
print('Second Value = ',Voltage)
drawnow(Figure)
plt.pause(0.01)
Most of the time during design stage of a measurement
setup, we need to keep our data for further post-processing goals. This next
video shows how we can measure a square wave voltage drop on a LED that
simulates an automation process. We plot this data in real time, and then
save it in a comma separated file (.csv). The next code snippet is organized
as the pseudo-code outline. This python code is on the previous script
and adjusted so that it turns the LED on and off to follow a square wave
that we plot it in real time and then we save the data.
Please copy the following code and run it on your computer.
# File: Lab1d_Measure_Continuously_Plot_andSaveData.py
# Written by George Bunget during Measurements Class, EGR 390, at Murray State University
# -------------------- Goal -------------------------------------
#Adjust the previous code, Lab1c_Measure_Continuously_AndPlot.py to plot data in
#real time while we continuously measure the voltage drop on the LED that we
#continuously turn it on & off to simulate an automation process.
# Moreover, at the end of the measurements we want to keep our data for
# post-processing
##------------- Outline of this short code (pseudocode) -----------------
## 1) Import needed libraries such as pyfirmata, time, and numpy
## 2) Connect to the board and set pins for measurement (reading)
## * Need to power the LED so we can collect its voltage drop
## 3) Define a function in python that will plot our measured data in
## real time
## 4) Continuously turn on and off the LED while we measure voltage
## and then plot it after each iterative measurement
## 5) Save data in a spreadsheet, a comma separated file, .csv
#-----------------------------------------------------------------------
## 1) Import needed libraries such as pyfirmata, time, and numpy, etc.
##=======================================================
from pyfirmata import Arduino, util
import time
import numpy as np
import matplotlib.pyplot as plt #import plotting library
from drawnow import * # import all functions within the drawnow library.
## 2) Connect to the board and set pins for measurement (reading)
##======================================================
board = Arduino('COM3')
# Now, we use util to start an iterator that allows us to read from the board
iterator = util.Iterator(board)
iterator.start()
time.sleep(1.0)# wait 1 sec. Sometimes this helps to give time for communication
#in order to get an actual value and not get 'None' value
# Define the pins that we access
LED = board.get_pin('d:13:o')# assign the digital pin 13 as an output
Measured = board.get_pin('a:0:i')# assign the analog pin 0 as an input to
## measure the voltage drop on the LED
## 3) Define a function in python that will plot our measured data in real time
##========================================================
def Figure():
plt.plot(Time,VoltageArray, 'bo-', markersize=5) # we plot with blue color and round markers for each
# data point
plt.xlabel('Time, [s]')
plt.ylabel('Voltage, [V]')
plt.grid(color='gray', linestyle=':', linewidth=0.5)
# -------------------- Prepare Plotting in Real Time ----------------------------
VoltageArray = [] # create empty array that will fill in with every new data point
Time = [] # create an empty array for time axis
## 4) Continuously turn on and off the LED while we measure voltage
## and then plot it after each iterative measurement
##==================================================
# --------- Continually turn the LED on and off & Measure Voltage -------------
value = 20
time0 = time.time() # get the time when you start running this file
# Create an infinte Loop to run continuously
try:
while(True):
for x in range(value):
LED.write(1)# write a digital 1 meaning 5V to pin 13
time.sleep(0.05)# wait 50 milisec. Sometimes this helps to give time for communication
#in order to get an actual value and not get 'None' value
Measured_Voltage = Measured.read()# measure the voltage on LED
instance = time.time() # get the time of the measured voltage
Abs_time = instance-time0# calculate an absolute value of time with 0 when we
# pressed the Run button of Python
Voltage = Measured_Voltage*5.0# convert to actual volts
VoltageArray.append(Voltage) # Load distance point in our DataArray
Time.append(Abs_time) # insert the absolute time value into the Time array
print('First value = ',Voltage)
for x in range(value):
LED.write(0)# write a digital 0 meaning 0V to pin 13
time.sleep(0.05)# wait 50 milisec. Sometimes this helps to give time for communication
#in order to get an actual value and not get 'None' value
Measured_Voltage = Measured.read()# measure the voltage on LED
instance = time.time() # get the time of the measured voltage
Abs_time = instance-time0 # calculate an absolute value of time with 0 when we
# pressed the Run button of Python
Voltage = Measured_Voltage*5.0
VoltageArray.append(Voltage) # Load distance point in our DataArray
Time.append(Abs_time) # insert the absolute time value into the Time array
print('Second Value = ',Voltage)
drawnow(Figure)
plt.pause(0.01)
except KeyboardInterrupt:
print("Press Ctrl-C to terminate while statement")
pass
## 5) Save data in a spreadsheet, a comma separated file, .csv
##==========================================================
# We need to take the two line arrays, Time and VoltageArray, and join them
# together to form a 2D array with Time as first column and Voltage as
# second column.
# The savetxt function uses a format with 3 decimal points, i.e. fmt="%1.3f"
data = np.stack((Time, VoltageArray), axis=1)
print('Data ', data)
np.savetxt('Voltage_Measurements_Midpoint.csv',data,delimiter=",", header="Time [s],Voltage [V]",
fmt="%1.3f", comments='')