Измеритель ёмкости аккумуляторов (Li-Ion/NiMH/NiCD/Pb)

Измеритель ёмкости аккумуляторов

Представлен проект измерителя емкости аккумуляторов, основанный на микроконтроллере, который может измерять практически все типы аккумуляторов. Измеритель может подключаться к компьютеру и давать полную информацию о аккумуляторе — график разряда и емкости.
Обратите внимание, что это мой первый серьёзный проект на Arduino.

Что должно получится в итоге

На этом графике произведены замеры аккумулятора с заявленной емкостью 2000 mAh. Реальная емкость оказалась 1580 mAh:

График напряжения

График измерений Li-Ion аккумулятора:

График измерений Li-Ion аккумулятора

Таблица замеров

Все графики сформированны из текстового документа, с значениями измерений, на ПК.

Начало начал – Arduino

Arduino

Эту копию Arduino Diecimila я ждал примерно 2 недели, поэтому я купил ATmega168 и подумал что смогу заставить её работать не хуже Arduino без нескольких компонентов (в частности без кварца). Но это не получилось и мне пришлось ждать 16МГц кварц и два конденсатора 22 пФ.

Конструкция измерителя

FET-транзистор с резистором 10 Ватт

К транзистору подключен резистор 2.2Ом 10 Вт. К резистору я подключил два A/D контакта Arduino и измерял падение напряжения на нем, вычисляя из этого значения ток I = DeltaV/R.
Я также добавил зуммер для оповещения окончания заряда и необходимости отключения аккумулятора.

Внешний вид измерителя

Для индикации я использовал ЖК-дисплей 2*16. Я нашел документацию и пример работы с ним на сайте Arduino и начала разрабатывать программу.

Тип используемого аккумулятора (NiMH/NiCD или Li-ION) определяется по диапазону напряжения. После определения типа аккумулятора, начнется его разрядка для определения параметров.

Внешний вид измерителя

Цикл разряда аккумулятора длится 30-120 минут. Длительность цикла зависит от емкости аккумулятора.

Схема управления нагрузкой

Параллельно резистору подключаются 2 A/D контакта.
Vr = Vbat-Vfet.

Программа

 #include LiquidCrystal.h  int sensorPin = 0;    // к пину Analog IN 0 int sensor2Pin = 2;   // к пину Analog IN 2 int SPKPin = 6;		  // пин к затвору транзистора int ledPin = 13;      // пин LED  LiquidCrystal lcd(12, 11, 5, 4, 3, 2); // initialize the library with the numbers of the interface pins  int sensorValue = 0;  // variable to store the value coming from the sensor  int sensor2Value = 0;  // variable to store the value coming from the sensor  float LiMinThreshold = 2700; // Lithium Minimal Voltage for load removal float LiMaxThreshold = 4200; // Lithium Max Voltage for load removal float NmhMinThreshold = 950; // NMH Minimal Voltage for load removal float NmhMaxThreshold = 1600; // NMH Max Voltage for load removal float SelectedMinThreshold = 5000; int i; int BatVoltage = 5000; int FetVoltage = 5000; long TotalCurrent = 0; boolean done = false; unsigned long PrevMillis ; unsigned long MillisPassed ;  void CL2(){   lcd.setCursor(0, 1);// Second line first char   lcd.print("                        ");   lcd.setCursor(0, 1);// Second line first char }    void setup() {   Serial.begin(9600);// start serial port to send data during run to the PC   pinMode(ledPin, OUTPUT);//activation led and enable for FET   pinMode(SPKPin, OUTPUT);//activation led and enable for FET   lcd.begin(24, 2);// set up the LCD's number of rows and columns:    lcd.print("Bat PWR Tester[Active]");  // Print a message to the LCD.   lcd.setCursor(0, 1);// Second line first char   lcd.print("Detecting Bat Type..."); // print voltage value   delay(2000);    lcd.setCursor(0, 1);// Second line first char   lcd.print("                        ");   lcd.setCursor(0, 1);// Second line first char   digitalWrite(ledPin, HIGH);   // set the LED on   sensorValue = analogRead(sensorPin);   // read the value from the sensor:   digitalWrite(ledPin, LOW);   // set the LED off   // Detecting battery type   BatVoltage = sensorValue*4.887;   if (BatVoltage > 4500){     lcd.print("Warning high-V! ");     done = true;}   else if (BatVoltage > LiMinThreshold){     lcd.print("Type:Li-Ion Bat ");     SelectedMinThreshold = LiMinThreshold;}   else if (BatVoltage > NmhMinThreshold){     lcd.print("Type:NiMH/Cd Bat ");     SelectedMinThreshold = NmhMinThreshold;}   else{     lcd.print("Unknown Bat V < 1");     done = true;}   lcd.print("V=");   lcd.print(sensorValue*4.887); // print voltage value   Serial.print("DT[ms]");     Serial.print("t");     Serial.print("Bat[mV]");     Serial.print("t");     Serial.print("Fet[mV]");     Serial.println("");    delay(3000);    CL2();   PrevMillis = millis(); }  void loop() {     if (BatVoltage > SelectedMinThreshold && !done) {       digitalWrite(ledPin, HIGH);   // set the LED on       sensorValue = analogRead(sensorPin);   // read the value from the sensor:       sensor2Value = analogRead(sensor2Pin);   // read the value from the FET:       FetVoltage = (sensor2Value*4.887);       BatVoltage = (sensorValue*4.887);       CL2();       lcd.print("V=");       lcd.print(BatVoltage); // print voltage value       lcd.print("mV");       //lcd.print(FetVoltage); // print voltage value       TotalCurrent=TotalCurrent+MillisPassed/1000*(BatVoltage-FetVoltage)/2.2/3.6;       lcd.print(" I=");       lcd.print(TotalCurrent/1000);            lcd.print("mAH         ");       delay(1000);        MillisPassed = millis()- PrevMillis;       PrevMillis = millis();       Serial.print(int(MillisPassed));        Serial.print("t");    // prints a tab       Serial.print(BatVoltage);        Serial.print("t");    // prints a tab       Serial.print(FetVoltage);        Serial.println("");    // prints a tab       CL2();     }     else     {       done=true;       digitalWrite(ledPin, LOW);   // set the LED off - stop loading       lcd.setCursor(0, 0);// First line first char       lcd.print("Bat Power Tester [DONE] ");  // Print a message to the LCD.       CL2();//clear line 2       sensorValue = analogRead(sensorPin);   // read the value from the sensor:       BatVoltage = (sensorValue*4.887);       lcd.setCursor(0, 1);// Second line first char       lcd.print("V=");       lcd.print(BatVoltage); // print voltage value       lcd.print("mV I=");       lcd.print(TotalCurrent/1000);            lcd.print("mAH            ");         for (int i=0; i<100 ; i++){           digitalWrite(SPKPin, HIGH);           delay(1);           digitalWrite(SPKPin, LOW);           delay(1);         }       delay(1000);     } } 

Схема подключения LCD к Arduino — стандартная. Посмотреть можно на официальном сайте по Arduino.

Обсуждение проекта на форуме