CROSS Technical Documentation User Manual and Technical Doc.
INFN Milano Bicocca
Loading...
Searching...
No Matches
The preamplifier Offset Drift Correcttion

Preamplifier Offset Drift Correcttion

SUMMARY:

Trimmer usage with preamplifier



The preamplifier has a quad trimmer AD5263. Two of the 4 trimmers are exploited to adjust the output offset voltage, coarse ancd fine. The third trimmer is for drift compensation while the last trimmer is for CMRR mitigation. The 4 trimmers are defined this way:

  1. trimmer_CMRR_compensation
  2. trimmer_fine_offset
  3. trimmer_thermal_compensation
  4. trimmer_coarse_offset



To write or read any trimmer we use only one function: preamplifier_scrittura_lettura_trimmer(uint8_t scheda_su_scheda_giu, uint8_t canale, uint8_t trimmer,uint8_t valore, uint8_t scrivi_1_leggi_0 ) where:

  • scheda_su_scheda_giu is the board where the trimmer is;
  • canale is the preamplifier channel (0 to 5);
  • trimmer is one of the 4 trimmers to write or to read (0 to 3 of the list above);
  • valore is the value to write, a unsigned int8 (0 to 255);
  • scrivi_1_leggi_0 is boolean: when true a write of valore is done, if 0 a reading of the content is done. For both cases the values of the trimmers are in the global matrix contenuto_trimmer_preamplifier[6][4] .


An example of writing of the value 158 in the trimmer for coarse offset compensation of the second channel is:

#define preamplifier_scrivi_il_trimmer
void preamplifier_scrittura_lettura_trimmer(uint8_t scheda_su_scheda_giu, uint8_t canale, uint8_t trimmer, uint8_t valore, uint8_t scrivi_1_leggi_0)
Setting the value of any trimmer for preamplifier trimmer, the contents of the trimmers are stored in...
Definition: Trimmer.c:283
#define trimmer_coarse_offset
Definition: Trimmer.h:82

In the example above:

Effects of trimmers on preamplifier



The effects of the trimmers on the output or input of the preamplifier are summarized in Table below:


Table 1: Effects of the trimmers on preamplifier
Trimmer Output Change per step Input Change per step
trimmer_CMRR_compensation Not Applicable Not Applicable
trimmer_fine_offset 0.985 mV xxx µV
trimmer_coarse_offset 121,3 mV xxx µV
trimmer_thermal_compensation x mV/°C y µV/°C

Preamplifier/PGA offset setting



Amplifer offset can be set with an accuracy of sligtly less than 16 bits via the 2 trimmers trimmer_coarse_offset and trimmer_fine_offset. Offset is implemented with 2 different modalities with the aim of speed up the process of correction and details are given below.
There are some common initial settings. We use 2 trimmers that are initialized. A few steps are adopted in order to minimize disturbances. First the PGA gains of all the channles of the board are set to 1 V/V. Then the offsets, for those channles that must be adjusted, being set at PGA gain of 1 V/V, are scaled by the gain factor. The same is done for the expected final error. This is done channel by channel. As an example if we need an output offset of 0.5 V at a PGA gain of 10, then, the PGA gain is set to 1 V/V and the offset adjusted at 0.05 V. Since some error can be introduced when the gain is returned at its value, the gain of every channel is not recovered at the end of the process, but a few bits before, 2 or 3 depending on the difference between the target value and the acyual value. This way possible errors are compensated.
The offset is adjusted in pseudo-paralalel way. Pseudo-parallel is intended for the fact the the ADC measurement is the only action that is made channel after channel, since only one ADC is present.
The ADC to perform the measurement can be that on the post-board or can be external. In the latter case every time the measurement is needed the µ-controller asks from the CAN bus the measurement. This is done in a way similar to the instr_output_offset_to_be_set.
The modalities for doing an adjustment can be set with the instr_preamplifier_scrittura_lettura_trimmer_offset
The main function to adjust the offset is instr_Vbias_to_be_set_function():

