Python U3 stream config for digital IO | LabJack
 

Python U3 stream config for digital IO

20 posts / 0 new
Last post
Terry
ttamboh's picture
Python U3 stream config for digital IO

Hello,

 

I am a bit new to using labjack U3. I am trying to configure streaming for digital input in python and I am running into the "This error is raised when you try to do an analog operation on a pin which is configured for digital." My understanding from reading the datasheet is that by default all the IO are set as digital inputs and only needs changing when we are dealing with analog inputs/output (ex. configIO(FIOAnalog=255))

A little about what I am trying to do. I have two hall sensor and 2 encoder, all outputting digital data, connected to the labjack. I am trying use the labjack to stream their data and save it to a file on my pc.

Following the stream. py code from the example, here is what I have 

import u3

MAX_REQUESTS = 75

d = u3.U3()

d.getCalibrationData()

d.configIO()

TestChannels = [0,1,3,8,10,17,19]

d.streamConfig( NumChannels = len(TestChannels), PChannels = TestChannels, NChannels = [ 31]*len(TestChannels), Resolution = 3, ScanFrequency = 5000 )

Is there something I am doing wrong?

 

Any help is appreciated

 

Thanks,

Terry

LabJack Support
LabJack Support's picture
That error indicates one or

That error indicates one or multiple channels you are trying to stream as analog inputs are configured as digital I/O. The TestChannels you use are analog input channels. Channels 0-15 are AIN0-AIN15. Channels 17 and 19 are not valid. If those are meant to be digital I/O, use channels 193 (EIO_FIO) and 194 (CIO). Those stream channels are documented here:

https://labjack.com/support/datasheets/u3/operation/stream-mode/digital-inputs-timers-counters

When getting the stream data with LabJackPython, the channel names are AIN#, where # is the channel number. So the digital readings will be in r["AIN193"] and r["AIN194"].

Before configuring/starting the stream, configure I/O as digital (with configIO and its FIOAnalog and EIOAnalog parameters) and digital directions to inputs (with getFeedback). The quickstart demonstrates configIO and getFeedback. To configure multiple digital directions, you can also use getFeedback with u3.PortDirWrite.

https://labjack.com/support/software/examples/ud/labjackpython/low-level

A quick demonstration of setting all FIOs and EIOs to digital I/O and direction to inputs (In the comments, numbers prefixed by "b" indicates binary. Each bit of the passed value is an I/O setting.):

# b0 = analog, b1 = digital
# FIOAnalog = 0 = b00000000
# EIOAnalog = 0 = b00000000
d.configIO(FIOAnalog=0, EIOAnalog=0)


# b0 = input, b1 = output
# Direction = [FIODirection, EIODirection, CIODirection] = [0, 0, 0] = [b00000000, b00000000, b0000]
d.getFeedback(u3.PortDirWrite(Direction=[0, 0, 0]))

LabJack Support
LabJack Support's picture
To add, factory power up

To add, factory power up defaults for FIOs and EIOs are digital inputs. On the U3-HV, FIO0-FIO3 are analog inputs only. So if you have not changed the power up defaults, or configured lines as analog inputs while the U3 has been powered, the configIO and getFeedback calls I mentioned at the end of my last post are not needed, but they do ensure all FIOs and EIOs are digital inputs before streaming.

Terry
ttamboh's picture
Thank you for yourn quick

Thank you for yourn quick responds,

Your guidance above is very helpful. To follow up, once I have configure all FIO, EIO and CIO as digital inputs (with channesl 193,194), how do i stream individual IO? Will the IO still follow the same numbering (0-15) for FIO_EIO and 17,19 in the CIO? If so can I just do the following:

for r in d.streamData(): if r is not None: # Our stop condition if dataCount >= MAX_REQUESTS: break print r['AIN0'], ",", r['AIN1'], ",", r['AIN3'], ",", r['AIN8'], ",", r['AIN10'], ",", r['AIN17'], ",",r['AIN19']
Terry
ttamboh's picture
I think I figured out it. 

I think I figured out it. 

I used the following and I don't get any errors at all

print (r['AIN193'][0]), ",", (r['AIN193'][1]), ",", (r['AIN193'][3]), ",", (r['AIN193'][8]), ",", (r['AIN193'][10]), ",", (r['AIN194'][17]), ",", (r['AIN194'][19])

 

LabJack Support
LabJack Support's picture
r['AIN193'] is a list of EIO

r['AIN193'] is a list of EIO and FIO samples. Each list element has a 2 element tuple, which are the FIO readings ( r['AIN193'][x][0] ) and EIO readings ( r['AIN193'][x][1] ).

