Labornetzteil
BASCOM-Quellcode Hauptprogramm
Im ersten Teil des Hauptprogrammes werden zuerst die beiden Taster abgefragt und bei Betätigung eine Unterroutine angesprungen. Danach erfolgt die Abfrage der Strom- und Spannungswerte. Ich beschreibe hier nur beispielgebend die Bearbeitung des ersten Kanals für die Spannung von 3,3 Volt. Die beiden anderen Kanäle sind identisch aufgebaut. Zuerst wird in einem Unterprogramm der Wert der Spannung von dem jeweiligen Strom-/Spannungswandler INA219 abgefragt. Dazu werden die Schreib- und Leseadresse, sowie das Register 02 hex in die Variablen übernommen und so dem Unterprogramm übergeben. Der Rückgabewert muss drei Bit nach rechts geschoben werden. Anschließend addiere ich einen Offset, um Toleranzen auszugleichen. Die Auflösung des Wandlers beträgt 4 mV pro Bit. Um auf eine Spannungsanzeige in Volt zu kommen, wird der Wert durch 250 geteilt. Danach erfolgt das Auslesen des Wertes für den Strom in Register 04 hex. Auch hier erfolgt wieder eine Offset-Korrektur. Bei der gewählten Konfiguration des Schaltkreises beträgt die Auflösung des Wandlers 50 µA pro Bit. Für eine Anzeige in Milliampere wird dieser Wert demzufolge mit 20 dividiert. In der nächsten Zeile wird ein Bit einer Variablen gesetzt, falls der gemessene Strom größer als 1 Ampere ist. Diese Variable wird später ausgewertet, um die Warn-LED anzusteuern. In den folgenden beiden Zeilen wird der Maximal- und Minimalwert des Stromes erfasst. Die Berechnung des Durchschnittstromes geschieht nach folgendem Muster: Zuerst wird der aktuell gemessene Strom zu einer Variablen addiert. Solange der Zähler noch nicht den Maximalwert von 32768 erreicht hat, wird dieser erhöht. Den Durchschnitt erhält man anschließend bei der Division der Variablen mit dem Zähler. Wenn der Maximalwert des Zählers erreicht ist, wird statt der Erhöhung des Zählers einmal der Durchschnittswert subtrahiert. Der Maximalwert für den Zähler wurde so gewählt damit die Variable des Durchschnittes nicht überläuft. Bei ca. 15 Messungen pro Sekunde erhält man damit einen Durchschnitt über ca. 36 Minuten. Die Berechnung des Durchschnitts für die serielle Ausgabe erfolgt analog. Eine getrennte Erfassung erfolgt deshalb, weil ich dort den Durchschnitt zwischen zwei Ausgaben haben wollte.
'######################## H A U P T P R O G R A M M ####################### Do 'Tastaturabfrage Debounce Pind.7 , 0 , Taste_o , Sub ' Taster oben Debounce Pind.6 , 0 , Taste_u , Sub ' Taster unten Warning = 0 'Ausgang 3,3 Volt Spannung messen 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 Ina219_reg = &H02 ' Bus Voltage Gosub Ina219_reg_read_w ' Register INA219 lesen Shift W , Right , 3 ' must bee shifted right by three bits W = W + 6 ' Offset U_3 = W / 250 ' Spannung Ausgang 3,3 Volt (4 mV pro Bit) 'Ausgang 3,3 Volt Strom messen Ina219_reg = &H04 ' Current Gosub Ina219_reg_read_i ' Register INA219 lesen I = I - 2 ' Offset I_3 = I / 20 ' Strom Ausgang 3,3 Volt in mA (50 µA pro Bit) If I_3 > 1000 Then : Warning.0 = 1 : End If ' Strom zu hoch If I_3 > I_3_max Then : I_3_max = I_3 : End If ' Maximalstrom If I_3 < I_3_min Then : I_3_min = I_3 : End If ' Minimalstrom 'Durchschnitt Strom für lokale Anzeige I_3_avg1 = I_3_avg1 + I_3 ' aktuellen Messwert f r Durchschnitt addieren If I_avg_count < 32768 Then ' maximal 32768 Messwerte Incr I_avg_count ' Zähler für Durchschnitt erhöhen Else I_3_avg1 = I_3_avg1 - I_3_avg ' Durchschnitt subtrahieren End If I_3_avg = I_3_avg1 / I_avg_count ' Durchschnitt Ausgang 3,3 Volt errechnen 'Durchschnitt Strom für serielle Ausgabe I_3_avg_s = I_3_avg1_s / I_avg_count_s ' Durchschnitt Ausgang 3,3 Volt errechnen I_3_avg1_s = I_3_avg1_s + I_3 ' aktuellen Messwert für Durchschnitt addieren If I_avg_count_s < 32768 Then ' maximal 32768 Messwerte Incr I_avg_count_s ' Zähler für Durchschnitt erhöhen Else I_3_avg1_s = I_3_avg1_s - I_3_avg_s ' Durchschnitt subtrahieren End If I_3_avg_s = I_3_avg1_s / I_avg_count_s ' Durchschnitt Ausgang 3,3 Volt errechnen |
Im Anschluss an die Messungen der Spannungen und Ströme erfolgt die Messung der Kühlkörpertemperatur und Steuerung des Lüfters abhängig von dieser. Der Temperaturwert wird in einem Unterprogramm aus dem Thermometerschaltkreis DS1621 gelesen und umgerechnet. Wenn die Temperatur höher als 45 °C ist, soll der Lüfter anlaufen. Der Wert für die Pulsweitenmodulation wird in Schritten von 5 pro 0,1 °C erhöht. Der Lüfter erreicht seine maximale Drehzahl dadurch bei 60 °C. Der errechnete Wert wird anschließend an Timer 2 übergeben. Bei Temperaturen größer als 50 °C wird noch ein Bit der Variablen "Warning" gesetzt, dadurch wird später die rote LED angesteuert und die Anzeige auf dem Display beginnt zu blinken.
'Temperatur messen und Lüfter regeln Gosub Ds1621_read ' Werte DS1621 auslesen und umrechnen If Temperatur >= 450 Then ' Lüfterregelung Beginn bei 45 C If Temperatur >= 500 Then ' ab 50 °C Warnung ausgeben Warning.3 = 1 ' LED rot blinkt End If W = Temperatur - 449 ' 1- If W <= 50 Then Fan_pwm = W * 5 ' 0,1 °C - 5,0 °C = 5 - 250 Else Fan_pwm = 255 ' volle Drehzahl End If Else Fan_pwm = 0 ' Lüfter aus End If Pwm2b = Fan_pwm ' PWM Timer 2 |
Den Aufbau der Anzeige und die Menüsteuerung werde ich anhand zweier Menüpunkte beschreiben. Die komplette Struktur ist ist auf der Seite "Menüstruktur" zu sehen. Menüpunkt 0 ist der Ausgangspunkt beim Einschalten des Netzteils und zeigt Spannungen und Ströme aller drei Kanäle an. In der If-Bedingung wird abgefragt, ob ein Neuaufbau der Anzeige nach Menüwechsel notwendig ist. Ist das der Fall, wird das Display gelöscht und bis zum Ausschalten der Hintergrundbeleuchtung nach 30 Sekunden in der ersten Zeile ein Pfeil nach rechts angezeigt. Dies soll anzeigen, das bei Betätigung der oberen Taste zum nächsten Menüpunkt gewechselt wird. Bei jedem Durchlauf der Hauptprogrammschleife wird anschließend die Anzeige der Spannungen und Ströme aktualisiert.
Select Case Menu Case 0 ' Anzeige Spannung und Strom If Lcd_refresh = 1 Then Lcd_refresh = 0 : Cls If Lcd_light = 1 Then Locate 1 , 40 : Lcd "{199}" ' Pfeil nach rechts End If End If 'Spannungen anzeigen Str6 = Fusing(u_3 , "#.##") ' Spannung 3,3 Volt runden und formatieren Locate 1 , 4 : Lcd Str6 ; " V" ' Spannung Ausgang 3,3 Volt anzeigen Str6 = Fusing(u_5 , "#.##") ' Spannung 5 Volt runden und formatieren Locate 1 , 18 : Lcd Str6 ; " V" ' Spannung Ausgang 5 Volt anzeigen Str6 = Fusing(u_25 , "#.##") ' Spannung 1,25-25 Volt runden und formatieren Locate 1 , 31 If U_25 < 10 Then : Lcd " " ; : End If ' Leerzeichen anzeigen Lcd Str6 ; " V" ' Spannung Ausgang 1,25-25 Volt anzeigen 'Strom anzeigen Lcd_zeile = 2 ' Anzeige Zeile S = I_3 : Lcd_pos = 2 : Z = 0 : Gosub Lcd_i ' Strom Ausgang 3 Volt anzeigen S = I_5 : Lcd_pos = 16 : Z = 1 : Gosub Lcd_i ' Strom Ausgang 5 Volt anzeigen S = I_25 : Lcd_pos = 30 : Z = 2 : Gosub Lcd_i ' Strom Ausgang 1,25-25 Volt übernehmen |
Beispielgebend hier der Menüpunkt 12 für die Einstellung der Übertragungsrate der seriellen Schnittstelle. Bei Wechsel in diesen Menüpunkt wird in der oberen Zeile die Bedeutung angezeigt und ganz rechts Pfeile nach rechts und darunter nach oben für die Funktion der beiden Tasten. Danach wird in die Variable "Wert" der aktuelle Index der Einstellung übernommen. In der Variablen "Wertmax" wird die obere Grenze, die der Wert annehmen darf, festgelegt. In der folgenden If-Abfrage wird ermittelt, ob eine Taste betätigt wurde. In der Tastaturabfrage wurde die Variable "Wert" verändert und wird anschließend in "Ser_baudindex" übernommen. Dieser Index bestimmt, welcher String anschließend aus der Datentabelle "Table_ser_baud" geladen wird. Der Textstring wird danach in der unteren Zeile des Displays angezeigt. Bei Änderung dieses Index gegenüber dem im EEPROM gespeicherten wird der neue Wert dauerhaft im EEPROM gesichert. Dadurch können beim Neustart des Netzteils die gespeicherten Einstellungen wieder hergestellt werden. Zum Schluss wird noch die serielle Schnittstelle mit dem neuen Wert in einer Unterroutine eingestellt.
Case 12 ' Einstellung Geschwindigkeit serielle Schnittstelle If Lcd_refresh = 1 Then Lcd_refresh = 0 : Cls Upperline : Lcd "Geschwindigkeit serielle Schnittstelle" Gosub Lcd_pfeil_lo ' Anzeige Pfeil nach rechts und oben Wert = Ser_baudindex ' Wert übernehmen Wertmax = 6 ' Einstellwerte Index 0-6 End If If Wert_refresh = 1 Then Wert_refresh = 0 ' nur einmal ausführen Ser_baudindex = Wert Str6 = Lookupstr(ser_baudindex , Table_ser_baud) Lowerline : Lcd Str6 Locate 2 , 6 ' Cursorposition If Ser_baudindex <> Ser_baudindex_eram Then Ser_baudindex_eram = Ser_baudindex ' Einstellungen speichern Gosub Ser_set_baud ' Einstellung Übertragungsrate serielle Schnittstelle End If End If |
Im folgenden Teil werden Warnungen bei zu hoher Stromentnahme oder Übertemperatur ausgewertet. Die rote LED blinkt im Takt von einer halben Sekunden gesteuert von Timer 1. Solange die Warnungen noch nicht durch eine Tastenbetätigung bestätigt wurden, werden in Abhängigkeit der Höhe der Warnmeldung die Menüpunkte 0 oder 10 aktiviert. Die Bits 0 bis 2 der Variablen "Warning" werden durch Überstrom aktiviert und Bit 3 durch Übertemperatur. Der Summer wird wiederum durch Timer 1 aktiviert. Sollte die Temperatur größer als 54,9 °C sein, so wird ein Warnton ausgegeben.
If Warning >= 1 Then If Led_rt <> Blinken.0 Then Led_rt = Blinken.0 ' Led rot blinkt End If If Quittung = 0 Then If Warning < 8 Then ' Strom zu hoch If Menu <> 0 Then : Menu = 0 : Lcd_refresh = 1 : End If ' Spannung und Strom anzeigen End If If Warning >= 8 Then ' Temperatur zu hoch If Menu <> 10 Then : Menu = 10 : Lcd_refresh = 1 : End If ' Temperatur anzeigen End If If Summer >= 1 Then Summer = 0 If Temperatur >= 550 Then ' ab 55 °C Sound Piezo , 100 , 768 ' 100 mS, 1 kHz End If End If End If Else Reset Led_rt ' Led rot aus Quittung = 0 End If |
Der nachfolgende Teil des Programmes ist zuständig für die Auswertung der über die serielle Schnittstelle empfangenen Daten. Bei jedem empfangenem Zeichen wird die Variable "Interrupt" auf den Wert 1 gesetzt und dadurch die Auswertung gestartet. Bei Empfang der Ziffern 0 bis 7 wird das Intervall der Ausgabe an der seriellen Schnittstelle eingestellt. Ein "C" startet die Ausgabe im CSV-Format. Bei Empfang eines "S" wird die Ausgabe für "Logview" (universelles Visualisierungs-Tool um Daten aufzuzeichnen und auszuwerten) eingeleitet. Dazu wird zuerst ein Header gesendet, der zur Konfiguration des Programmes dient. Danach wird die Ausgabe der Daten gestartet. Dieses Programm sendet bei Aufzeichnungsende eine "E" an das Netzteil um die Übertragung zu beenden. Nach Empfang eines "T" startet das Netzteil die Ausgabe im Textformat. Mit "H" kann eine kleine Hilfe in Form einer Auflistung aller Befehle angefordert werden.
'Empfang serielle Schnittstelle If Interrupt = 1 Then ' Zeichen von UART empfangen Set Led_rt ' LED rot einschalten Select Case Rxchar_uart ' Auswahl nach empfangenem Zeichen Case "0" Ser_intervall = 0 Case "1" Ser_intervall = 1 Case "2" Ser_intervall = 2 Case "3" Ser_intervall = 5 Case "4" Ser_intervall = 10 Case "5" Ser_intervall = 15 Case "6" Ser_intervall = 30 Case "7" Ser_intervall = 60 Case "C" Ser_format = 2 ' CSV Ser_ausgabe_kanal = 15 ' alle Kanäle ein Sec_count_l = 0 ' Sekundenzähler zurück setzen Case "S" Incr Ofz_nr : Ofz_nr_eram = Ofz_nr : Str6 = Str(ofz_nr) Print "$N$;LNT15 #" ; Format(str6 , "000") Print "$C$;"; If Ser_ausgabe_kanal.0 = 1 Then ' Ausgang 3,3 Volt Print "U_3[V,U];I_3[mA,I]" ; ' Spannung und Strom If Ser_ausgabe_kanal >= 2 Then Print ";" ; Else Print ' keine weitere Ausgabe End If End If If Ser_ausgabe_kanal.1 = 1 Then ' Ausgang 5 Volt Print "U_5[V,U];I_5[mA,I]" ; ' Spannung und Strom If Ser_ausgabe_kanal >= 4 Then Print ";" ; Else Print ' keine weitere Ausgabe End If End If If Ser_ausgabe_kanal.2 = 1 Then ' Ausgang 1,25-25 Volt Print "U_25[V,U];I_25[mA,I]" ; ' Spannung und Strom If Ser_ausgabe_kanal >= 8 Then Print ";" ; Else Print ' keine weitere Ausgabe End If End If If Ser_ausgabe_kanal.3 = 1 Then ' Temperatur Str6 = Str(temperatur) ' Temperatur übernehmen Print "T[ C,T];Fan[PWM,D]" ' Temperatur und PWM Lüfter End If Ser_format = 3 ' LogView Studio OpenFormat Zero Ser_ausgabe_kanal = 15 ' alle Kanäle ein Sec_count_l = 0 ' Sekundenzähler zurück setzen Ofz_start = 1 ' serielle Ausgabe beginnen Case "E" Ofz_start = 0 ' serielle Ausgabe beenden Ser_format = 0 ' serielle Ausgabe beenden Case "T" Ser_format = 1 ' Text Ser_ausgabe_kanal = 15 ' alle Kanäle ein Sec_count_l = 0 ' Sekundenzähler zurück setzen Case "H" Print "________________________________________" Print "Befehle Labornetzteil LNT 15:" Print "C - Start Ausgabe CSV-Format" Print "S - Start Ausgabe OpenFormat Zero" Print "T - Start Ausgabe Textformat" Print "E - Ende Ausgabe seriell" Print "0 - kontinuierliche Ausgabe" Print "1 - Intervall 1 Sekunde" Print "2 - Intervall 2 Sekunden" Print "3 - Intervall 5 Sekunden" Print "4 - Intervall 10 Sekunden" Print "5 - Intervall 15 Sekunden" Print "6 - Intervall 30 Sekunden" Print "7 - Intervall 60 Sekunden" End Select Interrupt = 0 : Rxchar_uart = "" ' zurück setzen Lcd_refresh = 1 : Wert_refresh = 1 End If ' ########## Ende Empfang seriell ########## |
Die Ausgabe der Daten an der seriellen Schnittstelle ist in drei Formaten möglich: Text, CSV und Logview. Jedes Senden von Daten signalisiert die rote LED mit kurzem Aufleuchten. Im Textformat werden Spannung und Strom der in den Einstellungen gewählten Kanäle ausgegeben, auch die Ausgabe von Temperatur und PWM-Wert des Lüfters ist möglich. Die Ausgaben im Format CSV und Logview sind im Prinzip gleich und werden deshalb von einem Unterprogramm abgearbeitet.
'Senden serielle Schnittstelle If Ser_format >= 1 Then If Sec_count >= Ser_intervall Then Sec_count = 0 Set Led_rt ' LED rot einschalten Select Case Ser_format Case 1 ' Textausgabe Print "------------------------------------" If Ser_ausgabe_kanal.0 = 1 Then ' Ausgang 3,3 Volt Str6 = Fusing(u_3 , "#.##") ' Spannung 3,3 Volt runden und formatieren Str8 = Fusing(i_3_avg_s , "#.##") ' Strom runden und formatieren If Str8 = "-0.00" Then : Str8 = "0.00" : End If Print "U_3: " ; Str6 ; " V I_3: " ; Str8 ; " mA" End If If Ser_ausgabe_kanal.1 = 1 Then ' Ausgang 5 Volt Str6 = Fusing(u_5 , "#.##") ' Spannung 5 Volt runden und formatieren Str8 = Fusing(i_5_avg_s , "#.##") ' Strom runden und formatieren If Str8 = "-0.00" Then : Str8 = "0.00" : End If Print "U_5: " ; Str6 ; " V I_5: " ; Str8 ; " mA" End If If Ser_ausgabe_kanal.2 = 1 Then ' Ausgang 1,25-25 Volt Str6 = Fusing(u_25 , "#.##") ' Spannung 1,25-24 Volt runden und formatieren Str8 = Fusing(i_25_avg_s , "#.##") ' Strom runden und formatieren If Str8 = "-0.00" Then : Str8 = "0.00" : End If Print "U_24: " ; Str6 ; " V I_24: " ; Str8 ; " mA" End If If Ser_ausgabe_kanal.3 = 1 Then ' Temperatur Str6 = Str(temperatur) ' Temperatur übernehmen Print "Temp: " ; Format(str6 , "0.0") ; " C PWM: " ; Fan_pwm End If I_3_avg_s = 0 : I_5_avg_s = 0 : I_25_avg_s = 0 I_3_avg1_s = 0 : I_5_avg1_s = 0 : I_25_avg1_s = 0 I_avg_count_s = 0 Case 2 ' CSV Str2 = "," Print Sec_count_l ; ","; ' Sekundenzähler ausgeben Gosub Ser_ausgabe ' serielle Ausgabe Daten CSV oder OFZ Case 3 If Ofz_start = 1 Then ' LogView Studio OpenFormat Zero If Warning = 0 Then : Set Led_rt : End If ' LED rot ein Str2 = ";" Print "$" ; Gosub Ser_ausgabe ' serielle Ausgabe Daten CSV oder OFZ End If End Select End If End If Loop End |
Hiermit endet die Hauptprogrammschleife. Die Beschreibung der Interrupt- und Unterroutinen erfolgt im dritten Teil der Programmbeschreibung.