Welcome to RacerNet


Lab1. Arduino Hardware and Software

    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.
    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, install the Arduino software, and upload Standard Firmata library that will give control of the board so that we can program it 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
			
		

Install Libraries with Pip on Command Prompt

    Sometimes the procedure that I presented above might not work on your computer. If that is the case, then you can use the command prompt and 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.



Python Serial Communication with Pyfirmata

    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.


Introduction to Python Measurements Programming

    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.

1) Measure & Print One Set of Values

    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 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)


			
		

2) Continuously Measure 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 for your machine.

	
# File: Lab1b_Measure_Continuously.py
# Written 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)



			
		

3) Plot Data in Real Time

    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 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)





			
		

4) Plot Data in Real Time and Save it

    Most of the time during design stage of a measurement setup, we need to keep our data for further post-processing goals. This 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 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='')