add basic tachometer reader

This commit is contained in:
King Kévin 2013-10-13 19:39:31 +02:00
parent e4cb5d1f8f
commit be4f8c64bb
1 changed files with 57 additions and 7 deletions

View File

@ -11,9 +11,14 @@
/* global variables */
volatile uint8_t pwr_ok;
volatile uint8_t fan;
volatile uint16_t tachometer = 0;
volatile uint8_t timer2_ovf = 0;
const uint16_t TIMER2_PRESCALE[8] = {0,1,8,32,64,128,256,1024};
/* PWR_OK interrupt */
ISR(PCINT0_vect) { /* PCINT1 is actually triggering PCI0 Interrupt Vector */
ISR(PCINT0_vect) { /* PCI0 Interrupt Vector for PCINT[7:0] */
if (pwr_ok!=(PINB&(1<<PWR_OK))) { /* did the PWR_OK pin state changed */
pwr_ok = PINB&(1<<PWR_OK); /* save new state */
if (pwr_ok) {
@ -24,6 +29,25 @@ ISR(PCINT0_vect) { /* PCINT1 is actually triggering PCI0 Interrupt Vector */
}
}
/* fan tachometer interrupt */
ISR(PCINT1_vect) { /* PCI0 Interrupt Vector for PCINT[14:8] */
if (fan!=(PINC&(1<<FAN))) { /* did the FAN pin state changed */
fan = PINC&(1<<FAN); /* save new state */
if (fan) {
tachometer = timer2_ovf*256+TCNT2; /* save time */
TCNT2 = 0; /* reset timer 2 */
timer2_ovf = 0; /* reset timer 2 overflow counter */
}
}
}
/* timer 2 interrupt used to measure fan tachometer */
ISR(TIMER2_OVF_vect) { /* timer 2 overflow interrupt verctor */
if(pwr_ok) { /* only measure tachometer if power is ok */
timer2_ovf++; /* increase time 2 overflow counter */
}
}
static void ioinit(void)
{
/* configure power */
@ -37,7 +61,22 @@ static void ioinit(void)
/* configure peripherals */
DDRB &= ~(1<<IR); /* IR receiver is input */
DDRC &= ~(1<<FAN); /* FAN is input */
/* configure FAN */
DDRC &= ~(1<<FAN); /* FAN (PC5/PCINT13) is input */
fan = PINC&(1<<FAN); /* save state */
PCIFR &= ~(1<<PCIF1); /* clear interrupt flag */
PCICR |= (1<<PCIE1); /* enable interrupt for PCINT[14:8] */
PCMSK1 |= (1<<PCINT13); /* enable interrupt for PCINT1 */
/* use timer 2 to measure the tachometer */
/* use normal mode */
TCCR2A &= ~((1<<WGM20)|(1<<WGM21));
TCCR2B &= ~(1<<WGM22);
/* /256 prescale timer */
TCCR2B |= (1<<CS22)|(1<<CS21);
TCCR2B &= ~(1<<CS20);
TIFR2 &= ~(1<<TOV2); /* clear timer 2 overflow interrupt flag */
TIMSK2 |= (1<<TOIE2); /* enable timer 2 overflow interrupt */
/* configure channels (used for powering LEDs using an nMOS) */
DDRC |= (1<<CH1_1)|(1<<CH1_2)|(1<<CH1_3)|(1<<CH1_4)|(1<<CH1_5); /* CH1_x is output */
@ -52,7 +91,7 @@ static void ioinit(void)
/* configure LED (on PD6/OC0A) */
DDRD |= (1<<LED); /* LED is output */
/* use phase correct PWM ode (because fast PWM is always on for at least 1 cycle) */
/* use phase correct PWM mode (because fast PWM is always on for at least 1 cycle) */
TCCR0A &= ~(1<<WGM01);
TCCR0A |= (1<<WGM00);
TCCR0B &= ~(1<<WGM02);
@ -89,13 +128,13 @@ int main(void)
}
break;
case 'a':
PINB |= (1<<nPS_ON);
printf("power supply: ");
printf("switching power supply ");
if (PINB&(1<<nPS_ON)) {
puts("off");
} else {
puts("on");
} else {
puts("off");
}
PINB |= (1<<nPS_ON);
break;
case 's':
printf("power: ");
@ -207,6 +246,17 @@ int main(void)
}
printf("increasing LED: %d\n",OCR0A);
break;
case 't':
if (tachometer) {
uint16_t prescale = TIMER2_PRESCALE[TCCR2B&((1<<CS22)|(1<<CS21)|(1<<CS20))];
if (prescale) {
uint32_t speed = ((60*F_CPU)/(prescale*(uint32_t)tachometer))/2;
printf("fan speed: %lurpm\n",speed);
}
} else {
printf("fan off or too slow\n");
}
break;
}
}