Go Down

Topic: ATtiny85 + I2C + pwm on 74HC595 (Read 724 times) previous topic - next topic

koniu

Mar 30, 2013, 02:41 pm Last Edit: Mar 30, 2013, 02:44 pm by koniu Reason: 1
Hello! I'm trying to drive by pwming one shift register (74HC595) through ATTiny85. The microcontroller gets commands from Arduino through i2c protocol (using TinyWireS library).

Testing i2c standalone succeeds, driving the shift register too, but these two won't run along - while using the leds i2c communication fails.
Probably pwming the leds is interrupting the i2c but I have no idea how to optimize the code to run two time-dependant tasks.

my setup (hardware):
Code: [Select]
  (RESET) = PB5 1      8 VCC = VCC
  LATCH   = PB3 2      7 PB2 = I2C SCL (ATMega328 - PC5)
  CLOCK   = PB4 3      6 PB1 = DATA
  GND     = GND 4      5 PB0 = I2C SDA (ATMega328 - PC4)


here's the code to pwm 74HC595 using timer1:
Code: [Select]
void timerinit() {
    TCCR1  = _BV(CTC1);              //clear timer1 when it matches the value in OCR1C 
    TIMSK |= _BV(OCIE1A);           //enable interrupt when OCR1A matches the timer value 
   
    // F_CPU = 8Mhz, no divider and all fuses set. 4 is the prescaler, 75 frequency and 256 brightness of the leds
    OCR1A = round(((float) F_CPU / (float)4) / ((float)75*((float) 256)) -1); //set the match value for interrupt
    OCR1C = round(((float) F_CPU / (float)4) / ((float)75*((float) 256)) -1); //and the same match value to clear the timer
     
    //setting prescaler = 4
    bitSet(TCCR1,CS10);
    bitSet(TCCR1,CS11);
    bitClear(TCCR1,CS12);
   
    sei(); //enable interrupts
}

ISR(TIMER1_COMPA_vect) {           
        PWMProcess();                 
}


timerinit() function is called in setup(). PWMProcess is called in every timer interrupt - setting leds on and off very fast.
Code: [Select]
void PWMProcess(){

  byte PWMsrVals; // here we have temporary array of SR values
  PWMticker++;
 
// TICKER_PWM_LEVELS is defined as 32,  TICKER_STEP is defined as 256/TICKER_PWM_LEVELS
  if(PWMticker > TICKER_PWM_LEVELS) PWMticker = 0; 
  // get ticker as a 0 to 255 value, so we can always use the same data regardless of actual PWM levels
  int myPos = PWMticker * TICKER_STEP;   
  // Loop through all bits in the shift register
  for (int i = 0 ; i < 8; i++ ){
    int myLev = 1;
    if (PWMsrPins[i] > myPos) myLev = 0;
    bitWrite(PWMsrVals, i, myLev);
  }

  bitClear(PORTB, LATCHPIN); // setting the latch off
  shiftOut(DATAPIN, CLOCKPIN, LSBFIRST, PWMsrVals); // setting the SR
  bitSet(PORTB, LATCHPIN);   // setting the latch on
}

I guess the PWMProcess() function may be the bottleneck and needs optimization, could you give me any tips how to do this?

Underline: how to run correctly time-dependant task (i2c) and clock-consuming task (pwm) so they don't bother eachother?

Derek_Z10

If you ever figured this out, I would love to know.

Yes, please let us know if/how you worked this out.  I'm trying to use an ATtiny85 to drive a motor and I seem to be having a similar problem using I2C and PWM at the same time.

Go Up