- fchao-Sinus-Wechselrichter AliExpress    Werbung      
Ergebnis 1 bis 4 von 4

Thema: PWM Generator bis 100kHz

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.303
    Code:
    // Enuberation für 1 bis 10000
    enum incs
    {
        ones = 1,
        tens = 10,
        hundrets = 100,
        thousends = 1000,
        tenthousends = 10000    
    };
    
    
    
    
    // Globale Variable für das aktuelle PER-Register
    static volatile uint16_t current_per = 240;
    
    
    
    uint8_t pwm_set_frequency(uint32_t freq_hz) {
        // Sicherheitsgrenzen prüfen
        if (freq_hz < 1 || freq_hz > 100000) {
            return 0; // Fehler: Frequenz außerhalb des erlaubten Bereichs
        }
    
        uint32_t ticks = 0;
        uint8_t clk_sel = 0;
    
        // Timer stoppen für glitchfreies Umschalten
        uint8_t ctrla_backup = TCA0.SINGLE.CTRLA;
        TCA0.SINGLE.CTRLA &= ~TCA_SINGLE_ENABLE_bm;
    
        // Dynamische Berechnung des optimalen Prescalers bei 24 MHz
        if (freq_hz >= 367) {
            ticks = F_CPU / freq_hz;
            clk_sel = TCA_SINGLE_CLKSEL_DIV1_gc;
            } else if (freq_hz >= 92) {
            ticks = (F_CPU / 4) / freq_hz;
            clk_sel = TCA_SINGLE_CLKSEL_DIV4_gc;
            } else if (freq_hz >= 46) {
            ticks = (F_CPU / 8) / freq_hz;
            clk_sel = TCA_SINGLE_CLKSEL_DIV8_gc;
            } else if (freq_hz >= 23) {
            ticks = (F_CPU / 16) / freq_hz;
            clk_sel = TCA_SINGLE_CLKSEL_DIV16_gc;
            } else if (freq_hz >= 6) {
            ticks = (F_CPU / 64) / freq_hz;
            clk_sel = TCA_SINGLE_CLKSEL_DIV64_gc;
            } else if (freq_hz >= 2) {
            ticks = (F_CPU / 256) / freq_hz;
            clk_sel = TCA_SINGLE_CLKSEL_DIV256_gc;
            } else {
            ticks = (F_CPU / 1024) / freq_hz;
            clk_sel = TCA_SINGLE_CLKSEL_DIV1024_gc;
        }
    
        // Das Periodenregister schreiben
        current_per = (uint16_t)(ticks - 1);
        TCA0.SINGLE.PER = current_per;
    
        // Neuen Prescaler in CTRLA schreiben
        TCA0.SINGLE.CTRLA = (TCA0.SINGLE.CTRLA & ~TCA_SINGLE_CLKSEL_gm) | clk_sel;
    
        // Timer wieder starten, falls er vorher lief
        TCA0.SINGLE.CTRLA |= (ctrla_backup & TCA_SINGLE_ENABLE_bm);
    
        return 1; // Erfolg
    }
    
    void pwm_set_duty_cycle_percent(float percent) {
        if (percent < 0.0) percent = 0.0;
        if (percent > 100.0) percent = 100.0;
    
        // Berechnung des Registerwertes basierend auf der aktuellen Periode
        uint16_t cmp_value = (uint16_t)((percent / 100.0) * current_per);
        
        // Vergleichsregister für Kanal 0 beschreiben (Gibt das Signal nun auf PA0 aus)
        if(percent >= 100)cmp_value++;
        TCA0.SINGLE.CMP0 = cmp_value;
    }
    
    void pwm_init(void) {
        // 1. PORTMUX konfigurieren: TCA0-Ausgang WO0 von PORTA auf PORTC umleiten
        // Das Bitfeld TCA0_bm in PORTMUX.TCAROUTEA steuert das Routing für TCA0
        //PORTMUX.TCAROUTEA = PORTMUX_TCA0_PORTC_gc;
    
        // 2. Pin PC0 (WO0) als Ausgang definieren
        PORTA.DIRSET = PIN0_bm;
    
        // 3. TCA0 im Single-Slope PWM Modus konfigurieren (WGMODE = SINGLESLOPE)
        TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_SINGLESLOPE_gc | TCA_SINGLE_CMP0EN_bm;
    
        // 4. Standardfrequenz beim Start setzen (z. B. 1 kHz)
        pwm_set_frequency(1000);
        pwm_set_duty_cycle_percent(50.0); // 50% Tastverhältnis starten
    
        // 5. Timer aktivieren (Der Prescaler wird in pwm_set_frequency gesetzt)
        TCA0.SINGLE.CTRLA |= TCA_SINGLE_ENABLE_bm;
    }
    Das funktioniert natürlich nur bei hohen Teilerfaktoren also niedrigen Frequenzen.
    Beim kleinsten Teilerfaktor = 1 sind dann schon 425Hz Sprünge drin.
    Das geht im Prinzip auch nicht genauer, weil der Controller natürlich nur Ganze Zahlen für das MAX ( PER ) Register verwenden kann.
    Das ist also ein Fehler von 0,4%.
    Bei größeren Teilfaktoren wird natürlich die Frequenzauflösung besser bis hinunter in den Hz Bereich.

    120kHz wären bei Duty Cycle mit 0,5% auch noch möglich. Aber auch der L293D schafft das nicht.

    Es läuft der interne 24MHz Generator. An Peripherie ist nur der Treiber, das Display, der Drehencoder und das Poti. Betrieben wird das Ganze vorerst mit nem Labornetzteil.

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von wkrug
    Registriert seit
    17.08.2006
    Ort
    Dietfurt
    Beiträge
    2.303
    Es gibt einen Schaltplan und eine Software.
    Soweit läuft auch alles.
    Die Spannung am Treiber ist über einen Jumper von 5V auf Eingangsspannung ( =max. 24V ) umstellbar.
    Ich hab auch einen Servo Ausgang vorgesehen, damit kann man dann auch Modellbau Servos testen, vorausgesetzt die Parameter liegen im gültigen Bereich!


    Bild  

    Bild vom Display

    Im Anhang der dazugehörige Schaltplan
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken PWM_Display.jpg  
    Angehängte Dateien Angehängte Dateien

Ähnliche Themen

  1. Sinus Generator 100khz-600khz/800khz
    Von deko im Forum Elektronik
    Antworten: 1
    Letzter Beitrag: 14.01.2013, 21:31
  2. Mathematik: 100kHz ISR
    Von Merlin321 im Forum C - Programmierung (GCC u.a.)
    Antworten: 11
    Letzter Beitrag: 27.01.2010, 18:12
  3. frequenzmessen über 100khz nicht möglich
    Von kleinstar im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 15.05.2007, 17:45
  4. Robby als 100KHz IIC Slave vervenden
    Von glowbrain1 im Forum Robby CCRP5
    Antworten: 2
    Letzter Beitrag: 31.10.2006, 20:25
  5. 100KHz IIC(I2C) Slave on MC05 (platform Robby)
    Von glowbrain1 im Forum Controller- und Roboterboards von Conrad.de
    Antworten: 1
    Letzter Beitrag: 01.08.2004, 13:22

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

    Werbung      12V Akku bauen