Проверим питание

Случилось у меня, наверное то, что иногда случается  и у всех — неожиданно перестала закрываться крышка телефона 🙁   Оказалось, что сильно «распух» аккумулятор. Пришлось заменить.acb

«Бочкообразный прямоугольник» раздувшегося аккумулятора забросил в стол и вспомнил о нем лишь через год…Встала задачка запитать Arduino Pro mini с датчиком давления и передатчиком. Замерил напряжение — нормальные 3,6В! Видимо АКБ осталась вполне рабочей.

Захотелось узнать — потянет ли такой аккумулятор питание устройства в течение хотя бы часа?

Для ответа на вопрос смастерил стенд:ArduinoProMini1

Задача скетча — имитировать работу устройства и фиксировать напряжение батареи в течение требуемого периода времени.

#define led    13  //светодиод тут

#include <EEPROM.h>

#define tPress 1000   //период включения ПРД
#define nPer 20  //число пер.вкл.ПРД между замерами
#define maxAddr 1024 //объем EEPROM 
byte aLow;
byte aHigh;
unsigned int valAlt;
long int valPress;
int addr;
int Nbuf;

long readVcc() {
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  
  #if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
    ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
    ADMUX = _BV(MUX5) | _BV(MUX0);
  #elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
    ADMUX = _BV(MUX3) | _BV(MUX2);
  #else
    ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  #endif  
 
  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 = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
  return result; // Vcc in millivolts
}

void MasToEE(unsigned int tAlt) {
  //запись в EEPROM замера
  EEPROM.write(addr, lowByte(tAlt));
  EEPROM.write(addr+1, highByte(tAlt));
  }

void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);  
//--------- начало блока считывания данных из EEPROM -------------  
     Serial.begin(19200);
     Serial.println("Read EEPROM from MC. Ver LiPo_test_3");
     for (addr=0; addr<maxAddr; addr = addr +4) {
        aLow  = EEPROM.read(addr);
        aHigh = EEPROM.read(addr+1);
        Serial.print(addr);
        Serial.print(";  ");
        Serial.print(aLow+aHigh*256);  //напряж.без ПРД
        Serial.print(";  ");
        aLow  = EEPROM.read(addr+2);
        aHigh = EEPROM.read(addr+3);
        Serial.print(aLow+aHigh*256);  //напряж при вкл ПРД
        Serial.print(";  ");
        Serial.println();
      }
     Serial.println("The End Read EEPROM");
//------- окончание блока считывания ------------------  

addr = 0;
Nbuf = 0;
//индикатор начала фиксации напряжения
   for (int i=0; i < 10; i++) {
       digitalWrite(led, HIGH); //включим
       delay(200);
       digitalWrite(led, LOW);  //погасим
       delay(200);
   }      
}

void loop() {
  long int tTek = millis();
  
   Nbuf++;
   if (Nbuf >= nPer) {
     //каждые nPer отсчетов делаем замер
     Nbuf = 0;
     valAlt = readVcc();  //это напр при выкл ПРД
     MasToEE(valAlt);  //запись в EEPROM 
     
     digitalWrite(led,HIGH);   //вкл.модуляция перед. 
     delay(200); //пусть поработает
     addr = addr + 2;
      
     valAlt = readVcc();  //это напр при вкл ПРД
     MasToEE(valAlt);  //запись в EEPROM 
     digitalWrite(led,LOW);   //выкл.модуляция перед. 

     addr = addr + 2;
   }
   
   //  каждый раз даем 300 мс меандр 1000Гц
    for (int i=0; i<300; i++) {
    digitalWrite(led,HIGH);   //вкл.модуляция перед. 
    delayMicroseconds(500);
    digitalWrite(led,LOW);   //выкл.модуляция перед. 
    delayMicroseconds(500);
   } ;

  if (addr >= maxAddr)  {
//останов
    while (1) {  //непрерывно передаем "точки" 
    digitalWrite(led,HIGH);   //вкл.модуляция перед. 
    delay(200);
    digitalWrite(led,LOW);   //выкл.модуляция перед. 
    delay(300);
   } ;
  }
    
  while ((tTek + tPress) > millis()) {} 
}

Программа работает следующим образом.

Сначала по последовательному каналу выводится содержимое EEPROM микроконтроллера (потом в мониторе копируем текст в буфер и сохраняем его в текстовый файл с расширением .csv).

Затем, собственно, запускается цикл имитации работы устройства (периодически включается передатчик — именно он, вместе со светодиодами, дает основную нагрузку по питанию). Делается замер напряжения при выключенном передатчике, затем при включенном. Периодичность регистрации замеров определяется константами  tPress * nPer и, в приведенном скетче равно 20 сек.

Напряжение питания определяется в процедуре readVcc(), которая была ранее подробно описана. Результат измерения в мВ записывается в две байтовые ячейки EEPROM микроконтроллера. Емкости ATmega328 хватает больше чем на полтора часа.

По заполнении EEPROM программа «останавливается» в непрерывном цикле.

Пример файла .csv

Read EEPROM from MC. Ver LiPo_test_3
0; 3606; 3583;
4; 3606; 3583;
8; 3606; 3583;
12; 3606; 3583;

График, выполненный средствами MS Excel выглядит так:testacb3

здесь напряжение питания в миливольтах (синим — при выключенном передатчике, сиреневым — при включенном).

ИТОГ: аккумулятор вполне подойдет для разовой часовой задачи (высотомер для модели ракеты).

Решил сделать эту запись, т.к. тут можно убедиться, что пятивольтовый Pro mini нормально работает при трехвольтовом питании; интересным может оказаться пример использования EEPROM в качестве накопителя регистратора.

Добавить комментарий