Ardutester il ritorno

Buona Sera,
Come dal titolo ho provato a riprendere il progetto ardutester con il nano partendo da Ardutester Millennium che ho ridotto ad un unico sketch, con display oled 0.96" I2c. Alimentazione con batteria 9v e Alimentatore 9v. Dopo innumerevoli variazioni e calibrature sono riuscito ad ottenere delle misure precise e anche accurate. Premetto che uso il regolatore di tensione del Nano e non ho usato un riferimento esterno (cosa che mi riprometto di aggiungere). Pero' accade una cosa a cui non so dare una spiegazione:
se misuro una resistenza 10000ohm ottengo 9947 come misurato dal multimetro quindi sembra funzionare perfettamente, ma se ripeto la misura per una decina di volte all'undicesima ottengo 9950 poi 9938 e poi per altre 10 volte 9947.
Tutto cio' accade sia con alimentazione a batteria sia con alimentatore (tradizionale con trasformatore) 9V 500 mA.

Il circuto e' il solito con i tre partitori 680/47000 e test batteria su A7, la batteria e l'alimentatore hanno un diodo 1N4007.

Qualcuno sa darmi una spiegazione? Gliene sarei grato.

Massimo

Senza vedere circuito ma soprattutto codice credo sia possibile solo tirare a indovinare

@Salvorhardin Buon Giorno,
Si lo so, ma ieri sera ero a casa e non avevo sotto mano il codice, che per altro e' molto lungo, oggi vedo di postarlo. Ho aperto questa discussione perche' pensavo fosse un problema noto visto che se n'e' parlato a lungo qui nel forum. In ogni caso non e' un gran problema, solo una curiosita'. Io penso che che con un riferimento esterno le cose possano cambiare.

Grazie comunque per l'attenzione

questo e' lo schema che ho seguito, realizzato su millefori

Stai parlando di variazioni dell'1‰ con un convertitore a 10 bit! Usa un convertitore esterno I2C a 24 o 32 bit.

Buona sera Datman

Sono consapevole della risoluzione dell'ADC del 328, ma faccio un corposo oversampling circa 200 letture, e comunque l' 1 per mille e' sulla resistenza non sulla tensione. Quello che mi rende perplesso e' che la lettura e' sempre costante, questo accade solo se faccio letture consecutive, a tal proposito oggi ho avuto una mezz'ora di tempo e ho provato a mettere 100nF sui contatti del pulsante di test, le letture sono piu' stabili, la variazione e' di circa 3-4 ohm su un numero di letture maggiore. Probabilmente un po' di capacita' deriva di fili che collegano lo zoccolo Zif dove metto i componenti. Credo che una precisione maggiore sia davvero difficile da ottenere con l'adc del 328, quindi sono abbastanza soddisfatto. Era solo per capire se si poteva fare di meglio. Ho realizzato l tester perche' devo mettere ordine tra i componenti elettronici che ho in laboratorio, e siccome sono daltonico faccio fatica con le resistenze specialmente quelle azzurre. E' olremodo comodo per i transistor per non dover cercare sui datasheet la piedinatura.... per i led e i condensatori. In fondo costa davvero poco.
Comunque grazie per l'attenzione.

Massimo

Lo sketch e ' davvero lungo anche se ho cercato di ridurre all'osso l'originale (sono circa una quarantina di schede) togliendo tutte le opzione che nn mi servono, rimangono piu' di 2000 righe. Apprezzo molto la tua disponibilita' ma sinceramente , visto che non e' un gran problema, mi vergogno un po' a farti leggere tutto sto malloppo, cerchero' di metterlo in odine e commentarlo come si deve, poi magari lo posto per tutti coloro che ne fossero interessati.
Grazie.

Massimo

Tiro ad indovinare, ovviamente, ma potrebbe essere anche dovuto ad una leggera ossidazione dei terminali.

Si, potrebbe essere, ho provato a pulire i contatti con lo spray e qualcosina e' cambiato.
Ho messo anche un riferimento esterno a 2.5v che uso per calibrare l'adc, e ancora qualche piccolo miglioramento.

Poi ho provato a usare un display lcd 20x4 e, magia, 50 letture consecutive sempre con lo stesso valore, ho ricollegato il display oled i2c e di nuovo valori instabili.
Ho misurato la resistenza sul display tra sda e vcc e scl e vcc in pratica su quel display non ci sono le pull up su i2c, quindi ho messo le pull up, poi un condensatore ceramico 100 nF e un elettrolitico 100uF sull'alimentazione, ho aggiunto un piccolo carico fittizio (20 mA) sui 5v. Ora ottengo letture ultra stabili con saltuarie variazioni dell'ordine di 3-4 ohm su 10.000, che potrebbero dipendere dalla risoluzione.
Probabilmente era la pompa di carica del display che creava disturbi sull'adc. Se non avessi provato, per puro caso, a cambiare il display, non ci sarei mai arrivato.

In ogni caso, come dici tu, pulendo bene i contatti le cose cambiano soprattutto sulla misura dei condensatori.

Grazie per l'interesse

Bravo, ottima analisi

Forse sono anche interferenze dalla trasmissione I2C.

anche quello, ho ridotto la velocita' a 100 khz ... isomma come si dice da noi ... tutto fa.

Io non so se accade anche a voi, ma ogni volta che vedo un tutorial o un progetto pubblicato su qualche sito, quando cerco di realizzarlo ho sempre 1000 problemi. Nei tutorial e' sempre tutto facile e tutto funziona alla prima... Mah saro' io che sono troppo vecchio ...

Massimo

Ma no, come si accaparrano i click se ti dicono che è complicato, devono dirti: Realizza il progetto in 5 minuti.

Ma in ogni settore è così: ti insegno la chitarra in 1 ora, Impara l’inglese i 3 giorni.

Siamo noi i creduloni che cerchiamo la cosa facile, e giustamente c’è chi la promette.

Ma quel detto: tra il dire e il fare c’è di mezzo il mare oggi vale ancora e forse varrà per sempre.

Ciao.

hai ragione! , il mondo gira proprio in questo modo.
Per questo ho scritto che sono troppo vecchio, io non cerco una cosa facile ma che funzioni e possibilmente che funzioni bene. Ora nel mio caso, un tester per componenti fatto con il 328p costa qualche decina di euro e, credo che funzioni anche bene, ma io sono un hobbista e quel poco che faccio mi serve per imparare e per divertirmi. Se faccio un coso che misura a capocchia basta che ci sia scritto ohm oppure uF, che soddisfazione ho? e, soprttutto, che cosa ho imparato? ... tanto vale che lo compri gia' fatto oppure che me lo faccia fare dall'AI, e rimarro' un emerito ignorante col saldatore in mano.

Massimo

Postare il codice così com’è potrebbe essere interessante, per entrambe, (sempre che non intervengano i soliti denigratori che solo quello sanno fare), principalmente per vedere quanti campioni acquisisce, se oversampling ecc, ma questo lo puoi pure appurare tu e postare solo la/le funzioni che acquisiscono e calcolano sul dato grezzo.

Ciao.

Si, certo posso postarlo, ma tengo a precisare che il software non e' mio, o meglio, sono partito da una versione di ardutester (la 13.1) che e' fatta di una trentina di schede tra .ino e file .h. Io ho ridotto il codice ad un solo sketch che utilizza un nano v3, un display oled, due alimentazioni (batteria e alimentatore) ecc. la parte calcolo ho mantenuto l'originale, eliminando funzioni che a me non servono. posso postare quello che e' piu' chiaro del mio, che non e' commentato.

Questa non e' la release definitiva, ma il calcolo e' rimasto questo, allego un file zip perche' il codice e' troppo lungo
Ardutester.zip (45,0 KB)

purtroppo la versione definitiva e in laboratorio, qui sul portatile ho solo questa.

Il progetto originale era scritto in un mix di C e AVR Assembly Code, per questo motivo ho dovuto mantenere il codice con una innumerevole serie di direttive, comunque e'perfettamente funzionante

ho isolato la lettura dell'adc

/*
#include <avr/io.h>
#include <stdlib.h>
#include "Transistortester.h"
#include "Makefile.h" //J-L
*/


/*
extern struct ADCconfig_t{
  uint8_t Samples;              // number of ADC samples to take
  uint8_t RefFlag;              // save Reference type VCC of IntRef
  uint16_t U_Bandgap;           // Reference Voltage in mV
  uint16_t U_AVCC;		// Voltage of AVCC
} ADCconfig;
*/


#ifdef INHIBIT_SLEEP_MODE
//  #define StartADCwait() ADCSRA = (1<<ADSC) | (1<<ADEN) | (1<<ADIF) | AUTO_CLOCK_DIV; /* enable ADC and start */
    #define StartADCwait() ADCSRA = (1<<ADSC)|(1<<ADEN)|(1<<ADIF)|AUTO_CLOCK_DIV; /* Start conversion */\
    while (ADCSRA & (1 << ADSC));  /* wait until conversion is done */
#else
    #define StartADCwait() ADCSRA = (1<<ADEN) | (1<<ADIF) | (1<<ADIE) | AUTO_CLOCK_DIV; /*enable ADC and Interrupt */\
    set_sleep_mode(SLEEP_MODE_ADC);\
    sleep_mode();	/* Start ADC, return, if ADC has finished */
#endif

/***********************************************************************************/
/* ReadADC takes ADCconfig.Samples ADC reads and build a sum of the data           */
/* One ADC read take a time period about 112us.                                    */
/* So 25 ADC reads take more than 2.8ms time.                                      */
/* for resistor and other measurements 190 ADC reads are done with more than 21ms  */


unsigned int ReadADC (uint8_t Probe) {
 unsigned int U; /* return value (mV) */
 uint8_t samples; /* loop counter */
 unsigned long Value; /* ADC value */

 Probe |= (1 << REFS0); /* use internal reference anyway */

#ifdef AUTOSCALE_ADC
get_sample:
#endif  /* AUTOSCALE_ADC */

#if (PROCESSOR_TYP == 644) || (PROCESSOR_TYP == 1280)
 if (Probe & (1 << REFS1)) Probe &= ~(1<<REFS0);	/* ATmega640/1280/2560 1.1V Reference with REFS0=0 */
#endif

 ADMUX = Probe; /* set input channel and U reference */

#ifdef AUTOSCALE_ADC
 /* if voltage reference changes, wait for voltage stabilization */
 if ((Probe & (1<<REFS1)) != ADCconfig.RefFlag) {
    //  Reference is switched, delay depends on NO_AREF_CAP option
    ADCconfig.RefFlag = (Probe & (1<<REFS1));	// save new reference state
 #ifdef NO_AREF_CAP
    wait100us(); /* time for voltage stabilization */
 #else
    wait_about10ms(); /* time for voltage stabilization */
 #endif
// allways do one dummy read of ADC, 112us
    StartADCwait();		/* start ADC and wait */
 }
#endif  /* AUTOSCALE_ADC */

 /* * sample ADC readings */
 Value = 0UL; /* reset sampling variable */
 samples = 0; /* number of samples to take */
 while (samples < ADCconfig.Samples) /* take samples */ {
    StartADCwait();		/* start ADC and wait */
    Value += ADCW; /* add ADC reading */
#ifdef AUTOSCALE_ADC
    /* auto-switch voltage reference for low readings */
    if ((samples == 4) && (ADCconfig.U_Bandgap > 255) && ((uint16_t)Value < 1024) && !(Probe & (1<<REFS1))) {
       Probe |= (1 << REFS1); /* select internal bandgap reference */
       goto get_sample; /* re-run sampling */
    }
#endif
    samples++; /* one more done */
 }  /* end while */
#ifdef AUTOSCALE_ADC
 /* * convert ADC reading to voltage * - single sample: U = ADC reading * U_ref / 1024 */
 /* get voltage of reference used */
 if (Probe & (1 << REFS1)) U = ADCconfig.U_Bandgap; /* bandgap reference */
 else U = ADCconfig.U_AVCC; /* Vcc reference */
#else
 U = ADCconfig.U_AVCC; /* Vcc reference */
#endif

 /* convert to voltage; */
 Value *= U; /* ADC readings * U_ref */
 Value /= 1023; /* / 1024 for 10bit ADC */
 /* de-sample to get average voltage */
 Value /= ADCconfig.Samples;
 U = (unsigned int)Value;
 return U;
//   return ((unsigned int)(Value / (1023 * (unsigned long)ADCconfig.Samples)));
}
unsigned int W5msReadADC (uint8_t Probe) {
  wait_about5ms();
  return (ReadADC(Probe));
}
unsigned int W10msReadADC (uint8_t Probe) {
  wait_about10ms();
  return (ReadADC(Probe));
}
unsigned int W20msReadADC (uint8_t Probe) {
  wait_about20ms();
  return (ReadADC(Probe));
}

