Ardutester - Arduino Component Tester (INCOMPLETO)

[quote author=Michele Menniti link=topic=163227.msg1306507#msg1306507 date=1373184426] Guglielmo, le hai usate da qualche parte, tutto ok? A me ricorda roba di trent'anni fa, non è che semplicemente sono straossidati i pin e non fanno contatto sulla bread? [/quote]

No, no, Michele, sono recentissime, le ultime me le hanno consegnate non più di una settimana fa ... e a me non danno problemi.

Però, ripeto, le mie sono comprate da un distributore qui e non in Polonia ... quindi ... non so quelle di Paolo ... :roll_eyes:

Guglielmo

Le mie le ho prese meno di 20 gg fa. Sembrano nuove e non ossidate: sono identiche a quelle di Guglielmo.

Allora succede qualcosa quando sono attraversate da correnti, potrebbero essere impedenze?

How to work!

Nel setup l'Ardutester setta la Seriale e inizializza LCd, poi passa a inizializzare l'ADC e carica i valori di default della configurazione

  ADCSRA = (1 << ADEN) | ADC_CLOCK_DIV;          //Enable ADC and set clock divider
  MCUSR &= ~(1 << WDRF);                         //Reset watchdog flag
  wdt_disable();                                 //Disable watchdog
  
//Cycling
  RunsMissed = 0;
  RunsPassed = 0;

 //Default offsets and values
  Config.Samples = ADC_SAMPLES;                  //Number of ADC samples
  Config.AutoScale = 1;                          //Enable ADC auto scaling
  Config.RefFlag = 1;                            //No ADC reference set yet
  analogReference(EXTERNAL);                     //Set Analog Reference to External
  pinMode(pushButton, INPUT_PULLUP);             //Set pin to input and turn on pullup resistors

imposta il riferimento esterno (si userà poi il riferimento interno a 1.1V) e il pulsante.

Nell loop, viene abilitato il watchdog a 2 secondi, resettate le variabili di riconoscimento di componenti e impostati tutti gli ingressi dell'ADc ad alta impedenza

  ADC_DDR &= ~(1<

Viene letta poi la tensione di riferimento.

Config.U_Bandgap = ReadU(0x0e);                //Get voltage of bandgap reference

dove la funzione ReadU è:

//Read ADC and return voltage in mV (GOTO Free - Thanks to PaoloP)
unsigned int ReadU(byte Probe)
{
  unsigned int      U;                            //Return value (mV)
  byte              Counter;                      //Loop counter
  unsigned long     Value;                        //ADC value
  Probe |= (1 << REFS0);                          //Use internal reference anyway
  boolean cycle;
  do {
    cycle = false;                                // One Time cycle
    ADMUX = Probe;                                //Set input channel and U reference
    //If voltage reference has changed run a dummy conversion
    Counter = Probe & (1 << REFS1);               //Get REFS1 bit flag
    if (Counter != Config.RefFlag)
    {
      waitus(100);                                //Time for voltage stabilization
      ADCSRA |= (1 << ADSC);                      //Start conversion
      while (ADCSRA & (1 << ADSC));               //Wait until conversion is done
      Config.RefFlag = Counter;                   //Update flag
    }
    //Sample ADC readings
    Value = 0UL;                                  //Reset sampling variable
    Counter = 0;                                  //Reset counter
    while (Counter < Config.Samples)              //Take samples
    {
      ADCSRA |= (1 << ADSC);                      //Start conversion
      while (ADCSRA & (1 << ADSC));               //Wait until conversion is done
      Value += ADCW;                              //Add ADC reading
      //Auto-switch voltage reference for low readings
      if ((Counter == 4) && ((unsigned int)Value < 1024) && !(Probe & (1 << REFS1)) && (Config.AutoScale == 1))
      {
        Probe |= (1 << REFS1);                    //Select internal bandgap reference
        cycle = true;
        break;                                    //Re-run sampling 
      }
      Counter++;                                  //One less to do
    }
  } 
  while (cycle);
  //Convert ADC reading to voltage
  if (Probe & (1 << REFS1)) U = Config.U_Bandgap; //Bandgap reference
  else U = UREF_VCC;                              //Vcc reference   
  //Convert to voltage
  Value *= U;                                     //ADC readings U_ref 
  //Value += 511 * Config.Samples;                //Automagic rounding
  Value /= 1024;                                  // / 1024 for 10bit ADC
  //De-sample to get average voltage
  Value /= Config.Samples;
  U = (unsigned int)Value;
  return U; 
}

Analizziamo bene la ReadU...

La funzione inizializza per primo il valore U che sarà poi quello restituito. Viene impostato il riferimento interno dell'ADC

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

Inizia il ciclo e viene scelto il canale dell'mux

ADMUX = Probe;                                //Set input channel and U reference

canale 14 ovvero la tensione interna a 1.1V (nuovo datasheet pag 255 --> http://www.atmel.com/Images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet.pdf) Siamo ancora nella fase di inizializzazione dei valori e non nella lettura delle sonde esterne.

il ciclo completo è

  boolean cycle;
  do {
    cycle = false;                                // One Time cycle
    ADMUX = Probe;                                //Set input channel and U reference
    //If voltage reference has changed run a dummy conversion
    Counter = Probe & (1 << REFS1);               //Get REFS1 bit flag
    if (Counter != Config.RefFlag)
    {
      waitus(100);                                //Time for voltage stabilization
      ADCSRA |= (1 << ADSC);                      //Start conversion
      while (ADCSRA & (1 << ADSC));               //Wait until conversion is done
      Config.RefFlag = Counter;                   //Update flag
    }
    //Sample ADC readings
    Value = 0UL;                                  //Reset sampling variable
    Counter = 0;                                  //Reset counter
    while (Counter < Config.Samples)              //Take samples
    {
      ADCSRA |= (1 << ADSC);                      //Start conversion
      while (ADCSRA & (1 << ADSC));               //Wait until conversion is done
      Value += ADCW;                              //Add ADC reading
      //Auto-switch voltage reference for low readings
      if ((Counter == 4) && ((unsigned int)Value < 1024) && !(Probe & (1 << REFS1)) && (Config.AutoScale == 1))
      {
        Probe |= (1 << REFS1);                    //Select internal bandgap reference
        cycle = true;
        break;                                    //Re-run sampling 
      }
      Counter++;                                  //One less to do
    }
  } 
  while (cycle);

Si controlla che il riferimento non sia cambiato e nel caso si effettua una lettura a vuoto

  //If voltage reference has changed run a dummy conversion
    Counter = Probe & (1 << REFS1);               //Get REFS1 bit flag
    if (Counter != Config.RefFlag)

se invece il riferimento non e stato modifica si esegue la lettura reale con un numero di lettura pari a Config.Samples (in questo caso 200). Config.RefFlag è posto a 1 nel setup.

Nel ciclo while interno

while (Counter < Config.Samples)              //Take samples
    {
      ADCSRA |= (1 << ADSC);                      //Start conversion
      while (ADCSRA & (1 << ADSC));               //Wait until conversion is done
      Value += ADCW;                              //Add ADC reading
      //Auto-switch voltage reference for low readings
      if ((Counter == 4) && ((unsigned int)Value < 1024) && !(Probe & (1 << REFS1)) && (Config.AutoScale == 1))
      {
        Probe |= (1 << REFS1);                    //Select internal bandgap reference
        cycle = true;
        break;                                    //Re-run sampling 
      }
      Counter++;                                  //One less to do
    }

è letto il valore dell’ADC a 16 bit, a differenze dell’analogread che legge 2 byte e poi li unisce

	// start the conversion
	sbi(ADCSRA, ADSC);

	// ADSC is cleared when the conversion finishes
	while (bit_is_set(ADCSRA, ADSC));

	// we have to read ADCL first; doing so locks both ADCL
	// and ADCH until ADCH is read.  reading ADCL second would
	// cause the results of each conversion to be discarded,
	// as ADCL and ADCH would be locked when it completed.
	low  = ADCL;
	high = ADCH;
#else
	// we dont have an ADC, return 0
	low  = 0;
	high = 0;
#endif
	// combine the two bytes
	return (high << 8) | low;

ADC è definito nelle lib AVR come

#define ADCW    _SFR_MEM16(0x78)

Alla 4° lettura, se il valore è inferiore a 1024, quindi meno di 256 a lettura e se è stato settato l'autoscale con riferimento normale (5V)

 if ((Counter == 4) && ((unsigned int)Value < 1024) && !(Probe & (1 << REFS1)) && (Config.AutoScale == 1))
      {
        Probe |= (1 << REFS1);                    //Select internal bandgap reference
        cycle = true;
        break;                                    //Re-run sampling 
      }

viene impostato il rifermento a 1.1V, la variabile cycle è vera e il ciclo ricomincia. (prima qui c'era un orribile goto. :grin: Così migliora la risoluzione in lettura. Terminato il campionamento, le solite operazioni.

if (Probe & (1 << REFS1)) U = Config.U_Bandgap; //Bandgap reference
  else U = UREF_VCC;                              //Vcc reference   
  //Convert to voltage
  Value *= U;                                     //ADC readings U_ref 
  //Value += 511 * Config.Samples;                //Automagic rounding
  Value /= 1024;                                  // / 1024 for 10bit ADC
  //De-sample to get average voltage
  Value /= Config.Samples;
  U = (unsigned int)Value;
  return U;

Il valore viene moltiplicato per il valore di riferimento, 1.1V o 5V, diviso per 1024 (dovrebbe essere 1023??), e diviso per il numero di campioni.

Tutto questo, la prima volta, dovrebbe restituire 1100 mV.

Nel loop(), una volta stabilita la tensione di riferimento interna con la migliore accuratezza possibile si passa alla scarica di eventuali componenti collegati (come i condensatori), poi al controllo dei cortocircuiti tra le sonde e se tutto va bene si passa all'analisi dei componenti collegati alle sonde, vero cuore dell'ArduTester.

//Try to discharge any connected component
  DischargeProbes();
  if (CompFound == COMP_ERROR)                   //Discharge failed
  {
    ErrFnd=4;                                    //Skip all other checks
  }
  //Short-circuit
  if (AllProbesShorted() == 3)
  {
    ErrFnd=3;                                    //New cycle after job is is done
  }
  else
  {
    //Check all 6 combinations of the 3 probes
    CheckProbes(TP1, TP2, TP3);
    CheckProbes(TP2, TP1, TP3);
    CheckProbes(TP1, TP3, TP2);
    CheckProbes(TP3, TP1, TP2);
    CheckProbes(TP2, TP3, TP1);
    CheckProbes(TP3, TP2, TP1);

La scarica dei componenti è semplice, vengono portati a massa tutte le resistenze (pull-down) effettuando dei cicli di lettura della tensione e controllando fino a un valore inferiore ad una soglia preimpostata. Dopo la scarica, viene effettuato il test per verificare il corto delle sonde e in caso positivo si passa al sefttest interno, altrimenti si procede con la funzione CheckProbes. (che vedremo dopo mangiato) :grin:

Viste cosi a occhio, quelle sembrano le resistenze che produceva la Welwyn per i tester analogici ... credo che esista ancora ...

Di migliori credo ci siano solo quelle a strato metallico della Vishay da 0,01%, laser trimmed ... ma l'ultima volta che ho visto uno dei loro listini, costavano come se fossero state fatte d'oro massiccio :P :fearful:

E usarle SMD ? ... ci sono anche le 1206 allo 0,1% ...

Le mie sono della Welwyn.

Ho acquistato da Digikey queste:

A103210CT-ND A103233CT-ND

Alla modica cifra di 124€ per reel (1.000 pezzi)

Allego il datasheet delle mie … sono CAR7 allo 0,1% di precisione … e costano un occhio (4 € cad … del resto … quando ne compri 10 e te le spediscono in 24 ore in ufficio … paghi anche il servizio) XD XD XD

Guglielmo

datasheet.pdf (254 KB)

La prossima settimana arriva la regina del Fablab e poi produrre le schedine in SMD sarà un gioco da ragazzi...

La regina è questa :D http://www.youtube.com/watch?v=5G17RgXVq38

Ce l'ho anch'io ... solo che la mia occupa meno spazio

:P XD XD XD

(... come ti odio ... scherzo, ovviamente :P)

Etemenanki: (... come ti odio ... scherzo, ovviamente :P)

:grin: Adesso devo trovare un service pcb in zona a buon mercato e dopo è fatta.

Chiuso OT, meglio concentrarsi sull'Ardutester.

Più tardi descrivo come funziona la CheckProbe. Pazientate. :blush:

PaoloP: Più tardi descrivo come funziona la CheckProbe. Pazientate. :blush:

Fai pure con comodo ... sto ancora cercando di capire quello che hai postato prima ...

Sono rimasto incastrato fra "ADCSRA = (1 << ADEN) | ADC_CLOCK_DIV;" e "MCUSR &= ~(1 << WDRF);" ... :P XD XD XD (scherzo, ma mica troppo :P)

riprendo l'argomento resistenze, vi ricordo che montate su Ardutester non lo fanno funzionare, la prova del 9, se ho ben capito è stata il montaggio di queste R al postoe delle sue sul circuito di cece, ha smesso di funzionare! Sembrerebbe che sotto lavoro combinino qualcosa di strano, una prova immediata e simpatica sarebbe quella di prenderne due (meglio se di valore diverso), fare un partitore sui 5V e vedere cosa si misura al centro, servono pochi secondi.....

ADCSRA è l"ADC Control and Status Register A", pag. 255 del nuovo datasheet linkato precedentemente.
E’ un registro a 8 bit, esso controlla l’attivazione dell’ADC (AD ENable - bit 7), la start della conversione analogico/digitale (bit 6), altre cosette e la funzione prescaler, ovvero il fattore demoltiplicante del clock dell’ADC nei confronti del clock di sistema. (bit 0, 1 e 2).

MCUSR è il registro di sistema (pag 54 del datasheet) che controlla tra le altre cose il watchdog.

@Michele
Sul quello di cece ho montato le mie, ma non quelle nere, quelle colorate al 5% e all’ 1%.
Insomma abbiamo fatto delle prove talmente incasinate, modificando di volta in volte più fattori che non ne siamo usciti.
Poi qualcuno offriva Prosecco dalle 10 del mattino… puoi immaginare.

questione chiusa, ed io che vi davo peso, banda di alcolizzati :fearful: