Morse-Übungsgenerator mit Mikroprozessor

  • Ja Daniel, dann hättest du keinen Speicher mehr für das Programm. Ein Atmega8 wäre wohl für deinen Zweck besser geeignet.


    72 de Wolf,DL2WRJ

  • HAllo,
    es hat zwar seinen Reiz, mit den ganz kleinen Attinys auszukommen, aber wenn man ehrich ist macht das nicht wirklich Sinn. DIe Dinger sind alle nicht teuer... Also wenigstens ein ATTiny 24. In die 2KByte Flash bekommt man schon eine ganze Menge Programm rein. Aber sind 1K für eine Sinustabelle nicht schon sehr großzügig?


    MfG Alexander

  • Hallo Leute,


    ich habe ein kleines Pythonskript geschrieben, das die erforderlichen Paramater ausrechnet und die Tabelle anlegt. 64 Schritte für die Sinuskurve sind schon viel zu viel, aber wenn ein AVR mit 9,6 MHz arbeitet, muss ich durch 64 teilen. Das Skript sinepwm.py.txt muss noch in sinepwm.py umbenannt werden, sonst funktioniert es nicht. Kurze Hinweise zur Bedienung sind in dem Skript (Use the source, Luke :)


    Gibt es eine Möglichkeit, den Mikroprozessor ohne externen Kristall zu verlangsamen?


    Wie das ganze ausgerechnet wird, ist in DG4FACs hervorragendem Tutorium erklärt. Wer sich die einfachsten Grundbegriffe von Python angesehen hat, wird vielleicht auch mein Programm verstehen. Mehr als was in dem Anfängertutorium für Python steht, kann ich auch nicht.


    Ansonsten kann ich das auch gerne hier vorrechnen. Der Graph wurde mit xmgrace geplottet.


    73 Daniel DM3DA

  • Hallo,


    die Mikrocontroller haben meistens einen internen Generator, den du mit einem RC Glied beeinflussen kannst.


    Hier ist das super am Beispiel dier PIC erklärt: http://sprut.de/electronic/pic/osc/index.htm


    Das sie Oszillatoren ein wenig ungenauer als Quarze oder Resonatoren gehen dürfte klar sein. Ob man das allerdings hört ist fraglich. Bei zeitkritischen Aufgaben wie eine Kommunikation über UART (Serielle Schnittstelle) wäre das zu ungenau!


    Edit: Bitte denkt auch daran, dass das Umstellen der Peripherie auch einige Taktzyklen benötigt! Die müssen mit eingerechnet werden, wenn wirklich so viel Wert auf Genauigkeit gelegt werden soll. Wenn man einen RC Generator nimmt, ist das aber hinfällig, da man dadurch nichtmehr viel Genauigkeit verliert!

  • Hallo Daniel,


    ich habe heute eine erste Version des Programms für einen atTiny45 / 85 geschrieben.


    und folgendes festgelegt:


    R/C Oszillator: 8MHz


    Timer 1 ist für die PWM zuständig
    PLL: Faktor 8
    PWM-Takt = 500.000kHz
    Schrittweite Sinus: 128 Werte
    PWM-Maximum (OCR1C): 128 Werte


    PB1 Ausgabe - PWM Ton 660 Hz
    PB0 Eingang - Paddle (10k pull-up nach Vcc und 1nF nach Masse)


    Dein Pytonprogramm habe ich kurzerhand missbraucht um die Datei sin_wave_660Hz.data zu erzeugen.


    Hier werden die 128 Sinus-PWM-Werte definiert.


    Das Programm wird mit dem makefile ohne Fehler für den atTiny85 übersetzt, nur einen Test mit realer Hardware konnte ich noch nicht machen.


    Die Codegröße


    $avr-size main.elf
    text data bss dec hex filename
    1296 6 35 1337 539 main.elf


    .

    73 de Uwe
    DC5PI

    Einmal editiert, zuletzt von de0508 ()

  • Hallo Uwe,


    vielen Dank! Deshalb habe ich das Pythonprogramm ja auch veröffentlicht :)


    Ich fange mit den Fragen mal unten an:


    Heißt das, dass das Programm 1296 byte Speicherplatz einnimmt? (man avr-size sagt nix zu den Einheiten)


    Die Entprellfunktion in Deinem Programm ist klasse.


    73 Daniel DM3DA

  • Hallo Daniel,


    ich musste das ZIP File löschen , da dort noch Code drin war, der nicht für die Öffentlichkeit ist.


    Hast Du schon die beiden Funktionen für das Anschwingen und das Abklingen definiert ?


    Wie war das 4-5ms bei 660Hz?
    Ich kann ja rechnen 4 Schwingungen bei 660Hz benötigen 6ms..


    Evtl. sollten man das An- und Abklingen auf mehr Schwingungen legen ?


    Dann könnte mit diesen speziellen Daten meinen Code auf realer Hardware testen.


    .

    73 de Uwe
    DC5PI

  • Moin zusammen,


    wenn ich es beim "kurzem Überfliegen" der Quellcodes richtig gesehen habe, findet hier eine vollständige Sinustabelle Anwendung. Falls der Speicher des Controllers mal knapp wird: Aufgrund der Symetrie dieser Funktion genügt auch ein Viertel der Tabelle zusammen mit einem Quadrantenzähler und ein paar Additionen und Subtraktionen ;)


    73 de "Sparsamprogrammierer" Roland / DK1RM

  • Hallo Roland,


    ja das ist richtig, die gute Idee ist von Daniel und deshalb habe ich das nach seiner Vorgabe umgesetzt.


    Eine Optimierung auf 1/4 Tabellengröße ist immer noch machbar, das spannende kommt ja erst noch, das spezielle 'hoch' und herunterfahren' der Lautstärke vor und nach dem "Tastenklick".

    73 de Uwe
    DC5PI

  • Hallo Uwe,


    ich habe mir die Zip-Datei rechtzeitig heruntergeladen, danke. Die Hüllkurve mache ich später. Erst einmal versuche ich, Deine Zahlen zu verstehen. Ich komme da auf etwas andere Einstellungen für die PWM. Sieh Dir einmal bitte die angehängten Dateien an: sinepwm.py.txt in einer neuen Version, weil ich die Gegenprobe falsch dargestellt habe. Und die Ausgabe dazu. Jetzt komme ich auf dieses Ergebnis:


    Code
    Vorgaben:
    Frequenz 660 Hz
    Prozessortakt 8000000 Hz
    Der Wert des Teilers ist 64
    Die Schrittweite ist 189
    
    
    Eine eine PWM-Schrittweite von 189 ergibt eine Sinuswelle mit 661.38 Hz
        Gegenprobe: 8000000 / ( 64 * 189 ) = 661.38


    Ich bin mir nicht sicher, dass ich die richtige Sprache spreche. Also Neudeutsch, um Missverständnisse auszuschließen:
    Attiny45
    8 MHz Clock (Die Geschwindigkeit, auf dem der Mikroprozessor läuft)
    Teiler = Auflösung, PWM Prescaler
    Der PWM Counter ist 8 Bit => Die höchste Zahl, die ich im PWM nehmen kann, ist 256
    Nach der Rechnung oben komme ich auf eine Schrittweite von 189 (CTC, Clear Timer on Compare).


    Ich habe das so verstanden, dass der PWM-Counter auf der 1/64-fachen Geschwindigkeit des Mikroprozessors läuft. Er zählt bis 189 und fängt dann neu an. Innerhalb dieser Zeit kann ich über die Pulsweite den Kondensator des RC-Netzwerkes laden. Dann kann der Puls längstens den Wert 189 bekommen. Das entspricht der vollen Betriebsspannung (5V). Wenn der Puls nur halb so lang ist (94 Schritte), bekomme ich 2,5 V am Kondensator.


    Um in Zeit-Einheiten zu reden: 8 MHz/64 = 125 kHz. Durch 189 = 661,38 Hz

    Hallo Günter,
    danke für die Links. Das sind genau die Dateien, auf die ich mich berufe, wenn ich DG4FAC zitiere. Dieses Tutorium ist so klasse, dass man es nicht oft genug erwähnen kann :)


    73 Daniel DM3DA

  • Hallo Uwe,


    OK, endlich habe ich es verstanden: Dein Ansatz funktioniert anders als der PWM-Generator, den DG5FAC beschrieben hat. Der erste Timer macht das Sinussignal aus der Tabelle, und ein anderer Timer stellt die Frequenz ein. Das ist super, weil wir dann nur eine einzige Tabelle für mehrere Frequenzen benötigen.


    Die Hüllkurve mache ich dann in den nächsten Tagen.


    73 Daniel

  • Hallo Daniel,


    die Idee eine Sigmoidfunktion zu verwenden, habe ich im Bereich von x= {-2.5, .. , 2.5} mit einer Schrittenweite von 0,2 (26 Stützstellen) umgesetzt.


    Das bedeute, dass das An- und Abschwingen 39,39ms dauert, ist das zu lange ?


    Siehe Anlage.


    Ich verwende die letzten 4 Stellen als Skalierung für den Sinuswerte aus der Tabelle und muss damit in 32 Bit Arithmetik rechnen.


    .

  • Hallo Daniel,


    so ich habe noch einen dritten Timer für das Entprellen und dem Taskmanager eingbaut.
    Der Watch-Doc-Timer wurde mit seinem 15ms Interrupt "missbraucht".


    So haben wir nun:
    * Timer 0 für die Freqeunzerzeugung, Taktzeit 660Hz * 128
    * Timer 1 für die PWM-Erzeugung; Takt 500.000kHz
    * und WDT Timer 15mS zum Entprellen und dem Taskmanager


    Über Timer 0 werden verschiedene interne Zustände verarbeitet und auch über die 26 Sigmoid Stützstellen die Sinusschwingung in der Amplitude 'geregelt'.


    Die Berechnungen werden in der Datei "sigmoid.c" durch


    Code
    void set_sigmoid_idx(uint8_t idx);


    und


    Code
    uint8_t scale_sigmoid(uint8_t sin_idx)


    durchgeführt.


    Ich finde diese Funktion sehr elegant und Flashspeicher sparend.


    Morgen werde ich versuche diese Programm auf einen atTiny85 aus zu führen.


    .

  • Hallo Daniel,


    ich habe heute das Programm auf realer Hardware getestet und weiterentwickelt.


    Nun habe wir auch die Möglichkeit über 2 Eingangssignale die Ausgabefrequenz zu verändern.
    Eingebaut habe ich:


    * PB3, PB4: Frequenz
    * offen, offen: 660Hz
    * geschlossen (GND), offen: 570Hz
    * offen, geschlossen (GND): 750Hz
    * geschlossen (GND), geschlossen (GND): 1000Hz


    Die Filterung habe ich ganz einfach gemacht, vom PWM_BIT: PB1 geht -- 33R Widerstand -- 100µF zum 8Ohm Lautsprecher.
    Edit:
    Als RC Filterglied habe ich jetzt gewählt:
    Widerstand 33R und ein Kondensator 2µF (MKP) nach Masse.
    Klingt super !


    Über den Widerstand stelle ich auch die Lautstärke ein so dass ich nun C ausrechnen kann:


    - C = 1/ (2* pi * f * R) ; Einheiten in Ferrad, Hz und Ohm



    An PB2 liegt nun ein LED die eine Funktion der Schaltung anzeigt:
    * LED blinkt 1/sec: dies zeigt den Status Idle an.
    * LED On: zeigt an, dass das Paddel gedrückt wurde.
    * LED Off: zeigt an, dass das Paddel losgelassen wurde und das Blinken startet nach 0,5 Sek erneut.


    Hier noch die Belegung des atTiny85/45:


    Code
    +------------+
                        RESET PB5 -| 1 ...... 8 |- VCC
                         INP0 PB3 -| 2 ...... 7 |- PB2 LED Output
                         INP1 PB4 -| 3 ...... 6 |- PB1 PWM Output
                              GND -| 4 ...... 5 |- PB0 Paddle Input
                                   +------------+


    Das Programm ist nun 1549 Byte groß:


    PHP
    avr-size main.elf 
       text data bss dec hex filename
       1514 2 33 1549 60d main.elf


    Die Änderung der Ton-Frequenz wird nach spätestens 0,5 Sekunden wirksam.


    .

    73 de Uwe
    DC5PI

    2 Mal editiert, zuletzt von de0508 ()

  • Hallo Uwe,


    toll, das ist ja viel besser als ich mir das je vorgestellt habe. Ich freue mich riesig. Kommentare zur Hüllkurve leider frühestens morgen, ich habe es gerade mal geschafft, mein DSO zu installieren (dazu schreibe ich noch einen Beitrag).


    73 Daniel

  • Hallo Daniel,


    wollen wir noch einen Begrüssungstext ausgeben ?


    Was könnte das sein ?

    73 de Uwe
    DC5PI

  • Hallo Uwe,


    hast Du einen Widerstand von 33 Ohm verwendet? Ich fürchte, das verbraucht zu viel Strom. Beispiel 50% (2,5 V): Der Kondensator wird mit einem Puls geladen, um dann während eines gleich langen Zeitraumes über den Widerstand entladen zu werden. Die Stromstärke entspricht also im zeitlichen Mittel 5 V/(2 * 33 R) = 76 mA.


    Sieh Dir mal bitte R5, C10, R6, C11 in Bild 3, Seite 297, Funkamateur 3, 2011 an. Die nehmen 4k7 und 22nF für 1750 Hz. Ich schlage vor, wir nehmen die selben Werte.


    73 Daniel DM3DA

  • Hallo Daniel,


    ich habe bei meinen Posting den Versuchsaufbau beschrieben, der Lautsprecher ist direkt angeschlossen.
    Vergessen habe ich nicht, dass Du noch einen LM386 o.ä. verwenden möchtest, dann ist auch ein hochohmiges 2-stufiges Tiefpassfilter einsetzbar.


    Im Anhang findest Du und alle Mitleser ein Versuchsaufbau.

    Wer baut den "Morse-Übungsgenerator mit Mikroprozessor" nach ?


    Das Hex-File stelle ich euch zur Verfügung, ihr benötigt einen attiny25 oder 45 oder 85.


    Getestet und entwickelt habe auf einem atTiny85.


    Der Code ist im Augenblick 1987 byte groß.


    Code
    text data bss dec hex filename
       1944  2 41   1987 7c3 main.elf


    Fuse-Bits
    Für die Programmierung des tiny85 verwende ich avrdude und usbasp, hier noch der Programmaufruf:


    Code
    avrdude -c usbasp -p attiny85 -P usb -U lfuse:w:0xd2:m -U hfuse:w:0xdc:m



    .

  • Hallo Uwe,
    kannst du mir erklären wie du mit dem einen Port ein Paddle abfragst?
    Das leuchtet mir nämlich nicht ein.


    72 Wolf, DL2WRJ