- MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad         
Seite 2 von 3 ErsteErste 123 LetzteLetzte
Ergebnis 11 bis 20 von 28

Thema: ADC Ausgabe an 7-Segment-Display

  1. #11
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.113
    Anzeige

    Powerstation Test
    Mach' die Umschalterei von Anfang an über einen Timer. Alles andere wirst du später bereuen.
    Und denke daran, immer erst alles abzuschalten, bevor du neue Werte auf die Ports gibst. Sonst bekommst du die leidigen Geisterbilder.

  2. #12
    Benutzer Stammmitglied
    Registriert seit
    20.01.2008
    Beiträge
    66
    Hab mich jetzt mal ein wenig mit dem multiplexen beschäftigt. Die Schaltung der gem. Anoden und den Transistoren funktioniert soweit. Leider hängt es wieder bei der Programmierung. Ich hab einen atmega8 mit 1Mhz Frequenz. Soweit ich es verstanden habe wird dem 8bit Timer automatisch ein 10bit prescaler also /1024 eingeschaltet. Stelle ich jetzt in der config einen prescaler 8 ein komm ich auf 122 Hz (richtig??). Mein eigentlches Problem ist die programmierung, um die beiden Ausgänge für die gem. Anoden an bzw. aus zu schalten. Ich komm nicht so richtig mit den variablen klar. Müssen jetzt die einzelnen Segmente abwechselnd oder jede einfach für sich ein/ausgeschaltet werden und wie sage ich jedem Ausgang das bei den Zehnern jetzt ne 1 und bei den Einern ne null angezeigt werden soll. Vielleicht kann mir jemand mal in Worten den Ablauf erklären?

  3. #13
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.113
    Deine 1MHz sind natürlich nicht so umwerfend schnell, aber es sollte trotzdem gehen.
    Deine Angaben mit dem Prescaler habe ich nicht verstanden. Was ist ein 10bit prescaler?
    Wenn du 2 Stellen umschalten willst und dies flimmerfrei mit 100Hz, dann muss deine ISR Frequenz folglich mindestens 200 Hz betragen.
    Du kommst auf die richtigen Werte für Prescale und Anzahl Überläufe über diesen Zusammenhang:

    Gewünschte Frequenz (bei dir 200) = $crystal / prescale / overflow_count
    Bei 1MHz Crystal also z.B.
    200 ~ 1.000.000 / 1024 / 5 oder
    200 ~ 1.000.000 / 64 / 78
    200 ~ 1.000.000 / 8 / 312

    Da du einen 8-bit Timer benutzen willst, wird die letzte Version nicht mehr gehen, da der Timer nur bis 255 zählen kann.
    Je kleiner der Prescale um so genauer kannst du den gewünschten Wert treffen. Das ist bei dir aber eher unerheblich.
    In der Timer_isr schaltest du jetzt bei jedem Aufruf zwischen den beiden Ausgängen für die gemeinsamen Anoden um und legst den neuen Wert auf die Ausgänge für die Segmente. Wenn die alle an einem Port liegen, kannst du dies sehr einfach mit einem Befehl tun. So ähnlich wie oben also mit
    PortD = Segmente(wert_der_stelle)

  4. #14
    Benutzer Stammmitglied
    Registriert seit
    20.01.2008
    Beiträge
    66
    Die Info mit dem 10bit Prescaler hab ich aus nem Buch für Atmel-Programmierung. "....Timer0 ist ein 8-Bit-Timer mit einem vorgeschaltetem 10-Bit-Prescaler."
    Das Schalten der Ausgänge für die Zehner/Einer hab ich so gelöst:
    Code:
    $regfile = "M8def.dat"
    $crystal = 1000000
    
    '--------Segmente---------------
    Config Portd = Output
    Portd = 1
    
    '----------Anode Display---------
    Config Portb = Output
    Digit1 Alias Portb.1
    Digit2 Alias Portb.2
    
    Portb = 0
    
    '---------AD-Wandler Config-------------
    Config Adc = Single , Prescaler = Auto , Reference = Avcc
    Start Adc
    
    '--------Timer Config----------------
    Dim A As Byte                                               'Umschaltung einer/zehner
    
    
    Config Timer0 = Timer , Prescale = 8
    On Timer0 Timer_routine
    Enable Timer0
    Enable Interrupts
    
    
    
    
    Dim Messung As Integer
    
    Dim I As Byte
    
    Dim X(10) As Byte
    
    Restore Segmente
    
    For I = 1 To 10
    Read X(i)
    Next I
    
    Do
    
       Messung = Getadc(0) / 103                                'Wert vom ADC/103 in Variable speichern
       Portd = X(messung  + 1)
    
    Loop
    
    
       End
    
    
    Timer_routine:
    
    Incr A                                                      'Variable um 1 erhöhen
    
    Portb = A                                                   'portb.1 /portb.2 an/aus schalten
    
    Return
    
    
    
    
    
    
    
    
    
    
    '---------------------------------------------------------------------------
    Segmente:
    'gemeinsame Anode:
    '      0      1       2      3        4      5        6      7     8      9
    'Data &H3F , &H6 , &H05B , &H04F , &H066 , &H06D , &H07D , &H7 , &H7F , &H6F
    'gemeinsame kathode:
    '      0      1       2      3      4      5     6      7     8      9
    Data &H40 , &H79 , &H24 , &H30 , &H19 , &H12 , &H02 , &H78 , &H00 , &H10
    Trotz viel Lesen und probieren ist es mir aber noch nicht gelungen z.B. eine "10" darzustellen. Ich hab ein Paar Beispiele mit "Select Case" gesehen, hab sie aber nicht verstanden? Ist das eine Möglichkeit die ich verwenden sollte?

  5. #15
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.113
    Sieht doch gar nicht so schlecht aus. Ich habe mal ein paar kleine Änderungen gemacht. Probier es mal aus.

    Code:
    $regfile = "M8def.dat"
    $crystal = 1000000
    
    '--------Segmente---------------
    Config Portd = Output
    Portd = 1
    
    '----------Anode Display---------
    Config Portb = Output
    Digit1 Alias Portb.1
    Digit2 Alias Portb.2
    
    Portb = 0
    
    '---------AD-Wandler Config-------------
    Config Adc = Single , Prescaler = Auto , Reference = Avcc
    Start Adc
    
    '--------Timer Config----------------
    Dim A As Byte                                               'Umschaltung einer/zehner
    
    
    Config Timer0 = Timer , Prescale = 8
    On Timer0 Timer_routine
    Enable Timer0
    Enable Interrupts
    A = 1
    
    
    
    Dim Messung As Word
    Dim Stelle(2) As Byte
    
    Dim I As Byte
    
    Dim X(10) As Byte
    
    Restore Segmente
    
    For I = 1 To 10
    Read X(i)
    Next I
    
    Do
    
       Messung = Getadc(0) / 11                                'Wert vom ADC/11 (0-99) in Variable speichern
       Stelle(1) =messung / 10                                  'Hinter dem Komma wird abgeschnitten, enthält also die Zehner
       Incr Stelle(1)                                                 'Damit die Werte von 1-10 gehen
       Stelle(2)=messung mod 10                             'gibt den Rest, also die Einer
       Incr Stelle(2)
    
    Loop
    
    
       End
    
    
    Timer_routine:
       Portb.a = 0                                              'Vorherige Stelle ausschalten
       Incr A
       If A=3 Then A=1
       Portd=X(Stelle(A))                                   'Neue Segmente ausgeben
       Portb.a = 1                                              'Neue Stelle einschalten
    Return
    
    Segmente:
    'gemeinsame Anode:
    '      0      1       2      3        4      5        6      7     8      9
    'Data &H3F , &H6 , &H05B , &H04F , &H066 , &H06D , &H07D , &H7 , &H7F , &H6F
    'gemeinsame kathode:
    '      0      1       2      3      4      5     6      7     8      9
    Data &H40 , &H79 , &H24 , &H30 , &H19 , &H12 , &H02 , &H78 , &H00 , &H10

  6. #16
    Benutzer Stammmitglied
    Registriert seit
    20.01.2008
    Beiträge
    66
    super!!! Manchmal flackkern die Zahlen zwar ein bisschen aber ich denke das hängt mit der niedrigen Grundfrequenz des Atmegas zusammen?! Ich werd mich mal durch den Code wuseln um zu verstehen was du alles gemacht hast.
    Vielen Dank

  7. #17
    Benutzer Stammmitglied
    Registriert seit
    20.01.2008
    Beiträge
    66
    Nachdem ich mir meinen Atmega "Verfused" habe und ihn nach viel lesearbeit, mit nem tiny wieder flott gemacht habe, sitz ich nun vor dem nächsten Problem.

    Es geht um die Berechnung des ADC-Wertes in eine Anzeigbare Temperatur.
    Hab schon viel über die KTY-Reihe gelesen und wie diese linearisiert werden (darauf kommts mir erstmal nicht an).
    Also ich verwende einen KTY81-120. Ich hab ihn über einen Spannungsteiler 1K am ADC-Pin angeschlossen. Nun hab ich mit meinem Multimeter eine Zimmertemperatur von 20 Grad gemessen. Dies wollte ich als Ausgangstemperatur nehmen. Am Sensor liegt also bei 20 Grad eine Spannung von 2,5 Volt an. Das entspricht einem ADC-Wert von 512. Der Widerstandbereich des KTY liegt bei 1721 Ohm (20 Grad = 1KOhm).
    Ich krieg die Formel für die Umrechnung einfach nicht hin, obwohl es doch gar nicht so schwer sein kann???

    @ for_ro
    Kannst du mir den Befehl "mod" und den Code-Abschnitt (siehe unten) noch erklären? Hab in der Hilfe keine Erklärung gefunden.

    Code:
    If A = 3 Then A = 1
       Portd = X(stelle(a))

  8. #18
    Benutzer Stammmitglied
    Registriert seit
    20.01.2008
    Beiträge
    66
    Ich hab mir nun folgendes Programm erarbeitet. Die Temperatur haut schonmal ganz gut hin. Allerdings hab ich es immer noch nicht hinbekommen eine weiter Stelle der 7-Segment-Anzeige anzusprechen. Hier soll einfach ein "°" angezeigt werden. Den Code in der Timer-Routine hab ich immer noch nicht ganz verstanden. Vielleicht kann mir jemand auf die Sprünge helfen.
    Code:
    $regfile = "M8def.dat"
    $crystal = 4000000
    
    '--------Segmente---------------
    Config Portd = Output
    Portd = 1
    
    '----------Anode Display---------
    Config Portb = Output
    Digit1 Alias Portb.1
    Digit2 Alias Portb.2
    Digit3 Alias Portb.3
    Portb = 0
    
    '---------AD-Wandler Config-------------
    Config Adc = Single , Prescaler = Auto , Reference = Avcc
    Start Adc
    
    '--------Timer Config----------------
    Dim A As Byte                                               'Umschaltung einer/zehner
    A = 1
    
    Config Timer0 = Timer , Prescale = 64
    On Timer0 Timer_routine
    Enable Timer0
    Enable Interrupts
    
    
    
    
    Dim Messung As Word
    Dim Stelle(3) As Word
    
    
    Dim I As Byte
    
    Dim X(11) As Byte
    
    Restore Segmente
    
    For I = 1 To 10
    Read X(i)
    Next I
    
    Do
    
       Messung = Getadc(0) * 64
       Messung = Messung / 101
       Messung = Messung - 151
       Stelle(1) = Messung / 10
       Incr Stelle(1)
       Stelle(2) = Messung Mod 10
       Incr Stelle(2)
    
    
    
    
       Loop
    
    
       End
    
    
    Timer_routine:
    
    
    
       Portb.a = 0                                              'Vorherige Stelle ausschalten
    
       Incr A                                                   'Neue Segmente ausgeben
       If A = 3 Then A = 1
       Portd = X(stelle(a))
    
       Portb.a = 1
    
       Return
    
    Segmente:
    'gemeinsame Anode:
    '      0      1       2      3        4      5        6      7     8      9
    'Data &H3F , &H6 , &H05B , &H04F , &H066 , &H06D , &H07D , &H7 , &H7F , &H6F
    'gemeinsame kathode:
    '      0      1       2      3      4      5     6      7     8      9      Grad
    Data &H40 , &H79 , &H24 , &H30 , &H19 , &H12 , &H02 , &H78 , &H00 , &H10 , &H63

  9. #19
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    16.02.2006
    Beiträge
    1.113
    Hallo Malte0815,
    ich hatte nicht gesehen, dass du mich schon einmal direkt gefragt hattest.
    If A = 3 Then A = 1
    Portd = X(stelle(a))


    A ist die Stelle, die aktuell eingeschaltet ist, in Stelle(A) steht der aktuelle Wert, der ausgegeben werden soll.
    In X(Stelle(A)) steht der entsprechende Segment-Wert für diese Ziffer.

    Wenn du jetzt 3 Stellen hast, dann musst du A bis 4 laufen lassen, bevor es wieder auf ein gesetzt wird. Also
    If A = 4 Then A = 1

    Das Gradzeichen würde ich am Anfang einmal fest in Stelle(3) schreiben, dann brauchst du sonst nichts mehr zu ändern. Also hinter
    For I = 1 To 10
    Read X(i)
    Next I


    einfach noch
    Read Stelle(3) oder direkt
    Stelle(3) = &H63

    Hier mal alles zusammen (mit noch etwas Kosmetik):

    Code:
    $regfile = "M8def.dat"
    $crystal = 4000000
    
    '--------Segmente---------------
    Config Portd = Output
    Portd = 0                                                   'anfangs alles aus
    
    '----------Anode Display---------
    Config Portb = Output
    Digit1 Alias Portb.1
    Digit2 Alias Portb.2
    Digit3 Alias Portb.3
    Portb = 0                                                   'auch hier alles aus
    
    '---------AD-Wandler Config-------------
    Config Adc = Single , Prescaler = Auto , Reference = Avcc
    Start Adc
    
    '--------Timer Config----------------
    Dim Stelle As Byte                                          'Umschaltung zehner/einer/grad_zeichen
    Stelle = 1                                                  'start mit Zehner
    
    Config Timer0 = Timer , Prescale = 64
    On Timer0 Timer_routine                                     'wird 4.000.000/64/256 ~ 244 mal pro Sekunde aufgerufen
    Enable Timer0
    Enable Interrupts
    
    Dim Messung As Word
    Dim Wert_stelle(3) As Byte
    Dim I As Byte
    Dim Temp As Word
    Dim Segmente(11) As Byte
    
    Restore Segment_daten
    
    For I = 1 To 10
       Read Segmente(i)
    Next I
    Wert_stelle(3) = &H63                                       '°fest auf Stelle 3
    
    Do
       Messung = Getadc(0) * 64
       Messung = Messung / 101
       Messung = Messung - 151
       Messung = Messung
       Temp = Messung / 10                                      'ganzahlige Division, also 47 / 10 = 4
       Wert_stelle(1) = Temp + 1
       Temp = Messung Mod 10                                    'Mod ergibt den Rest der Division, also bei 47 / 10 ist Mod = 7
       Wert_stelle(2) = Temp + 1
       Waitms 100                                               'hier vielleicht noch eine kleine Pause
    Loop
    
    
    End
    
    
    Timer_routine:
       Portb.stelle = 0                                         'Vorherige Stelle ausschalten
       Portd = 0                                                'zusätzlich alle Segmente aus
       Incr Stelle                                              'auf nächste Stelle umschalten
       If Stelle = 4 Then Stelle = 1                            'am Ende wieder zurück zur ersten Stelle
       Portd = Segmente(wert_stelle(stelle))                    'Neue Segmente ausgeben
       Portb.stelle = 1                                         'neue Stelle einschalten
    Return
    
    Segment_daten:
    'gemeinsame Anode:
    '      0      1       2      3        4      5        6      7     8      9
    'Data &H3F , &H6 , &H05B , &H04F , &H066 , &H06D , &H07D , &H7 , &H7F , &H6F
    'gemeinsame kathode:
    '      0      1       2      3      4      5     6      7     8      9      Grad
    Data &H40 , &H79 , &H24 , &H30 , &H19 , &H12 , &H02 , &H78 , &H00 , &H10       ', &H63

  10. #20
    Benutzer Stammmitglied
    Registriert seit
    20.01.2008
    Beiträge
    66
    Hmm...ich bin nun schon den ganzen Morgen am probieren aber irgdwo steckt noch der Wurm drin.
    Hab auch eben deinen überarbeiteten Code(danke für die Mühe ) probiert aber immer das selbe Phänomen.

    Sobald ich bei" If Stelle = 3 Then Stelle = 1" die 3 durch eine 4 ersetze, leuchten bei beiden Digits alle segmente auf und die zu darstellenden Zahlen leuchten etwas heller durch. Beim dritten Digit leuchtet eine Mischung aus Zehnern und einern.
    Anfangs dachte ich es hätte etwas mit der Frequenz zu tun aber mit Teiler 8 ist das selbe.
    Wenn ich nun wieder 3 einsetze, werden Einer und Zehner wieder normal angezeigt und beim dritten Digit unverändert eine Mischung aus beiden Zahlen.

    Ich versteh es nicht....wenn die Variable des Portb einfach um eins weiter zählen soll, kann sich doch bei der Darstellung nichts ändern, außer das die Frequenz ohne Anpassung niedriger wird, oder seh ich da was falsch?

Seite 2 von 3 ErsteErste 123 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress