Lettura VIN + precisa

Ciao a tutti.
Non ho trovato niente di simile girando nei forum per quanto riguarda una lettura precisa dell'alimentazione in uso, o meglio ci si basa sulla lettura dei 1,1 volt ma il tutto è legato alla fine alla variabile RESULT legata a una divisione del numero numero definirei MAGIC NUMBER che varia sia a secondo dei vari Arduino utilizzati (anche se sono tutti Uno o Nano) sia a seconda dell'alimentazione se USB o esterna e questo rende impossibile ottenere dei risultati decenti ad esempio nella misurazione di resistenze/volt in cui molto spesso viene usata una variabile Vin generica di 5.00 volt e ovviamente il risultato dell'operazione risulta errato, soprattutto se si usa l'alimentazione USB e di meno se si usa un'alimentazione esterna, perchè è più facile che con alimentazione esterna il risultato sia effettivamente 5 Volt.
Ci sono poi in giro delle dritte su come calcolare questo MAGIC NUMBER ma ne ho seguite un paio e mi davano risultati completamente errati.
Quello che ho fatto io è di mettere all'avvio di Arduino una routine che, dopo aver atteso un paio di secondi per attendere che l'alimentazione si stabilizzi, fà 16 campionamenti simili alla routine ReadVcc() e, a seconda del RESULT stabilisce se l'alimentazione arriva da USB o esternamente e poi, moltiplica questo RESULT con 2 variabili precedentemente misurate col tester tra ground e Aref ad esempio, per ottenere il nostro numero magico che viene memorizzato nella variabile globale MoltiplicatoreVin ed utilizzato nelle successive chiamate a ReadVCC.
Quello che dovete fare dunque è misurare col tester i valori restituiti da Aref sia che sia alimentato tramite USB oppure da alimentazione esterna e inserirlo nelle 2 variabili TesterUsb e TesterBatt.
Come potete vedere dai risultati nel monitor seriale, questi 2 numeri sono molto differenti tra loro, per cui metterne uno solo (come si vede nelle routines che girano nei forum) và a falsare i risultati a seconda se vi state alimentando da USB o da una batteria esterna.
Spero vi sia utile...ciaoooo

// inserite in queste 2 variabili i valori misurati col tester
//******************************************************************************************
float TesterUsb = 4560, TesterBatt = 5000;  // MISURATI CON TESTER TRA GROUND E AREF o VCC
//******************************************************************************************
long MoltiplicatoreVin = 0;
void setup() {
  analogReference(DEFAULT);
  Serial.begin(115200);
  while (!Serial)
    ;
  LeggoMoltiplicatore();
}

void loop() {
  float Vin = readVcc() / 1000.00;//valore in volt
  Serial.print("Vin = ");
  Serial.println(Vin,3);
  delay(1000);
}
long readVcc() {
  //long result;  // Read 1.1V reference against AVcc
  // 4,562 V da USB e 5,000 V da batteria
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);  // for arduino 328-168
  delay(2);                                                // Wait for Vref to settle
  ADCSRA |= _BV(ADSC);                                     // Start conversion
  while (bit_is_set(ADCSRA, ADSC))
    ;                   // measuring
  uint8_t low = ADCL;   // must read ADCL first - it then locks ADCH
  uint8_t high = ADCH;  // unlocks both
  long result = (high << 8) | low;
  result = MoltiplicatoreVin / result;
  return result;
}
void LeggoMoltiplicatore() {
  delay(2000);  // lasciare che il sistema si stabilizzi altrimenti la lettura non è corretta
  long result = 0;
  for (int r = 1; r <= 16; r++) {
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);  // for arduino 328-168
    delay(2);                                                // Wait for Vref to settle
    ADCSRA |= _BV(ADSC);                                     // Start conversion
    while (bit_is_set(ADCSRA, ADSC))
      ;                   // measuring
    uint8_t low = ADCL;   // must read ADCL first - it then locks ADCH
    uint8_t high = ADCH;  // unlocks both
    result += (high << 8) | low;
  }
  Serial.println("----------");
  result = (int)result / 16;
  // il valore 230 è una via di mezzo tra il risultato tramite USB o batteria
  if (result > 230) {  //244 alimentazione USB nel mio arduino
    MoltiplicatoreVin = result * TesterUsb;
    Serial.println("alimentazione USB");
    Serial.print("result = ");
    Serial.println(result);
  } else {  // 223 alimentazione a batteria nel mio arduino ma potrebbe variare nel vostro
    MoltiplicatoreVin = result * TesterBatt;
    Serial.println("alimentazione Batteria");
    Serial.print("result = ");
    Serial.println(result);
  }
  Serial.print("Moltiplicatore = ");
  Serial.println(MoltiplicatoreVin);
}

Se invece avete misurato i valori tra GND e AREF potete usare questa routine che identifica se l'alimentazione è a batteria oppure tramite USB.
E risparmiate i 2 secondi iniziali di attesa.
Cmq và bene se non sostituite arduino, altrimenti la prima volta vanno usate le 2 routines complete

long readVcc() {
  //long result;  // Read 1.1V reference against AVcc
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);  // for arduino 328-168
  delay(2);                                                // Wait for Vref to settle
  ADCSRA |= _BV(ADSC);                                     // Start conversion
  while (bit_is_set(ADCSRA, ADSC))
    ;                   // measuring
  uint8_t low = ADCL;   // must read ADCL first - it then locks ADCH
  uint8_t high = ADCH;  // unlocks both
  long result = (high << 8) | low;
  // il valore 230 è una via di mezzo tra il risultato tramite USB o batteria
  if (result > 230) {  //244 alimentazione USB
    result=4560;// valore letto col tester tra GND e AREF
  } else {  // 223 alimentazione a batteria
    result=5000;// valore letto col tester tra GND e AREF
  }
  return result;
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.