ADC managing
SUMMARY:
On Board Adc usage
The ADC on board is the 24 bits AD7732BRU datasheet. It has some parameters that can be set with flags in its instruction. Its main function to be called is ADC_lettura(), whose code is the following:
710int32_t
ADC_lettura(uint8_t scheda_su_scheda_giu_, uint8_t node_to_read, uint8_t cosa_fare){
713 if(scheda_su_scheda_giu_>1)scheda_su_scheda_giu_=1;
724 ADC_misura_fatta =
ADC_lettura_24bit( node_to_read, scheda_su_scheda_giu_, cosa_fare);
748 return ADC_misura_fatta;
long int ADC_lettura_24bit(char line_to_read_to_select_ADCch0_ADCch1, uint8_t up_down, uint8_t cosa_fare)
ADC Wakeup and 24 bits reading.
int32_t ADC_lettura(uint8_t scheda_su_scheda_giu_, uint8_t node_to_read, uint8_t cosa_fare)
This function allows to read the voltage of any of the selectable nodes.
#define spi_clock_for_relais
[ref_spi_clock_for_relais]
void Analog_mux_line_to_select_deselect(uint8_t scheda_su_scheda_giu, uint8_t line_to_select, uint8_t select_1_deselect_0)
Selection of the line to mesure with the analog MUX of the mainboard, driven by the I2C->parallel mux...
void Analog_mux_line_to_select_deselect_for_postmainboard(uint8_t scheda_su_scheda_giu, uint8_t line_to_select, uint8_t select_1_deselect_0)
Selection of the line to measure with the analog MUX's of the postmainboard, directely driven by the ...
@ node_voltage_Analog_Mux_0_offset
Starting Offset for this set of nodes, 32.
#define SPI_control_for_relay_driver
[ref_SPI_control_for_relay_driver]
Reading result has to be multiplied by numeratore, then divided by denominatore. This to work with integer numbers: remember that our voltages are in µV.
Each node to be read has its own identity; as an instance, the detector bias is read after a voltage attenuator. The reading nodes are organized in groups of 6, there is a vector structure whose locations are retreived by node_number/6:
Here is the vector ADC_coefficiente and here we see the coefficient values:
These number are exploited by the function ADC_compensazione_al_nodo() that needs as input parameters the node that is being measured by line_to_read. Then, from the ADc measured value, lettura_ADC and offset lettura_offset the actual node voltage is obtained. The above coefficiennts take into account the attanuator factors at the buffer inputs according to the following figure:
Figure_ADC_Buffeattenuation 1: ADC buffer in switchable resistor
- Note
- During the developing phase the board can be connected to an external ADC rather than that of the postfrontend, or mainboard B. Dscrimination between internal and external ADC can be made at the instruction level.
On Board ADC settings
At startup, within instr_inizializza_tutto_da_zero_function(), both ADC's are initialized. The first action done on ADC is the settings of its configuration pins. This is done at startup by the function ADC_pin_configurations(void). Soon after that the SPI protool is set, SPI_Inizialize(), the ADC's zero scale calibration is done, with ADC_selfcal_zero_scale(uint8_t up_down) invoked 2 times, one for each ADC present, than, the ADC's are sent into powerdown state with the function ADC_Sleep_fun(uint8_t up_down), invoked 2 times, too.
ADC Operation
The ADC functions list is here:
- ADC_misura_differenziale_con_media_generico() with inpt parameters uint8_t scheda_su_scheda_giu_, uint8_t preamplifier_externalADC_1_onboardADC_0, uint8_t nodo_da_misurare, uint8_t differenziale1_single_0
- ADC_misura_differenziale_single_ended() with input parameters uint8_t scheda_su_scheda_giu , uint8_t nodo_da_leggere, uint8_t differenziale_1_single_0
- ADC_pin_configurations(void)
- ADC_selfcal_zero_scale(uint8_t up_down)
- ADC_Sleep_fun(uint8_t up_down)
- ADC_Wakeup(uint8_t up_down)
- ADC_lettura_24bit(char ADC_0_o_1 , uint8_t up_down, uint8_t cosa_fare)
- ADC_lettura_registro(char ADC_0_o_1 , uint8_t up_down, uint8_t registro_ch0)
- ADC_lettura(uint8_t scheda_su_scheda_giu, uint8_t node_to_read, uint8_t cosa_fare)
- instr_ADC_LETTURA_function(void)
On the top of the above list there are the 2 functions that operate globally the ADC's to perform the measurement.
The first one is ADC_misura_differenziale_con_media_generico() that allows to set all the necessary parameters to perform the measurement. The user could use only this function to operate the ADC.
There are 2 parameters that are not passed to the function but are global and need to be set at least once, or their default values are considered.
The variable ADC_medie_per_misura is the first of the 2 variables that are not passed as a parameter but is a global. It can be set with the instruction via CAN, instr_ADC_LETTURA. It says to the function how many measurements of the node must be taken and averaged.
The other variable that is not passed, but is global is ADC_non_leggi_lo_offset_se_true. If it is true the input offset of the buffer which stands in front of the ADC is not read, Figure_ADC_Buffer_attenuation_input. With the new OA used the offset is very small and its measurement can be omitted. This shortens the reading time. This flag can be set ON or OFF from the instruction, instr_ADC_LETTURA.
The input parameters to the first function are:
- scheda_su_scheda_giu_ is the board selection;
- preamplifier_externalADC_1_onboardADC_0 indicates whether the ADC's on board are used or an external ADC is the selcted to perform the measurement, usually this parameter is set to zero since the external ADC is selected only for testing purpose;
- nodo_da_misurare is the node whose voltage is to be measured, the node list can be found at lista nodi;
- differenziale1_single_0 determines whether the measurement is performed differential os single ended. As an example, the ouput of the PGA amplifier is differential and we can read it as Vout_pos - Vout_neg , or to read Vout_pos and Vout_neg indipendently.
The second function, ADC_misura_differenziale_single_ended(), is invoked from the previous function. Its parameters are similar to the previous described above:
- scheda_su_scheda_giu is the board from which volateg nodes must be read;
- nodo_da_leggere is the node to be read according to lista nodi;
- differenziale_1_single_0 determines whether the measurement is performed differential os single ended.
The function ADC_pin_configurations() is invoked just one time, at the startup. Calibration is done at startup, too, and can be invoked from time to time from the CAN, too.
ADC_Wakeup() is called every time a reading must be taken, while ADC_Sleep_fun() is invoked at the end of the reading function.
ADC_lettura_24bit(char ADC_0_o_1 , uint8_t up_down, uint8_t cosa_fare) allows a single reading of the previously selected node. It needs to know which of the 2 ADC channels to use with ADC_0_o_1, and which ADC to consider with up_down. The last parameter cosa_fare allows to operate the 2 ADC in parallel, if needed. It cover 3 values as it follows:
- cosa_fare=1: The measurement is only started. The measurement function is not blocking and this allows to launch the measurement with the other ADC in parallel. The returned value is 0 in this case. Take care that the parallel operation is not possible with the 2 channels of the ADC because the ADC is multiplexed. If the parallel operation is anyway set for the 2 channels of the same ADC one measurement will be lost.
- cosa_fare=2: In this case the measuremen is launched and the result is waited and returned. This is a situation for which parallel operation is not exploited. This function is blocking.
- cosa_fare=3: In this case the result is waited of the measuremnt launched in a previous call with cosa_fare=1.
An example of parallel operation is here (cosa_fare=1 combined with cosa_fare=3):
int risultato[2];
#define I2C_mux_Scheda_giu
Selection of the I2C1 for lower board (purtroppo \'e contorto)
#define I2C_mux_Scheda_su
Selection of the I2C0 for the upper board (purtroppo \'e contorto)
An example of non parallel operation is here (cosa_fare=2):
The inputs of the ADCs are buffered. The input resistor of the buffer is a switchable, in principle. This feature cannot be used since the switches are MOS whos parasitic diode becomes forward bias when the input voltage goes negative. In this versione of the board the MOS are used for another fnctions and the resistirs is held to GND. Its value is not 10 KΩ, as in the picture below, but 82 KΩ; at the same time the resistor in series to the analog MUX's ouputs is now 8.2 KΩ. This combination attenuates a little the value of the input node to measure and avoid to be too close to the rails, where the accuracy of the buffer lowers a little.
Figure_ADC_Buffer_in 2: ADC buffer in switchable resistor
ADC_lettura_registro() allows to read a whatever ADC internal register of the selected ADC and ADC channel. Possible choices are (select the left number of the Addr column):
Figure_ADC_reg 3: ADC register MAP. Select the register number from the Addr column. In case 2 numbers are available, choose the left one.
ADC_lettura(uint8_t scheda_su_scheda_giu, uint8_t node_to_read, uint8_t cosa_fare) sets the path, from the node to read, to the ADC input. First of all scheda_su_scheda_giu determines the region to operate and the ADC to select. It needs to know the node(node_to_read) to set the path. Then cosa_fare is the parameter with which we can operate in parallel with the same sintax seen above.
Finally, instr_ADC_LETTURA_function(), is the function that is called when the CAN instruction is invoked, instr_ADC_LETTURA.
Off Board ADC
This option is anomalous becasue is the µ-controller that is asking back the requirement to read the node voltage. Through the CAN Bus and the ReadBack Node Voltage instruction any available node volatge can be read. The function that is able to perform this operation is:
718 uint8_t buffer_istruzione[8],iii;
719 for(iii=0;iii<8;iii++){
720 buffer_istruzione[iii]=
tx_data[iii];
735 while( (ii <50) && (
evento_CAN != ARM_CAN_EVENT_RECEIVE ) ){
746 valore_mis= ( ( ( *(int32_t *)
rx_data ) & 0xFFFFFFFF ) ) ;
750 for(iii=0;iii<8;iii++){
751 tx_data[iii]=buffer_istruzione[iii];
const struct ADC_coefficiente_type ADC_coefficiente[]
Node normalizing coeficinets used in ADC_lettura_24bit()
#define ADC_molteplicita_node_to_read
@ instr_readback_node_voltages
Nodes voltage read from external ADC.
uint8_t tx_data[8]
Transmission data vector.
uint32_t volatile evento_CAN
This is the variable which resembles the flags from the communication.
uint32_t tx_obj_idx
This is the variable which resembles the flags from the communication.
unsigned int indirizzo_CAN_della_scheda
Per ora lo assegnamo cos\i l'indirizzo della scheda.
volatile uint8_t rx_data[8]
Received data vector.
void ERROR_codifica_errore(uint8_t scheda_su_scheda_giu, unsigned char error_addres, unsigned char code_to_shift, uint8_t reset_count_se_0)
If an error is found its flag is codified here.
@ CAN_error_comunichiamo_qualche_dato_timeout_on_transmission
Transmission CAN error.
@ error_address_CAN
Error register for CAN bus
int32_t preamplifier_ADC_external_measured_node_function(uint8_t scheda_su_scheda_giu, uint8_t indice)
This function provide node reading from an external ADC.
void Aspetta_tanti_ms(int millisecondi)
The timing function.
Conclusions
This section must be expanded
The codes for mamnaging the ADC are: