Closed sjpark608 closed 1 year ago
ADC
By importing edgepi_adc module, the user should be able to measure input voltage in the form of digitized code, 24 or 32 bit, from an input terminal specified by the user and convert the measurement into a human-readable voltage value. The user should be able to change some high level configurations regarding the reading of the input.
Voltage Reading functionality
Specify the following parameters before perform reading command
* [ ] Specify Channel to read * [ ] ch0~7 when RTD_EN is False * [ ] ch0~3 when RTD_EN is True * [ ] Specify ADC * [ ] ADC 1 32bit long * [ ] ADC 2 24bit long * [ ] sampling rate / data rate * [ ] Instantaneous / set_number of samples * [ ] code to voltage conversion
Voltage Data representation
provide processed data
* [ ] statistic data * [ ] mean * [ ] stdev * [ ] median * [ ] min * [ ] max
Configuration
There are configuration registers affecting the performance of the module. Most of the registers should be set during the module instantiation. The user only interacts with a limited configuration to perform the measurements.
Default Setting
* [ ] POWER: Reset bit needs to be cleared on reset/powerup, rest of the bits stay in the default condition * [ ] INTERFACE: All bits stay in the default state, Checksum calculation implemented done in the test script. Let me know if you need help @flavius-t * [ ] MODE0: All bits in the default state * [ ] MODE1: All bits in the default state * [ ] MODE2: All bits in the default state * [ ] INPMUX: set MUXP = 0xF (Float), set MUXN = 0xA (AINCOM) * [ ] IDACMUX: All bits in the default state * [ ] IDACMAG: All bits in the default state * [ ] REFMUX: All bits in the default state
User setting
* [ ] INTERFACE: CRC bits can be changed, we need to provide them with CRC and checksum function * [ ] MODE0: rum mode can be selected between continuous or pulse conversion * [ ] MODE1: filter mode can be selected * [ ] MODE2: Data rate bits can be selected * [ ] INPMUX: MUXN is fixed with AINCOM, MUXP is selected according to the channel that the user provides
Note: MODE0~2 registers are related to the data rates. This still needs some research on how these registers affect the data sampling rate. In the future, users will just provide a sampling rate of interest, and a function will configure these registers in order to meet the provided rate.
Based on this, my understanding of the high level interface we need to provide to users is as follows:
read_input_voltage
(channel
,adc
)set_config
crc_mode
: CRC or checksumconversion_mode
: continuous or pulsefilter_mode
data_rate
adc_status
read conversion data
STATUS
byte foradc1
output faults
[ ] Instantaneous / set_number of samples
[ ] code to voltage conversion Does the first refer to
data_rate
? I am not sure whatcode to voltage conversion
refers to.
[ ] Specify Channel to read
- [ ] ch0~7 when RTD_EN is False
- [ ] ch0~3 when RTD_EN is True
When is RTD_EN
expected to be False? Is the user in control of setting this pin?
Voltage Data representation
provide processed data
* [ ] statistic data * [ ] mean * [ ] stdev * [ ] median * [ ] min * [ ] max
We will need to decide on whether to provide a set time frame for these statistics (i.e. the past hour, day, month, etc), or accept a time frame as an argument.
* [ ] INPMUX: MUXN is fixed with AINCOM, MUXP is selected according to the channel that the user provides
We do not want to also allow users to select ADC2 multiplexer?
Note: MODE0~2 registers are related to the data rates. This still needs some research on how these registers affect the data sampling rate. In the future, users will just provide a sampling rate of interest, and a function will configure these registers in order to meet the provided rate.
The thermocouple module had a similar averaging mode setting. The high level approach we took was to offer the available averaging modes (in this case data_rate
) as Enums. It seems there are a finite set of configurable data rates in the MODE2
register. I think this approach would be ideal rather than mapping a user input sampling rate.
@flavius-t could also list the proposed high level function signatures we discussed in our meeting?
@flavius-t could also list the proposed high level function signatures we discussed in our meeting?
@farzadpanahi
Based on this, my understanding of the high level interface we need to provide to users is as follows:
1. `read_input_voltage`(`channel`, `adc`) 2. `set_config` * `crc_mode`: CRC or checksum * `conversion_mode`: continuous or pulse * `filter_mode` * `data_rate` 3. `adc_status` * read conversion data `STATUS` byte for `adc1` output faults
set_config
crc_mode
: CRC or checksumconversion_mode
: continuous or pulsefilter_mode
data_rate
I don't think this is what we discussed in the meeting. can you take another look at your notes?
set_config
crc_mode
: CRC or checksumconversion_mode
: continuous or pulsefilter_mode
data_rate
I don't think this is what we discussed in the meeting. can you take another look at your notes?
@farzadpanahi For the set_config
I believe we discussed the exact settings we wanted users to be able to configure would be determined later, after @sjpark608 determined which were essential settings. From the meeting notes, I have recorded that input voltage reading, configuration setting, and a fault reading system for the STATUS byte is required. Am I missing anything else?
@flavius-t
Based on this, my understanding of the high level interface we need to provide to users is as follows:
read_input_voltage(channel, adc)
set_config
crc_mode: CRC or checksum
conversion_mode: continuous or pulse
filter_mode
data_rate
adc_status
read conversion data STATUS byte for adc1 output faults
This is correct
* [ ] Instantaneous / set_number of samples
* [ ] code to voltage conversion
Does the first refer to data_rate? I am not sure what code to voltage conversion refers to.
Instantaneous reading means it will read only one sample at that instance. The data/sampling rate is how fast the ADC chip convert the signal. So the first setting configures whether to do a single read or set number of reading.
The code to voltage conversion is just a function name, it shouldn't be a parameter to specify. Sorry for the confusion
When is RTD_EN expected to be False? Is the user in control of setting this pin?
This can be done by reading pininfo dataclass. The GPIO pin should be set when RTD module is instantiated.
Regarding ADC2, I'd like to verify the functionality and how to use them first before implementing it, since it has a possibility to collide with ADC1 operation.
Based on today's meeting, here is the updated high level interface for ADC: 74cf0f26cafb0fc9af864dc83938e015ff076740
The interface is in edgepi_adc.py
set_config
docstring: ba4cb7de052d7b819834d6efba44f8ab22f52a20@sjpark608 @farzadpanahi
Just to make sure we are using the right terminology, I think instead of ADCChannel
we can use something else, maybe ADCInput
? @sjpark608 what is the right terminology to use here?
Just to make sure we are using the right terminology, I think instead of
ADCChannel
we can use something else, maybeADCInput
? @sjpark608 what is the right terminology to use here?
ADC channel is better in my opinion since it is common to call it input channel or channel x. Reference image
However, I think it is also important to use a unified naming on both hardware and software. Right now, our label on the product say A/DINx
For DAC we used analog_out
in the user interface, maybe analog_in
would work here?
@sjpark is it important to have any settings that users can configure without having an ADC restart conversions? I'm wondering because for the settings that do restart conversions, it is advised to update these as a group (single write). However, it looks like this might not be very efficient in some cases. For example, when updating Group 1 registers together, it's possible we might have to update the intervening non-Group 1 registers as well.
If we want to update Group 1, Group 2, and other registers this would mean at least 3 separate writes. Unless we chose to include the intervening registers, in which case this becomes a single write operation including nearly all registers. So I am thinking it may be more efficient to update all registers at once, unless there are concerns about restarting conversions every time the ADC configuration is changed.
i.e. given the list of updated register values, writing to the groups individually would be something along these lines (Group 3 registers are those not in Groups 1 or 2):
# for each updated register
# if updated register belongs to GROUP1 add to list of GROUP1 register updates.
# else if updated register belongs to GROUP2, add to list of GROUP2 register updates
# else if GROUP3 and addx is between the addxs of any two in GROUP1, add to GROUP1 update list
# can be implemented by checking if GROUP3 entry is not either at beginning or end of GROUP1 list
# sorted by addx, then it must be between the GROUP1 blocks
# else write the GROUP3 update directly
# if GROUP1 or GROUP2 update lists not empty write each as block
@sjpark is it important to have any settings that users can configure without having an ADC restart conversions? I'm wondering because for the settings that do restart conversions, it is advised to update these as a group (single write). However, it looks like this might not be very efficient in some cases. For example, when updating Group 1 registers together, it's possible we might have to update the intervening non-Group 1 registers as well.
If we want to update Group 1, Group 2, and other registers this would mean at least 3 separate writes. Unless we chose to include the intervening registers, in which case this becomes a single write operation including nearly all registers. So I am thinking it may be more efficient to update all registers at once, unless there are concerns about restarting conversions every time the ADC configuration is changed.
i.e. given the list of updated register values, writing to the groups individually would be something along these lines (Group 3 registers are those not in Groups 1 or 2):
# for each updated register # if updated register belongs to GROUP1 add to list of GROUP1 register updates. # else if updated register belongs to GROUP2, add to list of GROUP2 register updates # else if GROUP3 and addx is between the addxs of any two in GROUP1, add to GROUP1 update list # can be implemented by checking if GROUP3 entry is not either at beginning or end of GROUP1 list # sorted by addx, then it must be between the GROUP1 blocks # else write the GROUP3 update directly # if GROUP1 or GROUP2 update lists not empty write each as block
I agree with the idea of updating all registers and re-starting the conversion. In most cases that the user wants to change the configuration, the configs are related to the conversion data or ADC configs. Selecting/filtering registers to be changed and writing them separately will add more complexity to the use case and to implementation.
It turns out we actually have 1262 instead which doesn't have ADC2.
I am waiting on TI engineer's reply to my question regarding the correlation between Data rate and the digital filter for ADC. However, it looks like by setting the DR bits in Mode2 register, we can achieve the maximum data rate of 38400SPS.
The first stage filter is always on, but the second stage filter is configurable.
When conversion first starts, there is a conversion latency according to the filter settings. The above table shows the conversion latencies. After the first conversion, the subsequent conversion rate will correspond to the data rate. This assumes the input voltage is settled.
When the INPMUX register changes, the conversion will automatically restart and the first conversion will have the conversion latency.
@sjpark608 did we have the wrong part number in the schematic file?
@sjpark608 did we have the wrong part number in the schematic file?
yes, the schematic has 1263, but the actual chip we have on board is 1262
@farzadpanahi @flavius-t TI engineer confirmed regarding the data rate of the ADC. Regardless of the setting of Filter Bits in MODE1 Register, DR bits in MODE2 Register overrides the sampling rate. Ex) if you want the maximum data rate of 38400SPS, set DR bits to 1111 in MODE2 Register.
It turns out we actually have 1262 instead which doesn't have ADC2.
I will remove ADC2 specific code from the implementation, unless I should leave it there in case we get the 1263 in the future?
@sjpark608 @farzadpanahi
@sjpark608 are we considering 1263 at all? can you confirm w/ Colin. If we are not going to use 1263 we should remove all the related code and simplify the interface.
@farzadpanahi @flavius-t Colin mentioned that we have both 1262 and 1263 at the moment. There was a shortage of 1263 and he got both chips. Colin suggested focusing on the common functionality of these two chips for now until we resolve the supply issue with 1263 chip. I partially agree with Colin, since ADC2 requires more testing regarding concurrency with ADC1 and calibrations.
OK, in that case, let's implement with one ADC but let's have two ADCs in mind in the design. So, for naming keep ADC1, remove ADC2, but keep the design such that we can add ADC2 without structural change later.
@farzadpanahi I will keep both ADC1 and ADC2 functionality in the lower level __config
method that handles the updates, but only offer ADC1
in the higher level set_config
method users will call. That way we can easily add ADC2 functionality for users in the future.
When conversion first starts, there is a conversion latency according to the filter settings. The above table shows the conversion latencies. After the first conversion, the subsequent conversion rate will correspond to the data rate. This assumes the input voltage is settled.
I ran some tests to see how these numbers line up with the actual conversion latency we see:
Conversions were performed in Pulse mode. Time was measured with perf_counter_ns
from after sending the READ_DATA
command up until the STATUS
byte of a voltage read indicated new data was available. Mean time in milliseconds after x trials is shown in each cell.
@farzadpanahi @sjpark608
@flavius-t this is related to the SPI issue I'm currently investigating refer to #89
I made a new spi6-4cs.dtbo in dt_src repo. please replace the overlay file on your test device and perform the test again.
@flavius-t this is related to the SPI issue I'm currently investigating refer to #89
I made a new spi6-4cs.dtbo in dt_src repo. please replace the overlay file on your test device and perform the test again.
@sjpark608 the data with the new overlay added:
Edit: this data represents the initial conversion delay time
I repeated the above tests in continuous sampling mode:
Mean conversion delay in milliseconds after x trials is shown in each cell. For each cell, representing a unique configuration of data_rate
and filter_mode
, conversion delay was computed by sending a START
command and then continuously sending a READ
command and checking whether the STATUS
bit indicated new data. Only a single START
command was sent before measuring conversion delay for all x trials. The time taken until new data was indicated is represented as the conversion delay above. The first two conversion delays recorded for each cell were not included in the mean conversion delay, as these were extreme outliers caused by the immediate commencement of conversions upon sending the START
command in continuous sampling mode (i.e. the STATUS bit indicated new data was available almost immediately upon the first two reads).
Edit: I increased the number of trials for the higher data rates, so the mean delays are different from what we saw in the meeting today.
@farzadpanahi @sjpark608
@flavius-t this is related to the SPI issue I'm currently investigating refer to #89 I made a new spi6-4cs.dtbo in dt_src repo. please replace the overlay file on your test device and perform the test again.
@sjpark608 the data with the new overlay added:
Edit: this data represents the initial conversion delay time
now it make sense why some of the high data rates are saturating around 100us, I should be related to the SPI transaction issue I just posted in #89, also posted in rpi-forum
ADC
By importing edgepi_adc module, the user should be able to measure input voltage in the form of digitized code, 24 or 32 bit, from an input terminal specified by the user and convert the measurement into a human-readable voltage value. The user should be able to change some high level configurations regarding the reading of the input.
Voltage Reading functionality
Specify the following parameters before perform reading command
Voltage Data representation
provide processed data
Configuration
There are configuration registers affecting the performance of the module. Most of the registers should be set during the module instantiation. The user only interacts with a limited configuration to perform the measurements.
Default Setting
User setting
Note: MODE0~2 registers are related to the data rates. This still needs some research on how these registers affect the data sampling rate. In the future, users will just provide a sampling rate of interest, and a function will configure these registers in order to meet the provided rate.