As said in a different topic I wanted to experiment with frequency sensing of a FAN pwm signal comming from a motherboard (input capture) on a Xmega.
At the moment I am doing so and I am running against some problems which I cannot figure out by myself.
As a start I used 2 sources of information:
https://www.avrfreaks.net/comment...
and
http://www.dolman-wim.nl/xmega/b... (paragraph 23.18)
And of course the information from the specific FAN:
http://media.digikey.com/pdf/Dat...
Furthermore I created a PWM LED which I could run at 0,5Hz (to test with variable PW).
My problem is that when I run the PWM led with 0,5Hz and lets say 80% this is detected and shown in my USART output. Same for 24k Hz and 80%.
I then get:
Current Frequency: 24060.1503 Hz Current PulseWidth: 80 % Current Frequency: 24060.1503 Hz Current PulseWidth: 80 % Current Frequency: 24060.1503 Hz
The code to generate the PWM:
#define Freq_Val 24000.0F // Required frequency #define PW_Val 80 // Pulse Width (percent) #define ICPreScale 1 // Input Capture Pre-scaler 1/2/4/8/64/256/1024 #define OCPreScale 1 // Output Control Pre-scaler 1/2/4/8/64/256/1024 uint32_t period; // Changed to 32-bits uint32_t pulseWidth; // Changed to 32-bits uint16_t FreqVal; uint16_t PWVal; float frequency;
void init_pwm(void) { PORTD.DIRSET = PIN0_bm; TCD0.CTRLB = TC0_CCAEN_bm | TC_WGMODE_SINGLESLOPE_gc; switch ( OCPreScale ) { case 1: TCD0.CTRLA = TC_CLKSEL_DIV1_gc; break; case 2: TCD0.CTRLA = TC_CLKSEL_DIV2_gc; break; case 4: TCD0.CTRLA = TC_CLKSEL_DIV4_gc; break; case 8: TCD0.CTRLA = TC_CLKSEL_DIV8_gc; break; case 64: TCD0.CTRLA = TC_CLKSEL_DIV64_gc; break; case 256: TCD0.CTRLA = TC_CLKSEL_DIV256_gc; break; case 1024: TCD0.CTRLA = TC_CLKSEL_DIV1024_gc; break; } FreqVal = (F_CPU/(Freq_Val*OCPreScale))-1; // Page 173 Xmega AU manual PWVal = ((PW_Val*(uint32_t)FreqVal)/100); TCD0.PER = FreqVal; TCD0.CCA = PWVal; }
Then my code to init the freq and PW:
void init_inputFREQcapture(void) { PORTD.DIRCLR = PIN4_bm; PORTD.PIN4CTRL = PORT_OPC_PULLDOWN_gc | PORT_ISC_RISING_gc; EVSYS.CH0MUX = EVSYS_CHMUX_PORTD_PIN4_gc; EVSYS.CH0CTRL = EVSYS_DIGFILT_8SAMPLES_gc; TCC0.CTRLD = TC_EVACT_FRQ_gc | TC_EVSEL_CH0_gc; TCC0.CTRLB = TC0_CCAEN_bm | TC_WGMODE_NORMAL_gc; switch ( ICPreScale ) { case 1: TCC0.CTRLA = TC_CLKSEL_DIV1_gc; break; case 2: TCC0.CTRLA = TC_CLKSEL_DIV2_gc; break; case 4: TCC0.CTRLA = TC_CLKSEL_DIV4_gc; break; case 8: TCC0.CTRLA = TC_CLKSEL_DIV8_gc; break; case 64: TCC0.CTRLA = TC_CLKSEL_DIV64_gc; break; case 256: TCC0.CTRLA = TC_CLKSEL_DIV256_gc; break; case 1024: TCC0.CTRLA = TC_CLKSEL_DIV1024_gc; break; } } void init_inputPWcapture(void) { PORTD.DIRCLR = PIN5_bm; PORTD.PIN4CTRL = PORT_OPC_PULLDOWN_gc | PORT_ISC_RISING_gc; EVSYS.CH1MUX = EVSYS_CHMUX_PORTD_PIN5_gc; EVSYS.CH1CTRL = EVSYS_DIGFILT_8SAMPLES_gc; TCC1.CTRLD = TC_EVACT_PW_gc | TC_EVSEL_CH1_gc; TCC1.CTRLB = TC1_CCAEN_bm | TC_WGMODE_NORMAL_gc; switch ( ICPreScale ) { case 1: TCC1.CTRLA = TC_CLKSEL_DIV1_gc; break; case 2: TCC1.CTRLA = TC_CLKSEL_DIV2_gc; break; case 4: TCC1.CTRLA = TC_CLKSEL_DIV4_gc; break; case 8: TCC1.CTRLA = TC_CLKSEL_DIV8_gc; break; case 64: TCC1.CTRLA = TC_CLKSEL_DIV64_gc; break; case 256: TCC1.CTRLA = TC_CLKSEL_DIV256_gc; break; case 1024: TCC1.CTRLA = TC_CLKSEL_DIV1024_gc; break; } }
And in my main loop:
while(1) { // Current period & pulse width period = TCC0.CCA; pulseWidth = TCC1.CCA; // Calculate frequency = (F_CPU/((float)period*ICPreScale)); // Frequency from last capture. uint16_t d1 = frequency; // Get the integer part (678). float f2 = frequency - d1; // Get fractional part (678.0123 - 678 = 0.0123). int d2 = trunc(f2 * 10000); // Turn into integer (123). sprintf (str, "%d.%04d", d1, d2); //sprintf(str,"%u", frequency); dbgPutStr("Current Frequency: "); dbgPutStr(str); dbgPutStr(" Hz\r\n"); // PulseWidth from last capture. sprintf(str,"%lu", (((pulseWidth+1)*100)/period)); dbgPutStr("Current PulseWidth: "); dbgPutStr(str); dbgPutStr(" %\r\n"); _delay_ms( BLINK_DELAY_MS ) ; // wait. }
The result when I am trying to get the frequency from my FAN PWM:
Current Frequency: 1252.4461 Hz Current PulseWidth: 4 % Current Frequency: 1204.1845 Hz Current PulseWidth: 4 % Current Frequency: 1203.1884 Hz Current PulseWidth: 4 % Current Frequency: 1250.7817 Hz Current PulseWidth: 4 % Current Frequency: 1244.3614 Hz Current PulseWidth: 4 % Current Frequency: 1990.7926 Hz
These are with the same settings as blinking the led...
I have read the manual multiple times, but it might be something with the PWM signal type. But at the moment I am shooting blind. Hope someone can give me a tip what to look for.
Thank you all in advance.