Will man mit serialcominstruments.com/instrument4.php seine Mess-oder Zählwerte grafisch auf dem PC-Monitor darstellen, bietet sich als Interface ein kleiner AVR an. Mit diesem Programm lassen sich auf einfachste Weise mehrere Werte gleichzeitig darstellen, wobei man die Anzahl, Größe, Auflösung und das Design der verschiedenen Messinstrumente selbst festlegen kann. Es lassen sich mehrere Werte gleichzeitig mit einstellbarem Messintervall als Verlauf grafisch darstellen und auch aufzeichnen. Ebenso ist es möglich, Texte vom MC zu empfangen und anzuzeigen. Auch einfache LED-Status-Anzeigen lassen sich in verschiedenen Formen vom MC aus steuern. Doch die Kommunikation funktioniert auch in die andere Richtung, die Software kann dem MC Werte von Schiebereglern schicken, verschiedene Schalter, natürlich in Größe und Design einstellbar, teilen ihren Status mit und nicht zuletzt kann man Befehle per Eingabefeld als Text senden("Licht an!"). Somit ist der MC komplett fernsteuerbar, ohne eine einzige Taste anzuschließen. Ein Terminal-Fenster lässt sich ebenfalls öffnen.
Daraus ergeben sich vielfältige Anwendungsmöglichkeiten. Angefangen von der Möglichkeit, z.B. mehrere Spannungen gleichzeitig zu messen und darzustellen, oder die Lade/Entladekurve eines Akku's grafisch aufzuzeichnen. Man überlege, mit wie viel Aufwand gerade letzteres zu realisieren wäre(Anzeige,Speicher etc.).
Screenshot (5).png
Ebenfalls denkbar, eine Riesen Anzeige, z.B. für Schulungen u.s.w.:
Screenshot (9).png
Und noch weitere Darstellungen
Screenshot (11).png
Diese Oberflächen sind alle mit ein paar Klick's erstellt. Es besteht auch die Möglichkeit, als Hintergrund ein(z.B. mit Paint erstelltes) Bild einzufügen.
Was noch fehlt, ist die Verbindung zur Aussenwelt. Die Kommunikation erfolgt über LAN oder eine Serielle Schnittstelle. Da diese an den wenigsten Rechnern noch zu finden sein dürfte, funktioniert das ganze auch über den USB-Anschluss per USB-RS232 Adapter.
Ich benutzte ein Adapterkabel, in welchem die Elektronik im Stecker verbaut ist. Es handelt sich dabei um den Chip PL2303, welcher von WIN7 sofort erkannt wurde. Nur WIN10 haderte mit dem Adapter, nach der Installation eines alten Treiber's(für WIN7/WIN8.1) funktioniert es aber zuverlässig ohne Aussetzer.
Neben RXD und TXD hat man auch gleich die 5 Volt Stromversorgung aus dem PC dabei. Ein 100nF Kondensator am MC, mehr braucht es nicht, da die interne Spannungsreferenz von 2.56 Volt des ATMega8 zum messen genutzt wird. Eine Hand voll Bauteile werden noch für den Spannungsteiler am ADC Eingang benötigt. Für den 100 Volt Bereich verwende ich: Messeingang - 180 KOhm - Trimmer 220 Ohm - 4,7 kOhm an GND. Die Mittelanzapfung des Trimmers über einen 12 kOhm Widerstand direkt an einen der sechs Ad-Wandler Eingänge legen. So lässt sich der Messwert ganz genau einjustieren. Am Mess-Eingang noch eine Diode in Sperrrichtung nach GND für den Verpolungsschutz. Aber hier muss jeder die Eingangsbeschaltung nach seinen Bedürfnissen ausrichten.
Die COM-Schnittstelle ist fest eingestellt auf 8 Data Bits, 1 Stop Bit und No Parity, wir brauchen also in unserem Bascom Code nichts einstellen.
Die Kommunikation erfolgt nun folgendermaßen: Der ATMega sendet seine gemessenen Werte als String über den UART mit 115200 kb an den PC. Für einen Kanal sieht das dann so aus:
Print "#1M" ; Str(i1) ; "<"
wobei # = Start Übertragung
1 = Kanalnummer
M = Start Messwert
String = Messwert
< = Ende Messwert
bedeuten.
Jetzt zeigen alle Messinstrumente, bei denen der Kanal 1 eingestellt ist, unseren Messwert schon an. Über eine Skalierung kann jedes Instrument noch an unseren Wert angepasst werden.
Mehrere Werte werden so übertragen:
Print "#1M" ; Str(i1) ; "<" ; "#2M" ; Str(i2) ; "<" ; "#3M" ; Str(i3) ; "<" ; "#4M" ; Str(i4) ; "<" ; "#5M" ; Str(i5) ; "<" ; "#6M" ; Str(i6) ; "<"
Eine LED darstellen:
Print "#40M" ; 2 ; 1 ; "<"
würde eine grüne(2), rechteckige(1) LED auf dem Icon mit Kanal 40 darstellen. Die Farben und Formen kann man dem sehr guten deutschen Manual entnehmen.
Mit:
Print "#40M" ; "Fehler21" ; "<"
erhält man im Textfeld mit der Kanalnummer 40 fortlaufend die Meldung "Fehler 21" mit Uhrzeit und Datum(Fehlerspeicher). Im Textfeld "Text Shape" erscheint die Meldung einmalig bis zur nächsten Meldung, aber man kann zusätzlich vom MC aus die Text und Background Farbe senden, bitte dem Manual entnehmen.
Screenshot (14).png
Zur Steuerung des MC durch die Software: Für einen Schalter mit Kanal 20 sendet das Programm #20Ms< wobei s=Status (0=Aus, 1=Ein) ist. Das ganze wird wieder als String gesendet, so dass man sich nun die einzelnen Byte's raus angeln muss.
Ich habe das so gelöst:
INT für jedes empfangene Byte:
Enable Urxc
On Urxc Uart0 'ISR
Enable Interrupts 'generell Interrupts einschalten
In der ISR zu einem String zusammen fügen:
Dat = Inkey() 'empfangenes Byte einlesen
S = S + Chr(dat) 'zum String dazu fügen
Das CRLF auswerten:
If Dat = 10 Then 'ENDE-Zeichen von UART auswerten
' Print S 'String zurück schicken zu Kontrolle im Terminal
Gosub Ausführen
S = "" 'String löschen
Dat = 0 'zuletzt empfangenes Byte löschen
End If
und die Aktion ausführen:
Aktor = Mid(s , 2 , 2) 'Aktoren(DAC und Schalter) müssen 2-Stellige Kanalnummern haben
Status = Mid(s , 5 , 1)
If Aktor = "20" Then 'Schalter1
If Status = "0" Then 'Aus
Led1 = 0
Elseif Status = "1" Then 'Ein
Led1 = 1
End If
Elseif Aktor = "21" Then 'Schalter2
If Status = "0" Then 'Aus
Led2 = 0
Elseif Status = "1" Then 'Ein
Led2 = 1
End If
Elseif Aktor = "10" Then 'DAC Kanal 10 auf Format"000" stellen, damit immer 3-stellig
Stellwert = Mid(s , 5 , 1)
Pwm_wert = Stellwert - 48 'wegen ASCII im String
Pwm_wert = Pwm_wert * 100 ' Hunderter
Stellwert = Mid(s , 6 , 1)
Byte_wert = Stellwert - 48
Byte_wert = Byte_wert * 10 'Zehner
Pwm_wert = Pwm_wert + Byte_wert
Stellwert = Mid(s , 7 , 1)
Byte_wert = Stellwert - 48 'Einer
Pwm_wert = Pwm_wert + Byte_wert
Print "#7M" ; Str(pwm_wert) ; "<" 'für eine Kontroll-Anzeige (Kanal 7)
Pwm1b = Pwm_wert
End If
Da das ganze bisher nur ein Test war, ist der Code noch nicht optimal. Eine CASE Anweisung ist bei mehreren Aktoren sicherlich übersichtlicher und die einzelnen Byte's lassen sich besser als Overlay des eingelesenen String auslesen.
Hier mal der gesamte,funktionierende Code für 6 ADC, 2 LED Ausgänge und ein PWM Ausgang mit Rückmeldung:
Alles anzeigen
Weil der ATMega Platz und Zeit hatte, habe ich für die ADC's je einen Medianfilter mit eingebaut, somit stören keine Ausreißer.
Der ATMega8 ist damit noch nicht halb gefüllt, da gibt es noch Reserven. Für aufwändigere Programme muss man dann einen anderen MC benutzen, wobei dann zu beachten ist, dass sich die UART Register, die Timer für die PWM und auch die interne Referenzspannung ändern können.
Daraus ergeben sich vielfältige Anwendungsmöglichkeiten. Angefangen von der Möglichkeit, z.B. mehrere Spannungen gleichzeitig zu messen und darzustellen, oder die Lade/Entladekurve eines Akku's grafisch aufzuzeichnen. Man überlege, mit wie viel Aufwand gerade letzteres zu realisieren wäre(Anzeige,Speicher etc.).
Screenshot (5).png
Ebenfalls denkbar, eine Riesen Anzeige, z.B. für Schulungen u.s.w.:
Screenshot (9).png
Und noch weitere Darstellungen
Screenshot (11).png
Diese Oberflächen sind alle mit ein paar Klick's erstellt. Es besteht auch die Möglichkeit, als Hintergrund ein(z.B. mit Paint erstelltes) Bild einzufügen.
Was noch fehlt, ist die Verbindung zur Aussenwelt. Die Kommunikation erfolgt über LAN oder eine Serielle Schnittstelle. Da diese an den wenigsten Rechnern noch zu finden sein dürfte, funktioniert das ganze auch über den USB-Anschluss per USB-RS232 Adapter.
Ich benutzte ein Adapterkabel, in welchem die Elektronik im Stecker verbaut ist. Es handelt sich dabei um den Chip PL2303, welcher von WIN7 sofort erkannt wurde. Nur WIN10 haderte mit dem Adapter, nach der Installation eines alten Treiber's(für WIN7/WIN8.1) funktioniert es aber zuverlässig ohne Aussetzer.
Neben RXD und TXD hat man auch gleich die 5 Volt Stromversorgung aus dem PC dabei. Ein 100nF Kondensator am MC, mehr braucht es nicht, da die interne Spannungsreferenz von 2.56 Volt des ATMega8 zum messen genutzt wird. Eine Hand voll Bauteile werden noch für den Spannungsteiler am ADC Eingang benötigt. Für den 100 Volt Bereich verwende ich: Messeingang - 180 KOhm - Trimmer 220 Ohm - 4,7 kOhm an GND. Die Mittelanzapfung des Trimmers über einen 12 kOhm Widerstand direkt an einen der sechs Ad-Wandler Eingänge legen. So lässt sich der Messwert ganz genau einjustieren. Am Mess-Eingang noch eine Diode in Sperrrichtung nach GND für den Verpolungsschutz. Aber hier muss jeder die Eingangsbeschaltung nach seinen Bedürfnissen ausrichten.
Die COM-Schnittstelle ist fest eingestellt auf 8 Data Bits, 1 Stop Bit und No Parity, wir brauchen also in unserem Bascom Code nichts einstellen.
Die Kommunikation erfolgt nun folgendermaßen: Der ATMega sendet seine gemessenen Werte als String über den UART mit 115200 kb an den PC. Für einen Kanal sieht das dann so aus:
Print "#1M" ; Str(i1) ; "<"
wobei # = Start Übertragung
1 = Kanalnummer
M = Start Messwert
String = Messwert
< = Ende Messwert
bedeuten.
Jetzt zeigen alle Messinstrumente, bei denen der Kanal 1 eingestellt ist, unseren Messwert schon an. Über eine Skalierung kann jedes Instrument noch an unseren Wert angepasst werden.
Mehrere Werte werden so übertragen:
Print "#1M" ; Str(i1) ; "<" ; "#2M" ; Str(i2) ; "<" ; "#3M" ; Str(i3) ; "<" ; "#4M" ; Str(i4) ; "<" ; "#5M" ; Str(i5) ; "<" ; "#6M" ; Str(i6) ; "<"
Eine LED darstellen:
Print "#40M" ; 2 ; 1 ; "<"
würde eine grüne(2), rechteckige(1) LED auf dem Icon mit Kanal 40 darstellen. Die Farben und Formen kann man dem sehr guten deutschen Manual entnehmen.
Mit:
Print "#40M" ; "Fehler21" ; "<"
erhält man im Textfeld mit der Kanalnummer 40 fortlaufend die Meldung "Fehler 21" mit Uhrzeit und Datum(Fehlerspeicher). Im Textfeld "Text Shape" erscheint die Meldung einmalig bis zur nächsten Meldung, aber man kann zusätzlich vom MC aus die Text und Background Farbe senden, bitte dem Manual entnehmen.
Screenshot (14).png
Zur Steuerung des MC durch die Software: Für einen Schalter mit Kanal 20 sendet das Programm #20Ms< wobei s=Status (0=Aus, 1=Ein) ist. Das ganze wird wieder als String gesendet, so dass man sich nun die einzelnen Byte's raus angeln muss.
Ich habe das so gelöst:
INT für jedes empfangene Byte:
Enable Urxc
On Urxc Uart0 'ISR
Enable Interrupts 'generell Interrupts einschalten
In der ISR zu einem String zusammen fügen:
Dat = Inkey() 'empfangenes Byte einlesen
S = S + Chr(dat) 'zum String dazu fügen
Das CRLF auswerten:
If Dat = 10 Then 'ENDE-Zeichen von UART auswerten
' Print S 'String zurück schicken zu Kontrolle im Terminal
Gosub Ausführen
S = "" 'String löschen
Dat = 0 'zuletzt empfangenes Byte löschen
End If
und die Aktion ausführen:
Aktor = Mid(s , 2 , 2) 'Aktoren(DAC und Schalter) müssen 2-Stellige Kanalnummern haben
Status = Mid(s , 5 , 1)
If Aktor = "20" Then 'Schalter1
If Status = "0" Then 'Aus
Led1 = 0
Elseif Status = "1" Then 'Ein
Led1 = 1
End If
Elseif Aktor = "21" Then 'Schalter2
If Status = "0" Then 'Aus
Led2 = 0
Elseif Status = "1" Then 'Ein
Led2 = 1
End If
Elseif Aktor = "10" Then 'DAC Kanal 10 auf Format"000" stellen, damit immer 3-stellig
Stellwert = Mid(s , 5 , 1)
Pwm_wert = Stellwert - 48 'wegen ASCII im String
Pwm_wert = Pwm_wert * 100 ' Hunderter
Stellwert = Mid(s , 6 , 1)
Byte_wert = Stellwert - 48
Byte_wert = Byte_wert * 10 'Zehner
Pwm_wert = Pwm_wert + Byte_wert
Stellwert = Mid(s , 7 , 1)
Byte_wert = Stellwert - 48 'Einer
Pwm_wert = Pwm_wert + Byte_wert
Print "#7M" ; Str(pwm_wert) ; "<" 'für eine Kontroll-Anzeige (Kanal 7)
Pwm1b = Pwm_wert
End If
Da das ganze bisher nur ein Test war, ist der Code noch nicht optimal. Eine CASE Anweisung ist bei mehreren Aktoren sicherlich übersichtlicher und die einzelnen Byte's lassen sich besser als Overlay des eingelesenen String auslesen.
Hier mal der gesamte,funktionierende Code für 6 ADC, 2 LED Ausgänge und ein PWM Ausgang mit Rückmeldung:
BASCOM-Quellcode
- $regfile = "m8def.dat"
- $crystal = 8000000
- $hwstack=40
- $swstack=16
- $framesize=32
- $baud = 115200
- '----------------------------------------------------------------------------------------------------------------------
- 'AD-Wandler einschalten
- Config Adc = Single , Prescaler = Auto , Reference = Internal
- Start Adc
- '----------------------------------------------------------------------------------------------------------------------
- 'INT UART-Empfang Int nach jedem empfangenen Byte
- Enable Urxc
- On Urxc Uart0 'ISR
- Enable Interrupts 'generell Interrupts einschalten
- '----------------------------------------------------------------------------------------------------------------------
- Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 64
- '----------------------------------------------------------------------------------------------------------------------
- Config Portd.7 = Output
- Config Portb.0 = Output
- Led1 Alias Portd.7
- Led2 Alias Portb.0
- '----------------------------------------------------------------------------------------------------------------------
- Dim I1 As Single
- Dim I2 As Single
- Dim I3 As Single
- Dim I4 As Single
- Dim I5 As Single
- Dim I6 As Single
- Dim Z As Byte
- Dim N As Byte
- Dim U As Word
- Dim Tabelle1(50) As Word
- Dim Tabelle2(50) As Word
- Dim Tabelle3(50) As Word
- Dim Tabelle4(50) As Word
- Dim Tabelle5(50) As Word
- Dim Tabelle6(50) As Word
- Dim Index As Byte
- Dim Median As Word
- Dim S As String * 13
- Dim Dat As Byte
- Dim Byte_wert As Byte
- Dim Pwm_wert As Byte
- Dim Stellwert As String * 3
- Dim Status As String * 1
- Dim Aktor As String * 2
- Pwm1b = 0
- Led1 = 1
- Waitms 200
- Led2 = 1
- Waitms 200
- Led1 = 0
- Led2 = 0
- Do
- If Dat = 10 Then 'ENDE-Zeichen von UART auswerten
- Print S 'String zurück schicken zu Kontrolle im Terminal
- Gosub Ausführen
- S = "" 'String löschen
- Dat = 0 'zuletzt empfangenes Byte löschen
- End If
- Index = Index + 1
- U = Getadc(0)
- Waitus 300
- Tabelle1(index) = U
- U = Getadc(1)
- Waitus 300
- Tabelle2(index) = U
- U = Getadc(2)
- Waitus 300
- Tabelle3(index) = U
- U = Getadc(3)
- Waitus 300
- Tabelle4(index) = U
- U = Getadc(4)
- Waitus 300
- Tabelle5(index) = U
- U = Getadc(5)
- Waitus 300
- Tabelle6(index) = U
- If Index = 50 Then
- Gosub Median50
- Print "#1M" ; Str(i1) ; "<" ; "#2M" ; Str(i2) ; "<" ; "#3M" ; Str(i3) ; "<" ; "#4M" ; Str(i4) ; "<" ; "#5M" ; Str(i5) ; "<" ; "#6M" ; Str(i6) ; "<"
- End If
- Loop
- Ausführen:
- Aktor = Mid(s , 2 , 2) 'Aktoren(DAC und Schalter) müssen 2-Stellige Kanalnummern haben
- Status = Mid(s , 5 , 1)
- If Aktor = "20" Then 'Schalter
- If Status = "0" Then 'Aus
- Led1 = 0
- Elseif Status = "1" Then 'Ein
- Led1 = 1
- End If
- Elseif Aktor = "21" Then 'Schalter
- If Status = "0" Then 'Aus
- Led2 = 0
- Elseif Status = "1" Then 'Ein
- Led2 = 1
- End If
- Elseif Aktor = "10" Then 'DAC Kanal 10 auf Format"000" stellen, damit immer 3-stellig
- Stellwert = Mid(s , 5 , 1)
- Pwm_wert = Stellwert - 48 'wegen ASCII im String
- Pwm_wert = Pwm_wert * 100 ' Hunderter
- Stellwert = Mid(s , 6 , 1)
- Byte_wert = Stellwert - 48
- Byte_wert = Byte_wert * 10 'Zehner
- Pwm_wert = Pwm_wert + Byte_wert
- Stellwert = Mid(s , 7 , 1)
- Byte_wert = Stellwert - 48 'Einer
- Pwm_wert = Pwm_wert + Byte_wert
- Print "#7M" ; Str(pwm_wert) ; "<" 'für eine Kontroll-Anzeige (Kanal 7)
- Pwm1b = Pwm_wert
- End If
- Return
- '---------------------------------------------------------------------------------------
- Median50:
- For N = 1 To 24 '24mal kleinsten Wert in Tabelle suchen und auf 65000 setzen
- Min(tabelle1(1) , Median , Index)
- Tabelle1(index) = 65000
- Next
- Min(tabelle1(1) , Median , Index) 'der 25. minwert ist der Median
- I1 = Median / 10
- For N = 1 To 24
- Min(tabelle2(1) , Median , Index)
- Tabelle2(index) = 65000
- Next
- Min(tabelle2(1) , Median , Index)
- I2 = Median / 10
- For N = 1 To 24
- Min(tabelle3(1) , Median , Index)
- Tabelle3(index) = 65000
- Next
- Min(tabelle3(1) , Median , Index)
- I3 = Median / 10
- For N = 1 To 24
- Min(tabelle4(1) , Median , Index)
- Tabelle4(index) = 65000
- Next
- Min(tabelle4(1) , Median , Index)
- I4 = Median / 10
- For N = 1 To 24
- Min(tabelle5(1) , Median , Index)
- Tabelle5(index) = 65000
- Next
- Min(tabelle5(1) , Median , Index)
- I5 = Median / 10
- For N = 1 To 24
- Min(tabelle6(1) , Median , Index)
- Tabelle6(index) = 65000
- Next
- Min(tabelle6(1) , Median , Index)
- I6 = Median / 10
- Index = 0
- Return
- Uart0:
- Dat = Inkey() 'empfangenes Byte einlesen
- S = S + Chr(dat) 'zum String dazu fügen
- Return
Der ATMega8 ist damit noch nicht halb gefüllt, da gibt es noch Reserven. Für aufwändigere Programme muss man dann einen anderen MC benutzen, wobei dann zu beachten ist, dass sich die UART Register, die Timer für die PWM und auch die interne Referenzspannung ändern können.
4.490 mal gelesen