278uint8_t iii,canale, indice;
279uint8_t volatile tx_data_buffer[8],fai_fai=1;
280int8_t variazione;
281 LED_rosso_fondo_scala=LED_lungo;
282
283 ERROR_codifica_errore(0,0,0,0); //Reset_ch0 errori
284 for(iii=0;iii < 8;iii++){// Potrebbe essere richiesto qualcosa sul can,
285 //bufferizziamo l'istruzione
286 tx_data_buffer[iii]= tx_data[iii];
287 }
288
289 //La funzione va sviluppata per ora si ritrona il fw
290 //verificare le modalit\'a di misura:
294 //attesa tra le misure
295 preamplifier_attesa_tra_le_misure = vettore_istruzioni[4] *100;
296 if ( preamplifier_attesa_tra_le_misure <100) preamplifier_attesa_tra_le_misure=100;
297 if (preamplifier_attesa_tra_le_misure > 10000) preamplifier_attesa_tra_le_misure=10000;
298 //errore tollerato
299 preamplifier_error_voltage= vettore_istruzioni[5] *1000;
300 //i canali da agiustare
301 preamplifier_canali_da_regolare= vettore_istruzioni[6] & 0x7F;
302 preamplifier_canali_da_regolare_old=preamplifier_canali_da_regolare;
303 scheda_su_scheda_giu = ((vettore_istruzioni[6] >> 7) & 1)*6;
304 //l'adc da usare, interno o esterno
305 preamplifier_externalADC_1_onboardADC_0 = vettore_istruzioni[3] & 1;
306// preamplifier_SAR_1_no_SAR_0 = ( vettore_istruzioni[3] >> 1 ) & 1;
307// preamplifier_fastSAR_1_no_fastSAR_0 = ( vettore_istruzioni[3] >> 2 ) & 1;
308
310 vettore_istruzioni[3] =0; //Non si fa altro
311 fai_fai=0;
312 EPROM_store_recover_state_M24C32_64(scheda_su_scheda_giu, vettore_istruzioni[6],0,0);
313 }
314
316 //Offset recalled from startup
317 EPROM_store_recover_state_M24C32_64(scheda_su_scheda_giu,preamplifier_canali_da_regolare,1,1);
318 fai_fai=0;
319 }
321 //Offset recalled from user location
322 EPROM_store_recover_state_M24C32_64(scheda_su_scheda_giu,preamplifier_canali_da_regolare,1,0);
323 fai_fai=0;
324 }
325
326 //Leggiamo le pendenze
327 uint8_t dati_scambio[4] , scheda=scheda_su_scheda_giu;
328 for( canale=0;canale<6;canale++){
329// if(canale==6) scheda =1;
330 EPROM_lettura_M24C32_64(scheda, I2C_mainboard, canale, Memory_preamplifier_slope_calibration_ON_0_OFF_ff <<2,dati_scambio);
331 if(dati_scambio[0] ==0){//solo se la misura \'e stata fatta si aggiornano le pendenze, altrimenti vale il fedault
332 EPROM_lettura_M24C32_64(scheda, I2C_mainboard, canale, Memory_preamplifier_address_coarse_trimmer_slope_offset <<2,dati_scambio);
333 preamplifier_coarse_step_trimmer[canale+scheda]=*(int32_t *)dati_scambio;
334 EPROM_lettura_M24C32_64(scheda, I2C_mainboard, canale, Memory_preamplifier_address_fine_trimmer_slope_offset <<2,dati_scambio);
335 preamplifier_fine_step_trimmer[canale+scheda]= *(int32_t *)dati_scambio;
336 }
337 preamplifier_error_voltage_at_the_moment[canale+scheda]= preamplifier_coarse_step_trimmer[canale+scheda] >>1; //mezzo bit di errore sul coarse all'inizio
338 }
339
340 if(fai_fai){
341//Initialization for default SAR
343 for( canale=0;canale<12;canale++){
344 preamplifier_SAR_ini[canale].starting_value =128;
345 preamplifier_SAR_ini[canale].starting_exp_value[0]=7;
346 preamplifier_SAR_ini[canale].starting_exp_value[1]=7;
347 }
348 }
349 for( canale=0;canale<6;canale++){ //a met\'a scala i trimmer fine che ci interssano
350 if((preamplifier_canali_da_regolare >> canale) & 1){
351 preamplifier_scrittura_lettura_trimmer( scheda_su_scheda_giu, canale,\
352 trimmer_fine_offset, 128, preamplifier_scrivi_il_trimmer );//Trimmer fine inizializzato met\'a scala
353 }
354 }
355
356//Ora impostiamo ad 1 tutti i guadagni, normalizziamo gli errori ed i target
357preamplifier_normalize_gain_offset_error(scheda_su_scheda_giu) ;
358
359//FINE: Initialization for default SAR, changes are applied in fastSAR, eventually
360
361 for( canale=0;canale<6;canale++){ //impostiamo la compensazione termica di default, se \'e stata fatta.
362 if((preamplifier_canali_da_regolare >> canale) & 1){
363 preamplifier_determina_trimmer_therma_comp( scheda_su_scheda_giu, canale, 0, 1);
364 termalizzazione_fatta[canale + scheda_su_scheda_giu]=0;
365 }
366 }
367
368
371
372 //Ora aggiustiamo il controllo termico per quei canali che inizialmente erano saturi
373 uint8_t ri_misuriamo=0;preamplifier_canali_da_regolare_old=preamplifier_canali_da_regolare;
374 for( canale=0;canale<6;canale++){ //impostiamo la compensazione termica di default, se \'e stata fatta.
375 if((preamplifier_canali_da_regolare_old >> canale) & 1){
376 if (termalizzazione_fatta[canale + scheda_su_scheda_giu]==0){
377 preamplifier_canali_da_regolare=1 <<canale;
378 ri_misuriamo=1;
379 }
380 }
381 }
382 //Se c'erano canali inizalmente saturi riaggiustiamo
383 if(ri_misuriamo){
386 }
387
388
389//Ora vediamo qualche setting
391 //Offset to be stored at memory location for sturtup
392 EPROM_store_recover_state_M24C32_64(scheda_su_scheda_giu,vettore_istruzioni[6],0,1);
393 }
395 //Offset to be stored at user memory location for sturtup
396 EPROM_store_recover_state_M24C32_64(scheda_su_scheda_giu, vettore_istruzioni[6],0,0);
397 }
398 }
399 for(iii=0;iii < 8 ;iii++){
400 tx_data[iii]= tx_data_buffer[iii];
401 }
402 tx_data[6] = preamplifier_canali_da_regolare; //i canali non in tolleranza hanno un 1 in corrispondenza
403 int32_t somma=0;
404 for( iii=0;iii<6;iii++){
405 somma += preamplifier_error_voltage_at_PGA_gain[iii+scheda_su_scheda_giu];
406 }
407 somma = somma / 6000;
408 if( somma >255) somma=255;
409 tx_data[5] = somma;
411}
volatile uint16_t ADC_medie_per_misura
the number of ADC readings to average, the maximum is 400
Definition: Adc.c:206
uint8_t tx_data[8]
Transmission data vector.
Definition: Can.c:321
#define detector_bit_per_storing_startup
#define detector_bit_per_storing_user_state
#define detector_bit_recall_user_defined
#define detector_bit_recall_startup
#define detector_bit_store_state_in_user_as_it_is
#define detector_offset_from_half_scale
void Error_imposta_la_istruzione(void)
Function to be located at the end of every instruction to mark the error, if any.
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.
volatile uint16_t LED_rosso_fondo_scala
Definition: Led.c:56
void EPROM_lettura_M24C32_64(uint8_t scheda_su_scheda_giu_, uint8_t mainboard_postmainboard, uint8_t canale, short indirizzo_memoria, uint8_t *dati_letti)
Read from preamplifier and on-board flashes.
void EPROM_store_recover_state_M24C32_64(uint8_t scheda_su_scheda_giu, uint8_t canali_da_regolare, uint8_t set_1_store_0, uint8_t startup_1_user_0)
Store the system state or recover and apply the system state.
@ Memory_preamplifier_slope_calibration_ON_0_OFF_ff
slope trimmer active if zero
@ Memory_preamplifier_address_fine_trimmer_slope_offset
fine slope for trimmer offset
@ Memory_preamplifier_address_coarse_trimmer_slope_offset
coarse slope for trimmer offset
void preamplifier_trova_il_guess(uint8_t trimmer_da_usare)
static void preamplifier_normalize_gain_offset_error(uint8_t scheda_su_scheda_giu_)
The ouput offset will be set at the value that was given with the instr_ouput_offset_we_want_to_set i...
void instr_output_offset_to_be_set_function(void)
The detector bias will be set at the value set with the function instr_detector_Vbias_we_want_to_set_...
void preamplifier_determina_trimmer_therma_comp(uint8_t scheda_su_scheda_giu, uint8_t canale, uint8_t valore_previsto_trimmer_offset, uint8_t solo_recupero_default_comp_se_1)
This function determines and set the thermal compensation trimmer.
void preamplifier_aggiusta_offset_SAR(void)
This function provide the output offset with the standard SAR method.
#define trimmer_fine_offset
Definition: Trimmer.h:80
volatile int8_t vettore_istruzioni[8]
This is a copy of the received 8 bytes from the CAN.


From it, after setting some variables, we go to preamplifier_normalize_gain_offset_error(), where the gain of all the channels are set to 1 V/V, the target offsets and the final target errors are normalized to 1 V/V, too:

524static void preamplifier_normalize_gain_offset_error(uint8_t scheda_su_scheda_giu_){
525 //First of all we set the PGA gain to minimum
526 //Then the offset is normalized to PGA at unity gain
527// uint8_t limitatore;
528 int32_t max_error=0;
529 uint8_t canale=0, indice;
530 if(scheda_su_scheda_giu_>=1) scheda_su_scheda_giu_=6;
531// int16_t pre_variazione;
532// int32_t variazione ;
533// int32_t variazione_1;
534 preamplifier_canali_da_regolare_old = preamplifier_canali_da_regolare;
535 //The PGA gain of all channells of the board are set to 1 V/V
536 for(canale=0; canale< 6; canale++){
537 indice= canale + scheda_su_scheda_giu_;
538 PGA_settled_gain_old[indice]= PGA_settled_gain[indice];
539 preamplifier_Output_offset_target_at_the_moment[indice] = preamplifier_Output_offset_target[indice] / PGA_settled_gain[indice];
540 if ( preamplifier_error_voltage < ((PGA_settled_gain[indice] * preamplifier_fine_step_trimmer[indice] *3 )/2) ){
541 //risoluzione minima di 1.5 bit LSb (*3/2)
542 preamplifier_error_voltage_at_PGA_gain[indice] =(3 * PGA_settled_gain[indice] * preamplifier_fine_step_trimmer[indice] )/2;
543 }else{
544 preamplifier_error_voltage_at_PGA_gain[indice] = preamplifier_error_voltage;
545 }
546 if( preamplifier_error_voltage_at_PGA_gain[indice] > max_error) max_error = preamplifier_error_voltage_at_PGA_gain[indice];
547// preamplifier_error_voltage_at_the_moment[indice]= (preamplifier_error_voltage_at_PGA_gain[indice]) / PGA_settled_gain[indice];
548
549 PGA_GAIN_CROSS( scheda_su_scheda_giu_ , canale , guadagno_minimo_PGA );
550 }
551 vettore_istruzioni[5] = max_error / 1000;
552}
void PGA_GAIN_CROSS(uint8_t scheda_su_scheda_giu, uint8_t canale, uint8_t PGA_gain_to_set)
Here the 2 digital signals from the trimmer are exploited to set the gain of the input stage of the P...
Definition: DAC_PGA.c:109
uint8_t guadagno_minimo_PGA
Definition: DAC_PGA.c:88
uint8_t PGA_settled_gain[12]
PGA set gain.
Definition: DAC_PGA.c:95
int32_t preamplifier_Output_offset_target[12]
Offset target values.


At this point if the standard SAR procedure is chosen we go to SAR_procedure, while if the Fast SAR procedure is adopted, a first measurement of the outputs is done from which a guess for the coarse trimmers is determined. Then, we go to FAST_SAR_procedure.

Note
Both SAR and Fast SAR procedures work rigtly if the calibration of the steps effects determined by the fine and coarse trimmers are known and stored in the preamplifier EPROM. This must be done during preampleifers initial test and the 2 instructions XXXXXXX and YYYYYY are dedicated to this.

SAR_procedure


SAR is implemented in standard way and both fine and coarse trimmers are initialized to 0. The function called by instr_Vbias_to_be_set_function() is preamplifier_aggiusta_offset_SAR():

565 uint8_t canale;
566 uint8_t indice;
567 uint8_t i_2_trimmer[]={trimmer_coarse_offset , trimmer_fine_offset}, indice_trimmer,scalata,confronto;
568 uint8_t target_raggiunto_1_non_raggiunto_0[]={0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0}; // si misura fino a che non diventa 1
569 int32_t ADC_misura_fatta_prov,ADC_misura_fatta_prov_vet[200];
570 uint16_t iii, media_prov; //medie=10;
571
572 if( scheda_su_scheda_giu>=1) scheda_su_scheda_giu=6;
573
574//Inizializzazione dei trimmer che servono alla regolazione
575//for(canale=0; canale<6;canale++){
576// if( (preamplifier_canali_da_regolare >> canale) & 1){
577// preamplifier_scrittura_lettura_trimmer( scheda_su_scheda_giu, canale, trimmer_coarse_offset, \
578// preamplifier_SAR_ini[canale + scheda_su_scheda_giu].starting_value, preamplifier_scrivi_il_trimmer );//Trimmer inizializzato a zero
579// preamplifier_scrittura_lettura_trimmer( scheda_su_scheda_giu, canale, trimmer_fine_offset, 128, preamplifier_scrivi_il_trimmer );//Trimmer inizializzato a zero
580// }
581//}
582//FINE Inizializzazione dei trimmer che servono alla regolazione
583
584// Esploriamo i 2 trimmer, a partie dal+ significativo, cio\'e il SAR veroe e proprio
585 preamplifier_canali_da_regolare_old= preamplifier_canali_da_regolare;
586 for(indice_trimmer=0; indice_trimmer<2;indice_trimmer++){//Facciamo 2 giri, uno per ogni trimmer
587
588 if( indice_trimmer) {
589 preamplifier_canali_da_regolare = preamplifier_canali_da_regolare_old;
590 for(canale=0; canale<6;canale++){
591 indice= canale + scheda_su_scheda_giu;
592 preamplifier_error_voltage_at_the_moment[indice]= preamplifier_error_voltage_at_PGA_gain[indice] / PGA_settled_gain_old[indice]; //Ripristiniamo l'errore
593 target_raggiunto_1_non_raggiunto_0[indice]=0;
594 }
595 preamplifier_trova_il_guess( i_2_trimmer[indice_trimmer]);
596 }
597
598 for(scalata=0; scalata<8; scalata++){
599 //SAR a guadagno 1 fino agli ultimi bit, per non creare sconquasso
600 preamplifier_ritorno_al_gain_originale(scalata , indice_trimmer, target_raggiunto_1_non_raggiunto_0);
601
602 confronto= 1 << (7-scalata); //Impostiamo il valore di prova da aggiungere al trimmer
603 for(canale=0; canale<6;canale++){ // Scansoniamo tutti i possibili canali sulla scheda selezionata
604 indice= canale + scheda_su_scheda_giu; //Solito 2 schede possibili, la prima schede ha indirizzi da 0 a 5, la seconda da 6 a 11
605 if( (preamplifier_SAR_ini[indice].starting_exp_value[indice_trimmer] >= (7-scalata))){ //Job starts just with the minimal cheks, always for the lower 8 bits
606 if( (preamplifier_canali_da_regolare >> canale) & 1){//Selezionaiamo solo i canali indicati
607 contenuto_trimmer_preamplifier[indice][i_2_trimmer[indice_trimmer]] += confronto;
608 preamplifier_scrittura_lettura_trimmer( scheda_su_scheda_giu, canale, i_2_trimmer[indice_trimmer], \
609 contenuto_trimmer_preamplifier[indice][i_2_trimmer[indice_trimmer]], preamplifier_scrivi_il_trimmer );
610 }
611 }
612 }
613 Aspetta_tanti_ms( preamplifier_attesa_tra_le_misure );
614
615 for(canale=0; canale<6;canale++){ // Scansoniamo tutti i possibili canali sulla scheda selezionata
616 indice= canale + scheda_su_scheda_giu; //Solito 2 schede possibili, la prima schede ha indirizzi da 0 a 5, la seconda da 6 a 11
617 if( (preamplifier_SAR_ini[indice].starting_exp_value[indice_trimmer] >= (7-scalata)) ){ //Job is done just with the minimal cheks
618 if( (preamplifier_canali_da_regolare >> canale) & 1){//Selezionaiamo solo i canali indicati
619 if( target_raggiunto_1_non_raggiunto_0[indice]==0){//Se non abbiamo ancora raggiunto la tolleranza continuamo, per i canali fuori target
620 ADC_misura_fatta =ADC_misura_differenziale_con_media_generico(scheda_su_scheda_giu,preamplifier_externalADC_1_onboardADC_0,canale,1);
621
622 if( ( ADC_misura_fatta - preamplifier_Output_offset_target_at_the_moment[indice] ) < \
623 ( - preamplifier_error_voltage_at_the_moment[indice]) ){
624 //siamo fuori tolleranza
625 target_raggiunto_1_non_raggiunto_0[indice]=0;
626 ADC_misura_fatta_old[indice]= ADC_misura_fatta; //
627 }else if ( ( ADC_misura_fatta - preamplifier_Output_offset_target_at_the_moment[indice] ) < \
628 (0 ) ){
629 //Siamo in tolleranza e dobbiamo fermarci
630 target_raggiunto_1_non_raggiunto_0[indice]=1;
631 preamplifier_canali_da_regolare -= 1 << canale ;
632 ADC_misura_fatta_old[indice]= ADC_misura_fatta; //
633 }else if ( ( ADC_misura_fatta - preamplifier_Output_offset_target_at_the_moment[indice] ) >\
634 ( preamplifier_error_voltage_at_the_moment[indice])){
635 //siamo fuori tolleranza
636 target_raggiunto_1_non_raggiunto_0[indice]=0;
637
638 contenuto_trimmer_preamplifier[indice][ i_2_trimmer[indice_trimmer]] -= confronto;
639 preamplifier_scrittura_lettura_trimmer( scheda_su_scheda_giu, canale, i_2_trimmer[indice_trimmer], \
640 contenuto_trimmer_preamplifier[indice][i_2_trimmer[indice_trimmer]], preamplifier_scrivi_il_trimmer );
641 }else if ( ( ADC_misura_fatta - preamplifier_Output_offset_target_at_the_moment[indice] ) >\
642 (0 ) ){
643 //siamo in tolleranza
644 target_raggiunto_1_non_raggiunto_0[indice]=1;
645 ADC_misura_fatta_old[indice]= ADC_misura_fatta; //
646 preamplifier_canali_da_regolare -= 1 << canale ;
647 }
648 }
649 }
650 }
651 }
652 }
653
654 }
655}
int32_t ADC_misura_differenziale_con_media_generico(uint8_t scheda_su_scheda_giu_, uint8_t preamplifier_externalADC_1_onboardADC_0, uint8_t nodo_da_misurare, uint8_t differenziale_1_single_0)
This function sets the original gain when a few LSb have to be determined. The umber of bits is bit_t...
Definition: Adc.c:899
void preamplifier_ritorno_al_gain_originale(uint8_t scalata, uint8_t indice_trimmer, uint8_t *target_raggiunto_1_non_raggiunto_0)
This function sets the original gain when a few LSb have to be determined. The umber of bits is bit_t...
void Aspetta_tanti_ms(int millisecondi)
The timing function.
Definition: Timer.c:52
uint8_t volatile contenuto_trimmer_preamplifier[12][4]
Definition: Trimmer.c:179


