Cómo generar una forma de onda de 1Hz a 40Hz mediante ATMEGA32U4 (placa Arduino)

0

Estoy utilizando ATMEGA32U4 (placa Arduino). Estoy enfrentando un problema con TIMER. Quiero generar una señal de 1 Hz a 40 Hz en dos pines y cambiar la señal PWM con un cierto período de tiempo.

Ejemplo:

TIME | PIN9 Freq. | PIN9 PWM | PIN10 Freq. | PIN10 PWM | Alternate Mode  
T0   |    2Hz     |      50% |         2Hz |       50% | 0   
T1   |    3Hz     |      50% |        15Hz |       20% | 0  
T2   |   30Hz     |      40% |         2Hz |       50% | 0  
T3   |    2Hz     |      50% |         2Hz |       50% | 1

La activación del modo alternativo proporciona un cambio de fase de 180 grados b / w PIN9 y PIN10.

    
pregunta Deepak Aagri

1 respuesta

1

Sólo un boceto rápido:

#define F_TIMER_TICK 300 // in Hz

#define PHASE_NORMAL 0
#define PHASE_INVERSE 1

typedef struct pwmDef {
    uint8_t ticksOnPerCylce;
    uint8_t ticksPerCycle;
    uint8_t phase;
} pwmDef_t;

typedef struct doublePwmDef {
    pwmDef_t pin9;
    pwmDef_t pin10;
} doublePwmDef_t;

const doublePwmDef_t T0 = {
    { 
        (uint8_t) (F_TIMER_TICK / (2 / 0.5)),
        (uint8_t) ( F_TIMER_TICK / 2 ),
        PHASE_NORMAL
    },
    {
        (uint8_t) ( F_TIMER_TICK / (2 / 0.5) ),
        (uint8_t) ( F_TIMER_TICK / 2 ), 
        PHASE_NORMAL
    }
};

const doublePwmDef_t T1 = {
    { 
        (uint8_t) ( F_TIMER_TICK / (3 / 0.5) ),
        (uint8_t) ( F_TIMER_TICK / 3 ),
        PHASE_NORMAL
    },
    {
        (uint8_t) ( F_TIMER_TICK / (15 / 0.2) ),
        (uint8_t) ( F_TIMER_TICK / 15 ),
        PHASE_NORMAL
    }
};

const doublePwmDef_t T2 = {
...
};

const doublePwmDef_t T3 = {
    { 
        (uint8_t) (F_TIMER_TICK / (2 / 0.5)),
        (uint8_t) ( F_TIMER_TICK / 2 ),
        PHASE_NORMAL
    },
    {
        (uint8_t) ( F_TIMER_TICK / (2 / 0.5) ),
        (uint8_t) ( F_TIMER_TICK / 2 ), 
        PHASE_INVERSE
    }
};

// etc.

const doublePwmDef_t[] PWM_DEFS = {
    T0,
    T1,
    T2,
    T3
}

// etc.


volatile uint8_t mode;
volatile uint8_t tickCount9;
volatile uint8_t tickCount10;

ISR(TIMER0_COMPA_vect) {

    OCR0A += <trigger again in 1/300s>;

    const doublePwmDef_t currentPwmDef = PWM_DEFS[ mode ];

    if ( tickCount9 >= currentPwmDef.pin9.ticksPerCycle ) {
        tickCount9 = 0;
    }

    if (tickCount9 < currentPwmDef.pin9.ticksOnPerCylce) {
        if ( currentPwmDef.pin9.phase == PHASE_NORMAL ) {
            // Turn pin 9 ON
        } else {
            // Turn pin 9 OFF
        }
    } else {
        if ( currentPwmDef.pin9.phase == PHASE_NORMAL ) {
            // Turn pin 9 OFF
        } else {
            // Turn pin 9 ON
        }
    }

    tickCount9++;

    // Repeat the above for pin 10...

}

void switchMode( uint8_t newMode ) {
    cli();
    mode = newMode;
    tickCount9 = 0;
    tickCount10 = 0;
    sei();
}

Si usa los pines de E / S correctos (por ejemplo, OC1A y OC1B), podría aprovechar el PWM de hardware, que no he considerado aquí; en ese caso, podría evitar escribir un ISR.

    
respondido por el JimmyB

Lea otras preguntas en las etiquetas