r['AIN194'] is a list of CIO samples. Each list element has a 2 element tuple, which are the CIO readings ( r['AIN194'][x][0] ) and 0 (no data, ignore it).

FIO, EIO and CIO stream readings/samples are byte values, where each bit is a line's state. Bit 0 is the FIO0/EIO0/CIO0 state, bit 1 is the FIO1/EIO1/CIO1 state, and so on. 0 is a low state, and 1 is a high state.

Digital I/O 0, 1, 3, 8, 10, 17, 19 are FIO0, FIO1, FIO3, EIO0,  EIO2, CIO1, CIO3. To get the first scan of samples of the FIO, EIO and CIO states (parsed into lists of states) and display the ones you want:

fio = [(r["AIN193"][0][0] >> i) & 1 for i in range(8)]
eio = [(r["AIN193"][0][1] >> i) & 1 for i in range(8)]
cio = [(r["AIN194"][0][0] >> i) & 1 for i in range(4)]
print("1st: %d %d %d %d %d %d %d" % (fio[0], fio[1], fio[3], eio[0], eio[2], cio[1], cio[3]))

Second scan of samples:

fio = [(r["AIN193"][1][0] >> i) & 1 for i in range(8)]
eio = [(r["AIN193"][1][1] >> i) & 1 for i in range(8)]
cio = [(r["AIN194"][1][0] >> i) & 1 for i in range(4)]
print("2nd: %d %d %d %d %d %d %d" % (fio[0], fio[1], fio[3], eio[0], eio[2], cio[1], cio[3]))

And so on.

Terry
ttamboh's picture
Hello,

Hello,

I have a follow up question to the above. Why do we have two states. What is the difference between them?

