Projekt: Oszilloskop mit dem ATMega

pcprofi

Neues Mitglied
12. Apr. 2008
90
0
0
Sprachen
Hallo Freunde,

hier mein neuestes Projekt: Ein Oszilloskop mit dem ATMega.

Hier mal die Momentanen Daten:

GLCD: 240*128
µC: ATMega16 @ 16MHz ext. Quarz -> BASCOM
Und eben ein bissl Hühnerfutter...

Kurze Funktionsbeschreibung:

ADC im Single-Modus, direkt mit den Registern gearbeitet, und den Komparator als Trigger...

Die Timebase fehlt noch die werde ich mit einem Timer machen, steht aber noch aus.

Bisher hab ich erstmal eni großes Problem, vielleicht könnt ihr mir da ja helfen. Der Trigger (-> Komparator) löst im Prinzip richtig aus. Nur hin und wieder, da scheint er die falsche Flanke zu erwischen, und das stört natürlich enorm. Weiß einer, woran das liegen kann?

Angehängt mal ein Paar Fotos; eine Sinuskurve unbekannter Frequenz und ein Dreieck, sowie der ganze Kram auf einem Breadboard (rechts Eingangssektion - biss Hühnerfutter, Eingang mit Spannungsteiler auf VCC/2 und dann mit nem C den Eingang.
Links das Poti, Referenzspannung für den Komparator, um den Trigger einzustellen.. Oben sieht man die ISP und das was nach unten auf dem Board weggeht, das sind die Display-Strippen...

Gruß Rainer
 

Anhänge

  • P8091146.jpg
    P8091146.jpg
    31,7 KB · Aufrufe: 217
  • P8091147.jpg
    P8091147.jpg
    31,2 KB · Aufrufe: 175
  • P8091148.jpg
    P8091148.jpg
    52,3 KB · Aufrufe: 171
Hallo Rainer,

die Oszillogramme sehen echt gut aus.

Es könnte sein dass du zwei oder mehrere Triggerereignisse direkt hintereinander bekommst, wenn die Referenzspannung und/oder das zu messende Signal verbrummt ist.

Abhilfe wäre zum Beispiel, eine Hysterese einzubauen, allerdings musst du hier aufpassen, dass du das zu messende Signal nicht verfälscht.

Ich würde wahrscheinlich den ADC im free running mode laufen lassen und nach erfolgter Wandlung (ADC Interrupt) dann entscheiden, ob ich die aktuelle Wandlung als Triggerpunkt verwende.

Grüße,
Dirk
 
Hallo Rainer,

die Oszillogramme sehen echt gut aus.

Es könnte sein dass du zwei oder mehrere Triggerereignisse direkt hintereinander bekommst, wenn die Referenzspannung und/oder das zu messende Signal verbrummt ist.

Abhilfe wäre zum Beispiel, eine Hysterese einzubauen, allerdings musst du hier aufpassen, dass du das zu messende Signal nicht verfälscht.

Nun, das Signal kommt von einem 2206 - weiß nicht, wie gut der "entbrummt" ist, aber im Prinzip sollte es ein sauberes Signal sein, hab leider keinen anderen Oscar zum nachsehen...

Ich würde wahrscheinlich den ADC im free running mode laufen lassen und nach erfolgter Wandlung (ADC Interrupt) dann entscheiden, ob ich die aktuelle Wandlung als Triggerpunkt verwende.

Grüße,
Dirk

Darüber habe ich auch nachgedacht. Aber: Ich muss ja immer nur einen Kanal messen, und während der ADC die ADC-Routine ausführt wo ich den ADMUX wieder auf den Kanal setzen könnte misst er Bereits wieder, so dass ich nachher ein Kanal-Mischmasch hätte - und das kann ich da aber brauchen.

Deswegen ja die Idee das mit dem Komparator zu machen.

Wenn ich das falsch sehe, dann würde ich dich bitten, das noch einmal näher zu erläutern...

Gruß Rainer
 
Darüber habe ich auch nachgedacht. Aber: Ich muss ja immer nur einen Kanal messen, und während der ADC die ADC-Routine ausführt wo ich den ADMUX wieder auf den Kanal setzen könnte misst er Bereits wieder, so dass ich nachher ein Kanal-Mischmasch hätte - und das kann ich da aber brauchen.

ADMUX ist single buffered. Während einer AD-Wandlung kannst du ADMUX ändern, der AVR aktualisiert den im temporären Puffer gespeicherten Wert, kurz bevor die Wandlung beendet ist.
Aufpassen musst du hier nur, wenn du zwischen Differenzkanälen umschaltest.

Man kann den ADC ja durch mehrere Quellen Triggern...
  • Analog Comparator
  • ExternInterruptRequest0
  • Timer0CompareMatch
  • Timer0Overflow
  • Timer1CompareMatchB
  • Timer1Overflow
  • Timer1CaptureEvent
oder einfach sich selbst Triggern lassen, das ist dann der free running mode.

Eine Lösungsmöglichkeit wäre wahrscheinlich:
  1. Trigger-Event durch AnalogComparator (nicht den ADC triggern, sondern den AnalogComparatorInterrupt verwenden, um AnalogComparator Interrupt wieder zu deaktivieren und dort den ADC zu starten mit ADC-Triggerung zum Beispiel auf Timer0CompareMatch, Timer0 hier auch starten. Man erhält somit eine konstante Zeitbasis)
  2. Es erfolgen nun nach dem AnalogComparatorInterrupt n Wandlungen mit konstanten Zeitabständen (n ist zum Beispiel die Breite von deinem Display in Pixel). n kann man im ADC Interrupt mitzählen, wenn n Wandlungen vorbei sind, stoppt man weitere ADC-Wandlungen und aktiviert wieder den Interrupt vom Analog-Comparator, somit ist man wieder bereit zur nächsten Triggerung (hier nicht vergessen, zuvor das Interrupt-Anforderungsflag vom AnalogCompInt zu löschen, es könnte sein, dass zwischendurch wieder ein AnalogComparatorEvent aufgetreten ist).
Man könnte anstelle durch Timer0CompareMatch Triggerung auch im free running mode laufen lassen (selbsttriggernd), die Zeitbasis ist jedoch nicht so einfach zu ändern (nur durch prescaler Einstellung des ADC). Den Timer0CompareMatch kann man aber schön einstellen, noch flexibler ist man mit dem Timer1, da 16bit, aber das braucht man wahrscheinlich nicht.

Grüße,
Dirk
 
Ich glaube, ich lasse euch jetzt erstmal am Code teilhaben.

Ich denke, bevor ich mich dann an die Timebase gebe, müsste ich erstmal klären, warum der Komparator manchmal die falsche Flanke trifft.

Wär schön, wenn ihr mal durch den Code schauen könntet, für Verbesserungen und fehlerkorrekturen wäre ich sehr dankbar...

Code:
$regfile = "m16def.dat"
$crystal = 16000000                                         'ext. Quarz
$hwstack = 64
$swstack = 64
$framesize = 128

Config Graphlcd = 240 * 128 , Dataport = Portd , Controlport = Portc , Ce = 2 , Cd = 3 , Wr = 0 , Rd = 1 , Reset = 4 , Fs = 5 , Mode = 6
Cursor On Blink
Cls

'Config Timer1 = Timer , Prescale = 1 , Compare A = Disconnect
'Compare1a = 10
'On Compare1a Messen

Config Adc = Single , Prescaler = Auto , Reference = Avcc
On Adc On_adc

Config Aci = On , Compare = Off , Trigger = Falling
On Aci On_aci

Declare Sub View_grid

Dim Zaehler As Byte
Dim Temp As Byte
Dim Temp2 As Byte
Dim X1 As Byte
Dim X2 As Byte
Dim Daten1 As Word
Dim Daten2 As Word
Dim Datenold1 As Word
Dim Datenold2 As Word
Dim Messen_an As Bit
Dim Startbereit As Bit


Dim Adcvalue_0 As Word

Dim Adcvalue_0_high As Byte At Adcvalue_0 + 1 Overlay
Dim Adcvalue_0_low As Byte At Adcvalue_0 Overlay

Dim Daten(140) As Word
Dim Datenold(140) As Word

Enable Aci
Enable Adc
Start Ac

Enable Interrupts
'Enable Compare1a

'Erste Messung starten
Adcsra.adsc = 1



Do

Locate 1 , 29
Lcd Messen_an
Locate 2 , 29
Lcd Startbereit




If Messen_an = 0 Then
  Call View_grid
  For Temp = 1 To 139
    Temp2 = Temp + 1
    Daten1 = Daten(temp) / 8
    Daten1 = 127 - Daten1
    Daten2 = Daten(temp2) / 8
    Daten2 = 127 - Daten2
    Datenold1 = Datenold(temp) / 8
    Datenold1 = 127 - Datenold1
    Datenold2 = Datenold(temp2) / 8
    Datenold2 = 127 - Datenold2
    X1 = Temp + 10
    X2 = Temp2 + 10
    Line(x1 , Datenold1) -(x2 , Datenold2) , 0
    Line(x1 , Daten1) -(x2 , Daten2) , 1
    Datenold(temp) = Daten(temp)
  Next
  Start Ac
  Startbereit = 1
End If

Loop


End

Sub View_grid
   Line(80 , 10) -(80 , 118) , 1                            'Y-Achse
   Line(10 , 62) -(150 , 62) , 1                            'X-Achse

   'Achseneinteilung
   'X-Achse
   Line(20 , 61) -(20 , 63) , 1
   Line(40 , 61) -(40 , 63) , 1
   Line(60 , 61) -(60 , 63) , 1
   Line(100 , 61) -(100 , 63) , 1
   Line(120 , 61) -(120 , 63) , 1
   Line(140 , 61) -(140 , 63) , 1
   'y-Achse
   Line(79 , 42) -(81 , 42) , 1
   Line(79 , 22) -(81 , 22) , 1
   Line(79 , 82) -(81 , 82) , 1
   Line(79 , 102) -(81 , 102) , 1

   'Gitternetz
   Line(19 , 22) -(21 , 22) , 1
   Line(20 , 21) -(20 , 23) , 1
   Line(39 , 22) -(41 , 22) , 1
   Line(40 , 21) -(40 , 23) , 1
   Line(59 , 22) -(61 , 22) , 1
   Line(60 , 21) -(60 , 23) , 1
   Line(99 , 22) -(101 , 22) , 1
   Line(100 , 21) -(100 , 23) , 1
   Line(119 , 22) -(121 , 22) , 1
   Line(120 , 21) -(120 , 23) , 1
   Line(139 , 22) -(141 , 22) , 1
   Line(140 , 21) -(140 , 23) , 1

   Line(19 , 42) -(21 , 42) , 1
   Line(20 , 41) -(20 , 43) , 1
   Line(39 , 42) -(41 , 42) , 1
   Line(40 , 41) -(40 , 43) , 1
   Line(59 , 42) -(61 , 42) , 1
   Line(60 , 41) -(60 , 43) , 1
   Line(99 , 42) -(101 , 42) , 1
   Line(100 , 41) -(100 , 43) , 1
   Line(119 , 42) -(121 , 42) , 1
   Line(120 , 41) -(120 , 43) , 1
   Line(139 , 42) -(141 , 42) , 1
   Line(140 , 41) -(140 , 43) , 1

   Line(19 , 82) -(21 , 82) , 1
   Line(20 , 81) -(20 , 83) , 1
   Line(39 , 82) -(41 , 82) , 1
   Line(40 , 81) -(40 , 83) , 1
   Line(59 , 82) -(61 , 82) , 1
   Line(60 , 81) -(60 , 83) , 1
   Line(99 , 82) -(101 , 82) , 1
   Line(100 , 81) -(100 , 83) , 1
   Line(119 , 82) -(121 , 82) , 1
   Line(120 , 81) -(120 , 83) , 1
   Line(139 , 82) -(141 , 82) , 1
   Line(140 , 81) -(140 , 83) , 1

   Line(19 , 102) -(21 , 102) , 1
   Line(20 , 101) -(20 , 103) , 1
   Line(39 , 102) -(41 , 102) , 1
   Line(40 , 101) -(40 , 103) , 1
   Line(59 , 102) -(61 , 102) , 1
   Line(60 , 101) -(60 , 103) , 1
   Line(99 , 102) -(101 , 102) , 1
   Line(100 , 101) -(100 , 103) , 1
   Line(119 , 102) -(121 , 102) , 1
   Line(120 , 101) -(120 , 103) , 1
   Line(139 , 102) -(141 , 102) , 1
   Line(140 , 101) -(140 , 103) , 1

   'Trennlinie
   Line(160 , 0) -(160 , 128) , 1
End Sub


On_adc:
  Adcvalue_0_low = Adcl
  Adcvalue_0_high = Adch
   Admux.0 = 0
   Admux.1 = 0
   Admux.2 = 0
   Admux.3 = 0


'Return

'Messen:
 If Messen_an = 1 Then
  If Zaehler = 140 Then
    Zaehler = 1
    Messen_an = 0
    Daten(zaehler) = Adcvalue_0
   Else
    Incr Zaehler
    Daten(zaehler) = Adcvalue_0
  End If
 End If
 Adcsra.adsc = 1

Return

On_aci:

Stop Ac
  If Startbereit = 1 Then
    Startbereit = 0
    Messen_an = 1
  End If

Return

Gruß Rainer
 
Sodele,

ich werde dann mal auf eine Software-Triggerung umsteigen, es gibt offenbar keinen, der weiß, woran das Phänomen liegt...

Hat denn einer eine Idee für die Software-Triggerung? Positive Flanke feststellen und ab dafür?

Das Problem was ich im Moment so kommen sehe, das ist, dass mir mit dem Mega16 der RAM ausgeht. Wenn ich aber den Comparator nicht brauche, habe ich ja den PortB frei.
Wie der Zufall so will hab ich ein paar "M514256A-80R" rumfliegen - kann man die irgendwie dann an den Port dranbasteln als ext. Ram, die Adressleitungen evt. mit einem Schieberegister?

Gruß Rainer
 
Hallo Rainer,
Hat denn einer eine Idee für die Software-Triggerung? Positive Flanke feststellen und ab dafür?

du könntest ja permanent eine AD-Wandlung durchführen und im ADC-Interrupt das Wandlungsergebnis mit dem Ergebnis der vorherigen Wandlung vergleichen. Stellst du eine bestimmte positive oder negative (pos. oder neg. Flanke) Differenz fest, merkst du dir die nächsten n Wandlungsergebnisse. n ist dann zum Beispiel die Breite deiner Anzeige in Pixel. Wenn n Wandlungen vorbei sind, gibst du die Wandlungsergebnisse auf dem Display aus und aktivierst wieder die Triggerung.

Grüße,
Dirk
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)