W małych mikrokontrolerach może i są wejścia przetwornika analogowego ale nie są w pełni elastycznie konfigurowalne, np. w PIC12F510 jeżeli chcesz korzystać z jednego kanału przetwornika ADC to musi być kanał AN2. (Logiczne, prawda?).
Zamontowałem układ w samochodzie, po wgraniu programu wszystko ruszyło. Wnioski z użytkowania są takie:
- Napięcie w instalacji samochodu (w tym przypadku Opel Corsa C) wynosi przy odpalonym silniku 14.2V, ale osiąga tą wartość dopiero kilka sekund po odpaleniu.
- Regulator alternatora ma pewną bezwładność czasową - kiedy włączę jednocześnie dmuchawę (10A) i światła mijania (ponad 10A) to napięcie w instalacji spada i powrót do wartości 14.2V zajmuje około sekundę. To byłby problem gdyby nie opóźnione wyłączenie świateł do jazdy dziennej.
- Dzięki sterowaniu świateł do jazdy dziennej na podstawie napięcia w sieci osiągnąłem (to nie był mój podstawowy cel) zabezpieczenie przed nadmiernym rozładowaniem akumulatora
- Funkcja załączania świateł w momencie kiedy centralny zamek zamyka lub otwiera drzwi - sterownik wykrywa pojedyncze mignięcie kierunkowskazu i włącza światła, ale wykrywa również włączenie świateł awaryjnych, w takiej sytuacji światła nie zostaną załączone (w przeciwnym razie zgaszone auto z włączonymi światłami awaryjnymi zawsze miałoby włączone światła do jazdy dziennej)
Kod jest tak prosty że pozostawiłem go w jednym pliku, poniżej źródło:
#include <stdio.h>
#include <stdlib.h>
#include <htc.h>
__CONFIG(OSC_IntRC & WDT_OFF & CP_OFF & IOSCFS_OFF);
#define MINIMUM_RUNNING_VOLTAGE (180)
#define MAXIMUM_IDLE_VOLTAGE (168)
void main(void)
{
char power=0;
enum {UP, DOWN}mode;
enum {ON, OFF}kierun;
enum {AON, AOFF}awaryjne;
int lans=0;
char kierZalaczenia=0; //ilosc zalczen kieruna w okresie czasu
int kierOkres=0;
kierun = OFF;
awaryjne = AOFF;
mode = UP;
CM1CON0 = 0; //wylacz komparator
OPTION = 0xC4;
ADCON0 = (1<<7); //wejscie analogowe
TRIS = (1<<0)|(1<<1)|(1<<2); //wejscie analogowe
ADCON0bits.ANS=1; //AN2 configured as analog input
ADCON0bits.CHS=2; //wybierz do konwersji kanal 2
ADCON0bits.ADON=1;//wlacz ADC
while(1)
{
//wystaw PWM
if(TMR0<power)
GPIObits.GP5=1;
else
GPIObits.GP5=0;
//mierz ADC
if(GO_nDONE==0)
{
if(lans==0) //normalna praca
{
if(ADRES<=MAXIMUM_IDLE_VOLTAGE) //silnik zgaszony
{
mode=DOWN;
if(kierun==ON && awaryjne==AOFF)
lans=4096;
}
if(ADRES>=MINIMUM_RUNNING_VOLTAGE) //silnik w ruchu
{
if(GPIO & (1<<1)) //swiatla mijania wlaczone
mode=DOWN;
else //swiatla mijania wylaczone
mode=UP;
}
}
else //tryb odmierzania lansu
{
mode=UP;
if(ADRES>=MINIMUM_RUNNING_VOLTAGE) //silnik w ruchu
lans=0; //wylacz tryb lansu - wroc do normalnego sterowania
if(awaryjne==AON) //jezeli wlaczone awaryjne to
lans=0; //wyjdz z trybu lansu
}
GO_nDONE=1;//wyzwol kolejna konwersje
}
//sprawdzaj czy wlaczone sa swiatla awaryjne
if(kierOkres>=500)
{
kierOkres=0;
if(kierZalaczenia>1)
awaryjne=AON;
else
awaryjne=AOFF;
kierZalaczenia=0;
}
//odmierzaj sciemnianie i rozjasnianie
if(TMR0>=0xFA)
{
TMR0=0;
if(mode==UP && power<0xFF)
power++;
if(mode==DOWN && power>0)
power--;
if(lans>0)
lans--;
kierOkres++; //odmierzaj okres zliczania migniec
if(GPIO & (1<<0)) //sprawdz czy kierun jest zalaczony
{
if(kierun==OFF)
kierZalaczenia++;//inkrementuj ilosc migniec tylko na zbocze zalaczajace
kierun=ON;
}
else
kierun=OFF;
}
}
}