uint16_t unsigned_diff(uint16_t v1, uint16_t v2)
{
  if (v1 > v2) return (v1 - v2);
  else         return (0);
}
uint16_t abs_diff(uint16_t v1, uint16_t v2)
{
  if (v1 > v2) return (v1 - v2);
  else         return (v2 - v1);
}

uint16_t vcc_diff(uint16_t v2)
{
  return unsigned_diff(ADCconfig.U_AVCC, v2);
//  if (ADCconfig.U_AVCC > v2) return (ADCconfig.U_AVCC - v2);
//  else         return (0);
}

qui il calcolo della resistenza, il numero di campioni e' definito nella direttiva
R_ANZ_MESS (massimo 200). Io uso 190.

/*
#include <avr/io.h>
#include <stdlib.h>
#include "Transistortester.h"
#include "Makefile.h" //J-L
*/

//******************************************************************
void GetResistance(uint8_t HighPin, uint8_t LowPin)
  {
  /*
  Function for checking the resistance of a component with the following pin assignment 
  parameters:
  HighPin: Pin, which will be switched to VCC at the beginning
  LowPin: Pin, which will be switch to GND at the beginning
*/
  struct {
     unsigned int hp1;
     unsigned int hp2;
     unsigned int lp1;
     unsigned int lp2;
     unsigned int tp1;
     unsigned int tp2;
  }adc;

uint8_t LoPinRL;		// mask to switch the LowPin with R_L
uint8_t LoPinRH;		// mask to switch the LowPin with R_H
uint8_t HiPinRL;		// mask to switch the HighPin with R_L
uint8_t HiPinRH;		// mask to switch the HighPin with R_H
uint8_t LoADCp;			// mask to switch the ADC port LowPin
uint8_t HiADCp;			// mask to switch the ADC port HighPin

#if FLASHEND > 0x1fff
  uint8_t ii;			// temporary variable
  int udiff;
#endif


  unsigned long lrx1;
  unsigned long lirx1;
  unsigned long lirx2;
  const uint8_t	*addr;
  uint8_t resnum;
  /*
    switch HighPin directls to VCC 
    switch R_L port for LowPin to GND 
    TristatePin remains switched to input , no action required 
  */
  wdt_reset();
  addr = &PinRLRHADCtab[LowPin-TP_MIN];		// address of the combined RL / RH / ADC pin table
  LoPinRL = pgm_read_byte(addr);		// instruction for LowPin R_L
#if (((PIN_RL1 + 1) != PIN_RH1) || ((PIN_RL2 + 1) != PIN_RH2) || ((PIN_RL3 + 1) != PIN_RH3))
  addr += 3;			// address of PinRHtab[LowPin]
  LoPinRH = pgm_read_byte(addr);		// instruction for LowPin R_H
#else
  LoPinRH = (LoPinRL + LoPinRL);
#endif
  addr += 3;			// address of PinADCtab[LowPin]
  LoADCp = pgm_read_byte(addr);		// instruction for ADC Low-Pin, including | TXD_VAL

  addr = &PinRLRHADCtab[HighPin-TP_MIN];
  HiPinRL = pgm_read_byte(addr);		// instruction for HighPin R_L
#if (((PIN_RL1 + 1) != PIN_RH1) || ((PIN_RL2 + 1) != PIN_RH2) || ((PIN_RL3 + 1) != PIN_RH3))
  addr += 3;			// address of PinRLtab[HighPin]
  HiPinRH = pgm_read_byte(addr);		// instruction for HighPin R_H
#else
  HiPinRH = (HiPinRL + HiPinRL);
#endif
  addr += 3;			// address of PinADCtab[HighPin]
  HiADCp = pgm_read_byte(addr);		// instruction for ADC High-Pin, including | TXD_VAL

//##########################################################################################
// Search for resistors
//##########################################################################################
  if ((ptrans.count  + ntrans.count) > 0) {
     return;	// no resistors are searched, if transistors are detected
  }
  resnum = (LowPin - TP_MIN + HighPin - TP_MIN - 1);	// resistor-Number 0:1 = 0, 0:2 = 1, 1:2 = 2
  // resistor measurement
  wdt_reset();
// U_SCALE can be set to 4 for better resolution of ReadADC result
#if U_SCALE != 1
  ADCconfig.U_AVCC = (adc_vcc_reference * U_SCALE);	// scale to higher resolution, mV scale is not required
  ADCconfig.U_Bandgap = (adc_internal_reference * U_SCALE);
#endif
#if R_ANZ_MESS != ANZ_MESS
  ADCconfig.Samples = R_ANZ_MESS;	// switch to special number of repetitions
#endif
  #define MAX_REPEAT (700 / (5 + R_ANZ_MESS/8))
#if FLASHEND > 0x1fff
  for (ii=0; ii<NumOfDiodes; ii++) {
     // never search a resistor at the same place, where a diode is detected
     if ((diodes.Anode[ii] + diodes.Cathode[ii]) ==  (HighPin + LowPin)) goto testend;
  }
#endif
  ADC_PORT = TXD_VAL;
  ADC_DDR = LoADCp | TXD_MSK;		//switch Low-Pin to output (GND)
  R_DDR = HiPinRL;		//switch R_L port for High-Pin to output (VCC)
  R_PORT = HiPinRL;	
#if FLASHEND > 0x1fff
  adc.hp2 = 0;
  for (ii=1;ii<MAX_REPEAT;ii++) {
     // wait until voltage is stable
     adc.tp1 = W5msReadADC(LowPin);	// low-voltage at Rx with load
     adc.hp1 = ReadADC(HighPin);		// voltage at resistor Rx with R_L
     udiff = adc.hp1 - adc.hp2;
     if (udiff < 0) udiff = -udiff;
     if (udiff < 3) break;
     adc.hp2 = adc.hp1;
     wdt_reset();
  }
  if (ii == MAX_REPEAT) {
 #if (DEBUG_OUT == 1)
     lcd_data('a');
 #endif
     goto testend;
  }
#else
  adc.tp1 = W5msReadADC(LowPin);	// low-voltage at Rx with load
  adc.hp1 = ReadADC(HighPin);		// voltage at resistor Rx with R_L
#endif
  if (adc.tp1 > adc.hp1) {
     adc.tp1 = adc.hp1;
  }
  R_PORT = 0;
  R_DDR = HiPinRH;		//switch R_H port for High-Pin to output (GND)
  adc.hp2 = W5msReadADC(HighPin);	// read voltage, should be down
  if (adc.hp2 > (20*U_SCALE)) {
     // if resistor, voltage should be down
 #if (DEBUG_OUT == 1)
     lcd_data('b');
 #endif
     goto testend;
  }
  R_PORT = HiPinRH;		//switch R_H for High-Pin to VCC
  adc.hp2 = W5msReadADC(HighPin);	// voltage at resistor Rx with R_H

  ADC_DDR = HiADCp | TXD_MSK;		//switch High-Pin to output
  ADC_PORT = HiADCp;		//switch High-Pin to VCC
  R_PORT = 0;
  R_DDR = LoPinRL;			//switch R_L for Low-Pin to GND
#if FLASHEND > 0x1fff
  adc.lp2 = 0;
  for (ii=1;ii<MAX_REPEAT;ii++) {
     // wait until voltage is stable
					// L--RL--RyyX--H
     adc.tp2 = W5msReadADC(HighPin);	//high voltage with load
     adc.lp1 = ReadADC(LowPin);		//voltage at the other end of Rx
     udiff = adc.lp1 - adc.lp2;
     if (udiff < 0) udiff = -udiff;
     if (udiff < 3) break;
     adc.lp2 = adc.lp1;
     wdt_reset();
  }
  if (ii == MAX_REPEAT) {
 #if (DEBUG_OUT == 1)
     lcd_data('c');
 #endif
     goto testend;
  }
#else
  adc.tp2 = W5msReadADC(HighPin);	//high voltage with load
  adc.lp1 = ReadADC(LowPin);		//voltage at the other end of Rx
#endif
  if (adc.tp2 < adc.lp1) {
     adc.tp2 = adc.lp1;
  }
					// L--RH--RX--H
  R_DDR = LoPinRH;			//switch R_H for Low-Pin to GND
  adc.lp2 = W5msReadADC(LowPin);
		
  if((adc.hp1 < (4400*U_SCALE)) && (adc.hp2 > (97*U_SCALE))) {
     //voltage break down isn't insufficient 
 #if (DEBUG_OUT == 1)
     lcd_data('d');
 #endif
     goto testend; 
  }
//    if((adc.hp2 + (adc.hp2 / 61)) < adc.hp1)
  if (adc.hp2 < (4972*U_SCALE)) { 
     // voltage breaks down with low test current and it is not nearly shorted  => resistor
//     if (adc.lp1 < 120)  // take measurement with R_H 
     if (adc.lp1 < (169*U_SCALE)) { // take measurement with R_H 
        if (adc.lp2 < (38*U_SCALE)) {
           // measurement > 60MOhm too big resistance
 #if (DEBUG_OUT == 1)
     lcd_data('e');
 #endif
           goto testend;
        }
        // two measurements with R_H resistors (470k) are made:
        // lirx1 (measurement at HighPin)
        lirx1 = (unsigned long)((unsigned int)R_H_VAL) * (unsigned long)adc.hp2 / vcc_diff(adc.hp2);
        // lirx2 (measurement at LowPin)
        lirx2 = (unsigned long)((unsigned int)R_H_VAL) * (unsigned long)vcc_diff(adc.lp2) / adc.lp2;
#define U_INT_LIMIT (990*U_SCALE)		// 1V switch limit in ReadADC for atmega family
#ifdef __AVR_ATmega8__
#define FAKT_LOW 2		//resolution is about twice as good
#else
#define FAKT_LOW 4		//resolution is about four times better
#endif
#ifdef AUTOSCALE_ADC
        if (adc.hp2 < U_INT_LIMIT) {
           lrx1 = (lirx1*FAKT_LOW + lirx2) / (FAKT_LOW+1);	//weighted average of both R_H measurements
        } else if (adc.lp2 < U_INT_LIMIT){
           lrx1 = (lirx2*FAKT_LOW + lirx1) / (FAKT_LOW+1);	//weighted average of both R_H measurements
        } else 
#endif
        {
           lrx1 = (lirx1 + lirx2) / 2;		//average of both R_H measurements
        }
        lrx1 *= 100;
        lrx1 += RH_OFFSET;			// add constant for correction of systematic error
     } else {
        // two measurements with R_L resistors (680) are made:
        // lirx1 (measurement at HighPin)
        if (adc.tp1 > adc.hp1) {
           adc.hp1 = adc.tp1;		//diff negativ is illegal
        }
        lirx1 =(unsigned long)RR680PL * (unsigned long)unsigned_diff(adc.hp1, adc.tp1) / vcc_diff(adc.hp1);
        if (adc.tp2 < adc.lp1) {
           adc.lp1 = adc.tp2;		//diff negativ is illegal
        }
        // lirx2 (Measurement at LowPin)
        lirx2 =(unsigned long)RR680MI * (unsigned long)unsigned_diff(adc.tp2, adc.lp1) / adc.lp1;

#ifdef AUTOSCALE_ADC
        if (adc.hp1 < U_INT_LIMIT) {
           lrx1 = (lirx1*FAKT_LOW + lirx2) / (FAKT_LOW+1);	//weighted average of both R_L measurements
        } else if (adc.lp1 < U_INT_LIMIT) {
           lrx1 = (lirx2*FAKT_LOW + lirx1) / (FAKT_LOW+1);	//weighted average of both R_L measurements
        } else
#endif
        {
           lrx1 = (lirx1 + lirx2) / 2;		//average of both R_L measurements
        }
     }
     // measurement is finished, lrx1 is the resistance value of one direction
     if(PartFound < PART_TRANSISTOR) {
        if (ResistorChecked[resnum] != 0) {
           // must be measurement with inverse polarity 
           // resolution is 0.1 Ohm, 1 Ohm = 10 !
           lirx1 = (labs((long)lrx1 - (long)ResistorVal[resnum]) * 10) / (lrx1 + ResistorVal[resnum] + 100);
           if (lirx1  > 0) {
              // mismatch of the two measurements
//              ResistorsFound--;		// this one isn't a resistor
//              goto testend; // <10% mismatch
 #if (DEBUG_OUT == 1)
     lcd_line3();
     DisplayValue(lrx1,-1,' ',4);
     DisplayValue(ResistorVal[resnum],-1,' ',4);
 #endif
           } else {
              // resistor has the same value in both directions
              if (PartFound < PART_DIODE) {
                 PartFound = PART_RESISTOR;	// only mark as resistor, if no other part found
              }
              ResistorChecked[resnum] = 2;		// mark as checked in both direction
              ResistorList[ResistorsFound] = resnum;	// save number of this resistor
              ResistorsFound++;			// 1 more resistor found
           }
           goto testend;
        } else {		// resistor is never checked before
           // must be a new one with other pins
           ResistorVal[resnum] = lrx1;	// save register value
           ResistorChecked[resnum] = 1;		// is checked in one direction

        } // end  ResistorChecked[] != 0
     }	/* end if (PartFound < PART_TRANSISTOR) */
  }
  testend:			// end of resistor measurement
#if U_SCALE != 1
  ADCconfig.U_AVCC = adc_vcc_reference;	// scale to higher resolution, mV scale is not required
  ADCconfig.U_Bandgap = adc_internal_reference;	// set back to normal resolution
#endif
#if R_ANZ_MESS != ANZ_MESS
  ADCconfig.Samples = ANZ_MESS;		// switch back to standard number of repetition
#endif

  return;
} // end GetResistance()

