Fehler bei kleinen CTC-Vergleichswerten

    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!

    • Fehler bei kleinen CTC-Vergleichswerten

      Hallo liebes Forum,

      ich möchte mittels Arduino mini (ATmega328P) und einem kleinen 4-bit-R/2R-Netwerk Sinusse erzeugen von maximal 2600 Hz.
      In dem Programm werden die oberen vier Bit von PortD (dort hängt das Netzwerk) schrittweise hoch und wieder runter gezählt und zwischendurch die erforderliche Zeit per Compare-Timer-Interrupt gewartet. Ich setzte bei jedem Schleifendurchlauf den Vergleichswert neu und warte mit BITWAIT auf ein Bit das in der ISR gesetzt wird. Das ist wahrscheinlich relativ ungenau aber das simpelste was mir einfiel.

      Das ganze funktioniert bei 500 Hz auch noch wie es soll, aber bei Vergleichswerten unter ca. 180 Takten versagt der ganze Algorithmus und ich weiß nicht warum! Beim entstehenden Signal ist meist nach einer Halbwelle Schluss und irgendein Wert bleibt konstant. Das angehängte Foto passt zum angehängten Quelltext, bei dem im Prinziep alle Vergleichswerte zu klein sind.
      In der Bascom-Internen Simulation funktioniert alles wunderbar.

      Ich kann mir auf den Kram keinen Reim machen. Ich habe mal unverfroren den ganzen Quelltext angehängt, vielleicht fällt jemanden was ins Auge :)
      Ich bin für jede Hilfe dankbar!

      Grüße,
      Thalamit
      Dateien
    • Das nachfolgende Programm sollte von ELO-Web sein.Bin mir aber nicht sicher.

      BASCOM-Quellcode

      1. ' Sinusoszillator
      2. '
      3. ' Erzeugung per PWM- Oszillator; sein Puls- Pausenverhältnis wird mit den 256 Werten einer approximierten
      4. ' Sinusfunktion geladen.
      5. ' Da die PWM- Taktfrequenz über 18 kHz betragen muss, damit man sie nicht hört, muss der AtTiny 13 mit 9,6 MHz
      6. ' Takt betrieben werden.
      7. ' Der Attiny 13 kann jedoch auf 1,2 MHz geflasht bleiben (Auslieferungszustand), die Taktumschaltung auf 9,6
      8. ' MHz erfolgt über das CLKPR- Register zur Laufzeit des Programms
      9. ' Der Sinus liegt an OC0A, also PB0
      10. '----------------------------------------------------------
      11. $regfile = "attiny13.dat"
      12. $crystal = 9600000
      13. $hwstack = 32
      14. $swstack = 8
      15. $framesize = 8
      16. 'Variablen
      17. Dim N As Word
      18. Dim M As Byte
      19. Clkpr = 128 ' Taktumschaltung 9,6 MHz
      20. Clkpr = 0
      21. Acsr.7 = 1 ' Analog-Komparator ausschalten, spart etwas Strom
      22. Ddrb = &B0000_0001 ' alle Pins bis auf PB0 Eingang
      23. Portb = &B0001_1110 ' alle Pins bis auf PB0 Pullup-Widerstand
      24. '----------------------------------------------------------
      25. Config Timer0 = Pwm , Prescale = 1 , Compare A Pwm = Clear Down
      26. Start Timer0
      27. Tccr0a.0 = 1 'wgm00
      28. Tccr0a.1 = 1 'wgm01
      29. Tccr0b.3 = 0 'wgm02
      30. Do
      31. Restore Sinusdata ' Zeiger auf Anfang der Tabelle setzen
      32. For N = 1 To 256
      33. Read M ' der Wert in PWM0A bestimmt das Puls- / Pausenverhältnis
      34. Pwm0a = M
      35. Next N
      36. Loop
      37. Sinusdata:
      38. Data 0 , 0 , 0 , 0 , 0 , 1 , 1 , 2 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9,
      39. Data 10 , 11 , 13 , 14 , 16 , 17 , 19 , 20 , 22 , 24 , 26 , 28 , 30 , 32 , 34 , 36,
      40. Data 38 , 41 , 43 , 45 , 48 , 50 , 53 , 55 , 58 , 61 , 63 , 66 , 69 , 72 , 74 , 77,
      41. Data 80 , 83 , 86 , 89 , 92 , 95 , 98 , 101 , 104 , 107 , 110 , 114 , 117 , 120 , 123 , 126,
      42. Data 127 , 130 , 133 , 136 , 139 , 142 , 145 , 148 , 151 , 154 , 157 , 160 , 163 , 166 , 169 , 172,
      43. Data 175 , 178 , 181 , 184 , 187 , 189 , 192 , 195 , 197 , 200 , 202 , 205 , 207 , 210 , 212 , 214,
      44. Data 217 , 219 , 221 , 223 , 225 , 227 , 229 , 231 , 232 , 234 , 236 , 237 , 239 , 240 , 242 , 243,
      45. Data 244 , 245 , 246 , 247 , 248 , 249 , 250 , 251 , 251 , 252 , 252 , 253 , 253 , 253 , 253 , 253,
      46. Data 253 , 253 , 253 , 253 , 253 , 252 , 252 , 251 , 251 , 250 , 250 , 249 , 248 , 247 , 246 , 245,
      47. Data 244 , 242 , 241 , 240 , 238 , 237 , 235 , 233 , 232 , 230 , 228 , 226 , 224 , 222 , 220 , 218,
      48. Data 216 , 213 , 211 , 209 , 206 , 204 , 201 , 199 , 196 , 193 , 191 , 188 , 185 , 183 , 180 , 177,
      49. Data 174 , 171 , 168 , 165 , 162 , 159 , 156 , 153 , 150 , 147 , 144 , 141 , 138 , 135 , 131 , 128,
      50. Data 125 , 122 , 119 , 116 , 113 , 110 , 106 , 103 , 100 , 97 , 94 , 91 , 88 , 85 , 82 , 79,
      51. Data 76 , 74 , 71 , 68 , 65 , 63 , 60 , 57 , 55 , 52 , 50 , 47 , 45 , 42 , 40 , 38,
      52. Data 36 , 33 , 31 , 29 , 27 , 25 , 23 , 22 , 20 , 18 , 17 , 15 , 14 , 12 , 11 , 10,
      53. Data 8 , 7 , 6 , 5 , 4 , 4 , 3 , 2 , 2 , 1 , 1 , 0 , 0 , 0 , 0 , 0,
      Alles anzeigen
    • Vielleicht ist dein Programm zu lahm? ;)
      Schau doch mal im Simulator, wie viele Takte du zwischen dem Laden der comparewerte hast (Einzelschritt, vorher die Werte für Takte und Zeit zurück setzten).
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Hallo Leute,

      ich habe die letzte Woche noch ein bisschen an dem Problem rumgefrickelt:
      @Michael: da hast du natürlich Recht, Schlamperei!
      @tschoeatsch: Ja, wahrscheinlich. Die ganze Bitwait-Konstruktion mit dem Interrupt ist auch ziemlicher Mist, wozu gibt's denn Flags?
      Ich habe das Programm von @ftelektro ausprobiert, funktioniert so auch ganz gut. Allerdings habe ich Probleme die verschiedenen Frequenzen von 1060 bis 2600 Hz zu filtern. Ist das Filter zu klein dimensioniert, schwanken die Amplituden, ist es zu groß, ist der Sinus unsauber. Hat da jemand eine Idee für einen steilflankigen Filter?

      Ich habe mir also gedacht, es wäre doch ganz nett und einfacher zu filtern, wenn ich über das R/2R gleich einen Sinus bekäme. Ich habe das Programm also noch mal neu geschrieben und es ist jetzt auch etwas schneller, jedoch nicht fehlerfrei. Es zählt jetzt per Flag eine gewisse Anzahl von Compare Matches durch, um dann per Data einen neuen Vergleichswert in OCCR1A einzulesen und beim nächsten mal länger (oder weniger lang) zu brauchen.
      Am meisten verwirrt mich, dass nicht jede Perioden gleich falsch aussieht, manche sogar richtig.
      Kann es sein, dass beim Arduino noch irgendetwas voreingestellt ist, was ich nicht beachte? Oder die Timer oder die Flags noch irgendwie auf einem dritten Weg beeinflusst werden? Oder so?

      BASCOM-Quellcode: Sinus_mit_Timern_und_Flags

      1. 'Ausgabe einer Sinus-Funktion
      2. $regfile "m328pdef.dat"
      3. $crystal = 16000000
      4. '***** Initialisierungen *********
      5. 'Initialisierung der Ports
      6. Config Portd = Output
      7. Portd = 0
      8. 'Initialisierungen der Variablen
      9. Dim Time_ctrl As Byte
      10. Time_ctrl = 10 'mit dieser Variable kann die Frequenz eingestellt werden
      11. Dim I As Byte
      12. Dim J As Byte
      13. Dim M As Byte
      14. 'Initialisierung des Timers
      15. Tccr1a.0 = 0
      16. Tccr1a.1 = 0
      17. Tccr1b.3 = 1 'CTC-Bit setzen
      18. Tccr1b.4 = 0
      19. Tccr1b.0 = 1 'Prescaler auf 1 setzen, timer starten
      20. '***** Hauptroutine **************
      21. Do
      22. Restore Sinusdata
      23. Portd = 0
      24. For J = 1 To 16 'es werden 16 Spannungsstufen hochgezählt
      25. While I < Time_ctrl 'diese Schleife dient zur Frequenzeinstellung
      26. If Tifr1.1 = 1 Then
      27. I = I + 1
      28. Tifr1.1 = 1
      29. End If
      30. Wend
      31. Portd = Portd + 16
      32. Read M
      33. Ocr1al = M
      34. I = 0
      35. Next J
      36. Restore Sinusdata 'dasselbe nochmal, nur wird PORTD jetzt dekrementiert statt inkrementiert
      37. Portd = 255
      38. For J = 1 To 16
      39. While I < Time_ctrl
      40. If Tifr1.1 = 1 Then
      41. I = I + 1
      42. Tifr1.1 = 1
      43. End If
      44. Wend
      45. Portd = Portd - 16
      46. Read M
      47. Ocr1al = M
      48. I = 0
      49. Next J
      50. Loop
      51. Sinusdata:
      52. Data 188 , 142 , 101 , 85 , 77 , 72 , 69 , 56 , 56 , 69 , 72 , 77 , 85 , 101 , 142 , 188 ,
      Alles anzeigen
      Ich habe wirklich keinen blassen Schimmer, was falsch läuft.

      Grüße,
      Thalamit
      Dateien
    • Dieser Teil
      Portd = Portd + 16
      Read M
      Ocr1al = M
      I = 0
      braucht laut meinem Simulator 47 Takte (genau kann isch's jetzt nicht sagen, der sim ist gerade irgendwie abgestürzt) und es kommen noch mehr Takte vom Rest der Schleife dazu. Du schafst den Schleifendurchgang nicht in der Zeit, die du zwischen compare hast.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Hallo Thalamit,
      Ich verstehe nicht den Sinn der While-Schleife.
      Die läuft Time-ctrl mal durch und überprüft dabei, ob in der Zwischenzeit ein Compate Match aufgetreten ist. Wenn ja, wird das Flag gelöscht. Wozu?
      Ein richtiges Problem bekommst du beim Ändern des OCR1A Registers. Dies wird beim CTC Modus nicht gepudert. Wenn der Timer dann z.B. Schon bis auf 100 gezählt hat und du das Register auf einen kleineren Wert setzt, dann läuft der Timer bis zum Top Wert hoch.
    • Hallo Leute,

      stimmt, wenn man OCR1A ungeschickt ändert, läuft TCNT1 bis MAX! Daher kamen die langen Striche im Graphen. Deswegen ist es so wichtig, dass man bestimmte Vergleihswerte nicht unterschreitet. Das hatte ich nicht verstanden, ich danke euch!

      BASCOM-Quellcode

      1. 'Ausgabe einer Sinus-Funktion
      2. $regfile "m328pdef.dat"
      3. $crystal = 16000000
      4. '***** Initialisierungen *********
      5. 'Initialisierung der Ports
      6. Config Portd = Output
      7. Portd = 0
      8. 'Initialisierungen der Variablen
      9. Dim I As Byte
      10. Dim J As Byte
      11. Dim M As Word
      12. 'Initialisierung des Timers
      13. Tccr1a.0 = 0
      14. Tccr1a.1 = 0
      15. Tccr1b.3 = 1 'CTC-Bit setzen
      16. Tccr1b.4 = 0
      17. Tccr1b.0 = 1 'Prescaler auf 1 setzen, timer starten
      18. '***** Hauptroutine **************
      19. Do
      20. Restore Sinusdata
      21. For J = 1 To 15
      22. Read M
      23. Ocr1ah = High(m)
      24. Ocr1al = Low(m)
      25. Portd = Portd + 16
      26. While Tifr1.1 = 0 'ist das Compare-Flag gesetzt?
      27. nop
      28. Wend
      29. Tifr1.1 = 1 'Compare-Flag zurücksetzen
      30. Next J
      31. For J = 1 To 15 'PortD wieder runtrzählen
      32. Read M
      33. Ocr1ah = High(m)
      34. Ocr1al = Low(m)
      35. Portd = Portd - 16
      36. While Tifr1.1 = 0
      37. nop
      38. Wend
      39. Tifr1.1 = 1
      40. Next J
      41. Loop
      42. Sinusdata:
      43. '1060 Hz
      44. 'Data 664% , 475% , 402% , 363% , 340% , 327% , 321% , 321% , 327% , 340% , 363% , 402% , 475% , 664% , 1764%,
      45. 'Data 664% , 475% , 402% , 363% , 340% , 327% , 321% , 321% , 327% , 340% , 363% , 402% , 475% , 664% , 1764%,
      46. '1160 Hz
      47. Data 607% , 434% , 367% , 332% , 311% , 299% , 294% , 294% , 299% , 311% , 332% , 367% , 434% , 607% , 1612%
      48. Data 607% , 434% , 367% , 332% , 311% , 299% , 294% , 294% , 299% , 311% , 332% , 367% , 434% , 607% , 1612%
      49. '1270 Hz
      50. 'Data 554% , 396% , 335% , 303% , 284% , 273% , 268% , 268% , 273% ; 284% , 303% , 335% , 396% , 554% , 1472%
      51. 'Data 554% , 396% , 335% , 303% , 284% , 273% , 268% , 268% , 273% ; 284% , 303% , 335% , 396% , 554% , 1472%
      52. '1400 Hz
      53. 'Data 503% , 359% , 304% , 275% , 258% , 248% , 243% , 243% , 248% , 258% ; 275% , 304% , 359% , 503% , 1336%
      54. 'Data 503% , 359% , 304% , 275% , 258% , 248% , 243% , 243% , 248% , 258% ; 275% , 304% , 359% , 503% , 1336%
      55. '1530Hz
      56. 'Data 460% , 329% , 278% ; 251% , 236% , 227% , 223% , 223% , 227% , 236% , 251% , 278% , 329% , 460% , 1222%
      57. 'Data 460% , 329% , 278% ; 251% , 236% , 227% , 223% , 223% , 227% , 236% , 251% , 278% , 329% , 460% , 1222%
      58. '1670 Hz
      59. 'Data 421% , 301% , 255% , 230% , 216% , 208$ , 204% , 204% , 208% , 216% , 230% , 255% , 301% ; 421% , 1120%
      60. 'Data 421% , 301% , 255% , 230% , 216% , 208$ , 204% , 204% , 208% , 216% , 230% , 255% , 301% ; 421% , 1120%
      61. '1830 Hz
      62. 'Data 384% , 275% , 233% , 210% , 197% , 190% , 186% , 186% , 190% , 197% , 210% , 233% , 275% , 384% , 1022%
      63. 'Data 384% , 275% , 233% , 210% , 197% , 190% , 186% , 186% , 190% , 197% , 210% , 233% , 275% , 384% , 1022%
      64. '2000 Hz
      65. 'Data 352% , 252% , 213% , 192% , 180% , 173% , 170% , 170% , 173% , 180% , 192% , 213% , 252% , 352% , 936%
      66. 'Data 352% , 252% , 213% , 192% , 180% , 173% , 170% , 170% , 173% , 180% , 192% , 213% , 252% , 352% , 936%
      67. '2200 Hz
      68. 'Data 320% , 229% , 194% , 175% , 164% , 158% , 155% , 155% , 158% , 164% , 175% , 194% , 229% , 320% , 850%,
      69. 'Data 320% , 229% , 194% , 175% , 164% , 158% , 155% , 155% , 158% , 164% , 175% , 194% , 229% , 320% , 850%,
      70. '2400 Hz
      71. 'Data 293% , 210% , 177% , 160% , 150% , 145% , 142% , 142% , 145% , 150% , 160% , 177% , 210% , 293% , 780%,
      72. 'Data 293% , 210% , 177% , 160% , 150% , 145% , 142% , 142% , 145% , 150% , 160% , 177% , 210% , 293% , 780%,
      73. '2600 Hz
      74. 'Data 270% , 192% , 163% , 147% , 138% , 132% , 130% , 130% , 132% , 138% , 147% , 163% , 192% , 270% , 718%
      75. 'Data 270% , 192% , 163% , 147% , 138% , 132% , 130% , 130% , 132% , 138% , 147% , 163% , 192% , 270% , 718%
      Alles anzeigen

      Das Programm macht jetzt genau das, was es soll, einwandfrei. a_64_3a718cae
      Bleibt nur noch eine kleine Frage, die eigentlich gar nichts mit dem Thema mehr zu tun hat:

      Ich würde das Programm jetzt gerne mit verschiedenen Frequenzen aufrufen, restore nimmt aber keine Variablen. Was mir einfällt ist da dieses:

      BASCOM-Quellcode

      1. '*** Hauptroutine ***
      2. while *Bedingung*
      3. restore sinus_xxxx_hz
      4. gosub sinus_periode
      5. wend
      6. '*** Subroutine ****
      7. sinus_periode:
      8. *sinus_periode*
      9. return
      Gibt's vielleicht eine Variante, die ohne Sprung nach jeder Periode auskommt?


      Grüße,
      Thalamit
      Dateien
    • Vielleicht deine gewünschten datas in ein array kopieren und das auslesen anstelle von read.

      warum ist eigentlich dein letzter Wert unverhältnismäßig groß?
      1. Data 607% , 434% , 367% , 332% , 311% , 299% , 294% , 294% , 299% , 311% , 332% , 367% , 434% , 607% , 1612%
      2. Data 607% , 434% , 367% , 332% , 311% , 299% , 294% , 294% , 299% , 311% , 332% , 367% , 434% , 607% , 1612%
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Dekaman schrieb:

      @Thalamit
      Du kannst auch eine Select ..Case Abfrage machen.
      z.B. Select Case Sprungziel
      Case = 1
      Restore Ziel_1
      Case=2
      Restore Ziel_2
      ----
      End select

      Dann hast du in Sprungziel deine Variable und kannst dann mit Restore
      deine Datazeilen anspringen

      Detlef
      Dann müsste diese Abfrage aber auch bei jeder Periode durchlaufen werden, wo jetzt im Programm das restore steht. Dazu hat er aber keine Zeit übrig.

      @Thalamit Galahat hat mir mal eine sehr flotte read-Anweisung geschrieben, schau mal hier kann man bei soft-SPI den Mosi-pin im laufenden Programm umschalten?
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Bei Word Typen dauert dies
      READ M
      OCR1A = M
      75 Takte, und dies
      OCR1A = Intervall(J)
      nur ganze 17 Takte. Dabei musst du natürlich vorher bei Frequenzwechsel die 16 Werte in das Array schreiben, wobei das dann ja nicht zeitkritisch ist. Dabei würde ich dann mit Lookup arbeiten, weil du den Index dann einfach über alle Frequenzen berechnen kannst.
      For I = 0 To 14
      Index = Frequenznr * 15 + I
      Intervall(I+1) = Lookup(Index,Sinusdata) 'Loopup ist 0-basiert, Intervall() dann 1-basiert
      Next I
      Frequenznr geht dabei von 0 - 10 in deinem Programm.

      Dieser Beitrag wurde bereits 7 mal editiert, zuletzt von hero ()

    • tschoeatsch schrieb:

      Dann müsste diese Abfrage aber auch bei jeder Periode durchlaufen werden, wo jetzt im Programm das restore steht. Dazu hat er aber keine Zeit übrig.
      Das sehe ich nicht so, es ist aber richtig," wo jetzt im Programm das restore steht."
      Das Restore muss natürlich vor der DO .. LOOP Schleife stehen. Man kann ja sicher beim Start
      des Programms fragen, welche Frequenz denn ausgegeben werden soll.
      Das waren meine "Hintergedanken" beim Select Case.

      Detlef
      Leichtsinn ist kein Mut, Vorsicht keine Feigheit.
    • Dekaman schrieb:

      Das Restore muss natürlich vor der DO .. LOOP Schleife stehen. Man kann ja sicher beim Start
      des Programms fragen, welche Frequenz denn ausgegeben werden soll.
      Und wenn dann 30x read die Daten holt, was wird dann beim nächsten Durchlauf für die nächste Sinuswelle an Daten gelesen?
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Hallo, ich weis nicht,wer mir gestern in geistiger Umnachtung diesen Schwachsinn
      hat schreiben lassen. Es tut mir leid, und es ist auch ein bisschen Schäm dabei. a_71_f9c57bbe

      Ich rede hier von meinen Posts #10 und #13.
      Tschoeatsch, zu dieser Erkenntnis bin ich ja auch gekommen.

      Wenn ein Admin den großen Radiergummi bei der Hand hat, dann bitte die beiden Posts löschen.
      Die stiften eh nur Verwirrung.

      Detlef
      Leichtsinn ist kein Mut, Vorsicht keine Feigheit.