arduino voltage monitor

Hallo allemaal,
Voor een project op mijn werk ben ik bezig een circuit te bouwen om een 3s lipo te beschermen tegen te diep ontladen. Ik wil hierbij gebruik maken van een arduino welke gevoed word door dezelfde lipo. Ik ga de afzonderlijke cellen d.m.v voltage dividers aansluiten op drie analoge pinnen op de arduino. Heb uitgerekend een 10k/10k divider voor 8,4 volt wordt dus 4,2 en een 20k/10k divider voor de 12,6 wordt dan ook 4,2v. de eerste cel kan ik gewoon direct aansluiten op een analoge pin. De sketch op de arduino zal beginnen met voltage check van de cellen en wanneer boven setpoint van 3,3v zal deze een relais inschakelen waarachter mijn gebruiker hangt, een pompje en wat verlichting.
Op het moment dat er 1 van de cellen onder het setpoint 3,3v komt zal het relais afgeschakeld worden.
Dit is zo’n beetje de bedoeling, maar nu lees ik veel over het gebruik van de aref pin om de meting preciezer te maken. Mijn vraag is is dit nodig voor mijn toepassing en zo ja kan ik dit af met een spanningsregelaar bijv 7805 gevoed door de lipo welke 5v genereert op de aref pin? Of voldoet de eigen spanningsregelaar van de arduino voor mijn behoefte.
Ik ben namelijk bang dat er verschil is in de interne 5v referentie bij een volle of lege accu.
Wie kan mij op weg helpen en oh ja ik wil 1 van de kleinere arduino boards gaan gebruiken (micro of mini of zo), maar dan wel 1 met genoeg analoge pinnen en natuurlijk met aref.

Als je de Arduino laat voeden door de onderste lipo kun je beter uitgaan van de interne referentie spanning van 1.1V. M.a.w. je zou dus de spanningsdelers moeten herberekenen. Als je uitgaat van VCC, dan kloppen de berekeningen niet meer bij spannings daling. Immers de analoge poorten gebruiken een ref van VCC en die gaat juist naar beneden. Dus dan lijkt het dat de LIPO altijd vol is ook al zakt de spanning weg. En daar je bij 4.2V begint (hoe weet je dat?) zit je gelijk al fout.
Of laat je de Arduino voeden op de hoogste Lipo? Dan is de 5V wel constant.

Soort bordje dat je gebruikt is niet zo belangrijk.

Het was de bedoeling om de arduino gewoon te voeden met de 'bovenste' lipo cell, dus 12,6V tot 9,9V bij leeg.
Vraag is of de 5V referentie spanning stabiel blijft over de gehele accuduur, of zal ik apart een circuit moeten maken om een stabiele 5v te geven aan de AREF pin.

De regulators geven spanningen af tussen de 4.95 en 5.05V meestal. Vaak nog minder spreiding. Dat zal geen echte afwijkingen geven:
Resolutie 4.95 / 1023 = 0.004839 V / stap
Resolutie 5.05 / 1023 = 0.004936 V / stap
De afwijking kan maximaal 14 zijn of je met de ene of de andere Vcc werkt terwijl je een meting tussen de 668 en 682 gaat kriigen. Ik vraag me af of je zoveel energie erin moet steken voor een lader.

het is geen eens een lader, alleen maar een meting wanneer de last moet afschakelen om de lipo niet te beschadigen, waarbij gekozen is voor circa 3.3V. Dit is ook al een veiligheidsmarge gezien beschadiging pas optreedt onder de 3.0V

Nou dan heb je aan de gewone referentie van VCC voldoende.

dit geintje kan dus ook met een simpele zener diode en een relais, maar ach, is wel leuk natuurlijk.
als je de voeding van de UNO gebruikt dus 12 V op Vin, dan kun je gewoon de 5 Volt ref gebruiken hoor.

persoonlijk zou ik een bistabiel relais gebruiken, of een simpele FET, die verbruiken geen stroom.

