Difference between revisions of "Python:DAQ 1"
Line 74: | Line 74: | ||
== Code == | == Code == | ||
− | The following code listing is for <code>three_bits.py</code> In lab, do not put all this code in at once! Follow along with the | + | The following code listing is for <code>three_bits.py</code> In lab, do not put all this code in at once! Follow along, save the code after each section, and run it. |
− | <source lang=" | + | |
+ | === Imports === | ||
+ | To access the functions to work with the DAQ card, you will need to import the PyDAQmx module. Since this module is dependent on numpy, you need to import numpy as well. Start your code with: | ||
+ | <source lang="python"> | ||
+ | #%% Import modules | ||
+ | import numpy as np | ||
+ | import PyDAQmx as daq | ||
+ | </source> | ||
+ | === Create a Task === | ||
+ | DAQ functions are run via a Task object, so next you will tell the daq module to create a task: | ||
+ | <source lang="python"> | ||
+ | #%% Create a task | ||
+ | task = daq.Task() | ||
+ | </source> | ||
+ | |||
+ | === Useful Functions === | ||
+ | There are two useful functions defined in this section. | ||
+ | |||
+ | The first one has all the code needed to take a list of binary digits (zeros and ones) and send them to the data acquisition card. Note that this function works using the task that you created earlier. | ||
+ | <source lang="python"> | ||
+ | #%% Define useful functions | ||
+ | # Function to change daq outputs | ||
+ | def write_data(data): | ||
+ | task.WriteDigitalLines(1, 1, 10.0, | ||
+ | daq.DAQmx_Val_GroupByChannel, | ||
+ | np.array(data, dtype=np.uint8), | ||
+ | None, None) | ||
+ | </source> | ||
+ | |||
+ | The second useful function converts a decimal number into a reverse-ordered list of binary digits. The reason for converting to binary is that the write_data() function needs binary digits. The reason for reversing the order is that write_data will take the first entry of the list and give it to the first output line you opened. The first line you opened is going to represent the 1s digit, followed to the 2s digit, followed by the 4s digit. That means you need to give the data from what you think of as right-to-left; this function will thus reverse the order for you: | ||
+ | <source lang="python"> | ||
+ | # Function to make 3-element LSB-first binary list from integer | ||
+ | def d_to_b(n): | ||
+ | bits = list(map(int, '{:03b}'.format(n))) | ||
+ | return bits[::-1] | ||
+ | </source> | ||
+ | |||
+ | === Adding Lines and Starting Tasks === | ||
+ | This part of the code will use the CreateDOChan to open digital output channels on the card specified in the first argument. Specifically, the card is Dev1 and on that device, the first bank of digital output lines is on port0. Within port 0, there are up to 8 lines - this code opens lines 0 through 2 (0:2). Once the lines are added, the code stops the task (in case it was still running) and then starts it - the card is now ready to work. | ||
+ | <source lang="python"> | ||
+ | #%% Add digital output lines | ||
+ | task.CreateDOChan("Dev1/port0/line0:2", "", | ||
+ | daq.DAQmx_Val_ChanForAllLines) | ||
+ | |||
+ | #%% Stop and start task | ||
+ | task.StopTask() | ||
+ | task.StartTask() | ||
+ | </source> | ||
+ | |||
+ | === Checking Lights === | ||
+ | Before doing anything interesting with the code, you will want to make sure all the lights are working. The following code will first turn the three channels on then it will wait for you to provide an input (you can just hit return). After that is done, it will turn the lights off. | ||
+ | <source lang="python"> | ||
+ | #%% Check lights | ||
+ | write_data([1, 1, 1]) | ||
+ | input('PAUSED - Hit return to continue ') | ||
+ | write_data([0, 0, 0]) | ||
+ | </source> | ||
+ | |||
+ | === Updating and Lighting Values === | ||
+ | This part of the code will start by turning the lights off, then it will ask the user for an input. The code converts that input to an integer (since input always returns strings) and sends that value to the write_data() function by first passing it through the d_to_b() function. That is, the code will convert the decimal number to a least-significant-bit-first 3-entry list, then it will send that list to the card. | ||
+ | <source lang="python"> | ||
+ | #%% Write values to output using base 10 | ||
+ | val = 0 | ||
+ | while 0 <= val <= 7: | ||
+ | write_data(d_to_b(val)) | ||
+ | val = int(input('Enter a number between 0 a 7: ')) | ||
+ | </source> | ||
+ | |||
+ | === Cleaning Up === | ||
+ | When the program is done, it should turn all the lights off and then stop the task. | ||
+ | <source lang="python"> | ||
+ | #%% Turn all off when finished and stop task | ||
+ | write_data(d_to_b(0)) | ||
+ | task.StopTask() | ||
+ | </source> | ||
+ | |||
+ | |||
+ | === Full Code === | ||
+ | Here is what the code will eventually look like: | ||
+ | <source lang="python"> | ||
#%% Import modules | #%% Import modules | ||
import numpy as np | import numpy as np |
Revision as of 22:25, 13 February 2019
This page contains pictures and graphs related to Data Acquisition Laboratory 1 (DAQ 1) of EGR 103. It has been updated for Spring, 2019 - including changing the language to Python.
Contents
Supporting Pundit Pages
Typographical Errors / Clarifications
- If the computer says your device is not found, try 'Dev2' instead of 'Dev1' in the
task.CreateDOChan("Dev1/port0/line0:2","", daq.DAQmx_Val_ChanForAllLines)
- line.
- If the you run the code and get an error:
DAQError: Specified operation cannot be performed while the task is running.
- or
DAQError: Requested operation could not be performed, because the specified digital lines are either reserved or the device is not present in NI-DAQmx.
- that generally means you had a task running and did not get a chance to stop it (for instance, if your code had an error before getting to the task.StopTask() line. To troubleshoot that:
- Try to run the code again - the task.StopTask() in the code might overcome the problem
- If that does not work, clear the variables by clicking the black and white eraser rhombus to the right above the IPython console. That generally removes all tasks so you can try again.
Module Installation
- From the Start menu, find the Anaconda3 folder
- In the Anaconda3 folder, start the Anaconda Prompt
- In the Anaconda Prompt, type
pip install pydaqmx
Equipment Used
National Instruments Data Acquisition Cards
B209 has machines with two different data acquisition cards. Most of the machines have NI PCI 6014e cards, which will be what is discussed here. The others have a newer NI PCI 6221 cards. The NI PCI 6014e card can read up to 16 single-ended (8 differential) analog voltage measurements, has two analog outputs, and has 8 configurable digital input/output lines. The 6221 cards are more powerful but, generally in EGR 103, we will limit ourselves to the features available on the 6014e cards.
Be careful when making connections; improperly connecting wires can lead to catastrophic damage on the DAQ cards, as is shown on the second picture at right.
CB-68LP
During this lab, you will use the CB-68LP to connect wires to parts of the NI PCI 6014e card. Be sure to use the proper connections - a map is available at the MATLAB:CB-68LP Pinout page.
Radio Shack Experimentor 350
The Experimentor 350 is a simple, but useful, prototyping board. It has two distribution strips (rows X and Y) with 20 pins each and 46 groups of 5 pins on its terminal strip. All the pins in row X are connected together, and all the pins in row Y are connected together; note, however, that X is not connected to Y.
For the main part of the board, half-columns are connected together. For example, rows (ABCDE) in column 3 are all connected. Note, however, that ABCDE are not connected to FGHIJ.
Also, there are some helpful index numbers at the top and bottom to help determine which column you are in. For rows X and Y, some indices do not exist. For example, there is no pin at X6, X12, X18, Y6, Y12, or Y18.
Resistors
Resistors take energy out of an electric circuit and convert that energy to heat. In this case, the light emitting diodes cannot handle the amount of current that the DAQ card can produce, so resistors are placed in parallel to reduce that current. You can use the Resistor Color Codes to determine the resistance of the resistors pictures at right; there should be four resistors (at least) in your box.
LEDs
A diode is an electrical element that generally only allows current to flow in one direction - and only after there is a sufficient voltage difference across the appropriate terminals. LEDs - Light Emitting Diodes - are a special form of diode that emit light when current flows through them.
Because diodes and LEDs are directional, there are visible clues about which side is which. In the first picture at right, the lengths of the leads on the diodes are clearly different - the longer lead should be placed where the higher voltage is expected, as current will be allowed to flow into the longer lead, through the diode, and out through the shorter lead. For the round LEDs, a flat is ground into the collar of the LED on the lower-voltage side - this is shown more clearly in the second picture. Finally, within the diode itself, the larger "flag" of metal inside the diode is on the lower voltage side.
Note that the color of the plastic is not what determines the color of the light - rather the specific semiconductor material and the geometry of the LED do that. The plastic is a convenient way of knowing what color the light will be, however.
Circuit Construction
The pictures at right show both the breadboard and the CB-68LP once everything has been properly connected. Note especially on the CB-68LP where the wires are - there will be no connections in the first two columns and there is only one connection - the black wire for digital ground - in the fifth column.
Code
The following code listing is for three_bits.py
In lab, do not put all this code in at once! Follow along, save the code after each section, and run it.
Imports
To access the functions to work with the DAQ card, you will need to import the PyDAQmx module. Since this module is dependent on numpy, you need to import numpy as well. Start your code with:
#%% Import modules
import numpy as np
import PyDAQmx as daq
Create a Task
DAQ functions are run via a Task object, so next you will tell the daq module to create a task:
#%% Create a task
task = daq.Task()
Useful Functions
There are two useful functions defined in this section.
The first one has all the code needed to take a list of binary digits (zeros and ones) and send them to the data acquisition card. Note that this function works using the task that you created earlier.
#%% Define useful functions
# Function to change daq outputs
def write_data(data):
task.WriteDigitalLines(1, 1, 10.0,
daq.DAQmx_Val_GroupByChannel,
np.array(data, dtype=np.uint8),
None, None)
The second useful function converts a decimal number into a reverse-ordered list of binary digits. The reason for converting to binary is that the write_data() function needs binary digits. The reason for reversing the order is that write_data will take the first entry of the list and give it to the first output line you opened. The first line you opened is going to represent the 1s digit, followed to the 2s digit, followed by the 4s digit. That means you need to give the data from what you think of as right-to-left; this function will thus reverse the order for you:
# Function to make 3-element LSB-first binary list from integer
def d_to_b(n):
bits = list(map(int, '{:03b}'.format(n)))
return bits[::-1]
Adding Lines and Starting Tasks
This part of the code will use the CreateDOChan to open digital output channels on the card specified in the first argument. Specifically, the card is Dev1 and on that device, the first bank of digital output lines is on port0. Within port 0, there are up to 8 lines - this code opens lines 0 through 2 (0:2). Once the lines are added, the code stops the task (in case it was still running) and then starts it - the card is now ready to work.
#%% Add digital output lines
task.CreateDOChan("Dev1/port0/line0:2", "",
daq.DAQmx_Val_ChanForAllLines)
#%% Stop and start task
task.StopTask()
task.StartTask()
Checking Lights
Before doing anything interesting with the code, you will want to make sure all the lights are working. The following code will first turn the three channels on then it will wait for you to provide an input (you can just hit return). After that is done, it will turn the lights off.
#%% Check lights
write_data([1, 1, 1])
input('PAUSED - Hit return to continue ')
write_data([0, 0, 0])
Updating and Lighting Values
This part of the code will start by turning the lights off, then it will ask the user for an input. The code converts that input to an integer (since input always returns strings) and sends that value to the write_data() function by first passing it through the d_to_b() function. That is, the code will convert the decimal number to a least-significant-bit-first 3-entry list, then it will send that list to the card.
#%% Write values to output using base 10
val = 0
while 0 <= val <= 7:
write_data(d_to_b(val))
val = int(input('Enter a number between 0 a 7: '))
Cleaning Up
When the program is done, it should turn all the lights off and then stop the task.
#%% Turn all off when finished and stop task
write_data(d_to_b(0))
task.StopTask()
Full Code
Here is what the code will eventually look like:
#%% Import modules
import numpy as np
import PyDAQmx as daq
#%% Create a task
task = daq.Task()
#%% Define useful functions
# Function to change daq outputs
def write_data(data):
task.WriteDigitalLines(1, 1, 10.0,
daq.DAQmx_Val_GroupByChannel,
np.array(data, dtype=np.uint8),
None, None)
# Function to make 3-element LSB-first binary list from integer
def d_to_b(n):
bits = list(map(int, '{:03b}'.format(n)))
return bits[::-1]
#%% Add digital output lines
task.CreateDOChan("Dev1/port0/line0:2", "",
daq.DAQmx_Val_ChanForAllLines)
#%% Stop and start task
task.StopTask()
task.StartTask()
#%% Check lights
write_data([1, 1, 1])
input('PAUSED - Hit return to continue ')
write_data([0, 0, 0])
#%% Write values to output using base 10
val = 0
while 0 <= val <= 7:
write_data(d_to_b(val))
val = int(input('Enter a number between 0 a 7: '))
#%% Turn all off when finished and stop task
write_data(d_to_b(0))
task.StopTask()
Other Resources
- Landing Lights Animation:
Questions
Post your questions by editing the discussion page of this article. Edit the page, then scroll to the bottom and add a question by putting in the characters *{{Q}}, followed by your question and finally your signature (with four tildes, i.e. ~~~~). Using the {{Q}} will automatically put the page in the category of pages with questions - other editors hoping to help out can then go to that category page to see where the questions are. See the page for Template:Q for details and examples.