Schaltung
Normalerweise würde man das Problem mit einem
Schmitt-Trigger lösen, den man aus einem Operationsverstärker
und ein paar externen Bauteilen aufbaut. Es geht aber auch mit einem
PIC. Die Schaltung besteht lediglich aus einem PIC12F675. Die analoge Spannung wird an GP0 (AN0, Pin 7) in den PIC gespeist. Der 1k-Widerstand dient nur dem Schutz vor Überspannung (>5V) und Unterspannung (<0V). Der digitale Ausgang ist Pin GP5 (Pin 2). Zum Aufbau eignet sich z.B. die 14-Pin/8-Pin-Testplatine mit der Analogplatine als Eingang. |
Programmablauf
Spannung messen:
Details
Der ADC wird so eingestellt, dass er sein 10 Bit langes Messergebnis
linksbündig in die Ergebnisregister ADRESH&ADRESL schreibt.
Die oberen 8 Bit stehen dann in ADRESH. Nur die werte ich aus.
Als Referenzspannung für den ADC verwende ich die 5V
Betriebsspannung.
2V Eingangsspannung entsprechen dann einem Messergebnis von
2V/5V*1023 = 409. Wandelt man das in eine Binärzahl, dann
erhält man
'0110011001'. In ADRESH stehen nur die oberen 8 Bit, das sind dann
'01100110', oder als Hexadezimalzahl 0x66.
1,6V Eingangsspannung entsprechen einem Messergebnis von
1,6V/5V*1023 = 327. Wandelt man das in eine Binärzahl, dann
erhält man
'0101000111'. In ADRESH stehen nur die oberen 8 Bit, das sind dann
eigentlich
'01010001', aber das bessere Rundungsergebnis ist '01010010' oder als
Hexadezimalzahl 0x52.
Steht nach der Spannungsmessung in ADRESH also ein Wert über
0x66,
dann liegen >2V am Eingang an, und die LED muss eingeschaltet werden.
Steht nach der Spannungsmessung in ADRESH aber ein Wert unter0x52,
dann liegen <1,6V am Eingang an, und die LED muss ausgeschaltet
werden.
In jeder Programmschleife lege ich eine Pause von 75 ms ein. Die ist
eigentlich unnötig, und soll das Flackern der LED auf maximal 7 Hz
begrenzen, wenn der Eingang ein stark verrauschtes Signal bekommt. Man
kann diese Warteschleife einfach weglassen, falls man die LED schneller
schalten muss.
Programmlisting
list
p=12f675 ;*********************************************************************** ;* Pinbelegung ;* ---------------------------------- ;* GP: 0 < analog ein ;* 1 - ;* 2 - ;* 3 - ;* 4 - ;* 5 > LED out ;* ;*********************************************************************** ; ;sprut (zero) Bredendiek 12/2010 ;http://www.sprut.de ; ; Schwellwertschalter mit Hysteresis ; ; Spannungsmessung mit ADC am Pin GP0 ; Schalttransistor für LED oder LED an GP5 ; LED an bei >2V 409 = 0x199 -> ADRESH=66 ; LED aus bei <1,6V 327 = 0x147 -> ADRESH=52 ; ; Prozessor 12F675 ; ; Prozessor-Takt 4 MHz intern ; ; ;*********************************************************************** ; Includedatei für den 12F675 einbinden #include <P12f675.INC> ERRORLEVEL -302 ;SUPPRESS BANK SELECTION MESSAGES ; Configuration festlegen: ; kein Power on Timer, kein Watchdog, int-Oscillator, kein Brown out __CONFIG _MCLRE_OFF & _PWRTE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _BODEN_OFF ;*********************************************************************** ; Variablen festlegen 20h ... 5Fh count equ 0x26 ; universeller zähler loops equ 0x27 ; timer für wait loops2 equ 0x28 ; timer für wait ;16 Bit Rechenregister f0 equ 0x29 ; f1 equ 0x2A ; Uon1 equ 0x2B ; Einschaltspannung Uoff1 equ 0x2C ; Ausschaltspannung ;*********************************************************************** org 0x00 goto Init ;*********************************************************************** ; Initialisierung ; Init ; IO-Pins bcf STATUS, RP0 ; Bank 0 clrf GPIO ; aus! movlw 0x07 movwf CMCON ; Comparator aus bsf STATUS, RP0 ; Bank 1 bcf TRISIO,5 ; GP5 output für Schalttransistor oder LED bcf STATUS, RP0 ; Bank0 ; internen Taktgenerator kalibrieren bsf STATUS, RP0 ; Bank 1 call 0x3FF movwf OSCCAL ; 4-MHz-Kalibrierung bcf STATUS, RP0 ; Bank 0 ; Interrupt bcf INTCON, GIE ; Int deaktiviert ; ADC initialisieren ; ADC einschalten BSF ADCON0, ADON ; ADON=1 ; ADC-Eingang AN0 auswählen BCF ADCON0, CHS1 ; ADCHS1=0 BCF ADCON0, CHS0 ; ADCHS0=0 ; ADC speed für 1,25 ... 5 MHz einstellen BSF STATUS,RP0 ; Bank1 clrf ANSEL BSF ANSEL, ADCS0 ; ADCS0=1 Fosc/8 ; AN0,1 analog BSF ANSEL, ANS0 ; AN1=analog BCF STATUS,RP0 ; Bank0 ; Daten linksbündig BCF ADCON0, VCFG ; RA2=digital BCF ADCON0, ADFM ; ADFM=1 linksbündig ;LED-Schaltspannungen festlegen movlw 0x66 ; Uon1 2V movwf Uon1 movlw 0x52 ; Uoff1 1,6V movwf Uoff1 ;*********************************************************************** ;Main Mainloop ; Messen call UMessen1 ; AN0 nach f1,f0 (f1 is entscheidend) call LED ; LED ein-/ausschalten call wait75ms ; Wartezeit, kann entfallen goto Mainloop ;*********************************************************************** ; Spannung wandeln nach f1, f0 UMessen1 BSF ADCON0, 1 ; ADC starten loop BTFSC ADCON0, 1 ; ist der ADC fertig? GOTO loop ; nein, weiter warten movfw ADRESH ; obere 8 Bit auslesen movwf f1 ; obere 8-Bit nach f1 bsf STATUS,RP0 ; Bank1 movfw ADRESL ; untere 2 Bit auslesen, werden aber nicht benötigt bcf STATUS,RP0 ; Bank0 movwf f0 ; untere 2-Bit nach f0 clrf count ; Warten, damit der ADC sich erholen kann warten DECFSZ count, f goto warten return ;*********************************************************************** ; LED ein/aus-schalten LED ; prüfen ob f1<Uoff MOVFW Uoff1 subwf f1, w ; w:=f1-w btfss STATUS, C bcf GPIO,5 ; LED aus ; prüfen ob f1>Uon MOVFW Uon1 subwf f1, w ; w:=f1-w btfsc STATUS, C bsf GPIO,5 ; LED an return ;*********************************************************************** ; 75 ms warten wait75ms movlw D'75' ; 75ms movwf loops goto WAIT ;*********************************************************************** ;Zeitverzögerung um loops * 1 ms ; 4 MHz externer Takt bedeutet 1 MHz interner Takt ; also dauert 1 ms genau 1000 Befehle ; 100 Schleifen a 10 Befehle sind 1000 Befehle = 1 ms WAIT top movlw .100 ; timing adjustment variable (1ms) movwf loops2 top2 nop ; sit and wait nop nop nop nop nop nop decfsz loops2, F ; inner loops complete? goto top2 ; no, go again ; decfsz loops, F ; outer loops complete? goto top ; no, go again retlw 0 ; yes, return from subWAIT ;*********************************************************************** end |