Ik zal even wat verdere info geven aangaande het project.
In een waterdichte behuizing liggen een vacuümpomp, een accu, wat elektronica en verlichting. De pomp zuigt lucht van buiten aan en blaast dit over een co-meter. Welke detecteert of er co aanwezig is in de lucht.
Een hele simpele uitvoering met maar 1 aan/uit schakelaar is de bedoeling.
ik heb voor een arduino gekozen omdat ik zo flexibel ben in eventuele uitbreiding.
Hoe ik het nu voor ogen heb wil ik de hoofdstroom schakelen. Wanneer deze ingeschakeld wordt start de arduino op en controleert de batterijspanning. Dit laat hij nog even zien met een stuk of 8 ledjes, 2 groen, 4 oranje, twee rood. Dit om de capaciteit weer te geven. Wanneer de spanning boven het ingestelde niveau is zal de arduino verder gaan en de set coil van het relais schakelen waardoor de pomp gaat draaien. Bij een accu niveau van twee rood zal de pomp uitgaan door de reset coil en wanneer de hoofdstroom nog niet is uitgeschakeld zal een tweede relais schakelen bij laag laag en de hoofdstroom onderbreken. Arduino uit dus en geen afnemers meer.

Dit is een beetje hoe ik het in mijn hoofd heb, nu alleen nog op een printplaat en dan programmeren. Leuke uitdaging dacht ik zo.

Ps. Nano of micro wat zal ik doen en waarom?

Het maakt eigenlijk niets uit welke van de 2 je neemt. Ze hebben allebei een 328P processor erop zitten. En als je toch een eigen PCB maakt... Ik weet niet hoe goed je met SMD bent....?

hmm, SMD nee.
Ik ben een beetje een hobbyist, dus ik kijk wat ik nodig heb en dat maak ik dan en dan hopen dat het werkt, haha.

Nou ben inmiddels een stuk verder en een collega van mij heeft een print ontworpen op basis van een Atmega328 en losse componenten dus geen kant en klaar arduino bordje dus.

Nu wordt 4,2V (cell1) aangeboden aan A1.
8,4V via 10k--10k spanningsdeler aan A3.
en 12,6V via 20k--10k spanningsdeler aan A5.

alles blijft dus netjes onder de 5V op de ingangen.
Er is een 7805 gemonteerd voor de gehele voeding van het systeem. Deze krijgt zijn spanning van cell2(8,4V) en voed verder de Vcc, AVCC en de AREF van de ATmega.

Dus volgens mij moet ik nu de EXTERNAL reference gaan gebruiken in mijn sketch, toch?

nee hoor internal is prima.

is het niet beter om de externe te gebruiken, deze is immers constant dacht ik zo.
verder wil ik de meting nog uitmiddelen maar wil niet erg lukken.
heb nu elke 10 seconden drie analogreads op pinnen a1,a3 en a5.
maar wil sneller achter elkaar gaan meten en dan elke 10sec een gemiddelde geven van circa 20 metingen.
op deze wijze ben ik minder gevoelig voor meetfouten en zal mijn led bargraph wat vloeiender lopen.
iemand die mee een beetje kan helpen toevallig.

float setpoint = 3.3;  //afschakel setpoint
float selfdestruct = 3.2;  //afschakel setpoint
int PompRelais = 2;
int timer =15;
int count =0;
const int ledCount = 10;
int ledPins[] = {9,10,11,12,5,6,7,8,4,3};   // an array of pin numbers to which LEDs are attached

void setup() {
Serial.begin(9600);
pinMode(PompRelais, OUTPUT);
for (int thisLed = 0; thisLed < ledCount; thisLed++)
            {
              pinMode(ledPins[thisLed], OUTPUT);
             }
             
pinMode(9, OUTPUT);
digitalWrite(9, HIGH);
delay(300);

KnightRider();
KnightRider();

pinMode(PompRelais, OUTPUT);
digitalWrite(PompRelais, HIGH);
delay(300);
}

