Mit der folgenden Schaltung soll es möglich sein, ein analoges Signal zu überwachen und bei Bedarf passend reagieren. Für ein externes analoges Signal
wird ein Grenzwert (Schwellenwert) fest eingestellt. Beim Überschreiten bzw. Unterschreiten dieses Grenzwertes wird ein Schaltvorgang ausgelöst. In unserem Fall wird ein
Relais, an das ein Endabnehmer wie z.B. ein Heizkörper oder ein Beleuchtungskreis angeschlossen werden kann, geschaltet. Damit im Bereich des Grenzwertes nicht zu
ungewollten kurzfristigen Ein- und Aus-Schaltvorgängen kommt, soll es möglich sein, eine Schalthysterese einzustellen. Die Schaltung realisieren wir mit einem
PIC-Mikrocontroller. Die Einstellung des Ein- und Aus-Grenzwertes erfolgt jeweils mit einem Potentiometer. Der Mikrocontroller muss also in der Lage sein, drei
analoge Signale zu verarbeiten. Die Verarbeitung der analogen Signale mit einem PIC-Mikrocontroller stellt gleichzeitig den Schwerpunkt der
Schaltung dar.
PIC 16F1503
Der PIC-Mikrocontroller 16F1503 stellt 14 Anschluss-Pins zur Verfügung. Durch entsprechende Konfiguration wird bestimmt, welcher Pin welche Rolle in einer
Schaltung übernimmt. Die Pins können z.B. als digitale Eingänge oder Ausgänge fungieren. In unserem Fall werden zwei Pins als digitale Eingänge, ein als digitaler
Ausgang und drei als analoge Eingänge konfiguriert. Um das Geschehen etwas zu visualisieren, treten in der Schaltung noch zwei 7-Segmentanzeigen auf. Sie werden von
zwei Schieberegister gesteuert. Um die Schieberegister zu bedienen, werden drei weitere Ausgänge des PIC-Mikrocontrollers
benötigt.
Der aktuelle Wert des externen analogen Signals wird auf einer 7-Segmentanzeige angezeigt. Die Genauigkeit der Anzeige beträgt 0,1V. Die Anzeige hilft auch
bei Einstellung der Grenzwerte. Die Selektierung der Anzeige erfolgt mithilfe von zwei Tastern. Bei gedrücktem Taster S1 (sehe Plan) wird der EIN-Schwellenwert
angezeigt und eingestellt. Der Taster S2 ist für den AUS-Schwellenwert zuständig. Eine 7-Segmentanzeige (hier mit Punkt als Segment Nr. 8) besteht im Grunde genommen
aus sieben Leuchtdioden. Damit sie nicht beschädigt werden, wird jedem Segment ein Widerstand vorgeschaltet. Diese Rolle übernehmen die
Widerstände R1 bis R14.
Es gibt zahlreiche Methoden, wie man eine 7-Segmentanzeige zum Leuchten bringen kann. Um die Ausgänge des Mikrocontrollers zu sparen, werden meist Treiber
dazwischengeschaltet. In unserer Schaltung übernehmen die Rolle zwei Schieberegister. Der Vorteil: Statt 14 werden für beide Anzeigen lediglich drei
Leitungen benötigt.
Um bei Bedarf mit der Schaltung auch größere Abnehmer schalten zu können, wird an einen PIC-Ausgang ein Relais angeschlossen. Dabei handelt es sich um ein
vorgefertigtes Relais-Modul, sodass wir keine weiteren Komponenten an dieser Stelle benötigen. Andernfalls müsste man sich hier zusätzlich um z.B. einen Transistor,
Freilaufdiode etc. kümmern. Das Modul ist mit dem Relais SRD-05VDC-SL-C ausgestattet. Bereits mit dem kleinen Relais können 10A-Abnehmer
geschaltet werden.
Wie ein Schwellenwertschalter mit Hysterese funktioniert zeigt die Abbildung unten:
Fällt der Wert des externen analogen Signals unter den Ein-Schwellenwert, wird der Ausgang des Schalters gesetzt. In unserem Fall geht das Relais an.
Das Relais bleibt solange an, bis der AUS-Schwellenwert überschritten wird. In dem neuen Zustand bleibt das Relais solange, bis der EIN-Schwellenwert wieder
unterschritten wird. Ein Schwellenwertschalter kann z.B. als Heizungsregler eingesetzt werden. Fällt die Temperatur unter eingestellte untere Grenze, wird die
Heizung eingeschaltet. Wird bestimmte Raumtemperatur überschritten, wird die Heizung wieder abgeschaltet.
Der untere Ein-Schwellenwert wird bei gedrücktem Taster S1 mit dem Potentiometer P2 eingestellt. Der obere Aus-Schwellenwert wird bei gedrücktem Taster S2 mit
dem Potentiometer P3 eingestellt.
Mit dem Potentiometer P1 wird das externe analoge Signal simuliert.
Das untersuchte Signal pendelt im Bereich 0-5VDC. In der Praxis arbeitet man überwiegend mit einem Signal 0-10VDC. Man kann ein solches Signal problemlos mit z.B.
einem Spannungsteiler auf den Bereich 0-5V skalieren.
Testschaltung
Programm
// ***************************************************************************
// Schwellenwertschalter mit PIC
// MPLAB X IDE v6.00
// XC8-Compiler 2.4
// ***************************************************************************
// CONFIG1
#pragma config FOSC = INTOSC
#pragma config WDTE = OFF
#pragma config PWRTE = OFF
#pragma config MCLRE = OFF
#pragma config CP = OFF
#pragma config BOREN = OFF
#pragma config CLKOUTEN = OFF
// CONFIG2
#pragma config WRT = OFF
#pragma config STVREN = OFF
#pragma config BORV = LO
#pragma config LPBOR = OFF
#pragma config LVP = OFF
#include <xc.h>
#include <stdbool.h>
#define _XTAL_FREQ 4000000
#define Externes_Analogsignal PORTAbits.RA0 // Analog Signal
#define Poti_Schwelle_EIN PORTAbits.RA1 // Poti 1 EIN
#define Poti_Schwelle_AUS PORTAbits.RA2 // Poti 2 AUS
#define Anzeige_Taster_EIN PORTCbits.RC0 // Taster 1 (Pin 10)
#define Anzeige_Taster_AUS PORTCbits.RC1 // Taster 2 (Pin 9))
#define Relais PORTAbits.RA5 // Relais Ausgang (Pin 2)
#define SH_CP_Pin PORTCbits.RC3 // Schieberegister SH_CP (Pin 7)
#define ST_CP_Pin PORTCbits.RC4 // Schieberegister ST_CP (Pin 6)
#define DS_Pin PORTCbits.RC5 // Schieberegister DS_Pin (Pin 5)
union { // Struct-Konstrukt für Bit-Zugriff
unsigned char Ziffer;
struct {
unsigned b0:1;
unsigned b1:1;
unsigned b2:1;
unsigned b3:1;
unsigned b4:1;
unsigned b5:1;
unsigned b6:1;
unsigned b7:1;
};
} byte_u;
int Wert_Analog; // Aktueller Wert am Analogeingang
int Externes_Signal;
int Wert_Poti_Schwelle_EIN; // Schwellenwert für Relais Ein
int Wert_Poti_Schwelle_AUS; // Schwellenwert für Relais Au
unsigned int Anzeige_Ziffer [2]; // Einzelne Ziffer für 7-Segmentanzeige
void Ziffer_Anzeige () { // Bits Übertragung zum Schieberegister
SH_CP_Pin = false; // Startvorbereitung
DS_Pin = byte_u.b0; // Bitwert
SH_CP_Pin = true; // Übernehmen
SH_CP_Pin = false;
DS_Pin = byte_u.b1;
SH_CP_Pin = true;
SH_CP_Pin = false;
DS_Pin = byte_u.b2;
SH_CP_Pin = true;
SH_CP_Pin = false;
DS_Pin = byte_u.b3;
SH_CP_Pin = true;
SH_CP_Pin = false;
DS_Pin = byte_u.b4;
SH_CP_Pin = true;
SH_CP_Pin = false;
DS_Pin = byte_u.b5;
SH_CP_Pin = true;
SH_CP_Pin = false;
DS_Pin = byte_u.b6;
SH_CP_Pin = true;
SH_CP_Pin = false;
DS_Pin = byte_u.b7;
SH_CP_Pin = true;
}
void main(void) {
TRISA = 0b00000111; // I/O PORT A, 1-Eingang, 0-Ausgang
TRISC = 0b00000011; // I/O PORT C, 1-Eingang, 0-Ausgang
ADCON0bits.ADON = 1;
ADCON1 = 0b10000000; // Ergebnis rechtsbündig
ANSELA = 0b00000111; // RA0, RA1, RA2 als analoge Eingänge
ANSELC = 0b00000000;
while (true) { // Endlosschleife
// Externes Signal lesen
if (Anzeige_Taster_EIN == true & Anzeige_Taster_AUS == true) {
Externes_Signal = Wert_Analog;
ADCON0bits.CHS0 = 0;
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS2 = 0;
ADCON0bits.CHS3 = 0;
ADCON0bits.CHS4 = 0;
}
// Poti 1 Wert lesen
if (Anzeige_Taster_EIN == false) {
Wert_Poti_Schwelle_EIN = Wert_Analog;
ADCON0bits.CHS0 = 1;
ADCON0bits.CHS1 = 0;
ADCON0bits.CHS2 = 0;
ADCON0bits.CHS3 = 0;
ADCON0bits.CHS4 = 0;
}
// Poti 2 Wert lesen
if (Anzeige_Taster_AUS == false) {
Wert_Poti_Schwelle_AUS = Wert_Analog;
ADCON0bits.CHS0 = 0;
ADCON0bits.CHS1 = 1;
ADCON0bits.CHS2 = 0;
ADCON0bits.CHS3 = 0;
ADCON0bits.CHS4 = 0;
}
__delay_ms(10);
ADCON0bits.GO = 1; // GO Bit setzen
while (ADCON0bits.GO) { // Schleife Analogwert lesen
Wert_Analog = (ADRESH << 8) + ADRESL; // Variable Wert_Analog beschreiben
}
Wert_Analog = Wert_Analog / 20; // Wert anpassen 5V ~ 50
Anzeige_Ziffer [1] = Wert_Analog / 10; // Ziffern für 7-Segmentanzeige
Anzeige_Ziffer [0] = Wert_Analog - (Anzeige_Ziffer [1] * 10);
ST_CP_Pin = false; // Schieberegister ST_CP
for (int i=0; i<2; i++) { // For-Schleife für beide Ziffern
// der Anzeige
int a = Anzeige_Ziffer [i];
switch (a) {
case 0: byte_u.Ziffer = 0b11111100; // Bitbelegung 7-Segmentanzeige
Ziffer_Anzeige (); // Unterprogramm aufrufen
break;
case 1: byte_u.Ziffer = 0b01100000;
Ziffer_Anzeige ();
break;
case 2: byte_u.Ziffer = 0b11011010;
Ziffer_Anzeige ();
break;
case 3: byte_u.Ziffer = 0b11110010;
Ziffer_Anzeige ();
break;
case 4: byte_u.Ziffer = 0b01100110;
Ziffer_Anzeige ();
break;
case 5: byte_u.Ziffer = 0b10110110;
Ziffer_Anzeige ();
break;
case 6: byte_u.Ziffer = 0b10111110;
Ziffer_Anzeige ();
break;
case 7: byte_u.Ziffer = 0b11100000;
Ziffer_Anzeige ();
break;
case 8: byte_u.Ziffer = 0b11111110;
Ziffer_Anzeige ();
break;
case 9: byte_u.Ziffer = 0b11110110;
Ziffer_Anzeige ();
break;
}
}
ST_CP_Pin = true; // Anzeige aktualisieren
__delay_ms(10); // Wartezeit
if (Externes_Signal <= Wert_Poti_Schwelle_EIN) {
Relais = true;
}
if (Externes_Signal >= Wert_Poti_Schwelle_AUS) {
Relais = false;
}
}
}