Note that the function preamplifier_ritorno_al_gain_originale() is called to verify if it is the time to come back to the original gain. Normally this is done when 2 or 3 bits of the fine trimmer are those remaining to test and set, for compensanting any possible small error introducd by the gain change.

FAST_SAR_procedure


The Fats SAR procedure tries to reduce the numeber of SAR steps from 16 to between 4 and 6.
When the gains are set to 1 V/V the PGA output voltages are read and a tentative calculation of the 8 MSB for target offset is done (in instr_Vbias_to_be_set_function()). Then, depending on how far is the new measured offset from the target, the 2 or 3 LSb of the MSB, or coarse trimmer, are set to 0 and the SAR is applied from here to the end of the MSB. At this point, the final adjustment part is left to the LSB, or fine trimmer, that was set to 0.
The first step with the setting of the LSB is to recover to the original value the gains. Then, the target values for the LSB are calculated from the measured offset and, depending on how far the new offset is from the final value, the 2 or 3 LSb are set to 0 and the SAR is applied to them.
The Fast SAR function preamplifier_aggiusta_offset_FastSAR() is this:

Note
If, when the gain is set to 1 V/V, the output voltage of any channel is found outside the saturation levels (high and low), the procedure is set to standard SAR, for those channels.

Node measurements with internal or external ADC



