
W ostatnim czasie zmieniłem pracę na taką, która wymaga wyjazdów w delegacje. Jako, że teraz w domu bywam rzadziej, rzadziej też poruszam się moim prywatnym samochodem, a to wiadomo, że niekorzystnie wpływa na zdrowie akumulatora. Zwłaszcza w aktualnym, zimowym okresie. Postanowiłem więc, zrobić sobie jakieś proste urządzonko do monitorowania napięcia akumulatora, tak by wiedzieć w jakiej aktulanie znajduje się on kondycji.
Naładowanie akumulatora powinno się kontrolować ze względu na to, iż zejście na nim napięcia poniżej 11.8 V skutkować może jego trwałą degradacją.
Założenie urządzenia
Układ powinien pobierać bardzo mało prądu, tak by mógł być zasilany bateryjnie, lub z samego akumulatora i by sam nie powodował nazbyt dużego rozładowania. Tak więc, większość czasu znajduje się w stanie uśpienia, budzi się co 30 minut (taki interwał pomiaru uznałem za wystarczający), robi pomiar, wysyła go radiowo i idzie spać.
Jako mikrokontrolera używałem attiny814, pomiar wykonuję przez dzielnik rezystorowy, a odczyt wysyłam przez układ nrf24l01.
Na bazie tych układów radiowych (nrf24l01) mam zbudowanych sporo czujników w mieszkaniu, wszystkie co jakiś czas swoje odczyty wysyłają do urządzenia centralnego na bazie esp32. Centrala stanowi most pomiędzy tymi układami, a siecią wifi i moim domowym serwerem. Z tego też powodu, to właśnie urządzenie wykorzystałem do obierania odczytu stanu akumulatora.
Prawidłowe napięcie akumulatora samochodowego
Za akumulator naładowany uznaje się napięcie w okolicy i powyżej 12.5V. 12.5 – 12V to naładowanie w średnim stopniu, a poniżej 12V – rozładowany.
Kod i działanie urządzenia w praktyce
Nowe układy z serii ATtiny programuje w środowisku Arduino IDE z rdzeniem megaTinyCore.
#include <RF24.h> #include <nRF24L01.h> #include <avr/sleep.h> #include <avr/io.h> #define DEVICE_ID 49 #define ODCZYT_DELAY 1800 #define BUFFER_SIZE 5 RF24 radio(1, 0); const uint64_t pipe0 = 0xF0F0F0F0E1LL; volatile uint16_t intr_counter = ODCZYT_DELAY-1; volatile bool pomiar = false; uint8_t nrf_buf[BUFFER_SIZE] = {DEVICE_ID,0,0,0}; void sprawdz_napiecie(void) { uint16_t adc_value = 0; ADC0.COMMAND |= ADC_STCONV_bm; while(!(ADC0.INTFLAGS & ADC_RESRDY_bm)); ADC0.INTFLAGS = ADC_RESRDY_bm; adc_value = ADC0.RES>>6; float nap1 = 13.11*adc_value; float napiecie = nap1/1023; uint8_t pomocnicza = (napiecie-(uint8_t)napiecie)*100.0; nrf_buf[1] = (uint8_t)napiecie; nrf_buf[2] = pomocnicza/10; nrf_buf[3] = pomocnicza%10; nrf_buf[4] = adc_value/5; } bool send_nrf(void) { radio.powerUp(); bool sukces = radio.write(&nrf_buf, BUFFER_SIZE); radio.powerDown(); return sukces; } void setup() { // Konfiguracja nrf24l01 radio.begin(); radio.openWritingPipe(pipe0); radio.setPALevel(RF24_PA_HIGH); radio.setDataRate(RF24_250KBPS); radio.stopListening(); radio.setRetries(10, 30); radio.setAutoAck(true); radio.powerDown(); // Konfiguracja ADC VREF.CTRLA |= VREF_ADC0REFSEL_1V1_gc; ADC0.CTRLA = ADC_ENABLE_bm; ADC0.CTRLB = ADC_SAMPNUM_ACC64_gc; ADC0.CTRLC = ADC_PRESC_DIV8_gc; ADC0.MUXPOS = ADC_MUXPOS_AIN6_gc; // Konfiguracja RTC RTC.PITINTCTRL = RTC_PI_bm; RTC.PITCTRLA = RTC_PITEN_bm | RTC_PERIOD_CYC32768_gc; sei(); // Konfiguracja uśpienia uC SLPCTRL.CTRLA |= SLPCTRL_SMODE_PDOWN_gc | SLPCTRL_SEN_bm; sleep_cpu(); } void loop() { if (pomiar == true) { sprawdz_napiecie(); send_nrf(); pomiar = false; } sleep_cpu(); } ISR(RTC_PIT_vect) { RTC.PITINTFLAGS = RTC_PI_bm; intr_counter += 1; if ( intr_counter >= ODCZYT_DELAY ) { pomiar = true; intr_counter = 0; } }
Napięcie odniesienia ustawione na wewnętrzne 1.1V, dobrałem dzielnik rezystorowy składający się z R1 – 220k i R2 – 20k. W przypadku napięcia wejściowego 13.1V, na wyjściu pojawi się ok. 1.09, czyli prawie pełen zakres napięcia odniesienia.
W kodzie powyżej można zobaczyć jak to sobie odczytuje i zamieniam wartość z ADC na napięcie.
Mikrokontroler zasilam z bateryjki cr2032, akurat nie miałem pod ręką stabilizatora napięcia przeznaczonego do mało-prądowych zastosowań. Taki ams1117, sam z siebie bierze ok. 5mA to przy poborze mikro-amperowym przez samo urządzenie (tylko w piku przy wysyłaniu weźmie kilkanaście mA) jest zupełnie nieefektywnym rozwiązaniem.
Do tego dochodzi spora róznica napięć gdyby chcieć zasilać samo urządzenie z akumulatora +/- 12.5V – 3.3V.
Rozwiązanie z baterią daje jednak radę, urządzenie działa już około miesiąca i bez problemu przesyła odczyt. Nadajnik od odbiornika znajduje się stosunkowo niedaleko, auto parkuje praktycznie pod moim oknem, a mieszkam na drugim piętrze. Attiny taktowany jest wewnętrznym zegarem 1 MHz.
Co więcej baterie typu cr2032 są bateriami litowymi, a więc dobrze radzą sobie w niskich temperaturach. W tym przypadku było to bardzo istotny czynnik.

I to w zasadzie tyle. Prosty układ, kod, a jakie użyteczne urządzenie 🙂 . Nic nie stoi na przeszkodzie by użyć innych standardów radiowych/komunikacyjnych. Wszystko ostatecznie zależy od przypadku, ja na bazie modułów nrf24l01 mam po prostu zrobione opomiarowanie mieszkania to i tego użyłem. U mnie to działa, aczkolwiek w wielu innych sytuacjach radio na częstotliwości 2.4GHz nie zda egzaminu przez łatwość jego tłumienia. Schematu nawet nie będę rysował, wyjście dzielnika rezystorowego jest bezpośrednio podane na mikrokontroler, nrf24l01 po spi, jakiś kondensator i bateria, to wszystko.
Pozdrawiam.