void loop() {
float outputvoltage = 5.022;		//meten van 5V out van arduino
int sensorValue = analogRead(A1); //cell 1
int sensorValue2 = analogRead(A3); //cell 2
int sensorValue3 = analogRead(A5); //cell 3 total voltage
float voltage = sensorValue * (outputvoltage / 1023.0 / (4.175/4.181)); //spanning voor en na 10k meten en delen op elkaar
float voltage2 = sensorValue2 * (outputvoltage / 1023.0 / (4.160/8.377)) - voltage; //spanning voor en na 10k meten en delen op elkaar
float voltage3 = sensorValue3 * (outputvoltage / 1023.0 / (4.194/12.58)) - voltage - voltage2; //spanning voor en na de 20k meten en delen op elkaar
float voltagetotal = sensorValue3 * (outputvoltage / 1023.0 / (4.194/12.58)); //zelfde parameter als hierboven

			Serial.print("cell1 = ");
			Serial.println(voltage,4);
			Serial.print("cell2 = ");
			Serial.println(voltage2,4);
			Serial.print("cell3 = ");
			Serial.println(voltage3,4);
			Serial.print("total = ");
			Serial.println(voltagetotal,4);
			Serial.println("---------------------------");

int ledLevel = map(voltagetotal, 9.6, 12.6, 0, ledCount);

  for (int thisLed = 0; thisLed < ledCount; thisLed++) 
    // if the array element's index is less than ledLevel,
    // turn the pin for this element on:
    if (thisLed < ledLevel) {
      digitalWrite(ledPins[thisLed], HIGH);
    }
    // turn off all pins higher than the ledLevel:
    else {
      digitalWrite(ledPins[thisLed], LOW);
      
if (voltage < setpoint || voltage2 < setpoint || voltage3 < setpoint)
{
digitalWrite(PompRelais, LOW);   //
 
}
if (voltage < selfdestruct || voltage2 < selfdestruct || voltage3 < selfdestruct)
{
  digitalWrite(9, LOW);
}

delay(10000);
}
}

void KnightRider(){

for (count=1; count<10;count++)
{
  digitalWrite(ledPins[count], HIGH);
  delay(timer);
  digitalWrite(ledPins[count + 1], HIGH);
  delay(timer);
  digitalWrite(ledPins[count], LOW);
  delay(timer*2);
}
for (count=10; count>1;count--)
{
  digitalWrite(ledPins[count], HIGH);
  delay(timer);
  digitalWrite(ledPins[count - 1], HIGH);
  delay(timer);
  digitalWrite(ledPins[count], LOW);
  delay(timer*2);
}

}

Ik had als eens een library gemaakt voor voortschrijdend gemiddelde : GitHub - nicoverduin/MovingAverage: Generic Arduino library for calculating moving averages
Met voorbeeld....
**Vwb externe ref: **
Je kan natuurlijk een externe referentie spanning gebruiken om daar een grotere nauwkeurigheid te bereiken. Echter dan heb je ook een nauwkeurige referentie spanning nodig. En dan kom je niet weg met een voltage regulator of een zener diode.. Maar moet je echt aan de bak om een constante stabiele referentie spanning te maken. Een 7805 heeft ook vaak nog een 'wiebel' erop zitten. En je moet je afvragen of deze nauwkeurigheid nu werkelijk nodig is in deze schakeling.
Dan kan je net zo goed de interne referentie pakken (INTERNAL) maar dan moet je alles omrekenen met je weerstanden naar 1.1V en als je toch bezig bent 0.1% weerstanden gebruiken met een hele lage ppm waarde. Anders ben je wederom met een 'schijn nauwkeurigheid' bezig. Een el cheapo 'mag niks kosten' metaalfilm weerstand verloopt net zo hard als de temperatuur varieert.