FTDI ADC Device¶
pybarst.ftdi.adc
¶
FTDI ADC device¶
The FTDI ADC module controls an CPL ADC device connected to the FTDI channel’s digital pins. You can connect multiple ADC devices in parallel to different pins, and they can be configured to be connected to a variable number of channel pins.
-
class
pybarst.ftdi.adc.
ADCSettings
(clock_bit, lowest_bit, num_bits, sampling_rate=None, chan1=False, chan2=False, hw_buff_size=25, transfer_size=100, chop=True, input_range='-10, 10', data_width=16, reverse=False, rate_filter=None, double crystal_freq=6000000.0, **kwargs)¶ Bases:
pybarst.ftdi.FTDISettings
The settings for a CPL ADC device connected to the the FTDI channel.
When an instance of this class is passed to a
FTDIChannel
in the channels parameter, it will create aFTDIADC
indevices
.This settings class indicates and controls how the device is connected to the FTDI bus as well as the settings used to configure the ADC device.
Parameters: - hw_buff_size: float
The buffer size of the USB device. See
hw_buff_size
. Defaults to 25.- transfer_size: int
The number of data points for the server to accumulate before sending it to the client. See
transfer_size
. Effectively this controls how often data is sent to the client. E.g. if the sampling rate is 1000Hz and this value is 500, then 500 data point will be sent at once, or data will be sent to the client twice per second. Defaults to 100.- clock_bit: int
The pin connected to the ADC clock pin. Ssee
clock_bit
.- lowest_bit: int
The lowest data pin connected to the ADC device. See
lowest_bit
.- num_bits: int
The number of data pins connected to the ADC device. See
num_bits
.- chop: bool
Whether chopping (hardware sampling smoothing) is enabled. See
chop
. Defaults to True.- chan1: bool
Whether channel 1 of the ADC device is enabled and sampled. Each ADC device has two channels, either or both of which can be enabled. See
chan1
. Defaults to False.- chan2: bool
Whether channel 2 of the ADC device is enabled and sampled. Each ADC device has two channels, either or both of which can be enabled. See
chan2
. Defaults to False.- input_range: str
The voltage input range supported by the ADC device. See
input_range
. Defaults to ‘-10, 10’.- data_width: int
The bit depth of the ADC data points; either 16 or 24. See
data_width
. Defaults to 16.- reverse: bool
Whether the data pins of the ADC device are connected in the reverse order compared to the FTDI USB bus. See
reverse
. Defaults to False.- sampling_rate: float
The sampling rate that should be used by the ADC device for each channel. See
sampling_rate
. If None, it’ll use rate_filter filter instead. Defaults to None. Note, the device will try to find to closest sampling rate possible, which is not likely to be equal to sampling_rate.- rate_filter: int
The sampling rate code used by the device to set the sampling rate. See
rate_filter
. If None, it’ll use sampling_rate filter instead. Defaults to None. This controls the actual sampling rate, and the sampling_rate parameter, if supplied, gets first converted to rate_filter internally.- crystal_freq: float
The frequency of the crystal on the ADC device. Defaults to 6000000.
Note
The settings can not be changed after they have been passed to the constructor. I.e. setting the properties directly might result in incorrect states.
-
chan1
¶ chan1: ‘unsigned char’
Indicates whether channel 1 should be active and read and send back data.
-
chan2
¶ chan2: ‘unsigned char’
Indicates whether channel 2 should be active and read and send back data.
-
chop
¶ chop: ‘unsigned char’
Indicates whether chopping mode (noise reduction) should be active on the ADC device. It typically lowers the sampling rate when enabled.
-
clock_bit
¶ clock_bit: ‘unsigned char’
The pin to which the clock line of the ADC device is connected at the FTDI channel. Typically between 0 - 7.
-
data_width
¶ data_width: ‘unsigned char’
The bit depth of each data point read by the ADC device. Acceptable values are either 16, or 24.
-
hw_buff_size
¶ hw_buff_size: ‘float’
When The FTDI channel is communicating with the peripheral ADC device we continuously read/write to it. The larger the buffer we write/read at once the faster it performs. For instance, for fastest communication we would write in buffer multiples of the maximum buffer size. Because each FTDI channel can be used for multiple peripherals devices, if we were to write in multiples of the maximum buffer size then although it’d be most efficient for the ADC device, during this write/read other devices of this channel will have to wait until we are finished writing the buffer and before move on to the next buffer to be able to update their device. This means, the larger the buffer the more we have to wait between writes to other devices and the longer we have to wait between to update a device.
hw_buff_size
tells us the percentage (0-100) of the maximum buffer to use for ADC read / write. The smaller this is, the faster other devices will be able to update, but might reduce the ADC bit rate which could be unsuited at higher ADC sampling rates.
-
input_range
¶ input_range: ‘unsigned char’
The internal Barst code the correspond to the
input_range_str
string.
-
input_range_str
¶ input_range_str: str
The voltage input range that the device should accept. Can be one of 4 strings: ‘0, 5’, ‘0, 10’, ‘-5, 5’, or ‘-10, 10’. For a particular setting, voltage outside its range will show as error.
-
lowest_bit
¶ lowest_bit: ‘unsigned char’
Defines which pins on the FTDI USB bus are data pins. The data pins are connected to the FTDI bus starting from pin number
lowest_bit
untillowest_bit
+num_bits
.
-
max_rate
¶ max_rate: ‘double’
Indicates the highest possible sampling rate possible for the current device settings.
-
min_rate
¶ min_rate: ‘double’
Indicates the lowest possible sampling rate possible for the current device settings.
-
num_bits
¶ num_bits: ‘unsigned char’
Indicates the number of pins on the FTDI bus that are connected to the ADC data port. Range is [2, 8]. See
lowest_bit
.
-
rate_filter
¶ rate_filter: ‘unsigned char’
The internal code indicating the current sampling rate of the device.
sampling_rate
gets converted to the closestrate_filter
value which controls the final sampling rate of the device.Following, is the meaning of
rate_filter
:- If
chop
is True,rate_filter
can range between 2-127, inclusive. Therefore: - If
chop
is False,rate_filter
can range between 3-127, inclusive. Therefore:
In all cases, if both channels are enabled, the sampling rate above is for both channels, therefore the sampling rate per channel is half the rate quoted above. Also, Freq is the crystal frequency of the ADC board. This is controlled by the crystal_freq parameter. The resulting sampling rate is expressed in Hz.
- If
-
reverse
¶ reverse: ‘unsigned char’
Indicates how the ADC is connected to the FTDI USB bus. If True, indicates that the data pins on the USB bus are flipped relative to the pins on the ADC device; e.g. pin 7 connects to pin 0 etc. If False the pins on the USB bus and ADC device go in the same direction; e.g. pin 2 is connected to pin 5, pin 3 to pin 6 etc.
-
sampling_rate
¶ sampling_rate: ‘double’
The sampling rate used by the ADC device for each channel. The value controls both channels. The available sampling rates is a function of all the other device options.
-
transfer_size
¶ transfer_size: ‘DWORD’
This parameter allows you to control over how often the ADC sends data read back to the client. The server will wait until
transfer_size
data points for each channel (if two channels are active) has been accumulated and than sendstransfer_size
(for each channel) data points to the client.
-
class
pybarst.ftdi.adc.
ADCData
¶ Bases:
object
A data object returned by the ADC client after a read from the server. Each instance holds the most recently read data from the server for both channel 1 and / or 2. The class returns both the raw and actual voltage data points as well other information about the data. See the class attributes.
This class is not instantiated by the user, but is returned by
FTDIADC.read()
.-
bad_count
¶ bad_count: ‘short’
A value indicating the number of times for this packet that invalid data was read by the USB from the ADC device. None-zero values might indicate connection or hardware issues.
-
chan1_data
¶ chan1_data: array.array
An array of doubles containing the scaled data from channel 1. Each data point is the actual voltage sampled at the ADC channel port and has been scaled appropriately to be within the
ADCSettings.input_range_str
range.For example:
>>> print data.chan1_data array('d', [-0.00152587890625, -0.00152587890625, -0.00152587890625, -0.00152587890625, -0.00152587890625, -0.00152587890625, -0.00152587890625, -0.00152587890625, -0.00152587890625, -0.00152587890625])
-
chan1_oor
¶ chan1_oor: ‘char’
A bool indicating whether the voltage sensed on channel 1 is outside the range defined when creating the channel,
ADCSettings.input_range_str
.
-
chan1_raw
¶ chan1_raw: array.array
An array containing the raw un-scaled 16 or 24 bit raw unsigned int data acquired for channel 1. If this channel is disabled, it defaults to None.
For example:
>>> print data.chan1_raw array('L', [32763L, 32763L, 32763L, 32763L, 32763L, 32763L, 32763L, 32763L, 32763L, 32763L])
-
chan1_ts_idx
¶ chan1_ts_idx: ‘DWORD’
Each read operation by the USB from the ADC device gets time stamped after the read (uncertainty of the time stamp is a few ms, depending on the USB communication uncertainty). The time stamp is associated with a particular data point within the array since that data point would have been the first data point read in the next USB read. This time stamp is recorded in
ts
. This parameter tells you the index of this data point withinchan1_raw
andchan1_data
for channel 1. E.g. a value of 10 indicates that data point 10 inchan1_data
was taken at aboutts
.Because the data in one USB read can be broken down and sent in multiple packets based on the
ADCSettings.transfer_size
setting. If this packet doesn’t have a data point that was time stamped,ts
is zero.Because data points are time stamped by the system clock regularly, it can be used to compare with the ADC clock (which is the number of data points of this channel received, multiplied by the sampling rate).
For example:
>>> print data.chan1_ts_idx 10
-
chan2_data
¶ chan2_data: array.array
An array of doubles containing the scaled data from channel 2. Each data point is the actual voltage sampled at the ADC channel port and has been scaled appropriately to be within the
ADCSettings.input_range_str
range.For example:
>>> print data.chan2_data array('d', [-0.001220703125, -0.00091552734375, -0.00091552734375, -0.00091552734375, -0.00091552734375, -0.00091552734375, -0.00091552734375, -0.00091552734375, -0.00091552734375])
-
chan2_oor
¶ chan2_oor: ‘char’
A bool indicating whether the voltage sensed on channel 2 is outside the range defined when creating the channel,
ADCSettings.input_range_str
.
-
chan2_raw
¶ chan2_raw: array.array
An array containing the raw un-scaled 16 or 24 bit raw unsigned int data acquired for channel 2. If this channel is disabled, it defaults to None.
For example:
>>> print data.chan2_raw array('L', [32764L, 32765L, 32765L, 32765L, 32765L, 32765L, 32765L, 32765L, 32765L])
-
chan2_ts_idx
¶ chan2_ts_idx: ‘DWORD’
The index in
chan2_data
that approximately corresponds withts
. Seechan1_ts_idx
.For example:
>>> print data.chan2_ts_idx 9
-
count
¶ count: ‘DWORD’
The packet number of this instance. Everytime the server sends data to the client (every time
FTDIADC.read()
is called) the internal index gets incremented and stored here. This allows us to recognize if a data packet is missing, since this index should be a continuous value.For example:
>>> print data.count 44
-
fullness
¶ fullness: ‘float’
As mentioned in
ADCSettings.hw_buff_size
, we can select different sizes for the buffer length that is written to the FTDI USB device at once. If it is too small, than most of the buffer read would be full with ADC data. If it’s very large, then it should be mostly empty because it’s more efficient. This parameter tells you the percentage of the read buffer that was filled with ADC data.If this parameter is close to 100, that means the device is close to losing data because the buffer might be too small or the USB clock too slow to be able to read the data fast enough. So you should increase the buffer size or set a smaller sampling rate.
For example:
>>> print data.fullness 0.0122897801921
-
noref
¶ noref: ‘char’
A bool indicating whether the hardware voltage reference on the ADC device is not detected. A value of True indicates a hardware error.
-
overflow_count
¶ overflow_count: ‘short’
Indicates the number of times data was skipped while reading the ADC device. For example, if the ADC is operating at a very high sampling rate and the FTDI USB channel is too slow, then data might simply be lost. If none-zero, this indicates the number of times it happened.
-
rate
¶ rate: ‘float’
Debug information. With every packet, the server also computes the estimated sampling rate at which the data was taken. It should be close to
ADCSettings.sampling_rate
.For example, the sampling rate was set to 1000Hz:
>>> print data.rate 1187.5
-
ts
¶ ts: ‘double’
The time stamp, in server time
clock()
that thechan1_ts_idx
andchan2_ts_idx
data points were approximately taken. Seechan1_ts_idx
.For example:
>>> print data.ts 5.7277356845
-
-
class
pybarst.ftdi.adc.
FTDIADC
¶ Bases:
pybarst.ftdi.FTDIDevice
Controls an ADC device connected to the
FTDIChannel
. SeeADCSettings
for details on this device type.For example:
>>> # create a adc device with clock connected to pin 7, and 4 data >>> # lines at pins 3 - 6. The sampling rate is 1kHz. Both channels are >>> # active. Send back data to client at every 100 data points (10Hz) >>> settings = ADCSettings(clock_bit=7, lowest_bit=3, num_bits=4, sampling_rate=1000, chan1=True, chan2=True, hw_buff_size=25,transfer_size=100) >>> # create and open the channel >>> ft = FTDIChannel(channels=[settings], server=server, desc='Birch Board rev1 B') >>> adc = ft.open_channel(alloc=True)[0] >>> print adc <pybarst.ftdi.adc.FTDIADC object at 0x027984C8> >>> adc.open_channel() >>> adc.set_state(True) >>> data = adc.read() >>> print data <pybarst.ftdi.adc.ADCData object at 0x0278C6B8> >>> print data.chan1_data array('d', [-0.00152587890625, -0.00152587890625, -0.00152587890625, -0.00152587890625, -0.00152587890625, ..., -0.00152587890625]) >>> print data.chan2_data array('d', [-0.00091552734375, -0.00091552734375, -0.00091552734375, -0.00091552734375, -0.00091552734375, ..., -0.00091552734375]) >>> # the channel time stamp of the the data point at data.chan1_ts_idx >>> print data.ts 7.34521248027 >>> # the rate should be approximately at 1kHz +/ a few hundred Hz. >>> print data.rate 1058.51062012
-
get_conversion_factors
(self)¶ Returns the factors used to scale the raw data into floating points.
Returns a 3-tuple of bit-depth, multiplier, and subtractend.
The formula is float = (raw / 2 ** bit_depth) * multiplier - subtractend.
-
open_channel
(self)¶ See
open_channel()
for details.
-
read
(self)¶ Requests the server to read and send the next available data from the ADC. This method will wait until the server sends data, or an error message, thereby tying up this thread. Depending on how often data is sent, this might take a while under error conditions.
After the first call to
read()
the server will continuously read from the device and send the results back to the client. This means that if the client doesn’t callread()
frequently enough data will accumulate in the pipe.To cancel a read request while the read is still waiting, from another thread you must call
close_channel_client()
, orclose_channel_server()
, or just delete the server, which will cause this method to return with an error.A more gentle way of canceling a read request while not currently waiting in
read()
, is to callset_state()
to set it inactive, which will cause the next read operation to return with an error, but will not delete/close the channel. See that methods for more details.Returns: Each call to this method returns the next data read from the active channels in a ADCData
instance. As long as data points are not missing, the data returned from subsequent reads can be concatenated to get a continuous data stream at the device’s sampling rate.Warning
Before this method can be called,
open_channel()
must be called and then device must be set to active usingset_state()
.read()
may/should be called immediately afterset_state()
is called activating this device. When the state is activated, the device immediately starts sampling the ADC port, however, data only begins to be sent back to the client afterread()
is called the first time. So any data sampled beforeread()
is called for the first time is lost. Onceread()
is called, ifread()
is not called frequently enough, it just accumulates in the pipe, but does not get discarded.Note
The error attributes of
ADCData
(ADCData.chan1_oor
,ADCData.chan2_oor
,ADCData.noref
,ADCData.bad_count
,ADCData.overflow_count
) should be checked for every returned instance to detect errors with the ADC device.Note
Although multiple clients can simultaneously connect to the same FTDI channel, and FTDI peripheral devices; e.g. 2 clients instances can open the same ADC channel at the same time. Only one client is allowed to read at any time. That is after activation, once a client has called
read()
, no other client is allowed to callread()
until the initial client set the state to inactive withset_state()
. After that, any client can activate the state and callread()
again.
-