Hello,
I am working on trying to make three 7-segment displays dim according to input from a potentiometer. I am using the MCP23017 port expander attached to an UNO board to control each section of the displays. I am not having any problem with the code that makes the displays run, just with my minimal code to try to get my software timer PWM to work the way I want it to. So the goal of the code I've attached below is to dim the onboard LED attached to pin13 to dim according to the input from the pot. I'm using an interrupt on overflow on Timer2 to control the period and an interrupt on compare on Timer0(CTC mode) to control the pulse width. The problem that I am having is that I cannot figure out why the Timer0 interrupt is not firing? From what I understand from the datasheet, the CTC mode will start the ISR when the TCNT0 register hits the same value as the OCR0A register.
So now that I think I've described my problem clearly, I have two questions:
- Is there a better way to control dimming on the port expander (I'm using I2C to talk to it)?
- Why is the Timer0 interrupt not working (The ISR increments a counter every time it fires but the counter value is never changing, which says to me that the ISR is never firing)?
const int ledPin = 13;
int ledState = LOW;
long previousMillis = 0;
long interval = 1000;
volatile int overflowCount = 0;
int lastCount = 0;
volatile int count2 = 0;
int lastCount2 = 0;
unsigned int tcnt2 = 0;
unsigned int tcnt0 = 0;
int toggle = 0;
int POT = A1;
volatile int potVal = 50;
int lastPot = 0;
ISR(TIMER2_OVF_vect) // interrupt service routine that executes when Timer2
//overflows
{
TCNT2 = tcnt2;
TCNT0 = tcnt0;
// digitalWrite(ledPin, toggle == 0 ? HIGH : LOW);
// toggle = ~toggle;
++overflowCount;
digitalWrite(ledPin, HIGH);
}
ISR(TIMER0_COMPA_vect) //interrupt service routine that executes when Timer0
//matches OCR0A (potVal)
{
++count2;
digitalWrite(ledPin, LOW);
}
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
//Timer2 for LED turn on
TIMSK2 &= ~(1<<TOIE2); //dissable interrupt while configuring
TCCR2A &= ~((1<<WGM21) | (1<<WGM20)); // configure timer2 in normal mode
//counting up with no PWM
TCCR2B &= ~(1<<WGM22);
ASSR &= ~(1<<AS2); //select internal clock source
TIMSK2 &= ~(1<<OCIE2A); //disable Compare Match A interrupt enable
TCCR2B |= /*(1<<CS20) |*/ (1<<CS21) | (1<<CS22); //set bits
TCCR2B &= ~((1<<CS20) /*| (1<<CS21) | (1<<CS22)*/); //clear bits
TCNT2 = tcnt2;
TIMSK2 |= (1<<TOIE2); //interrupt on Timer2 overflow
//Timer0 for LED turn off
TCCR0A |= (1<<WGM01); //CTC mode
OCR0A = potVal;
TIMSK0 |= (1<<OCIE0A); //interrupt on Compare A match enable
TCNT0 = tcnt0;
TCCR0B |= /*(1<<CS00) |*/ (1<<CS21) | (1<<CS22); //set bits
TCCR0B &= ~((1<<CS00) /*| (1<<CS21) | (1<<CS22)*/); //clear bits
}
void loop()
{
potVal = analogRead(POT);
if ((potVal > (lastPot+25)) | (potVal < (lastPot-25)))
{
potVal = potVal/4;
OCR0A = potVal;
}
if (overflowCount > lastCount)
{
lastCount = overflowCount;
// Serial.print("overflow = ");
// Serial.println(overflowCount);
Serial.print("POT = ");
Serial.println(potVal);
}
if (count2 > lastCount2)
{
Serial.print("count = ");
lastCount2 = count2;
Serial.println(count2);
}
}