Tonerkennung im Audiosignal

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Mitch64 schrieb:

      Ich kann den Code nicht testen, muss erst mal ein Signal zum dekodieren haben.
      Aber vielleicht kannst du mir sagen, ob du es etwa so gemacht hast.
      Hallo Mitch,

      Aus dem aktuellen und dem letzten Timerwert das Zeitintervall zu berechnen, und aus dem aktuellen und dem letzten Zeitintervall deren Differenz zu berechnen, habe ich genau so gemacht.

      Allerdings mache ich das bei jeder Flanke, und nicht nur dann, wenn das letzte gemessene Intervall im Bereich von 1000 - 2500 µS liegt. D.h. die Abfrage Select Case TimerDelta würde ich weglassen.

      Warum?

      Stell Dir mal vor, nach dem Ende des Nutzsignal kommen erstmal Rausch-Wellen, die so hoch- oder niederfrequent sind, dass die Impulslängen außerhalb dieses Bereiches liegen - dann findet gar keine Auswertung statt, und der Controller merkt nicht, dass der Ton schon längst vorbei ist.

      Da Rauschen (fast) jede Impulslänge produzieren kann, werden in meiner Anwendung alle Impulse ausgewertet, um nach dem Ende des Signals dieses Ende möglichst schnell zu erkennen.
    • Einzeller schrieb:

      Allerdings mache ich das bei jeder Flanke, und nicht nur dann, wenn das letzte gemessene Intervall im Bereich von 1000 - 2500 µS liegt. D.h. die Abfrage Select Case TimerDelta würde ich weglassen.
      Nochmal zurück.
      Ich habe das TimerDelta nicht weggelassen, weil ich ja bewerten muss, ob der Puls im Bereich 400Hz bis 1kHz liegt.
      Das darf ich nicht weg lassen.

      Der code ist actuell so:

      BASCOM-Quellcode

      1. ' ----------------------------------------------
      2. ' Input-Capture-Interrupt,
      3. ' wird vom Analog-Comparator ausgelöst.
      4. ' ----------------------------------------------
      5. ISR_ICP1:
      6. TimerNew = Timer1
      7. TimerDelta = TimerNew - TimerOld ' Timerdifferenz zur letzten Flanke berechnen
      8. TimerTemp = TimerDelta - TimerDeltaOld ' Differenz zwichen Letzter und aktueller Zeitmesung
      9. Select Case TimerDelta
      10. Case 1000 to 2500 ' 400 - 1000Hz Zählerwert = f(timer) / f(ton)
      11. ' Flanken innerhalb des erlaubten Bereichs
      12. Select Case TimerTemp
      13. Case -30 to 30 ' Zulässige Abweichung
      14. Incr CountFlankeOK
      15. If CountFlankeOK > CountFlankeMax then
      16. CountFlankeOk = CountFlankeMax
      17. CountFlankeFail = 0
      18. Set SFlags.FLAG_TON
      19. End If
      20. Case Else
      21. Incr CountFlankeFail
      22. If CountFlankeFail > CountFlankeMax then
      23. CountFlankeFail = CountFlankeMax
      24. CountFlankeOK = 0
      25. Reset SFlags.FLAG_TON
      26. End If
      27. End Select
      28. End Select
      29. TimerOld = TimerNew
      30. TimerDeltaOld = TimerDelta
      31. Return
      Alles anzeigen
      Die Bewertung (TimerDelta) vereinfacht per Select Case-Anweisung die Auswertung für den Bereich.
      Ich muss ja Zählen, ob ein Puls OK war oder nicht.

      Würde ich das weglassen, habe ich keine Überprüfung bezüglich der Ton-Frequenz.
    • Einzeller schrieb:

      Warum muss Du das denn bewerten?
      Das ist die Aufgabenstellung. Ich erwarte Morse-Töne zwischen 400Hz und 1kHz. Irgendwo muss man das begrenzen.

      Mit 50Hz-Ton funkt ja keiner und viel oberhalb von 1kHz auch nicht.

      Die Zeitmessung und die Zeitdifferenzmessung zur letzten Zeitmessung mache ich ja bei jeder Flanke.
      Die Werte werden ja auch gesichert für die nächste Flanke.

      Aber wenn da ein Ton kommt von z.B. 200 Hz, dann soll mein Ding nicht drauf reagieren. Das ist der ganze Hintergrund.

      Ich brauche erst mal ein Signal, dann kann ich da mal messen und schauen.
    • Pluto25 schrieb:

      Wird die Erkennung denn nicht erheblich besser wenn er weiß das die nächsten 1,15 ms (400 Hz) kein High mehr gültig ist bzw schon nach 0,5 ms eins erwachtet werden kann (1khz)
      Ich muss erst mal Ton erkennen. Wenn ich 2 Möglichkeiten habe den Ton zu erkennen, muss man beide ausprobieren.
      Ich Kopf kann ich das nicht simulieren.

      Ich brauche erst ein Signal.

      Vielleicht habe ich ein Denkfehler im Code, das merke ich spätestens, wenn der Ton nicht erkannt wird.

      Solange kann ich nicht sagen was besser ist.
    • Für die interessierten unter euch.

      Ich habe kein Mittelwellen- oder Langwellen-Radio. Daher benutze ich einen WebSDR-Empfänger.
      Könnt ihr selber mal ausprobieren:

      dk0te.dhbw-ravensburg.de:8901/

      Das ist so einer. Lickt da mal unten links auf 80m Band und rechts davon auf CW-narrow.

      In dem Bad, welches nach oben läuft achtet ihr mal auf einen dünnen Strich mit Unterbrechungen. Das sind die Morse-Signale.
      Da den Cursor hinsetzen.

      Das Signal muss ich erst mal vom PC auf die Werkbank bekommen.

      Wenn man nicht die richtigen Stecker hat wirds blöd.
    • Mitch64 schrieb:

      Das ist die Aufgabenstellung. Ich erwarte Morse-Töne zwischen 400Hz und 1kHz. Irgendwo muss man das begrenzen.

      Mit 50Hz-Ton funkt ja keiner und viel oberhalb von 1kHz auch nicht.
      In meiner Militärzeit war ich Funker (Tastfunker). Das nennt man Telegrafie (CW), im Amateufunk A1A,(Maschinell A1B). "Gemorst" wird mittels Tastung des HF-Trägers(also tonlos). Im Empfänger entsteht der Morseton durch leichte Verstimmung, d.h. man stimmt den Empfänger leicht neben die Sendefrequenz. Es entsteht dadurch ein Überlagerungston. DieTonhöhe stellt man damit am Empfänger also selbst ein. Die CW-Bereiche erstrecken sich im KW-Bereich von 1.8MHz bis 28MHz in mehreren Bereichen. Aber Mittelwelle? Da befindet sich kein Amateurband.
      Korrektur: Gibts jetzt doch: 472...479kHz und Langwelle 135,7...137.8kHz. (aber nur mit 1W ERP)
      DI2AG hat versuchsgenehmigungen für 440kHz und 505,1kHz erhalten.

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von oscar ()

    • Oscar, das ist eine coole Info.

      Wusste nicht, dass der Ton durch Verstimmung zustande kommt. Demnach kann ich eigentlich auf die Frequenz-Selektion verzichten.
      Das mit Mittelwelle war mal so daher geredet. Bei den alten Radions damals mit Lang und Kurzwelle konnte man das auch empfangen.

      Die Aufgabenstellung habe ich mir selber gegeben. Irgendwelche Ziele muss man ja setzen.

      Übrigens wird im 80m-Band mächtig gemorst.

      Das nennt man bei den Amateurfunkern aber auch CW. 1A1 oder ..B hab ich auch schon mal bei maschinellen Übertragungen gehört.
      Aber ich glaube die machen es dann auch teilweise mit 2 Tönen (FSK).

      Ich stecke da nicht so tief drin.
    • Mitch64 schrieb:

      Übrigens wird im 80m-Band mächtig gemorst.
      Ja Mitch, dem Vernehmen nach ist CW wieder groß im Kommen. Das fordert den sportlichen Ehrgeiz heraus und es sind damit große Entfernungen zu überbrücken. Es stellt sozusagen große Anforderungen an die damit befassten Enthusiasten und das reizt halt daran.
      Übrigens, trotz der vielen Jahre die verflossen sind, seit ich aktiver Funker war und seitdem nichts mehr damit gemacht habe, könnte ich heute noch etwas telegrafieren, viel langsamer zwar aber man verlernt es nie ganz(ist wie bei einer Fremdsprache), das befindet sich sozusagen im Hirn-EEPROM: :D
      Damals war Tempo 100...120 im Hören (Zeichen pro Minute) normal, geben konnte ich noch schneller.Das ist aber Geschichte.
      Wer sich dafür interessiert:darc.de/home/
    • Erste Erfolge:
      Morse-Signal-2.jpg

      Das gelbe Signal ist das Audiosignal. Das scheint ein Testsender zu sein (80m Band CW).
      Das Blaue Signal spuckt mein Dekoder aus. Sieht ja schon mal vielversprechend aus.

      Die ISR_ICP1 habe ich etwas abgeändert.

      BASCOM-Quellcode

      1. ISR_ICP1:
      2. TimerNew = Timer1
      3. TimerDelta = TimerNew - TimerOld ' Timerdifferenz zur letzten Flanke berechnen
      4. TimerTemp = TimerDelta - TimerDeltaOld ' Differenz zwichen Letzter und aktueller Zeitmesung
      5. Select Case TimerTemp
      6. Case -30 to 30 ' Zulässige Abweichung vom Ton
      7. Incr CountFlankeOK
      8. If CountFlankeOK > CountFlankeMax then
      9. CountFlankeOk = CountFlankeMax
      10. CountFlankeFail = 0
      11. Set SFlags.FLAG_TON
      12. End If
      13. Case Else
      14. Incr CountFlankeFail
      15. If CountFlankeFail > CountFlankeMax then
      16. CountFlankeFail = CountFlankeMax
      17. CountFlankeOK = 0
      18. Reset SFlags.FLAG_TON
      19. End If
      20. End Select
      21. TimerOld = TimerNew
      22. TimerDeltaOld = TimerDelta
      23. Return
      Alles anzeigen
    • Hey Mitch,

      gratuliere - das Oszillogramm vom Ton- und Digitalsignal sieht ziemlich perfekt aus!
      Und wie Oscar schon schrieb: Die Tonhöhe kannst Du beliebig variieren, wenn Du mit der Empfängerfrequenz in feinen Schritten (10Hz) hin- und herspielst.

      Meine Loop-Antenne auf dem Dach geht zwar nicht bis zum 80-Meter-Band runter, aber ab 40 Meter aufwärts deckt sie alles ab, und mein kleiner Eigenbau-Transceiver (Winterprojekt 2011/12) auch. Wenn der eigentliche CW-Zeichendekoder also irgendwann mal fertig ist und "Testsignale" brauchst, um ihn Decoder auf den Prüfstand zu stellen: Kein Problem!

      Gruß,

      Daniel
    • Einzeller schrieb:

      Wenn der eigentliche CW-Zeichendekoder also irgendwann mal fertig ist und "Testsignale" brauchst, um ihn Decoder auf den Prüfstand zu stellen: Kein Problem!
      Danke fürs Angebot.
      Aber mit den Morse-Tonen gibt's noch Probleme.

      Komischerweise, wenn Ton erkannt werden soll, sollte ein High kommen. Das Signal scheint aber invertiert zu sein.
      Die Flanken bei Config Timer und Config ACI haben keinen Einfluss darauf.

      Ich komme aber im Moment nicht dahinter, wo das Problem liegt.

      Ich poste hier mal den Code. Vielleicht fällt jemanden was auf.

      BASCOM-Quellcode

      1. ' Morse-Decoder
      2. ' Anforderungen
      3. ' - Encoder mit Mega8 und 8MHz Quarz-Takt
      4. ' - Erkennung des Morsetons
      5. ' - Automatische Ermittlung/Anpassung der Symboldauer während dem Empfang
      6. ' - Dekodieren des Morsesignals in Plaintext
      7. ' - Ausgabe des Plaintext via Hardware-UART mit 9600 Baud
      8. ' Weitere techn. Details
      9. ' - Audio-Eingang am Analog-Comperator
      10. ' - LED-Anzeige, die Ton-Erkennung anzeigt
      11. $Regfile = "m8def.dat"
      12. $HWStack = 32
      13. $SWStack = 48
      14. $Framesize = 48
      15. $Crystal = 8000000 ' Quarz
      16. $Baud = 9600
      17. 'SignalInput Alias PinD.6 ' Eingang Morse-Signal (Audio)
      18. LED_Ton Alias PortC.5
      19. Config LED_Ton = Output
      20. Dim Dauer_Symbol as Byte
      21. Dim Dauer_Punkt as Byte
      22. Dim Dauer_Strich as Byte
      23. Dim Dauer_Pause as Byte
      24. Dim TStart as Word
      25. Dim TStop as Word
      26. Dim TWert as Word
      27. Const CountFlankeMax = 10 ' Anzahl Flanken als Triggerschwelle Tonerkennung
      28. Const PauseTimeout = 500 ' [ms] Pause Morseton
      29. Const ST_IDLE = 0
      30. Const ST_PULSE = 1
      31. Const ST_PAUSE = 2
      32. Const ST_WORD_PAUSE = 3
      33. Const ST_ERROR = 10
      34. ' interne Variablen
      35. Dim TimerOld as Word
      36. Dim TimerNew as Word
      37. Dim TimerDelta as Integer
      38. Dim TimerDeltaOld as Integer
      39. Dim TimerTemp as Integer
      40. Dim CountFlankeOK as Byte ' Zähler für Flanken im erlaubten Zeitbereich
      41. Dim CountFlankeFail as Byte ' Zähler für Flanken im falschen Bereich
      42. Dim SFlags as Byte
      43. Const FLAG_TON = 0 ' Ton erkannt
      44. Config Timer1 = Timer , Prescale = 8 , Capture_Edge = Rising , Noise Cancel = 1
      45. Config ACI = On , Compare = On , Trigger = Rising
      46. On ICP1 ISR_ICP1
      47. Enable ICP1
      48. Dauer_Symbol = 100
      49. $Include "C:\Program Files (x86)\Elektronik\BASCOM-AVR\LIB\Include\Globals.inc"
      50. $Include "C:\Program Files (x86)\Elektronik\BASCOM-AVR\LIB\Include\msTimer.inc"
      51. $Include "C:\Program Files (x86)\Elektronik\BASCOM-AVR\LIB\Include\Statemachine.inc"
      52. Enable Interrupts
      53. ' ----------------------------------------------------------------------------
      54. ' Hauptschleife
      55. ' ----------------------------------------------------------------------------
      56. Call SetMachineState(ST_IDLE) ' Startzustand festlegen
      57. Do
      58. LED_Ton = SFlags.FLAG_TON ' Anzeige des Ton-Empfangs
      59. Loop
      60. ' ----------------------------------------------
      61. ' Input-Capture-Interrupt,
      62. ' wird vom Analog-Comparator ausgelöst.
      63. ' ----------------------------------------------
      64. ISR_ICP1:
      65. TimerNew = Timer1
      66. TimerDelta = TimerNew - TimerOld ' Timerdifferenz zur letzten Flanke berechnen
      67. TimerTemp = TimerDelta - TimerDeltaOld ' Differenz zwichen Letzter und aktueller Zeitmesung
      68. Select Case TimerTemp
      69. Case -50 to 50 ' Zulässige Abweichung vom Ton
      70. Incr CountFlankeOK
      71. If CountFlankeOK > CountFlankeMax then
      72. CountFlankeOk = CountFlankeMax
      73. CountFlankeFail = 0
      74. Set SFlags.FLAG_TON
      75. End If
      76. Case Else
      77. Incr CountFlankeFail
      78. If CountFlankeFail > CountFlankeMax then
      79. CountFlankeFail = CountFlankeMax
      80. CountFlankeOK = 0
      81. Reset SFlags.FLAG_TON
      82. End If
      83. End Select
      84. TimerOld = TimerNew
      85. TimerDeltaOld = TimerDelta
      86. Return
      Alles anzeigen
      Und hier noch ein aktuelles Oszillogramm
      Morse-Signal-3.jpg

      Es sieht irgendwie aus, als ob er einen Ton erkennt, wenn das Signal schwach ist, und keinen Erkennt, wenn der Ton stark ist.
      Ich glaub ich muss mal ne Nacht drüber schlafen.
    • Während du für Gutes Wetter zu hause sorgst, habe ich noch einen Test gemacht.

      Habe den Code in der ISR jetzt wie folgt gemacht.

      BASCOM-Quellcode

      1. ISR_ICP1:
      2. TimerNew = Timer1
      3. TimerDelta = TimerNew - TimerOld ' Timerdifferenz zur letzten Flanke berechnen
      4. TimerTemp = TimerDelta - TimerDeltaOld ' Differenz zwichen Letzter und aktueller Zeitmesung
      5. TimerTemp = Abs(TimerTemp) ' Absolutwert bilden
      6. If TimerTemp < 50 then ' Aktuelle Periodendauer war mit letzter vergleichbar, also gleiche Frequenz
      7. Incr CountFlanke
      8. Else
      9. Decr CountFlanke
      10. End If
      11. If CountFlanke > 5 then
      12. CountFlanke = 5 ' Begrenung des Zählers
      13. Set SFlags.FLAG_TON ' Ton erkannt
      14. ElseIf CountFlanke < -5 then
      15. CountFlanke = -5 ' Begrenzung
      16. Reset SFlags.FLAG_TON ' Kein Ton
      17. End If
      18. ' Select Case TimerTemp
      19. ' Case -50 to 50 ' Zulässige Abweichung vom Ton
      20. ' Incr CountFlankeOK
      21. ' If CountFlankeOK > CountFlankeMax then
      22. ' CountFlankeOk = CountFlankeMax
      23. ' CountFlankeFail = 0
      24. ' Set SFlags.FLAG_TON
      25. ' End If
      26. ' Case Else
      27. ' Incr CountFlankeFail
      28. ' If CountFlankeFail > CountFlankeMax then
      29. ' CountFlankeFail = CountFlankeMax
      30. ' CountFlankeOK = 0
      31. ' Reset SFlags.FLAG_TON
      32. ' End If
      33. ' End Select
      34. TimerOld = TimerNew
      35. TimerDeltaOld = TimerDelta
      36. Return
      Alles anzeigen
      Die Pulse sind noch immer invertiert.
      Ich glaube ich mach dann mal Schluss für heute.

      Bis morgen.
    • Mitch64 schrieb:

      Komischerweise, wenn Ton erkannt werden soll, sollte ein High kommen. Das Signal scheint aber invertiert zu sein.
      Die Flanken bei Config Timer und Config ACI haben keinen Einfluss darauf.
      Das ist seltsam - ich komme auch zu dem Schluss, dass SFlags.0 bei konstanter Pusdauer (=Ton) high sein müsste...
      Ich habe aber noch nie so richtig mit dem Analog-Komparator gearbeitet. Wie gesagt, in meiner Anwendung habe ich das NF-Signal so hoch verstärkt, dass auch aus leisem Rauschen ohne Ton ein Rechteck-Signal wurde, das dann bei jeder steigenden Flanke einen Interrupt ausgelöst hat.

      Eine Nacht darüber zu schlafen hat aber schon oft geholfen :)