Node reading can be made with the internal or external ADC. In case an external ADC is chosen, the function called is the preamplifier_ADC_external_measured_node_function():

712int32_t preamplifier_ADC_external_measured_node_function(uint8_t scheda_su_scheda_giu, uint8_t indice){
713 //richiedere sul CAN la misura
714 //In questo caso scheda su o gi\'u non ha importanza perch\'e l'ADC esterno sar\'a connesso direttamente ad una sola scheda
715 uint8_t ii=0;
716 int32_t valore_mis;
717 evento_CAN=10;
718 uint8_t buffer_istruzione[8],iii;
719 for(iii=0;iii<8;iii++){
720 buffer_istruzione[iii]=tx_data[iii];
721 }
722 if ( (indice >= node_voltage_Analog_Mux_0_offset ) ){
723 //Misura su uno dei 2 nodi dei mux
724 Analog_mux_line_to_select_deselect(scheda_su_scheda_giu, indice , 1);
725 }
726 tx_data[5]= indice; //The node to be measured, the code includes also the selected board
727 tx_data[6]= 1; //This must be "1" and says that the node voltage read must be returned here
728 tx_data[7]= instr_readback_node_voltages ; //instr code
729 tx_msg_info.id = ARM_CAN_EXTENDED_ID(indirizzo_CAN_della_scheda);
730 CANdrv->MessageSend(tx_obj_idx, &tx_msg_info, tx_data, 8U);//msg to CAN back to the control room
731 Aspetta_tanti_ms(100); //From here we wait the answer or generate an error
732 //Aspettare che la misura sia fatta, o generare errore
733 //! [CAN error marker]
734 //Before here a CAN message has been sent with success, we hope
735 while( (ii <50) && ( evento_CAN != ARM_CAN_EVENT_RECEIVE ) ){
736 Aspetta_tanti_ms(200);
737 ii++;
738 }
740 //! [CAN error marker]
741 if( (indice >= node_voltage_Analog_Mux_0_offset ) ){
742 //Reset di uno dei 2 mux usati per la misura
743 Analog_mux_line_to_select_deselect(scheda_su_scheda_giu, indice , 0);
744 }
745
746 valore_mis= ( ( ( *(int32_t *)rx_data ) & 0xFFFFFFFF ) ) ;
747 //Convertiamo in funzione del nodo dal leggere
748 valore_mis = (valore_mis * ADC_coefficiente[indice / ADC_molteplicita_node_to_read].numeratore )\
749 / ADC_coefficiente[indice / ADC_molteplicita_node_to_read].denominatore ;
750 for(iii=0;iii<8;iii++){
751 tx_data[iii]=buffer_istruzione[iii];
752 }
753 return valore_mis; //The value returned is the voltage in microV
754}
const struct ADC_coefficiente_type ADC_coefficiente[]
Node normalizing coeficinets used in ADC_lettura_24bit()
Definition: Adc.c:210
#define ADC_molteplicita_node_to_read
Definition: Adc.h:64
@ instr_readback_node_voltages
Nodes voltage read from external ADC.
uint32_t volatile evento_CAN
This is the variable which resembles the flags from the communication.
Definition: Can.c:326
uint32_t tx_obj_idx
This is the variable which resembles the flags from the communication.
Definition: Can.c:323
unsigned int indirizzo_CAN_della_scheda
Per ora lo assegnamo cos\i l'indirizzo della scheda.
Definition: Can.c:335
volatile uint8_t rx_data[8]
Received data vector.
Definition: Can.c:318
ARM_DRIVER_CAN * CANdrv
Definition: Can.c:333
@ CAN_error_comunichiamo_qualche_dato_timeout_on_transmission
Transmission CAN error.
@ error_address_CAN
Error register for CAN bus
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...
@ node_voltage_Analog_Mux_0_offset
Starting Offset for this set of nodes, 32.
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.


