В прошивке измерителя ёмкости аккумуляторов есть код, который считает время разряда аккумулятора. Этот код я нашёл на одном из форумов посвящённых Arduino тематике и он выглядит довольно простым:
volatile uint8_t runTimeIsr = 0; uint8_t runTimeLoop; uint32_t runTime; // https://gist.github.com/raspberrypisig/8bf856ae9b55bb433d4c11ac9540a881 void timerInit() { noInterrupts(); // Clear registers TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; // 1 Hz (16000000/((15624+1)*1024)) OCR1A = 15624; // CTC TCCR1B |= (1 << WGM12); // Prescaler 1024 TCCR1B |= (1 << CS12) | (1 << CS10); // Output Compare Match A Interrupt Enable TIMSK1 |= (1 << OCIE1A); interrupts(); } ISR(TIMER1_COMPA_vect) { runTimeIsr += 1; }
После запуска таймера переменная runTimeIsr считывается в основном цикле и затем обнуляется. Поскольку операция сложения с четырёхбайтной переменной занимает несколько циклов, то используется промежуточная переменная runTimeLoop чтобы избежать конфликта с обработчиком прерывания
void timerDo() { runTimeLoop = runTimeIsr; runTimeIsr = 0; runTime += runTimeLoop; }
В теории обработчик прерывания должен вызываться каждую секунду если микроконтроллер работает на частоте 16 МГц, но в реальности за 3 часа тестирования время, измеренное микроконтроллером отстало от реального на 35 секунд.
При этом посчитанная ёмкость составила 299 мАч вместо ожидаемых 300 - выглядит как допустимая погрешность, но стало любопытно в чём причина.