Hallo Leute.
Nach langer Zeit habe ich mich mal wieder an das Programmieren gemacht. ,
Ich wollte mir mit 4 Siebensegmentanzeigen einen Tacho, die Uhrzeit sowie 2 Temperaturen ans Moped (Simson) bauen (der Original Tacho ist ein Schätzeisen).
soweit so gut. Die Uhr und die beiden Temperaturen war kein Problem geht ja auch schon in anderen Projekten bei mir.
Jetzt ging es aber ans multiplexen der 7 Segmentanzeigen diese Funktioniert im Prinzip ja auch super die einzelnen Segmente zeigen mir die richtige Zahl an alles super. ( Im Einzelprogramm )
Das Problem was ich habe ist wenn ich im Programm die Tempmessung und das Multiplexen gleichzeitig ablaufen lasse funktioniert meine Tempmessung nicht mehr.
Er Error bei den DS18b20 Sensoren an.
Klammere ich eins aus z.B das Multiplexen geht die Tempmessung super, klammere ich z.b Tempmessung aus geht das Multilexen super aber es geht nicht beides zusammen.
Das einzige was ich mir vorstellen kann ist das ich die 7 Segmente (a-g) auch noch zwingend über Transistoren steuern muss da ich dies zur Zeit noch nicht mache
es wird nur die gemeinsame Kathode mit je einem BC337-40 getrieben.
Wollte es eigentlich erstmal nur testen, wusste ja nicht das ich es so schnell hinbekomme mit dem multiplexen, aber da hat mir hier das Forum sehr geholfen habe einen schönen Programmschnipsel gefunden mit dem es auf Anhieb geklappt hat.
edit:
Sorry falsche stelle
Als Highside Treiber könntest Du natürlich auch einen UDN 2981 einsetzen.
Als Lowside Treiber wäre auch ein ULN 2003 möglich ( bzw. ULN 2803 ), anstatt der einzelnen Transistoren.
Ich denk mal, das dein Problem eher eine Timinggeschichte ist.
Leider schreibst Du nichts über die Struktur deines Programmes.
Ich vermute mal, das das Timing für das Multiplexing in einem Interrupt läuft.
Ich hab jetzt das 1wire Protokoll nicht auf dem Schirm, aber war da nicht was mit den Impulslängen? Dann:
Wenn dann während der Abfrage der Temperatursensoren eine Timer Interrupt auftritt werden die Temperatursensoren nicht mehr richtig ausgelesen ( Bitfehler ).
Das kann man nun auf verschiedene Weise lösen.
Eine Möglichkeit wäre den Timer Interrupt abzuschalten und das Timer Interrupt Flag im Hauptprogramm abzufragen, zu verarbeiten und wieder zu löschen.
Dadurch treten dann keine Timing Konflikte mehr auf, allerdings werden dann einzelne Segmente u.U. länger angesteuert, wenn gerade eine Komunikation mit dem 1 wire Bus läuft.
Da die Temperaturmessung vermutlich nur mal max 2x/ Minute gemacht wird, dürfte das aber kein Problem sein.
Eine weitere Möglichkeit wäre, während der 1wire Komunikation alle Interrupts per "CLI" zu sperren und dann sofort wieder freizugeben.
Dadurch werden aber natürlich alle! interruptbasierten Messungen ( Drehzahl ? ) beeinflusst!
Im ersten Versuch würde ich die CLI Variante ausprobieren, weil einfacher zu proggen.
Wenn dann alles geht, bestätigt sich mein Verdacht mit dem Timing.
Wie man das dann letztlich löst müsste man gucken.
$regfile = "m32def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 8
$framesize = 24
Match_rom Alias &H55
Skip_rom Alias &HCC
Auslesen Alias &HBE
Messen Alias &H44
Dim Lftag As Word 'Tag des Jahres
Dim Jahreszeit As Bit 'Jahreszeiten für Sommer / Winter
Dim Tz As Byte 'Zeit Zone
Dim Wochentag As Byte , Monat As Byte , Jahr As Word 'Datums anzeige
Dim Takt as byte , Takt_alt as byte
Dim Ds1820id(16) As Byte , Sc(9) As Byte 'Anzahle sensoren 8 = 1 16 = 2 , 24 = 3 , 32 = 4 ,40 = 5 , 48 = 6 , 54 = 7
Dim I As Byte
Dim Dgc As Integer
Dim T1 As Integer , T2 As Integer ,temperr as bit
'für Multiplexen
Dim Einerh as byte , Zehnerh as byte , Einermin as byte , Zehnermin as byte
Dim Zahl as Byte , Stelle as Byte
Dim Dezimalziffern(4) as Word
'Für Temperatur
Dim T10 As Integer , T20 As Integer 'für min max berechnung
'Für Geschwindikeit
Dim Strecke as byte , weg as word , radzeit as byte , kmh1 as word , kmh as word
'Für ADC
Dim Messwert As word , Spannung As Single , Spannung1 As Single , Target As String * 10
Declare Sub Funkuhr
Declare Sub Tempmessung
declare Sub Geschwindigkeit
declare Sub Einzelzeit
Declare Function Decigrades18b20(byval Sc(9) As Byte) As Integer 'für DS18b20 ( China Sensoren )
Config Lcd = 16 * 2 '8x2 Display = 16x1a
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , _
Db7 = Portd.7 , E = Portd.2 , Rs = Portd.3
Initlcd
Cls
Config Dcf77 = PinC.0 , Timer = 1 , Timer1sec = 1 , Debug = 1 , Update = 0 , Check = 1 , Inverted = 0 , Gosub = Sectic 'Update = 2 wird stündlich (default 3uhr nachts), Update = 0 Funkhr wird immer aktuell gehalten
'Config Dcf77 = PinC.0 , Timer = 1 , Debug = 1 , Check = 1 , Inverted = 0 , Gosub = Sectic
Config Date = Dmy , Separator = .
Cursor off
Config Adc = Single , Prescaler = auto , Reference = Internal_2.56 'Internal_1.1 oder Internal_2.56 avcc aref
Const Adc_multi = 0.0025 '2,56/1024
Config Portb.3 = Output
Config timer2 = Timer , PRESCALE = 8
Config Timer0 = Pwm , Compare Pwm = Clear Up , Prescale = 8
On Ovf2 Isr_multiplex 'hier werden die Anzeigen geschalten
Enable Ovf2
Enable Interrupts
' 76543210
Ddra = &B00001111 'Tempsensoren A6, Reedkontakt A5, Spannung A4 , A0-A3 Transistor für Segmente Eingang = 0 Ausgang = 1
DDRC = &B11111110 'C7 - C1 4 * 7 Segmentanzeigen , C0 DCF-77
'************ Auslesen Temp Sensoren ************************
Config 1WIRE = Porta.6 '1Wire-Port festlegen war mal PortC.1
Restore Sensor_ids
For I = 1 To 17
Read Ds1820id(i)
Next I
1wreset
1wwrite Skip_rom
1wwrite Messen
Cls
Reed Alias PinA.5
Set PortA.5
reed = 1
Start Adc
Do
Dezimalziffern(1) = Zehnerh 'einzenle Zahlen für die Zeit anzeige
Dezimalziffern(2) = Einerh 'einzenle Zahlen für die Zeit anzeige
Dezimalziffern(3) = Zehnermin 'einzenle Zahlen für die Zeit anzeige
Dezimalziffern(4) = Einermin 'einzenle Zahlen für die Zeit anzeige
Debounce Reed , 0 , Kilometer , Sub 'Reedkontakt für Geschwindigkeit (noch nicht ganz sicher ob es bis 80km/h geht
Call Tempmessung 'Temperaturmessung starten
Call Geschwindigkeit 'kmh anzeige aufrufen
Call Einzelzeit 'Einzelne Zeitstellen
OCR0 = 250 'Display helligkeit
Locate 1 , 1
lcd Zehnerh ; einerh ;":" ; Zehnermin ; Einermin 'Einzelne Zeit anzeigen
'if Takt >=3 and Takt <=30 or Takt >=33 and Takt <=59 then 'später wieder einblenden
if kmh <= 9 then
Locate 2 , 11 '10
Lcd " "; kmh ; "km/h"
else
Locate 2 , 11 '10
Lcd kmh ; "km/h"
end if
'end if
'Messwert = 2
Messwert = Getadc(4)
Spannung = Messwert * Adc_multi
Spannung = Spannung * 5
'if Takt <3 or Takt >30 and Takt <33 then 'später wieder einblenden
'Runden Board Spannung messen
Target = Str(spannung)
Target = Fusing(spannung , "#.##")
If spannung <9 then
Locate 2 , 6 '10
Lcd " " ; Target ; "V"
else
Locate 2 , 6 '10
Lcd Target ; "V"
end if
'end if
Loop
'(
Sub Funkuhr
Lftag = Dayofyear() 'Tag des Jahres
Incr Lftag 'Tag des Jahres
Tz = Dcf77timezone() 'Zeitzone
End Sub Funkuhr
')
Sub Tempmessung
'Belegung von Pins zu einen von Links nach Rechts Flach oben
'1 = GND
'2 = Signal
'3 = VCC (5V)
' - - -
' 1 2 3
' \ _ /
If Takt <> Takt_alt Then
Takt_alt = Takt
1wverify Ds1820id(1) 'Sensor aus China
Locate 2 , 1
If Err = 1 Then
temperr = 1
Lcd "L NIO"
Elseif Err = 0 Then
1wwrite Auslesen
Sc(1) = 1wread(9)
T1 = Makeint(sc(1) , Sc(2))
If Sc(9) = Crc8(sc(1) , 8) Then
Dgc = Decigrades18b20(sc(9))
End If
if Takt >=5 and Takt <10 or Takt >=15 _
and Takt <20 or takt >=25 and Takt <30 _
or takt >=35 and Takt <40 or takt >=45 _
and Takt <50 or takt >=55 then
If T1 >= 10 Then
Locate 2 , 1
Lcd "L " ; Dgc ; "C"
Else
Locate 2 , 1
Lcd "L " ; Dgc ; "C"
End If
end if
End if
1wverify Ds1820id(9) 'Sensor aus China
Locate 2 , 1
If Err = 1 Then
temperr = 1
Lcd "O NIO"
Elseif Err = 0 Then
1wwrite Auslesen
Sc(1) = 1wread(9)
T2 = Makeint(sc(1) , Sc(2))
If Sc(9) = Crc8(sc(1) , 8) Then
Dgc = Decigrades18b20(sc(9))
End If
if Takt <5 or Takt >=10 and Takt <15 _
or Takt >=20 and takt <25 or Takt >=30 _
and takt <35 or Takt >=40 and takt <45 _
or Takt >=50 and takt <55 then
If T2 >= 10 Then
Locate 2 , 1
Lcd "O " ; Dgc ; "C"
Else
Locate 2 , 1
Lcd "O " ; Dgc ; "C"
End If
end if
If Takt = 9 Or Takt = 19 Or Takt = 29 _
Or Takt = 39 Or Takt = 49 Or Takt = 59 then 'alle 10 sekunden Messen
Restore Sensor_ids
For I = 1 To 17
Read Ds1820id(i)
Next I
1wreset
1wwrite Skip_rom
1wwrite Messen
End If
End if
End If
End Sub TEMPMESSUNG
Sub Geschwindigkeit
'V = S : T
'Geschwindigkeit = Weg / Zeit
if radzeit > 1 then
radzeit = 0
strecke = 0
end if
weg = Strecke * 1455 'radumfang im mm gemessen an Heidenheim reifen
if radzeit = 1 then
kmh1 = weg / radzeit
end if
kmh= kmh1 / 3600
End Sub Geschwindigkeit
Sub Einzelzeit
'Zehner Stunden
If _hour <10 or _hour = 20 then Zehnerh = 0
if _hour =>10 and _hour <20 then Zehnerh = 1
if _hour >=20 then Zehnerh = 2
'Einer Stunden
If _hour <10 then einerh = _hour
if _hour =>10 and _hour <20 then
Einerh = _hour - 10
End if
if _hour >20 then
einerh = _hour - 20
End if
'Zehner Minuten
if _Min <10 then Zehnermin = 0
if _Min =>10 and _Min <20 then Zehnermin = 1
if _Min =>20 and _Min <30 then Zehnermin = 2
if _Min =>30 and _Min <40 then Zehnermin = 3
if _Min =>40 and _Min <50 then Zehnermin = 4
if _Min =>50 then Zehnermin = 5
'einer Minuten
if _min <10 then einermin = _min
if _min >=10 and _min <20 then
einermin = _min - 10
end if
if _min >=20 and _min <30 then
einermin = _min - 20
end if
if _min >=30 and _min <40 then
einermin = _min - 30
end if
if _min >=40 and _min <50 then
einermin = _min - 40
end if
if _min >=50 then
einermin = _min - 50
end if
End sub Einzelzeit
'Formal für China Sensoren ( DS18B20 )
Function Decigrades18b20(byval Sc(9) As Byte)
Decigrades18b20 = 0
Decigrades18b20 = Makeint(sc(1) , Sc(2))
Decigrades18b20 = Decigrades18b20 / 16
End Function
Sectic:
Takt = _sec
Radzeit = Radzeit + 1
Return
Kilometer:
incr STRECKE
return
'Tempsensoren
Sensor_ids:
Data &H28 , &HA0 , &H29 , &H34 , &H05 , &H00 , &H00 , &H3A 'Innen Sensor T1
Data &H28 , &HDE , &H06 , &H34 , &H05 , &H00 , &H00 , &H26 'Ausen Sensor T2
Isr_multiplex:
'Bei jedem Aufruf der ISR wird
'sicherheitshalber alle Stellen über die Transistoren der Stellenansteueung die Anzeige abgeschaltet
'die Segmente der nächsten anzuzeigenden Dezimalziffer vorbereitet
'die entsprechende Stelle eingeschaltet.
If Stelle < 5 Then Incr Stelle Else Stelle = 1 'Index weiterschalten zur nächsten Stelle
Porta = Porta And &B00000000 'Alle 4 Stellen abschalten, andere Portpins nicht verändern '&B11110000
Portc = Lookup(dezimalziffern(stelle) , Ziffern_pattern) 'Lookup holt aus den Daten unter Ziffern_pattern
'das Pattern, das zur Zahl in Dezimalstellen(stelle) gehört
'und setzt damit im PORTB die Segmentportpins
Select Case Stelle 'und eine Stelle der vier wieder unter Strom setzen
Case 1 : Porta.0 = 1 'Stelle 1 einschalten am Porta.0
Case 2 : Porta.1 = 1 'Stelle 2 einschalten am Porta.1
Case 3 : Porta.2 = 1 'Stelle 3 einschalten am porta.2
Case 4 : Porta.3 = 1 'Stelle 4 einschalten am porta.3
End Select
Return
Ziffern_pattern: 'Daten zur Segmentansteuerung.
'Eine "1" bringt zusammen mit der Stellenansteuerung
'das entsprechende Segment zum leuchten
' 10 9 8 7 6
' . . . . .
' a e = 1
' 76543210 ' ________ d = 2
Data &B01111110 '0 ' | | A(K) = 3
Data &B00001100 '1 ' | | c = 4
Data &B10110110 '2 ' f | | b DP = 5
Data &B10011110 '3 ' | g | b = 6
Data &B11001100 '4 ' |_______ | a = 7
Data &B11011010 '5 ' | | A(K) = 8
Data &B11111010 '6 ' | | f = 9
Data &B00001110 '7 ' e | | c g = 10
Data &B11111110 '8 ' | d |
Data &B11011110 '9 ' |________|
' . . . . .
' 1 2 3 4 5
Im Großen und Ganzen sieht das Programm so aus.
aber es kann gut sein wie du schreibst das es daran liegt da muss ich mir das nochmal anschauen.
wie gesagt die multiplex Sache hab ich hier gefunden und im großen und ganzen nur etwas auf mein Projekt angepasst.
gibt bestimmt auch noch andere Möglichkeiten
Searcher
07.05.2017, 20:40
Hallo Mikegen,
Dein geposteter Code ist praktisch unlesbar. Zum Posten von Code gibt es die Codetags [ CODE] hier das Programm [ /CODE] aber ohne die Leerzeichen nach der öffnenden eckigen Klammer. Sieht dann so aus:
hier das Programm
Wenn Du beim Antwort schreiben unten rechts auf den "Erweitert" button klickst, geht das auch per Mausklick auf das # Zeichen.
Das was ich aber schon gesehen habe ist diese Zeile.
"If Stelle < 5 Then Incr Stelle Else Stelle = 1 'Index weiterschalten zur nächsten Stelle"
Es muß heißen
"If Stelle < 4 Then Incr Stelle Else Stelle = 1 'Index weiterschalten zur nächsten Stelle"
Das hatte ich hier (https://www.roboternetz.de/community/threads/70270-Wie-richtig-mit-Bascom-7-Segmentanzeige-Multiplexen?p=635443&viewfull=1#post635443) in der geposteten Datei auch schon berichtigt. Keine Ahnung ob das Deine Probleme behebt. recovery hat den Fehler auch übernommen und hat ihn anscheinend nicht gestört. Die 5 ist aber definitiv falsch!
Gruß
Searcher
- - - Aktualisiert - - -
Dann gibt es noch diese Zeilen bei Dir:
Ddra = &B00001111 'Tempsensoren A6, Reedkontakt A5, Spannung A4 , A0-A3 Transistor für Segmente Eingang = 0 Ausgang = 1
Config 1WIRE = Porta.6
Reed Alias PinA.5
Set PortA.5
reed = 1
PortA wird außer für 7 Segment also noch anders genutzt.
Beim Multiplexen hast Du folgendes aber nicht angepaßt:
"Porta = Porta And &B00000000 'Alle 4 Stellen abschalten, andere Portpins nicht verändern '&B11110000"
Versuch es mal so:
"Porta = Porta And &B1111_0000 'Alle 4 Stellen abschalten, andere Portpins nicht verändern '&B11110000"
Danke für die antwort
Also wenn ich das jetzt richtig verstanden habe darf der Port wo multiplext wird von nix anderem belegt sein.
Gut das dazu noch die Fehler im Programm sind das hab ich dann scheinbar komplett übersehen wenn man sich das 10mal anschaut sieht man nix mehr.
Werde das morgen dann mal versuchen soweit es geht so anzupassen das dann auf dem Port wo multiplext wird nix anderes dran ist.
Das mit der
"If Stelle < 5 Then Incr Stelle Else Stelle = 1 'Index weiterschalten zur nächsten Stelle"
Es muß heißen
"If Stelle < 4 Then Incr Stelle Else Stelle = 1 'Index weiterschalten zur nächsten Stelle"
stört so erstmal nicht das hatte ich dann auch schon gefunden muss aber eben definitiv 4 sein bei 4 Stellen oder man macht ein <= 5 draus :-) aber das ist ja jetzt auch erstmal egal.
Wenn es nicht gehen sollte dann lasse ich das mit der Temperaturen eben weg das soll mich nicht stören wenn ich keine habe.
Ebenso die Board / Batterie Spannung ist nur ein netter Nebeneffekt gebraucht wird es eigentlich überhaupt nicht.
Das was ich brauche und was mir wichtig ist ist eben die Uhr und die Geschwindigkeit und das auf den Segmenten weil die schön klein sind.
Später wenn es mal fertig ist soll das Display auch weg dann soll alles im Wechsel auf den Segmenten angezeigt werden.
Searcher
07.05.2017, 21:48
Also wenn ich das jetzt richtig verstanden habe darf der Port wo multiplext wird von nix anderem belegt sein.
Doch, da darf schon noch mehr drauf sein.
Diese Zeile:
Porta = Porta And &B1111_0000 'Alle 4 Stellen abschalten, andere Portpins nicht verändern '&B11110000
schaltet durch die AND Verknüpfung alle Portpins, die in der Maske &B1111_0000 "0" sind ab; setzt sie auf "0" und läßt die anderen unverändert. Da kann also noch was drauf sein.
Du hast als Maske mit &B00000000 aber alle Portpins im PORTA auf "0" gesetzt. Auch die Eingangsportpins was sich durch Abschalten des Pullups (wie hier der hier gesetzte: "Set PortA.5") wahrscheinlich irgendwie bemerkbar macht? Werden die roten Nuller in der Maske zu Einsern, bleiben im PORTA nach der Zeile "Einser" "Einser" und "Nuller" "Nuller"
Gruß
Searcher
Searcher
08.05.2017, 08:06
$regfile = "m32def.dat"
$crystal = 16000000
$hwstack = 32
$swstack = 8
$framesize = 24
Ich würde auch noch mindestens HWSTACK um mindestens 2 auf mindestens 34 erhöhen ;) Siehe auch
http://halvar.at/elektronik/kleiner_bascom_avr_kurs/speicher_hwstack_swstack_frame/
danke habe es hinbekommen war echt nur ein Timing Problem.
mache es jetzt einfach mit dem Timer der bei einem gewissen Punkt kurz die Tempmessung anstöst und in der Zeit ( ca. ne halbe Sekunde ) flackern kurz die Anzeigen aber das ist kaum wahrzunehmen.
Man muss dann genau in dem Moment auch noch hinschauen. ich werde die Zeit zwischen den Messung dann mit Sicherheit auch noch verlängen weil auf dem Moped braucht man es nicht das er alle 30 Sekunden die Temp misst da reichen 5 Minuten ( 300 Sekunden ) aus denke ich.
...Tempmessung anstöst und in der Zeit ( ca. ne halbe Sekunde ) flackern kurz...
Da ist sicher noch eine Optimierungsmöglichkeit da.
Du musst ja nicht während der ganzen Temperaturabarbeitung irgendwas blocken.
Es reicht ja wenn man das so lange macht, so lange Komunikation auf dem 1wire Bus ist.
5 min Messdauer für z.B. die Motor Kopftemperatur wär mir auch zu lang.
Für eine Umgebungsmessung reichte es aber natürlich allemal.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.