what is the difference between r["AIN193"][0][0] and (r["AIN193"][1][0]

 

LabJack Support
LabJack Support's picture
r["AIN193"][0][0] is the

r["AIN193"][0][0] is the first reading of FIO0-7 states and r["AIN193"][1][0] is the second reading of FIO0-7 states. To continue, r["AIN193"][2][0] is the third, r["AIN193"][3][0] is the fourth, and so on. In my previous post I demonstrate parsing out the FIO, EIO, and CIO states for the first two set of readings (scans) and displaying the FIO0, FIO1, FIO3, EIO0,  EIO2, CIO1, and CIO3 states. My previous post goes into more details of the returned stream data when streaming with channels 193 and 194.

Terry
ttamboh's picture
I guess I am confused about

I guess I am confused about the following:

1. How are you getting the values of FIO1,FIO3 from below?

fio = [(r["AIN193"][0][0] >> i) & 1 for i in range(8)]
print("1st: %d %d %d" % (fio[0], fio[1], fio[3]))

I was under the impression that the values are obtained by doing r["AIN193"][1][0], r["AIN193"][3][0]. How is the fioproviding data for all FIO channels?

 

LabJack Support
LabJack Support's picture
With stream mode you are

With stream mode you are reading many samples/readings which the hardware is sampling at the configured scan rate. Refer to stream mode documentation for general details:

https://labjack.com/support/datasheets/u3/operation/stream-mode

r["AIN193"][1][0] is the second reading of FIO0-FIO7 states, and r["AIN193"][3][0] is the fourth reading of FIO0-FIO7 states. r["AIN193"][x] is not the digital I/O channel, but the reading number. When streaming digital I/O, you are reading digital I/O grouped. Refer to post #6 for details.

So lets break down the first reading of FIO0-7, which would be in r["AIN193"][0][0]. That will be a value of 0 to 255, an 8-bit value. Each bit is a state (0 = low, 1 = high). Bit 0 is the state of FIO0, bit 1 is the state of FIO1, and so on. For example, if FIO0-3 are low, and FIO4-7 are high, that would be a read value of 240, which in binary is b11110000. This code is parsing out the individual states from the 8-bit value (0-255):

fio = [(r["AIN193"][0][0] >> i) & 1 for i in range(8)]

Broken down is something like:

fio = [0]*8  # Create an 8 element array for the individual states
fio[0] = (r["AIN193"][0][0] >> 0) & 1  # Bit 0 value (FIO0 state)
fio[1] = (r["AIN193"][0][0] >> 1) & 1  # Bit 1 value (FIO1 state)
fio[2] = (r["AIN193"][0][0] >> 2) & 1  # Bit 2 value (FIO2 state)
fio[3] = (r["AIN193"][0][0] >> 3) & 1  # Bit 3 value (FIO3 state)
fio[4] = (r["AIN193"][0][0] >> 4) & 1  # Bit 4 value (FIO4 state)
fio[5] = (r["AIN193"][0][0] >> 5) & 1  # Bit 5 value (FIO5 state)
fio[6] = (r["AIN193"][0][0] >> 6) & 1  # Bit 6 value (FIO6 state)
fio[7] = (r["AIN193"][0][0] >> 7) & 1  # Bit 7 value (FIO7 state)

So if r["AIN193"][0][0] is value 240 for demonstration purposes, the above code parses it to:

fio[0] = 0
fio[1] = 0
fio[2] = 0
fio[3] = 0
fio[4] = 1
fio[5] = 1
fio[6] = 1
fio[7] = 1

So parsing the first reading's FIO states using the one line of code parsing is:

fio = [(r["AIN193"][0][0] >> i) & 1 for i in range(8)]

The second reading's FIO states:

fio = [(r["AIN193"][1][0] >> i) & 1 for i in range(8)]

The third:

fio = [(r["AIN193"][2][0] >> i) & 1 for i in range(8)]

The fourth:

fio = [(r["AIN193"][3][0] >> i) & 1 for i in range(8)]

and so on.

If you are reading digital I/O at a rate under 100 Hz, consider using command-response mode which is less complex than stream mode. Your software will control the rate of the readings. For example, getting one reading of FIO0, FIO1, FIO3, EIO0,  EIO2, CIO1, CIO3 could be:

command = [u3.BitStateRead(0), u3.BitStateRead(1), u3.BitStateRead(3), u3.BitStateRead(8), u3.BitStateRead(10), u3.BitStateRead(17), u3.BitStateRead(19)]
states = d.getFeedback(command)  # Returned are the states of only [FIO0, FIO1, FIO3, EIO0,  EIO2, CIO1, CIO3]

Terry
ttamboh's picture
Thank you for the explanation

Thank you for the explanation. How do I retrieve the actual sample values from the streams for the above channels? 

LabJack Support
LabJack Support's picture
Please see the above posts.

Please see the above posts. If that doesn't explain it, can you ask a more specific question?

Terry
ttamboh's picture
So the problem I am having is

So the problem I am having is I have a max_request of 75, each request should contain 48 packets and each packet should have 25 samples. So I should expect 90,000 samples in total per channel. So for 7 channel, i should expect a 90,000 x7 matrix of samples. However, I dont get that. I get 75 x7 samples.

LabJack Support
LabJack Support's picture
 

Why are you using 7 in your multiplication? Channels 193 and 194 are the only channels (as far as the returned array goes) you are streaming.

Do you understand how to parse out the FIO bits, EIO bits and CIO bits, which are the states? Do my previous explanations make sense?

You are streaming two channels Each channel will be one sample. You are not streaming 7 channels, but the two channels do contain the states you want (including all digital I/O states).

Channel 193 contains the FIO and EIO states in the one sample (the two element tuple mentioned earlier) and channel 194 contains the CIO states in one sample (also in a two element tuple). This is mentioned in post 6.

If you do len(r[“AIN193”]) and len(r[“AIN194”]) you will see how many samples there are for each channel, and you need to parse out the states from the samples. Previous posts go over the parsing out the states.

Terry
ttamboh's picture
Hello,

Hello,

Sorry for the confusion, the 7 that i was referring to was the 7 states that was pulling out of the AIN193 and AIN194. It seems that I was taking the first reading of each scan only. I just needed a loop to step through all the readings and do the approriate bitwise conversions you showed in post 6 and now I am getting the satisfied result. 

One question that I had is whether it is possible to stream 2 hall sensors and 2 encoders (quadrature with differential outputs) data at the same time. I am trying to map the hall states to the position of the encoders. I understand that each encoder takes 2 timers to operate. Is there a way to a way to have the two encoders share the same times? Could you point in the direction of how set that up perhaps an example? 

Thanks

LabJack Support
LabJack Support's picture
it is possible to stream 2

it is possible to stream 2 hall sensors and 2 encoders

To measure two quadrature encoders with the U3 you would need to stop and reconfigure the timers are regular intervals. Doing so would mean that reading of one encoder would be suspended while the other encoder is being read. To get that to work you would need to be able to guarantee that the encoder not being read is either not generating counts, or at least not generating counts that we care about.

Another possibility is to use a counter. The counter will just count pulses on one signal and thus will not have any indication of direction; will only count up.

Beyond that, we need a DAQ capable of reading two encoders or a second DAQ.

Terry
ttamboh's picture
Knowing direction is not

Knowing direction is not important because I will control that with the motor controller and will. Do you have any examples on how the counter(s) should be setup?

 

Thanks,

LabJack Support
LabJack Support's picture
You enable counters with

You enable counters with configIO. If enabling both counters, do it in one call. For example, to enable counters 0 and 1 on FIO4 and FIO5:

# Configuring Counter 0 and Counter 1 on FIO4 and FIO5. TimerCounterPinOffset sets the starting pin (4 = FIO4).
d.configIO(FIOAnalog=0x0f, EnableCounter0=True, EnableCounter1=True, TimerCounterPinOffset=4)

We have general documentation on timers and counters here:

https://labjack.com/support/datasheets/u3/hardware-description/timers-counters

As for streaming counters, the channels to use are mentioned here:

https://labjack.com/support/datasheets/u3/operation/stream-mode/digital-inputs-timers-counters

Keep in mind that a stream sample is 16-bits, and a counter reading is 32-bits, so 2 channels are needed for the full 32-bit value reading. So to configure the stream for digital I/O and 2 counters, with streamConfig you would use a scan list (PChannels) of [193, 194, 210, 224, 211, 224].

The 210/224 channel pair is for the full counter 0 reading and 211/224 channel pair for the full counter 1 reading. 210 and 211 are the lower 16-bits (LSW), and 224 is the upper 16-bits (MSW) of the reading.

Since 224 is used twice in the scan list (PChannels), both 224 scan readings will be put in r["AIN224"], so you will notice len(r["AIN224"]) will be double in size of len(r["AIN210"]) or len(r["AIN211"]. Data is interleaved for AIN224 in this case ([counter0_MSW, counter1_MSW, counter0_MSW, counter1_MSW, ...]).

So the first scan of readings are in:

FIO_EIO: r["AIN193"][0]
CIO: r["AIN194"][0]
Counter0 (LSW, MSW): r["AIN210"][0], r["AIN224"][0]
Counter1(LSW, MSW): r["AIN211"][0], r["AIN224"][1]

The second scan:

FIO_EIO: r["AIN193"][1]
CIO: r["AIN194"][1]
Counter0 (LSW, MSW): r["AIN210"][1], r["AIN224"][2]
Counter1(LSW, MSW): r["AIN211"][1], r["AIN224"][3]

Third:

FIO_EIO: r["AIN193"][2]
CIO: r["AIN194"][2]
Counter0 (LSW, MSW): r["AIN210"][2], r["AIN224"][4]
Counter1 (LSW, MSW): r["AIN211"][2], r["AIN224"][5]

and so on:

FIO_EIO: r["AIN193"][x]
CIO: r["AIN194"][x]
Counter0 (LSW, MSW): r["AIN210"][x], r["AIN224"][x*2]
Counter1 (LSW, MSW): r["AIN211"][x], r["AIN224"][x*2+1]

Parsing the the 32-bit counter values for the first scan:

counter0 = r["AIN210"][0] + (r["AIN224"][0] << 16)
counter1 = r["AIN211"][0] + (r["AIN224"][1] << 16)

The second scan:

counter0 = r["AIN210"][1] + (r["AIN224"][2] << 16)
counter1 = r["AIN211"][1] + (r["AIN224"][3] << 16)

And so on:

counter0 = r["AIN210"][x] + (r["AIN224"][x*2] << 16)
counter1 = r["AIN211"][x] + (r["AIN224"][x*2+1] << 16)

If you are fine with the counters being a 16-bit value (0-65536), you could simplify the the scan list to [193, 194, 210, 211]. Also, I just want to point out that stream channels 193 and 194 are the only channels where a channel reading is a 2 element tuple. All other channels a channel reading is just a value, so as seen above r["AIN210"][x], r["AIN211"][x], and r["AIN224"][x] are values (16-bit unsigned integer in those cases), instead of a tuple, when calculating the 32-bit counter value.

Terry
ttamboh's picture
Hello,

Hello,

 

Another thing i am curious about is how to set up differential inputs for streaming. I understanded that when we designate NChannels = [31], the 31 signifies single-end input. For differential inputs say for FIO0 and FIO1, Do I put EIO0 in the PChannel and EIO1 in the NChannel?

example: d.streamConfig(NumChannels = 1, PChannel = [0], NChannel=[1],  Resolution = 3, ScanFrequency = 1600)

Also if I want to use channels 193, 194, how do I set up the Nchannel

Thank

LabJack Support
LabJack Support's picture
Digital I/O cannot be

Digital I/O cannot be configured for differential, so with PChannels 193 and 194, the corresponding NChannel setting is not applicable (needs to be set but is ignored). Only analog inputs can be configured for differential. So say you want a AIN8-AIN9 (EIO0-EIO1 when analog) differential, that would be PChannel and NChannel 8 and 9.