¿Por qué mi código está funcionando tan lento?

1

Hola chicos. Estoy construyendo un chaser de 9 RGB LED, usando un ATTiny2313 para conducirlo. Los cátodos están conectados a todo PORTB y el pin 6 de PORTD. Escribí un código para conducirlos a todos, pero por alguna razón es muy lento. Si el rojo está establecido en 200 y el azul en 100, puede ver que el rojo permanece encendido el doble de tiempo y casi puede cronometrarlo. Esto debería suceder muchas, muchas veces por segundo, pero va muy lento.

#include <avr/interrupt.h>    // Defines pins, ports, etc to make programs easier to read
#define F_CPU 1000000UL       // Sets up the default speed for delay.h
#include <util/delay.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>

#define bit_get(p,m) ((p) & (m))
#define bit_set(p,m) ((p) |= (m))
#define bit_clear(p,m) ((p) &= ~(m))
#define bit_flip(p,m) ((p) ^= (m))
#define bit_write(c,p,m) (c ? bit_set(p,m) : bit_clear(p,m))
#define BIT(x) (0x01 << (x))
#define LONGBIT(x) ((unsigned long)0x00000001 << (x)) 

#define RED 1
#define BLUE 0
#define GREEN 2


void delay_ms(uint16_t ms) {
  while ( ms ){
    _delay_ms(1);
    ms--;
  }
}
struct LED {
    uint8_t r;
    uint8_t g;
    uint8_t b;
};

volatile struct LED strip[9];
uint8_t x;
uint8_t y;

int main(void)
{
DDRD = 0xFF;
DDRB = 0xFF;
for(x = 0; x <= 8; x++){
    strip[x].r = 0;
    strip[x].g = 0;
    strip[x].b = 255;
}
while(1){
    PORTB = 0xFF;
    PORTD = (1 << 6);
    for(x = 0; x <= 255; x++){
        for(y = 0; y <= 8; y++){

            if(strip[y].r > x)
                bit_set(PORTD, BIT(RED));
            else
                bit_clear(PORTD, BIT(RED));
            if(strip[y].g > x)
                bit_set(PORTD, BIT(GREEN));
            else
                bit_clear(PORTD, BIT(GREEN));
            if(strip[y].b > x)
                bit_set(PORTD, BIT(BLUE));
            else
                bit_clear(PORTD, BIT(BLUE));    

            _delay_us(1);
            if(y == 0){
                bit_clear(PORTD, BIT(6));
                PORTB = 0xFF;
            }else{
                bit_clear(PORTB, BIT(y-1));
                bit_set(PORTD, BIT(6));
            }
            _delay_us(10);
            PORTB = 0xFF;
            PORTD |= (1 << 6);
            _delay_us(1);
        }
    }
}
}

Cualquier ayuda sería muy apreciada :)

    
pregunta starblue

2 respuestas

3

Haz los cálculos de cuántos ciclos utiliza:

255 * 9 * ca 100 ciclos por iteración / 1 MHz = ca 0.25s

donde 100 es una estimación aproximada, podría ser más dependiendo de la implementación de delay_us.

Aumentaría la frecuencia del reloj y utilizaría un enfoque basado en interrupciones.

Pero aún será difícil hacer una atenuación adecuada cuando también realiza la multiplexación, estará limitado a algunos colores para evitar demasiados parpadeos.

    
respondido por el starblue
1

¿Reprogramaste el fusible CLK8DIV desde su configuración predeterminada? El ajuste de fábrica divide la frecuencia del reloj por 8. Es posible realizar una atenuación PWM rápida de un número razonable de LED en el AVR, pero el código debe escribirse con mucho cuidado.

    
respondido por el mikeselectricstuff

Lea otras preguntas en las etiquetas