logo_elektromys.eu

/ Hlídač olověného akumulátoru |

Žena potřebovala napájet fotopast z olověného akumulátoru. Potřeboval jsem tedy jednoduché zařízení, které fotopast (zátěž) odpojí kdžy napětí akumulátoru klesne pod jistou mez. A zase připojí zpět když je akumulátor nabitý. Tuto práci by hravě zvládnul komparátor s hysterezí, ale protože jsem neměl v šuplíkových zásobách žádný s rozumně nízkým odběrem (hrozí že baterie bude ve vybitém stavu dlouho čeká na výměnu), rozhodl jsem se zařízení zrealizovat mikropočítačem. Jednak proto že je vcelku snadné stáhnout spotřebu do oblasti uA a pak také proto že se mi tu roky válelo několik již nepotřebných Attiny13A a chtěl jsem jim dát šanci :)

Schéma zapojení

/ Hardware |

Zapojení je přímočaré. Jako regulátor napětí (IC2) jsem zvolil MCP1703. V prvé řadě má velmi nízký odběr (typicky 2uA) a také má slušnou přesnost výstupního napětí (0.4%), což je velmi žádoucí protože díky tomu může zároveň posloužit jako reference AD převodníku v MCU k zajištění přesného měření napětí akumulátoru. Snese maximální napětí 16V, což by mělo stačit, protože provozní napětí olověných akumulátorů jsou pod 15V. Dělič napětí složený z R1 a R2 dělí v poměru přibližně 1:3.2, takže typické maximální napětí akumulátoru (14.4V) odpovídá napětí na vstupu MCU 4.5V. Přičemž klidový odběr děliče nepřekračuje typicky 4uA. Kondenzátor C4 slouží jako zásoba náboje aby AD převod nezatěžoval dělič. Ke spínání zátěže slouží nízkonapěťový MOSFET LGE2312 (Q1). Pulldown R3 má za úkol držet MOSFET zavřený v okamžiku kdy MCU startuje po zapojení napájení.

/ Program |

Program je přímočarý. Watchdog je nastaven do režimu časovače a každé 4s MCU probudí a nechá ho vykonat kód v hlavní smyčce. V ní změří napětí, porovná je se zvolenými limity a podle toho připojí nebo odpojí zátěž a zase usne. Aby program nereagoval na krátkodobé změny napětí akumulátoru způsobené například odběrem zátěže, je potřeba aby rozhodovací úroveň napětí byla překročena třikrát po sobě (tedy v trvání více jak 12s). Pro úsporu energie jsou vypnuty všechny nevyužité periferie, všechny nepoužité piny mají aktivovaný pullup rezistor aby na nich byla "legální" logická úroveň. A stejně tak je mimo dobu používání vypnutý i AD převodník. Rozhodovací úrovně jsou nastaveny na přibližně 11V (vypnutí zátěže) a 12V (zapnutí zátěže).

/*
 * Attiny13A Odpojovac
 * Created: 24.08.2024 10:15:50
 * Author : mdudk
 */ 

// Clock 9.6MHz/8 = 1.2MHz
// PB3 ADC input (divider from battery 2M2 + 1M || 100n)
// PB4 MOSFET output 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>

#define TURN_OFF_THR 695 // 11.0V
#define TURN_ON_THR 755 // 12.0V
#define DISABLE_LOAD PORTB &=~(1<<4) // vypnout MOSFET (zátěž)
#define ENABLE_LOAD PORTB |= (1<<4) // zapnout MOSFET (zátěž)

uint16_t get_volt(void);
uint16_t volt; // změřené napětí
uint8_t counter=0; // jednoduchý filtr

// Rutina přerušení od "watchdog timeru"
ISR(WDT_vect) {
 asm("nop"); // není co dělat, jde jen o to se probudit
}

int main(void){
 PRR = (1<<PRTIM0) | (1<<PRADC); // vypnout clock periferiím
 ACSR = (1<<ACD); // vypnout komparátor
 DDRB = 1<<4; // nastavit PB4 jako výstup (MOSFET)
 PORTB = 0b100111; // zapnout pullup rezistory na nevyužitých pinech
 ADMUX = 0b11; // Zvolit VCC jako refrenci pro ADC a jako vstup pin PB3 (ADC3)
 DIDR0 = 0b111111; // Vypnout vstupní buffery na všech pinech 
 WDTCR |= (1<<WDP3); // PErioda pro watchdog přibližně 4s
 WDTCR |= (1<<WDTIE); // spustit watchdog v režimu "časovače"
 sei(); // globální povolení přerušení
 set_sleep_mode(SLEEP_MODE_PWR_DOWN); // volím režim spánku Power Down (nejhlubší)
 
 while (1){ // kdykoli se čip probudí
  volt = get_volt(); // změří napětí
  if(volt < TURN_OFF_THR){ // pokud je menší jak "vypínací" napětí
   if(counter > 3){ // alespoň třikrát po sobě
    DISABLE_LOAD; // tak vypne zátěž
   }else{ // pokud ještě nebylo třikrát po sobě
    counter++; // započítá ho
   }
  }else if(volt > TURN_ON_THR){ // pokud je napětí větší jak "zapínací"
   if(counter > 3){ // alespoň třikrát po sobě
    ENABLE_LOAD; // zapne zátěž
   }else{
    counter++;
   }
  }else{ // jinak nuluje počítadlo / filtr
   counter = 0;
  }
  sleep_mode(); // MCU jde spát
  asm("nop"); // to je tu asi zbytečně (možná jsem to tam měl kvůli debugu)
  asm("nop"); // to je tu asi zbytečně
 }
}

// funkce pro měření napětí
uint16_t get_volt(void){
 uint16_t tmp;
 
 PRR &=~(1<<PRADC); // nejprve zpět povolí clock pro ADC
 DIDR0 = 0b111111; // tohle je tu asi navíc
 ADMUX = 0b11; // Zvolit VCC jako refrenci pro ADC a jako vstup pin PB3 (ADC3)
 ADCSRA = (1<<ADEN) | (1<<ADPS1); // Zapne ADC s clokem 1.2MHz / 4 = 300kHz
 ADCSRA |= (1<<ADSC); // spustí převod
 while(ADCSRA & (1<<ADSC)){} // počká na jeho dokončení
 tmp = ADC; // vyčte výsledek
 ADCSRA = 0; // vypne ADC
 PRR = (1<<PRTIM0) | (1<<PRADC); // vypne clock všem periferiím (tedy i ADC, timer už ho má vypnutý)
 return tmp; // vrátí výsledek převodu
}

/ Hardware a parametry |

Celkový odběr je přibližně 16uA při 12.8V. DPS má rozměry 26x29mm, k připojení k baterii slouží kabel s fastony. Na připojení k fotopasti pak kabel s "DC jack" konektorem. Programování mikropočítače je možné provést skrze ISP konektor na desce, nebo třeba v nepájivém poli ještě před osazením. DPS jsem nechával vyrábět v JLC PCB a vycházela na rovnou stokorunu i s poštovným (5ks DPS).

| Odkazy /

Home
| V1.00 07.12.2024 /
| By Michal Dudka (m.dudka@seznam.cz) /