Signal-Analyse mit Analog-Comparator

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • Signal-Analyse mit Analog-Comparator

      Hallo zusammen
      Ich bastel hier grad rum um komme nicht weiter.

      Was ich machen will ist folgendes.
      Per Comparator möchte prüfen, ob eine anliegende Frequenz am AIN0 (+) in einem bestimmten Frequenzbereich liegt.
      Dafür löst der AC ein Interrupt aus bei fallenden Flanken.
      Der Comparator sollte so konfiguriert sein, dass beim Auslösen des Interrupts der Timerwert von Timer1 ins Capture-Register kopiert wird.

      Die ISR wird sauber ausgelöst und das schön im Takt der Eingangsfrequenz. Alles korrekt.
      Aber wenn ich in der ISR den Capture-Wert auswerte, kommt was falsches raus.

      Wenn die Frequenz stimmt, sollte die Grüne LED an gehen, stimmt sie nicht, die Rote.

      Hier mal das Programm

      BASCOM Source Code

      1. $Regfile = "m168def.dat"
      2. $HWStack = 40
      3. $SWStack = 40
      4. $Framesize = 40
      5. $Crystal = 8000000
      6. Dim ISRTimeOld as Word ' letzter Timer1-Stand
      7. Dim ISRTimeNew as Word ' aktueller Timer1-Stand
      8. Dim ISRTimeDelta as Word ' Differenz der TimerNew-TimerOld
      9. Dim ISRCountOK as Byte ' Zähler Flanken-Anstand korrekt
      10. Dim ISRCountFail as Byte ' Zähler Flanken-Abstand nicht korrekt
      11. Dim GrenzeLow as Word
      12. Dim GrenzeHigh as Word
      13. GrenzeLow = 625 ' 1 / (625 * 8µs) = 200Hz
      14. GrenzeHigh = 125 ' 1 / (125 * 8µs) = 1kHz
      15. PinTrigger Alias PortC.5 ' Test-Pin
      16. Config PinTrigger = Output
      17. LED_OK Alias PortC.4
      18. LED_Fail Alias PortC.3
      19. Config LED_OK = Output
      20. Config LED_Fail = Output
      21. Declare Sub ISR_Flanke()
      22. Declare Sub ISR_Timer1Overflow()
      23. Config ACI = On , Compare = On , Trigger = falling
      24. ' Erzeugt FastPWM mit ca. 488kHz
      25. Config Timer1 = Timer , Prescale = 64 , PWM = 8 , Compare_A = Clear , Compare_B = CLEAR ' Periodendauer 8µs
      26. Config PortB.1 = Output
      27. Config PortB.2 = Output
      28. Compare1A = 20
      29. Compare1B = 20
      30. On ACI ISR_Flanke
      31. Enable ACI
      32. On OVF1 ISR_Timer1Overflow
      33. 'Enable OVF1
      34. Enable Interrupts
      35. Do
      36. NOP
      37. Loop
      38. Sub ISR_Flanke()
      39. ISRTimeNew = Capture1 ' Zeitstempel holen
      40. ISRTimeDelta = ISRTimeNew - ISRTimeOld ' Differenz berechnen
      41. ISRTimeOld = ISRTimeNew ' Aktuelle Stand sichern
      42. ' Bewerten, ob Flankenabstand im Range ist
      43. ' Select Case ISRTimeDelta
      44. ' Case GrenzeHigh to GrenzeLow ' 200Hz bis 1kHz
      45. ' 'If ISRCountOK < 255 then Incr ISRCountOK
      46. ' 'If ISRCountFail > 0 then Decr ISRCountFail
      47. ' Set LED_OK
      48. ' Reset LED_Fail
      49. ' Case Else ' außerhalb gültigem Bereich
      50. ' 'If ISRCountOK > 0 then Decr ISRCountOK
      51. ' 'If ISRCountFail < 255 then Incr ISRCountFail
      52. ' Reset LED_OK
      53. ' Set LED_Fail
      54. ' End Select
      55. If ISRTimeDelta > GrenzeLow and ISRTimeDelta < GrenzeHigh then
      56. Set LED_OK ' Grüne LED an
      57. Reset LED_Fail
      58. Else
      59. Reset LED_OK ' Rote LED an
      60. Set LED_Fail
      61. End If
      62. Set pinTrigger ' Test-Pin (Kontrolle ISR-Aufruf)
      63. Waitus 5
      64. Reset PinTrigger
      65. End Sub
      66. Sub ISR_Timer1Overflow()
      67. ' Pegel der Bewertung als PWM ausgeben:
      68. 'Compare1A = ISRCountOK
      69. 'Compare1B = ISRCountFail
      70. 'Compare1B = ISRCountFail
      71. End Sub
      Display All
      Das Programm zeigt beharrlich nur rot an.
      Das könnte man auch ohne Programm hinbekommen 8)

      Aber was stimmt am Programm nicht?

      Wird hier der Timer1-Wert nicht im Capture-Register gespeichert?
      Kaum macht man es richtig - und schon geht's!
    • Du rechnest mit word deine differenzen aus. Dein capture bewegt sich aber innerhalb eines bytes (pwm=8). Du musst die oberen bits bei der differenz ausblenden, also vom Ergebnis der Differenberechnung auch nur 8 bit nehmen.

      Überhaupt passen deine Grenzwerte mit 600trallala nicht in ein byte.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------

      The post was edited 1 time, last by tschoeatsch ().

    • Du meinst weil bei Config Timer1=Timer,PWM=8
      angegeben ist?

      Das PWM=8 habe ich rausgenommen. Der Timer soll durchlaufen und dann wieder bei 0 anfangen.

      Ich habs jetzt so im Programm:

      Source Code

      1. Config Timer1 = Timer , Prescale = 64 , Compare_A = Clear , Compare_B = Clear ' Periodendauer Takt 8µs
      Aber es gibt auch nicht.

      LED immer rot.
      Kaum macht man es richtig - und schon geht's!
    • Hast du das gemacht?
      The main trigger source for the Input Capture unit is the Input Capture pin (ICP1). Timer/Counter1 can alternatively use the Analog Comparator output as trigger source for the Input Capture unit. The Analog Comparator is selected as trigger source by setting the Analog Comparator Input Capture (ACIC) bit in the Analog Comparator Control and Status Register (ACSR).
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • If ISRTimeDelta > GrenzeLow and ISRTimeDelta < GrenzeHigh then
      es muss heißen
      If ISRTimeDelta < GrenzeLow and ISRTimeDelta > GrenzeHigh then


      mit case wäre das wahrscheinlich nicht passiert. ^^
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Du meinst so solls heißen:

      If ISRTimeDelta < GrenzeLow and ISRTimeDelta > GrenzeHigh then

      Wenn ich werte einsetze:

      If ISRTimeDelta < 625 and ISRTimeDelta > 125 then

      Die Gesamtbedingung ist war, wenn Delta Werte von 126 bis 624 annimmt.

      Das ist nicht die Ursache.

      Was sich da nicht verträgt ist, wenn ich Timer1 als PWM (8-Bit) nehme und Capture verwenden möchte.
      Ich habs auch mit Byte-Variablen probiert.

      Mache ich keine PWM:
      Config Timer1 = Timer , Prescale = 64

      Dann zeigen die LED's korrekt an.

      Ach ja, der zählt ja erst vorwärts, dass rückwärts.
      Ich probier was.
      Kaum macht man es richtig - und schon geht's!
    • Mitch64 wrote:

      If ISRTimeDelta < 625 and ISRTimeDelta > 125 then

      Die Gesamtbedingung ist war, wenn Delta Werte von 126 bis 624 annimmt.
      eben, jetzt wäre 500 ein Wert für grün
      du hattest
      If ISRTimeDelta > 625 and ISRTimeDelta < 125 then
      500 ist nicht größer 625 und gleichzeitig kleiner 125
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Stimm!
      Hast recht! Jetzt check ich das auch.

      So wegen meinem anfänglichen Problem.

      Ich habe versucht, mit einem einzigen Timer (Timer1) eine 8-Bit PWM zu machen und gleichzeitig Zeiten zu messen.
      Dann nicht die falschen Variablen (Word anstatt Byte).

      Aber es verträgt sich nicht PWM und Capture1.
      Ich habs auch probiert den Timerwert direkt zu lesen (als ich 8-Bit PWM verwendet habe mit Clear Timer=1), geht auch nicht.

      keine Ahnung warum. Ich versteh's nicht. (Vielleicht wegen Abfrage < 625?

      Wenn der Timer als Timer konfiguriert ist, dann funktioniert das mit Captire1 und Timer1 auslesen gut, und das mit den selben Routinen.
      Kaum macht man es richtig - und schon geht's!
    • Hallo Mitch,
      ohne das jetzt genauer überprüft zu haben, würde ich sagen, dass der Timer im Input Capture Mode laufen muss. Also sowas:
      Config Timer1 = Timer , Prescale = 1 , Capture Edge = Rising , Noise Cancel = 1
      Ob tatsächlich PWM gleichzeitig geht, weiß ich jetzt nicht, könnte aber sein.
    • Der Timer tut ja.
      Die LED's zeigen richtig an.
      Das Capture wird ja mit dem Config ACI=... konfiguriert.

      Das ist dann zusammen so konfiguriert:
      Config ACI = On , Compare = On , Trigger = falling
      Config Timer1 = Timer , Prescale = 64

      Aber sobald ich die PWM versuche dazuzunehmen gehts nimmer:
      Config Timer1 = Timer , PWM = 8 , Prescale = 64 , Compare_A = Clear , Compare_B = Clear , Clear Timer = 1

      Auch nicht, wenn ich die Variablen ISRTime-New/Old/Delta in Bytes dimensioniere.


      Guenther wrote:

      Capture Edge = Rising
      Das bezieht sich auf den Timer, wenn der den Clock vom Prescaler bekommt.

      In meinem Fall wird aber Capture getriggert durch das gesetzte Bit ACSR.ACIC.
      Kaum macht man es richtig - und schon geht's!
    • So jetzt geht es mit LED und PWM an einem Timer.
      Man war das jetzt ne Geburt. a_28_2c02f089

      BASCOM Source Code

      1. $Regfile = "m168def.dat"
      2. $HWStack = 40
      3. $SWStack = 40
      4. $Framesize = 40
      5. $Crystal = 8000000
      6. ' ----------------------------------------------
      7. ' Variablen
      8. Dim ISRTimeOld as Byte ' letzter Timer1-Stand
      9. Dim ISRTimeNew as Byte ' aktueller Timer1-Stand
      10. Dim ISRTimeDelta as Byte ' Differenz der TimerNew-TimerOld
      11. Dim ISRCountOK as Byte ' Zähler Flanken-Anstand korrekt
      12. Dim ISRCountFail as Byte ' Zähler Flanken-Abstand nicht korrekt
      13. Dim GrenzeLow as Byte ' Definiert Zählerwert für obere Grenzfrequenz
      14. Dim GrenzeHigh as Byte ' Definiert Zählerwert für untere Grenzfrequenz
      15. ' ----------------------------------------------
      16. ' IO-Definition
      17. PinTrigger Alias PortC.5 ' Test-Pin (Kontrolle ISR)
      18. LED_OK Alias PortC.4 ' Indikator Frequenz im Bereich
      19. LED_Fail Alias PortC.3 ' Indikator Frequenz außerhalb des Bereichs
      20. ' ----------------------------------------------
      21. ' Deklarationen
      22. Declare Sub ISR_Flanke()
      23. Declare Sub ISR_Timer1Overflow()
      24. ' ----------------------------------------------
      25. Config ACI = On , Compare = On , Trigger = falling
      26. On ACI ISR_Flanke
      27. Enable ACI
      28. ' ----------------------------------------------
      29. ' Initialisierung
      30. ' ----------------------------------------------
      31. ' Grenzfrequenzen festlegen in Takten zu je 8µs
      32. GrenzeHigh = 250 ' 250 Takte = 500 Hz
      33. GrenzeLow = 125 ' 125 Takte = 1 kHz
      34. Config LED_OK = Output
      35. Config LED_Fail = Output
      36. Config PinTrigger = Output
      37. ' ----------------------------------------------
      38. Config Timer1 = Timer , PWM = 8 , Prescale = 64 , Compare_A_PWM = Clear_UP , Compare_B_PWM = Clear_Down , Clear Timer = 1 ' Periodendauer Takt 8µs
      39. 'Config Timer1 = Timer , Prescale = 64
      40. Config PortB.1 = Output ' OC1A-Pin
      41. Config PortB.2 = Output ' OC1B-Pin
      42. Compare1A = 0
      43. Compare1B = 0
      44. ' ----------------------------------------------
      45. Enable Interrupts
      46. ' ----------------------------------------------
      47. ' Hauptschleife
      48. ' ----------------------------------------------
      49. Do
      50. NOP
      51. Loop
      52. ' ----------------------------------------------
      53. ' ISR-Routinen
      54. ' ----------------------------------------------
      55. ' ----------------------------------------------
      56. ' ISR wird durch Flanke an Analog-Comparator ausgelöst
      57. Sub ISR_Flanke()
      58. ISRTimeNew = Capture1 ' Zeitstempel holen
      59. ISRTimeDelta = ISRTimeNew - ISRTimeOld ' Differenz berechnen
      60. ISRTimeOld = ISRTimeNew ' Aktuelle Stand sichern
      61. ' Bewerten, ob Flankenabstand im Range ist
      62. Select Case ISRTimeDelta
      63. Case GrenzeLow to GrenzeHigh ' 125 to 250 (500Hz bis 1000Hz)
      64. If ISRCountOK < 255 then Incr ISRCountOK
      65. If ISRCountFail > 0 then Decr ISRCountFail
      66. Set LED_OK
      67. Reset LED_Fail
      68. Case Else ' außerhalb gültigem Bereich
      69. If ISRCountOK > 0 then Decr ISRCountOK
      70. If ISRCountFail < 255 then Incr ISRCountFail
      71. Reset LED_OK
      72. Set LED_Fail
      73. End Select
      74. Compare1A = ISRCountOK
      75. Compare1B = ISRCountFail
      76. 'Set pinTrigger ' Test-Pin (Kontrolle ISR-Aufruf)
      77. 'Waitus 5
      78. 'Reset PinTrigger
      79. End Sub
      Display All
      Jetzt hab ich aber noch ein Problem festgestellt.
      Die PWM an OC1A soll den Wert für ISRCountOK repräsentieren,
      die PWM an OC1B den Wert ISRCountFail.
      Kaum macht man es richtig - und schon geht's!
    • Eher ein Tondetektor.

      Ein Ton in einem verrauschtem Signal erkennen.
      Die PWM ist nur ein Kontrollwerkzeug um zu schauen, bei welchen Rauschverhältnis zum Signal
      wieviel korrekte und wieviel falsche Flanken ermittelt werden.

      Daraus kann man dann vielleicht eine Toleranzschwelle ableiten, wann überhaupt versucht wird das Signal zu erkennen. Oder wieviel Falsche Flanken in einem korrekten Ton zulässig sind.

      Ist ein Versuch.
      Kaum macht man es richtig - und schon geht's!