Verklaring van de werking:
De voeding voor de schakeling wordt betrokken uit de start batterij (via een 78L05 spanningsregelaar).
De spanning die gemeten wordt, is die van de lichtbatterij of van de combinatie licht/startbatterij (als de brug
aan staat). De spanning wordt gemeten m.b.v. een spanningsdeler gevormd door R3/R4 om binnen 5V te blijven. De maximale
ingangsspanning bedraagt 15V (voldoende voor de situatie waarbij de batterij maximaal is opgeladen en er volop
zonlicht is).
Als de spanning onder 12,4 volt komt, wordt de brug uit gezet. Komt de spanning boven 13,5 volt, wordt de brug
aan gezet. Tussen deze twee waarden wordt de brug gelaten zoals hij was (dat kan dus zowel aan als uit zijn,
afhankelijk of men van de "hoge" kant komt dan wel de "lage").
De werking berust op het gebruik van 2 opamps die de spanning vergelijken met een vooraf ingestelde spanning.
De ene opamp wordt gebruikt voor de "lage" drempel, de andere voor de "hoge" drempel. Het resultaat is telkens 0 of
1 (eronder of erover) en de twee uitgangen van de opamps worden naar de ingang van een microprocessor gestuurd
die de sturing van de brug softwarematig afhandelt.
De twee opamps vinden we in IC LM324 dewelke er vier behuist, ruim voldoende dus.
De lage drempel en de hoge drempel kunnen best op ca. 12,4 resp. 13,5 volt staan, instellen kan via resp. POT1 en
POT2.
De brug zelf bestaat uit een zgn. bistabiele relais die twee spoelen heeft (een voor uit en een voor aan). Dit relais
heeft een spoelspanning van 12V en een schakelstroomsterkte van 12A bij 12V.
Het contact gedeelte van de brug is in het schema niet getoond, je moet gewoon het maak-contact van het relais
gebruiken en een uiteinde met de startbatterij verbinden, het andere met de lichtbatterij.
Een bistabiele relais gebruikt geen stroom in welke toestand hij ook staat (brug aan of brug uit). Enkel tijdens
het omschakelen is korte tijd een stroom nodig (pulsje van ca. 0,2 seconden).
De beide spoelen van het bistabiel relais worden gestuurd met een BC337 transistor, deze is hiervoor sterk genoeg.
Merk op dat de spoelen via het 12V circuit gestuurd worden en niet via het 5V circuit.
Relay 3 in de schakeling stelt eigenlijk de "uit" spoel voor, Relay 2 de "aan" spoel.
Relay 1, niet strikt noodzakelijk, dient eigenlijk om tijdens het omschakelen van de brug een eventueel extern
alarsysteem even te deactiveren. Dit komt uitsluitend omdat ik een alarmsysteem heb dat reageert op plotselinge
veranderingen van de spanning en het omschakelen van de brug zou het alarm laten afgaan. Je kan Relay 1 dus rustig
weglaten als je een dergelijke interface met je alarmsysteem niet nodig hebt.
Men kan ten allen tijde met een drukknop de brug manueel bedienen met behulp van SW1 (maar alleen indien de spanning
in het zweef-bereik zit t.t.z. tussen ca. 12,4 en 13,5 Volt).
Het relais is dus zoals gezegd een bistabiel relais van een zo fors mogelijke uitvoering, bijvoorbeeld
Conrad bestelnr. 504173 - 62.
Deze schakelt tot 16A. De software zorgt voor de aansturing.
Indien men een bistabiel relais zou kunnen vinden van een nog hogere contact)amperage (vb. 30A) wat mij dus niet gelukt is,
zou men de schakeling ook kunnen gebruiken om een brug te leggen tijdens het rijden. Een software aanpassing is dan wel
noodzakelijk.
Handig is ook om twee LEDs (met voorschakelweerstand) parallel op de spoelen van het relais te zetten (niet getekend
in het schema) zodat men kan zien wanneer omgeschakeld wordt (kortstondig aangaan van de LED).
;;
;;
;; Zonnebatterij automaat, a PIC 16F84 program to switch two lead-acid batteries in parallel
;; when there is enough sunlight.
;;
;; Copyright (C) 2000 Geert Van Espen (geert@vanespen.com)
;;
;;
LIST P=16F84
errorlevel 0,-305
processor 16f84
include "p16f84.inc"
__CONFIG _CP_OFF & _RC_OSC & _PWRTE_ON & _WDT_ON
;
;
;
;
; commando om dit project naar de pic te sturen:
; TOPIC -RWG SOLARSW.HEX
;
;
;
;
;
; current settings: low level = 12.29 V
; high level = 13.45 V
;
; general purpose register allocation
werk equ 0x0c ; werkregister
t1 equ 0x0d ; telwerk 1
t2 equ 0x0e ; telwerk 2
TIJDl equ 0x10 ; to keep track of time
TIJDh equ 0x11
ddd equ 0x13 ; debug only
KLAPPERTIJD0 equ 0x14 ; hysteresis 0
KLAPPERTIJD1 equ 0x15 ; hysteresis 1
KLAPPERTIJD2 equ 0x16 ; hysteresis 2
KLAPPERTIJD3 equ 0x17 ; hysteresis 3
RB0_STAND equ 0x18 ; 0=uit 1=aan
RB1_STAND equ 0x19 ; 0=uit 1=aan
RB2_STAND equ 0x1a ; 0=uit 1=aan
RB3_STAND equ 0x1b ; 0=uit 1=aan
tempvar equ 0x1c ;
Wl equ 0x20 ;
Wh equ 0x21 ;
BRUG equ 0x22 ; 0 = geen doorkoppeling batterijen
; 1 = wel doorkoppeling batterijen
CONTACT equ 0x23 ; 0 = contactsleutel uit
; 1 = contactsleutel aan
PrevRB0 equ 0x24 ; vorige RB0 situatie
PrevRB1 equ 0x25 ; vorige RB1 situatie
PrevRB2 equ 0x26 ; vorige contact situatie
PrevBtn equ 0x27 ; vorige pushbutton situatie
; tijdconstanten
;;;;;;;;;;;;;;;;
m_input_a equ b'00000000' ; input mask, which bits are input
m_input_b equ b'11111111' ;
org 0x00 ; reset vector
goto main
dt "2000-10-10 geert@vanespen.com Zonnebatterij automaat"
;***********************************************************************
;* *
;* initialise *
;* *
;***********************************************************************
initialise: ; set up ports
MOVLW 0 ;
TRIS 5 ;
MOVLW 0x0F ;
TRIS 6 ;
MOVLW 0x80 ;
OPTION ;
clrf TIJDl ; initialisaties
clrf TIJDh ;
clrf KLAPPERTIJD0 ;
clrf KLAPPERTIJD1 ;
clrf KLAPPERTIJD2 ;
clrf KLAPPERTIJD3 ;
clrf RB0_STAND ;
clrf RB1_STAND ;
clrf RB2_STAND ;
clrf RB3_STAND ;
clrf BRUG ;
clrf CONTACT ;
clrf PrevRB0 ;
clrf PrevRB1 ;
clrf PrevRB2 ;
clrf PrevBtn ;
clrf PORTA ; UIT laag
clrf PORTB
; uitgang even aan en uit laten knipperen om te laten zien dat het
; apparaat werkt
movlw 0xFE ; startwaarde
movwf PORTA ;
movlw 6 ; knipper 3 keer
movwf t1 ;
functiontest:
movlw 0x19 ; wacht halve seconde
call wachtlus ;
movlw 0xFF ;
xorwf PORTA, f ;
decfsz t1, f ;
goto functiontest ;
clrf PORTA ; UIT laag
retlw 0
;***********************************************************************
;* *
;* wachtlus *
;* *
;***********************************************************************
wachtlus:
; wacht x keer 18 milliseconden, met x in w
movwf werk ; zet w in werk
; debug only
; movlw 1
; movwf werk
slapertje:
sleep ;
decfsz werk, f ;
goto slapertje ;
retlw 0 ;
;***********************************************************************
;* *
;* test_portRB0 *
;* *
;***********************************************************************
; hysteresis voor poort RB0: als RB0 een tijdje 0 is wordt RB0_STAND
; ook 0; als RB0 1 is wordt RB0_STAND onmiddellijk 1
test_portRB0:
movf PORTB, w ; w = PORTB
andlw 1 ; we willen alleen RB0
movwf tempvar ;
movf tempvar, w ;
btfss tempvar, 0 ;
goto test0_low ;
movlw 1 ;
movwf RB0_STAND ;
clrf KLAPPERTIJD0 ; KLAPPERTIJD0 = 0
retlw 0 ;
test0_low:
subwf RB0_STAND, w ;
btfss STATUS, Z ; RB0 input = RB0_STAND?
goto test0_hyst1 ;
clrf KLAPPERTIJD0 ; ja: KLAPPERTIJD0 = 0
goto test0_hyst2 ;
test0_hyst1:
incf KLAPPERTIJD0, f ; neen: verhoog KLAPPERTIJD0
test0_hyst2:
btfss KLAPPERTIJD0, 2 ; KLAPPERTIJD0 hoog?
goto test0_hyst3 ; neen: gedaan
movf tempvar, w ;
movwf RB0_STAND ; ja: RB0_STAND = RB0 input
clrf KLAPPERTIJD0 ; KLAPPERTIJD0 = 0
test0_hyst3:
retlw 0 ;
;***********************************************************************
;* *
;* test_portRB1 *
;* *
;***********************************************************************
; hysteresis voor poort RB1: als RB1 een tijdje 0 is wordt RB1_STAND
; ook 0; als RB1 1 is wordt RB1_STAND onmiddellijk 1
test_portRB1:
movf PORTB, w ; w = PORTB
andlw 2 ; we willen alleen RB1
movwf tempvar ;
bcf STATUS, C ;
rrf tempvar, f ;
movf tempvar, w ;
btfss tempvar, 0 ;
goto test1_low ;
movlw 1 ;
movwf RB1_STAND ;
clrf KLAPPERTIJD1 ; KLAPPERTIJD1 = 0
retlw 0 ;
test1_low:
subwf RB1_STAND, w ;
btfss STATUS, Z ; RB1 input = RB1_STAND?
goto test1_hyst1 ;
clrf KLAPPERTIJD1 ; ja: KLAPPERTIJD1 = 0
goto test1_hyst2 ;
test1_hyst1:
incf KLAPPERTIJD1, f ; neen: verhoog KLAPPERTIJD1
test1_hyst2:
btfss KLAPPERTIJD1, 2 ; KLAPPERTIJD1 hoog?
goto test1_hyst3 ; neen: gedaan
movf tempvar, w ;
movwf RB1_STAND ; ja: RB1_STAND = RB1 input
clrf KLAPPERTIJD1 ; KLAPPERTIJD1 = 0
test1_hyst3:
retlw 0 ;
;***********************************************************************
;* *
;* test_portRB2 *
;* *
;***********************************************************************
; hysteresis voor poort RB2: als RB2 een tijdje 1 is wordt RB2_STAND
; ook 1; als RB2 een tijdje nul is wordt RB2_STAND ook nul
test_portRB2:
movf PORTB, w ; w = PORTB
andlw 0x04 ; we willen alleen RB2
movwf tempvar ;
bcf STATUS, C ;
rrf tempvar, f ;
rrf tempvar, f ;
movf tempvar, w ;
subwf RB2_STAND, w ;
btfss STATUS, Z ; RB2 input = RB2_STAND?
goto test2_hyst1 ;
clrf KLAPPERTIJD2 ; ja: KLAPPERTIJD2 = 0
goto test2_hyst2 ;
test2_hyst1:
incf KLAPPERTIJD2, f ; neen: verhoog KLAPPERTIJD2
test2_hyst2:
btfss KLAPPERTIJD2, 1 ; KLAPPERTIJD2 hoog?
goto test2_hyst3 ; neen: gedaan
movf tempvar, w ;
movwf RB2_STAND ; ja: RB2_STAND = RB2 input
clrf KLAPPERTIJD2 ; KLAPPERTIJD2 = 0
test2_hyst3:
retlw 0 ;
;***********************************************************************
;* *
;* test_portRB3 *
;* *
;***********************************************************************
; hysteresis voor poort RB3: als RB3 een tijdje 1 is wordt RB3_STAND
; ook 1; als RB3 een tijdje nul is wordt RB3_STAND ook nul
test_portRB3:
movf PORTB, w ; w = PORTB
andlw 0x08 ; we willen alleen RB3
movwf tempvar ;
bcf STATUS, C ;
rrf tempvar, f ;
rrf tempvar, f ;
rrf tempvar, f ;
movf tempvar, w ;
subwf RB3_STAND, w ;
btfss STATUS, Z ; RB3 input = RB3_STAND?
goto test3_hyst1 ;
clrf KLAPPERTIJD3 ; ja: KLAPPERTIJD3 = 0
goto test3_hyst2 ;
test3_hyst1:
incf KLAPPERTIJD3, f ; neen: verhoog KLAPPERTIJD3
test3_hyst2:
btfss KLAPPERTIJD3, 2 ; KLAPPERTIJD3 hoog?
goto test3_hyst3 ; neen: gedaan
movf tempvar, w ;
movwf RB3_STAND ; ja: RB3_STAND = RB3 input
clrf KLAPPERTIJD3 ; KLAPPERTIJD3 = 0
test3_hyst3:
retlw 0 ;
;***********************************************************************
;***********************************************************************
;* *
;* programma *
;* *
;***********************************************************************
main:
btfsc STATUS, NOT_TO ; if this is a reset or power-up ...
call initialise ; set port drivers and WDT prescaler
movlw 1 ; veronderstel contact aan
movwf CONTACT ;
movlw 3 ;
movwf PrevRB0 ;
movwf PrevRB1 ;
movwf PrevRB2 ;
movwf PrevBtn ;
start:
main_loop:
;
; LAGE DREMPELSPANNING (poort RB0)
;
call test_portRB0 ; test spanning op poort RB0
movf PrevRB0, w ; test of RB0_STAND veranderd is
subwf RB0_STAND, w ;
;;;;; btfsc STATUS, Z ; is de stand veranderd?
;;;;; goto test0_af ;
; veranderd
movf RB0_STAND, w ; ja, de stand is veranderd
movwf PrevRB0 ;
btfsc RB0_STAND, 0 ; is spanning laag?
goto test0_af ; neen, gedaan
btfss BRUG, 0 ; ja: test of brug al af stond
goto test0_af ; brug af: gedaan
bsf PORTA, 2 ; spanning laag: alarm-disable relais
bsf PORTA, 0 ; en RA0 een tijdje aanzetten
movlw 0xc ; wacht fractie seconde
call wachtlus ;
clrf BRUG ; bewaar huidige toestand
bcf PORTA, 0 ; poorten terug uitzetten
bcf PORTA, 2 ;
movlw 0x6f ; wacht 2 seconden
call wachtlus ;
test0_af:
;
; HOGE DREMPELSPANNING (poort RB1)
;
btfsc CONTACT, 0 ; als contact aan,
goto test1_af ; dan nooit brug maken!
call test_portRB1 ; test spanning op poort RB1
movf PrevRB1, w ;
subwf RB1_STAND, w ;
;;;;; btfsc STATUS, Z ; is de stand veranderd?
;;;;; goto test1_af ;
; veranderd
movf RB1_STAND, w ; ja, de stand is veranderd
movwf PrevRB1 ;
btfss RB1_STAND, 0 ; is spanning hoog?
goto test1_af ; neen, gedaan
btfsc BRUG, 0 ; ja: test of brug al aan stond
goto test1_af ; brug aan: gedaan
bsf PORTA, 2 ; spanning hoog: alarm-disable relais
bsf PORTA, 1 ; en RA1 een tijdje aanzetten
movlw 0xc ; wacht fractie seconde
call wachtlus ;
bsf BRUG, 0 ; bewaar huidige toestand
bcf PORTA, 1 ; poorten terug uitzetten
bcf PORTA, 2 ;
movlw 0x6f ; wacht 2 seconden
call wachtlus ;
test1_af:
;
; CONTACTSLEUTEL (poort RB2)
;
ContactSleutel:
call test_portRB2 ; test spanning op poort RB2
movf PrevRB2, w ;
subwf RB2_STAND, w ;
btfsc STATUS, Z ; is de stand veranderd?
goto test2_af ;
; veranderd
movf RB2_STAND, w ; ja, de stand is veranderd
movwf PrevRB2 ;
btfsc RB2_STAND, 0 ; is contact aan?
goto test2_aan ;
clrf CONTACT ; neen: bewaar huidige toestand
bsf PrevRB0, 3 ; herinitialiseer spanningstesten
bsf PrevRB1, 3 ;
goto test2_af ;
test2_aan:
bsf CONTACT, 0 ; bewaar huidige toestand
bsf PORTA, 2 ; alarm-disable relais en
bsf PORTA, 0 ; RA0 een tijdje aanzetten
movlw 0xc ; wacht fractie seconde
call wachtlus ;
clrf BRUG ; bewaar huidige toestand
bcf PORTA, 0 ; poorten terug uitzetten
bcf PORTA, 2 ;
movlw 0xfe ; wacht 5 seconden
call wachtlus ;
test2_af:
;
; PUSHBUTTON (poort RB3)
;
btfss CONTACT, 0 ; als contact aan,
goto PushButton ; dan nooit brug maken!
clrf PrevBtn ;
goto PushButton_samen;
PushButton:
call test_portRB3 ; als pushbutton gedrukt is,
movf PrevBtn, w ; dan toggelen
subwf RB3_STAND, w ;
btfsc STATUS, Z ; is de stand veranderd?
goto PushButton_gelijk;
PushButton_changed:
movf RB3_STAND, w ; ja: PrevBtn = RB3_STAND
movwf PrevBtn ;
btfss RB3_STAND, 0 ; is pushbutton gedrukt?
goto PushButton_af ;
movlw 1 ; ja: toggle BRUG
xorwf BRUG, f ;
; reflect BRUG value onto output ports
btfss BRUG, 0 ; BRUG waarde testen
goto PushButton_Reflect_uit;
PushButton_Reflect_aan:
bsf PORTA, 2 ; alarm-disable relais en
bsf PORTA, 1 ; RA1 een tijdje aanzetten
movlw 0xc ; wacht fractie seconde
call wachtlus ;
bcf PORTA, 1 ; poorten terug uitzetten
bcf PORTA, 2 ;
goto PushButton_samen;
PushButton_Reflect_uit:
bsf PORTA, 2 ; alarm-disable relais en
bsf PORTA, 0 ; RA0 een tijdje aanzetten
movlw 0xc ; wacht fractie seconde
call wachtlus ;
bcf PORTA, 0 ; poorten terug uitzetten
bcf PORTA, 2 ;
goto PushButton_samen;
PushButton_samen:
PushButton_gelijk:
goto PushButton_af ;
PushButton_af:
movlw 0x2 ; wacht fractie seconde
call wachtlus ;
goto start ;
;;
;;
end
Download bron code (assembler) Download hex bestand (machine code)