The function invokes the reading from an external ADC from the CAN.
In case the internal ADC is used, the function to call is the XXXXXXXX():

Sw details



Let's see the function preamplifier_scrittura_lettura_trimmer() for writing, reading the trimmer:

283void preamplifier_scrittura_lettura_trimmer(uint8_t scheda_su_scheda_giu, uint8_t canale, uint8_t trimmer, \
284 uint8_t valore, uint8_t scrivi_1_leggi_0 ){
285
286 if( scheda_su_scheda_giu >=1) scheda_su_scheda_giu=6;
287
288 uint8_t spedizione[2]={ ( (trimmer << 5) & maschera_solo_bit_di_scrittura_trimmer), valore}; //The trimmer and what to write
289
290 I2C_mux_select_ch( scheda_su_scheda_giu, I2C_mainboard, address_preamplifier_trimmer[canale].quale_I2C); //Select the I2C to be used
291
292 if (scrivi_1_leggi_0){
293
294 I2C_mux->MasterTransmit( (uint8_t) address_preamplifier_trimmer[canale].indirizzo_I2C , spedizione, 2,false); //Write to the selected trimmer of the selcted channel
295
296 }else{
297
298 I2C_mux->MasterTransmit( (uint8_t) address_preamplifier_trimmer[canale].indirizzo_I2C , spedizione, 1,false); //set the channel to read only
299 }
300
301 while( I2C_mux->GetStatus().busy){}; // Write transmission complete
302
303 I2C_mux->MasterReceive( address_preamplifier_trimmer[canale].indirizzo_I2C, &tappo, 1,false); //Read back, the trimmer value
304
305 while( I2C_mux->GetStatus().busy){};
307
308 contenuto_trimmer_preamplifier[canale + scheda_su_scheda_giu][trimmer] = tappo;
309}
volatile uint32_t Error_bad_operation
exploited to mark the errors
@ I2C_error_termometro_0
termometro ch0
@ error_address_I2C1_B
Error register B for I2C1
void I2C_mux_select_ch(uint8_t scheda_su_scheda_giu, uint8_t mainboard_postmainboard, uint8_t canale_da_abilitare)
The I2C mux.
Definition: I2C_mux.c:100
const struct address_detector_bias_trimmer_type address_preamplifier_trimmer[6]
Preamplifier trimmer addresses
Definition: Trimmer.c:139
#define maschera_solo_bit_di_scrittura_trimmer
Mask for command of the trimmer.
Definition: Trimmer.h:76


The identification of the trimmers is done with the structure address_preamplifier_trimmer[6]:

//struct address_detector_bias_trimmer_type {
// uint8_t quale_I2C;
// uint8_t indirizzo_I2C;
//};


The I2C addresses are 2 less than those of the detector trimmer (remember that to communicate with the 6 trimmers we use 3 different I2C):


The codes for mamnaging the trimmer are: