Labornetzteil
BASCOM-Quellcode Initialisierung Hardware und Deklaration Variablen
Zuerst werden die Compiler-Optionen festgelegt. Verwendet wird ein ATmega168P. Der Takt wird mit einem sog. Baudraten-Quarz mit einer Frequenz von 9,216 MHz erzeugt. Damit sind Übertragungsraten auf der seriellen Schnittstelle bis zu 115200 Baud möglich. Die Übertragungsrate der Schnittstelle wird erst einmal mit nur 38400 Baud initialisiert. Sie kann aber später in der Software verändert werden. Für den I²C-Bus wird die Hardwareschnittstelle verwendet. Bei AVR nennt sich das TWI (Two Wire Interface). Der Takt des Busses wird auf 400 kHz festgelegt.
$regfile = "m168pdef.dat" ' ATMega 168p $crystal = 9216000 ' used crystal frequency $hwstack = 128 ' default use 32 for the hardware stack $swstack = 128 ' default use 10 for the SW stack $framesize = 128 ' default use 40 for the frame space $baud = 38400 ' Baudrate UART 38400 $version 1 , 0 , 1 'we use the TWI pins of the Mega168P $lib "i2c_twi.lbx" ' we do not use software emulated I2C but the TWI Config Scl = Portc.5 ' we need to provide the SCL pin name Config Sda = Portc.4 ' we need to provide the SDA pin name Config Twi = 400000 I2cinit |
Als nächstes wird die serielle Schnittstelle eingerichtet. Bei Empfang eines Zeichens über die serielle Schnittstelle wird ein Interrupt "URXC" ausgelöst. Dadurch soll dann später die Interrupt-Service-Routine "Int_rx_uart" aufgerufen werden. Danach werden diverse Einstellungen aus dem EEPROM des AVR geladen und die Schnittstellen dementsprechend eingestellt.
'serielle Schnittstelle Dim Rxchar_uart As Byte ' Keyboard data On Urxc Int_rx_uart ' define serial receive ISR Enable Urxc ' enable Serial RX complete interrupt Dim Interrupt As Byte ' Interrupt ausgelöst Dim Ser_baudindex As Byte ' Geschwindigkeit serielle Ausgabe Dim Ser_baudindex_eram As Eram Byte ' Geschwindigkeit serielle Ausgabe EEPROM Ser_baudindex = Ser_baudindex_eram If Ser_baudindex >= 7 Then ' Fehler abfangen Ser_baudindex = 4 : Ser_baudindex_eram = 4 ' Startwert Geschwindigkeit seriell 38400 End If Gosub Ser_set_baud ' Einstellung Übertragungsrate serielle Schnittstelle Dim Ser_format As Byte ' Format serielle Ausgabe Dim Ser_format_eram As Eram Byte ' Format serielle Ausgabe EEPROM Ser_format = Ser_format_eram If Ser_format >= 4 Then ' Fehler abfangen Ser_format = 1 : Ser_format_eram = 1 ' Startwert Ausgabeformat seriell End If Dim Ser_intervall As Byte ' Intervall serielle Ausgabe Dim Ser_intervall_index As Byte ' Index Intervall serielle Ausgabe Dim Ser_intervall_index_eram As Eram Byte ' Index Intervall serielle Ausgabe EEPROM Ser_intervall_index = Ser_intervall_index_eram If Ser_intervall_index >= 8 Then ' Fehler abfangen Ser_intervall_index = 1 : Ser_intervall_index_eram = 1 ' Startwert Intervall 1 Sekunde End If Ser_intervall = Lookup(ser_intervall_index , Table_intervall) ' Intervall in Sekunden aus Tabelle laden Dim Ofz_nr As Byte ' Nummer für Logview OpenFormat Zero Dim Ofz_nr_eram As Eram Byte ' Nummer für Logview OpenFormat Zero EEPROM Ofz_nr = Ofz_nr_eram Dim Ofz_start As Byte ' Ausgabe OpenFormat Zero gestartet Dim Sec_count As Byte ' Sekundenzähler für Abstand serielle Ausgabe Dim Ser_ausgabe_kanal As Byte ' Kanal ausgeben ja/nein Dim Ser_ausgabe_kanal_eram As Eram Byte ' Kanal ausgeben ja/nein EEPROM Ser_ausgabe_kanal = Ser_ausgabe_kanal_eram If Ser_ausgabe_kanal >= 16 Then ' Fehler abfangen Ser_ausgabe_kanal = 15 : Ser_ausgabe_kanal_eram = 1 ' Ausgabe alle Kanäle End If |
Im folgenden Abschnitt wird das LCD konfiguriert für Betrieb am 4-Bit breiten Bus und die Anschlüsse dafür werden festgelegt. Ich benutze ein HD44780-kompatibles Display mit 2 Zeilen je 40 Zeichen. Nach der Initialisierung und Deklaration einiger Variablen werden zwei Portanschlüsse als Ausgang für eine LED und die Steuerung der LCD-Hintergrundbeleuchtung definiert. Auf die Einrichtung von 2 Eingängen für die Taster und Einschaltung deren Pullup-Widerständen folgt noch ein Ausgang für einen Piezosummer. Im Anschluss daran werden zwei Timer initialisiert. Timer 1, ein 16-Bit-Timer, wird eingerichtet mit einem Takt von einer halben Sekunde für das Blinken der LED und die Ausgabe der seriellen Daten. Timer 2 wird für PWM konfiguriert. Output-Compare-Ausgang B steuert hierbei den Lüfter. Ich habe mit verschiedenen PWM-Frequenzen experimentiert, mit der Frequenz von 36 kHz funktioniert der gewählte Lüfter am besten.
'LCD 40x2 Config Lcdpin = Pin , Rs = Portb.1 , E = Portb.2 , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3 Config Lcd = 40 * 2 Initlcd Cursor Off Noblink Cls ' clear the screen Dim Lcd_refresh As Byte ' Anzeige neu aufbauen Dim Lcd_light_off As Byte ' LCD-Hintergrundbeleuchtung Lcd_light_off = 1 ' LCD-Hintergrundbeleuchtung Timer ein Dim Lcd_zeile As Byte Dim Lcd_pos As Byte Config Portb.0 = Output : Led_rt Alias Portb.0 ' LED rot Config Portd.2 = Output : Lcd_light Alias Portd.2 ' LCD-Hintergrundbeleuchtung 'Taster Config Pind.7 = Input : Portd.7 = 1 ' Taster oben, Pullup ein Config Pind.6 = Input : Portd.6 = 1 ' Taster unten, Pullup ein 'Piezo Config Portd.4 = Output : Piezo Alias Portd.4 ' Piezo-Summer Dim Summer As Byte Dim Quittung As Byte 'Timer 1 für Sekundentakt Config Timer1 = Timer , Prescale = 256 ' Timer 1 als Zähler Timer1 = &HB9B0 ' Overflow nach 0,5 Sekunden On Timer1 Tmr1_isr ' ISR Enable Timer1 : Start Timer1 'Timer 2 für PWM-Lüfterdrehzahl, 36000.000 Hz Config Timer2 = Pwm , Prescale = 1 , Compare_a_pwm = Clear_up , Compare_a = Disconnect , Compare_b = Clear Dim Fan_pwm As Byte ' PWM für Lüfter Dim Bsec As Byte , Bmin As Byte , Bhour As Byte , Bday As Byte Dim Sec_count_l As Long ' Sekundenzähler für Durchschnitt und serielle Ausgabe |
Hier erfolgt jetzt die Einrichtung der Konstanten und Variablen für den Thermometer-Schaltkreis DS1621. Danach wird die Temperaturmessung des Schaltkreises durch Schreiben des Befehlt "EE" gestartet. Nach einer Pause von einer Sekunde wird die rote LED und die LCD-Hintergrundbeleuchtung eingeschaltet, sowie eine Versionsinformation auf dem LCD ausgegeben. Falls als serielles Ausgabeformat "Text" ausgewählt ist, wird auch eine Info an die serielle Schnittstelle gesendet.
'DS1621 Thermometer Const Ds1621_adr_w = &H90 ' Address of DS1621 Thermometer for write Const Ds1621_adr_r = &H91 ' Address of DS1621 Thermometer for read Dim Ds_lsb As Byte ' LSB DS1621 Dim Ds_msb As Byte ' MSB DS1621 Dim C_p_c As Byte ' Count per C - Read Slope [A9h] Dim C_r As Byte ' Count Remain - Read Counter [A8h] Dim Temperatur As Integer ' Temperatur I2cstart I2cwbyte Ds1621_adr_w ' Address of DS1621 Thermometer for write I2cwbyte &HEE ' Temperaturmessung starten I2cstop Wait 1 Set Led_rt ' LED rot ein Set Lcd_light ' LCD-Hintergrundbeleuchtung ein Gosub Lcd_info ' Anzeige Version und Compilierzeit If Ser_format = 1 Then ' serielle Ausgabe Textformat Print "------------------------------------" Print "LNT 15 - ATmega 328P, INA219, DS1621" Print "Version: " ; Version(2) ; ", " ; Version(1) End If Wait 2 |
Die Einrichtung der Variablen und Konstanten für die Strom- und Spannungssensoren INA219 sind etwas umfangreicher, da sie für 3 Schaltkreise definiert werden müssen. Die Konstanten der Hardware-Adressen sind bestimmt durch die Beschaltung der Adresseingänge der Schaltkreise. Die Variablen für Spannungen, Ströme, Leistungen, Durchschnitts-, Maximal- und Minimalströme werden jeweils als Gleitkommazahlen definiert.
'INA219 - CURRENT/POWER MONITOR Dim Ina219_adr_w As Byte ' Schreibadresse INA219 Dim Ina219_adr_r As Byte ' Leseadresse INA219 Const Ina219_25_adr_w = &H80 ' Schreibadresse INA219 Ausgang 1,25-25 Volt Const Ina219_25_adr_r = &H81 ' Leseadresse INA219 Ausgang 1,25-25 Volt Const Ina219_3_adr_w = &H82 ' Schreibadresse INA219 Ausgang 3,3 Volt Const Ina219_3_adr_r = &H83 ' Leseadresse INA219 Ausgang 3,3 Volt Const Ina219_5_adr_w = &H88 ' Schreibadresse INA219 Ausgang 5 Volt Const Ina219_5_adr_r = &H89 ' Leseadresse INA219 Ausgang 5 Volt Dim Ina219_reg As Byte ' Register Dim U_3 As Single ' Spannung Ausgang 3,3 Volt Dim U_5 As Single ' Spannung Ausgang 5 Volt Dim U_25 As Single ' Spannung Ausgang 1,25-25 Volt Dim I_3 As Single ' Strom Ausgang 3,3 Volt Dim I_5 As Single ' Strom Ausgang 5 Volt Dim I_25 As Single ' Strom Ausgang 1,25-25 Volt 'Durchschnitt Strom für lokale Anzeige Dim I_3_avg As Single ' Durchschnitt Strom Ausgang 3,3 Volt Dim I_5_avg As Single ' Durchschnitt Strom Ausgang 5 Volt Dim I_25_avg As Single ' Durchschnitt Strom Ausgang 1,25-25 Volt Dim I_3_avg1 As Single ' Durchschnitt Strom Ausgang 3,3 Volt Dim I_5_avg1 As Single ' Durchschnitt Strom Ausgang 5 Volt Dim I_25_avg1 As Single ' Durchschnitt Strom Ausgang 1,25-25 Volt Dim I_avg_count As Word ' Z hler f r Durchschnitt Strom 'Durchschnitt Strom für serielle Ausgabe Dim I_3_avg_s As Single ' Durchschnitt Strom Ausgang 3,3 Volt Dim I_5_avg_s As Single ' Durchschnitt Strom Ausgang 5 Volt Dim I_25_avg_s As Single ' Durchschnitt Strom Ausgang 1,25-25 Volt Dim I_3_avg1_s As Single ' Durchschnitt Strom Ausgang 3,3 Volt Dim I_5_avg1_s As Single ' Durchschnitt Strom Ausgang 5 Volt Dim I_25_avg1_s As Single ' Durchschnitt Strom Ausgang 1,25-25 Volt Dim I_avg_count_s As Word ' Zähler für Durchschnitt Strom Dim I_3_max As Single ' Maximum Strom Ausgang 3,3 Volt Dim I_5_max As Single ' Maximum Strom Ausgang 5 Volt Dim I_25_max As Single ' Maximum Strom Ausgang 1,25-25 Volt Dim I_3_min As Single ' Minimum Strom Ausgang 3,3 Volt Dim I_5_min As Single ' Minimum Strom Ausgang 5 Volt Dim I_25_min As Single ' Minimum Strom Ausgang 1,25-25 Volt I_3_max = -10000 : I_5_max = -10000 : I_25_max = -10000 I_3_min = 10000 : I_5_min = 10000 : I_25_min = 10000 Dim P_3 As Single ' Leistung Ausgang 3,3 Volt Dim P_5 As Single ' Leistung Ausgang 5 Volt Dim P_25 As Single ' Leistung Ausgang 1,25-25 Volt |
Im folgenden werden zuerst einige Variablen für die Menu-Steuerung definiert. Im Anschluss daran folgen Variablen, die nur temporär verwendet werden. Das heißt, das diese nur vorübergehend für Schleifen oder Zwischenergebnisse bei Berechnungen verwendet werden. Das nächste Programmstück ist eigentlich für das Endprodukt nicht mehr erforderlich. Es scannt den I²C-Bus über alle möglichen Adressen und gibt diese aus. Man erkennt also, wenn irgendein I²C-Teilnehmer nicht mehr ansprechbar ist. Danach werden global die Interrupts eingeschaltet.
'Variablen für Menu Dim Menu As Byte ' Menunummer Dim Menu_old As Byte Dim Menuverlassen As Byte ' Zähler um ins Hauptmenu zurück zu springen Dim Wertmax As Word ' maximal einstellbarer Wert Dim Wert As Word ' Wert hoch/runter Dim Wert_refresh As Byte ' Wert wurde geändert Dim Warning As Byte ' Warnung ein Dim Blinken As Byte ' LCD + LED blinkt 'temporäre Variablen Dim X As Byte , Y As Byte , Z As Byte Dim W As Word Dim W_low As Byte At W Overlay : Dim W_high As Byte At W + 1 Overlay Dim I As Integer , I1 As Integer Dim I_low As Byte At I Overlay : Dim I_high As Byte At I + 1 Overlay Dim S As Single Dim L As Long Dim Str2 As String * 2 Dim Str6 As String * 6 Dim Str8 As String * 8 Dim Str12 As String * 12 Dim Str40 As String * 40 Cls Upperline : Lcd "I2C-Bus Scan" Wait 1 Cls Upperline : Lcd "INA219-1" Locate 1 , 11 : Lcd "INA219-2" Locate 1 , 21 : Lcd "INA219-3" Locate 1 , 31 : Lcd "DS1621" Y = 0 : Z = 1 For X = 2 To 254 Step 2 ' for all odd addresses I2cstart ' send start I2cwbyte X ' send address If Err = 0 Then ' we got an ack Locate 2 , Z Lcd "hex: " ; Hex(x) ' Adresse anzeigen Incr Y : Z = Z + 10 End If I2cstop ' free bus Next If Y = 0 Then Lowerline Lcd "I2C-Error, no Slave found!" End If Wait 2 Enable Interrupts |
Als letztes vor dem Beginn der Hauptprogrammschleife erfolgt die Konfiguration der Strom- und Spannungssensoren INA219. Die Konfigurationsregister der ICs sind 16 Bit breit. Die Kommentare zu den Bits habe ich bewusst im Code gelassen. Der erste und zweite Ausgang (3,3 und 5 Volt) wird auf maximal 16 Volt Eingangsspannung konfiguriert. Möglich sind zwei Messbereiche: 16 oder 32 Volt. "PG" ist die Maximalspannung über dem Shunt zur Strommessung. Bei den gewählten Widerständen von je 0,1 Ohm entspricht dies einem Maximalstrom von 1,6 Ampere. Alle drei Wandler werden mit der maximal möglichen Auflösung von 12 Bit betrieben. Es werden 128 Samples (Messungen) durchgeführt und daraus ein Durchschnitt gebildet. Das dauert zwar 68 Millisekunden, liefert aber eine ruhige Anzeige. Ca. 15 Messwerte pro Sekunde reichen mir, das Hauptprogramm braucht ja sowieso noch seine Zeit um die Messwerte umzurechnen, anzuzeigen und evtl. seriell auszugeben. Mit dem Wert für "Optional Second Calibration" können Ungenauigkeiten der Shunts ausgeglichen werden. Der 3. Kanal wird abweichend zu den anderen auf 32 Volt Eingangsspannung und 80 mV Maximalspannung über dem Shunt konfiguriert.
'W = &B 0 0 1 11 0011 0011 111 Default Configuration Register 00h ' | | | || |||| |||| ||| ' | | | || |||| |||| +++- MODE 1-3 ' | | | || |||| ++++- SADC 1-4 ' | | | || ++++- BADC 1-4 ' | | | ++- PG 0-1 ' | | +- BRNG ' | +- - ' +- RST 'W = &B0011100110011111 ' Default Configuration Register 00h 'W = &B0011111111111111 ' Register 00h, 12 Bit, 128 Samples, Bus Voltage Range 32 V 'W = &B0001111111111111 ' Register 00h, 12 Bit, 128 Samples, Bus Voltage Range 16 V 'W = &B0001011111111111 ' Register 00h, 12 Bit, 128 Samples, Bus Voltage Range 16 V, Gain +4 (160 mV) 'Ausgang 3,3 Volt Ina219_adr_w = Ina219_3_adr_w ' Schreibadresse INA219 Ausgang 3,3 Volt Ina219_adr_r = Ina219_3_adr_r ' Leseadresse INA219 Ausgang 3,3 Volt W = &B0001011111111111 ' Register 00h, 12 Bit, 128 Samples, Bus Voltage Range 16 V, PG 160 mV Ina219_reg = &H00 ' Configuration Register Gosub Ina219_reg_write ' Register INA219 schreiben 'W = 8192 ' Calibration Register Value W = 7880 ' Optional second Calibration step Ina219_reg = &H05 ' Calibration Register Gosub Ina219_reg_write ' Register INA219 schreiben 'Ausgang 5 Volt Ina219_adr_w = Ina219_5_adr_w ' Schreibadresse INA219 Ausgang 5 Volt Ina219_adr_r = Ina219_5_adr_r ' Leseadresse INA219 Ausgang 5 Volt W = &B0001011111111111 ' Register 00h, 12 Bit, 128 Samples, Bus Voltage Range 16 V, PG 160 mV Ina219_reg = &H00 ' Configuration Register Gosub Ina219_reg_write ' Register INA219 schreiben 'W = 8192 ' Calibration Register Value W = 7502 ' Optional second Calibration step Ina219_reg = &H05 ' Calibration Register Gosub Ina219_reg_write ' Register INA219 schreiben 'Ausgang 1,25-25 Volt Ina219_adr_w = Ina219_25_adr_w ' Schreibadresse INA219 Ausgang 1,25-25 Volt Ina219_adr_r = Ina219_25_adr_r ' Leseadresse INA219 Ausgang 1,25-25 Volt W = &B0010111111111111 ' Register 00h, 12 Bit, 128 Samples, Bus Voltage Range 32 V, PG 80 mV Ina219_reg = &H00 ' Configuration Register Gosub Ina219_reg_write ' Register INA219 schreiben 'W = 40960 ' Calibration Register Value W = 37654 ' Optional second Calibration step Ina219_reg = &H05 ' Calibration Register Gosub Ina219_reg_write ' Register INA219 schreiben Reset Led_rt ' LED rot aus Cls |
Nachdem die rote LED ausgeschaltet wurde, wird noch die Anzeige auf dem LCD gelöscht. Die Beschreibung der Hauptprogrammschleife erfolgt im nächsten Teil der Dokumentation.