Spero di non aver fatto casini, a quest'ora crollo dal sonno

Se la funzione usa millis() o delay(), visto che il for è bloccante io lo avrei fatto atomico e per i delay avrei usato le funzioni della avr_libc. La isr di millis viene eseguita circa ogni 1000us e a memoria impiega circa 80us, pertanto visto che millis() non è strettamente necessaria io la disabiliterei, forse potrebbe pure bastare un cli()prima del for e un sei()dopo il for usando la delay di avr_libc. Ma questo non è detto che aumenti la precisione, si ha solo il vantaggio che il tempo tra i 190 campioni è costante e la isr del timer0 non rompe.

Se non fosse per il codice complesso da esaminare e modificare tenterei l’oversampling, ma invece sai che ti dico che già il risultato è ottimo e i margini di miglioramento richiedono un investimento di tempo troppo lungo.

Ciao.

ciao Mauro
anche io nelle mie applicazioni uso millis e quasi mai delay, pero' come dicevo ieri quel codice non e' mio, e la complessita' e molta per questo ho mantenuto l'originale, mentre ho lavorato con l'hardware per ottenere un minimo di accuratezza. Oggi sono riuscito a mettere "in bella copia" la versione definitiva, devo aggiungere ancora qualcosina cosi' se a qualcuno interessa puo' divertirsi a fare il tester.
Ho fatto alcuni test con due multimetri, uno dovrebbe essere preciso, l'altro e' un cinese un po' piu' decente... risultato tutti e tre misurano in modo diverso .... chissa' quale e' giusto, comunque le differenze sono minime.

Massimo