Search code examples
avrledatmelpwmattiny

ATTiny85 PWM for 4 LEDs


I need to control 4 individual LEDs via PWM on an ATTiny85. I have found lots of info on how to control 3 LEDs. But apparently to control 4 with PWM, you have to really twist the 85 into knots. Is there an easier way to handle 4 LEDs on the 85, or would it be better to step over to the 84? If I went with the 84, would I be likely to run into the same brick walls as with the 85?

I found this code for controlling 4 on the 85, but it's above my skill level. Anyone see any issues with it?

/* Four PWM Outputs */

// ATtiny85 outputs
const int Red = 0;
const int Green = 1;
const int Blue = 4;
const int White = 3;
volatile uint8_t* Port[] = {&OCR0A, &OCR0B, &OCR1A, &OCR1B};

void setup() {
  pinMode(Red, OUTPUT);
  pinMode(Green, OUTPUT);
  pinMode(Blue, OUTPUT);
  pinMode(White, OUTPUT);
  // Configure counter/timer0 for fast PWM on PB0 and PB1
  TCCR0A = 3<<COM0A0 | 3<<COM0B0 | 3<<WGM00;
  TCCR0B = 0<<WGM02 | 3<<CS00; // Optional; already set
  // Configure counter/timer1 for fast PWM on PB4
  TCCR1 = 1<<CTC1 | 1<<PWM1A | 3<<COM1A0 | 7<<CS10;
  GTCCR = 1<<PWM1B | 3<<COM1B0;
  // Interrupts on OC1A match and overflow
  TIMSK = TIMSK | 1<<OCIE1A | 1<<TOIE1;
}

ISR(TIMER1_COMPA_vect) {
  if (!bitRead(TIFR,TOV1)) bitSet(PORTB, White);
}

ISR(TIMER1_OVF_vect) {
  bitClear(PORTB, White);
}

// Sets colour Red=0 Green=1 Blue=2 White=3
// to specified intensity 0 (off) to 255 (max)
void SetColour (int colour, int intensity) {
  *Port[colour] = 255 - intensity;
}  

void loop() {
  for (int i=-255; i <= 254; i++) {
    OCR0A = abs(i);
    OCR0B = 255-abs(i);
    OCR1A = abs(i);
    OCR1B = 255-abs(i);
    delay(10);
  }
}

Solution

  • If you want to save pins at the expense of a more complicated strategy, you can get away with only 3 pins by connecting the LEDs as two sets of two like this...

    enter image description here

    Instead of using the built in PWM, you will need to do the PWM manually by setting a timer and then changing the INPUT/OUTPUT and ON/OFF of each of the pins each time the timer expires.

    +-----+----------+----------+----------+
    | LED |    A     |    B     |    C     |
    +-----+----------+----------+----------+
    |   1 | OUTPUT 1 | INPUT    | OUTPUT 0 |
    |   2 | OUTPUT 0 | INPUT    | OUTPUT 1 |
    |   3 | INPUT    | OUTPUT 1 | OUTPUT 0 |
    |   4 | INPUT    | OUTPUT 0 | OUTPUT 1 |
    +-----+----------+----------+----------+
    

    Update or comment if you want more details on this strategy.