edge28
Newbie level 3
Hello,
sorry fo my English. I have the following problem.
I made a induction tachometer with a PIC16F876A (28 pin) and I view the RPM on LCD display. I am attaching the electronic scheme of my circuit. In input to optoisolator 4n35 arrive the pulses induced in a wire wrapped around the spark plug. The maximum induced voltage is about 4V.
The PIC firmware works in this mode:
For each pulse generates an interrupt which goes to increment a counter. After a second multiply the pulses counted for 60 and get the RPMs. In this way the reading is inaccurate because the displayed values fluctuate a lot and reading is not stable. To resolve this problem, I made an average of 4 readings and then I displayed the result on the LCD. In this way the reading is more stable but I always get variations between readings and the next. Basically I would not change between reading and the next if the variation is within + / - 50 rpm.
Example :
- first reading: 1520 RPM
- second reading: 1568 RPM
in this case the value displayed on the LCD must remain 1520 and not 1568 because the variation è < +/- 50 RPM. How can I do to stabilize the reading in C language ?
I use like reference tachometer the "TINY TACH" induction tachometer which is very stable :-(
The firmware of my PIC is the sequent:
I tried to write code like:
but does not work. Continue reading to vary even if the difference between the current and the next is between +/- 50 rpm.
sorry fo my English. I have the following problem.
I made a induction tachometer with a PIC16F876A (28 pin) and I view the RPM on LCD display. I am attaching the electronic scheme of my circuit. In input to optoisolator 4n35 arrive the pulses induced in a wire wrapped around the spark plug. The maximum induced voltage is about 4V.
The PIC firmware works in this mode:
For each pulse generates an interrupt which goes to increment a counter. After a second multiply the pulses counted for 60 and get the RPMs. In this way the reading is inaccurate because the displayed values fluctuate a lot and reading is not stable. To resolve this problem, I made an average of 4 readings and then I displayed the result on the LCD. In this way the reading is more stable but I always get variations between readings and the next. Basically I would not change between reading and the next if the variation is within + / - 50 rpm.
Example :
- first reading: 1520 RPM
- second reading: 1568 RPM
in this case the value displayed on the LCD must remain 1520 and not 1568 because the variation è < +/- 50 RPM. How can I do to stabilize the reading in C language ?
I use like reference tachometer the "TINY TACH" induction tachometer which is very stable :-(
The firmware of my PIC is the sequent:
Code:
#define COST 120
#define DIFF 120
sbit LCD_RS at RB2_bit;
sbit LCD_EN at RB3_bit;
sbit LCD_D4 at RB4_bit;
sbit LCD_D5 at RB5_bit;
sbit LCD_D6 at RB6_bit;
sbit LCD_D7 at RB7_bit;
sbit LCD_RS_Direction at TRISB2_bit;
sbit LCD_EN_Direction at TRISB3_bit;
sbit LCD_D4_Direction at TRISB4_bit;
sbit LCD_D5_Direction at TRISB5_bit;
sbit LCD_D6_Direction at TRISB6_bit;
sbit LCD_D7_Direction at TRISB7_bit;
char txt1[]="Tach/hr";
char txt2[]="wait";
char txt3[]="RPM";
char txt4[]="TACH";
int cnt=0;
int display=0;
int ricevuto=0;
int confermato=0;
int ciclo=0;
int risultato=0;
char minuti=0;
char secondi=0;
char ore=0;
char ore2=0;
char pp[6];
char pp3[3];
char pp4[2];
char pp5[2];
int k=0;
int cont=0;
unsigned int rpm_avg[4]; // last 4 RPM values, used to average them
unsigned int rpm_diff[2];
int differenza;
unsigned char diff;
unsigned char avcount; // used to average 4 RPM values
unsigned long accum; // these used for 32bit math to calc RPM
unsigned long math;
void interrupt()
{
if(INTCON.INTF)
{
INTCON.INTF=0;
ricevuto=1;
}
if(INTCON.TMR0IF)
{
//TMR0=22;
TMR0=100;
INTCON.TMR0IF=0;
confermato=1;
}
}
void main()
{
PORTB = 0; // Initialize PORTB
PORTC = 0;
TRISB = 1; // PORTB is output
math = 2; // add half the divisor to stop rounding errors
//Settaggio interrupt
//OPTION_REG.INTEDG=1;
OPTION_REG=0xC6;
secondi=0;
// setup vars
avcount = 0;
diff=0;
rpm_diff[0]=0;
rpm_diff[1]=0;
rpm_avg[0] = 0; // clear average before start
rpm_avg[1] = 0;
rpm_avg[2] = 0;
rpm_avg[3] = 0;
Lcd_Init(); // Initialize LCD
Lcd_Cmd(_LCD_CLEAR); // Clear display
Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
Lcd_Out(1,1,txt1); // Write text in first row
Lcd_Out(2,1,txt2); // Write text in second row
Delay_ms(500);
for(k=0; k<3; k++)
{
Lcd_Out(2,k+5,".");
Delay_ms(1000);
}
Delay_ms(1000);
Lcd_Cmd(_LCD_CLEAR);
Delay_ms(100);
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CLEAR);
ripeti:
Lcd_Out(2,1,txt4);
INTCON=0xB0;
//TMR0=22;
TMR0=100;
/*----------------------------------------------------------------------------*/
do{
}while(ricevuto==0);
if(ricevuto==1)
{
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CLEAR);
Lcd_Out(1,1,txt3);
}
while(cnt<=6)
{
if(ricevuto==1)
{
INTCON.GIE=0;
INTCON.INTE=0;
cont++;
ricevuto=0;
INTCON.GIE=1;
INTCON.INTE=1;
}
if(confermato==1)
{
INTCON.GIE=0;
INTCON.INTE=0;
confermato=0;
risultato=cont;
//TMR0=22;
TMR0=100;
cont=0;
secondi++;
INTCON.GIE=1;
INTCON.INTE=1;
rpm_avg[avcount] = (risultato*60); // include the new RPM value
avcount++;
display++;
if(display>=5) display=5;
if(avcount >= 4) avcount = 0;
// now add the 4 last RPM values
math = (rpm_avg[0] + rpm_avg[1] + rpm_avg[2] + rpm_avg[3]);
math += 2; // add half the divisor to stop rounding errors
// divide the total by 4 to give an average
math = (math / 4);
//risultato = math;
if(display<5)
{
WordToStr(math,pp);
Lcd_Out(2,1,pp);
}
if(display>=5)
{
WordToStr(math,pp);
Lcd_Out(2,1,pp);
}
}
if(math<=2)
{
cnt++;
ricevuto=0;
}
}
if(cnt>6)
{
cnt=0;
Lcd_Cmd(_LCD_CLEAR);
Lcd_Cmd(_LCD_CLEAR);
goto ripeti;
}
}
I tried to write code like:
Code:
rpm_diff[diff]=math;
diff++;
if(diff>=1) diff=0;
difference=(rpm_diff[0]-rpm_diff[1]);
if((difference<=50) &&(difference>=-50))
{
asm nop;
}
else ..... displays the result on LCD
but does not work. Continue reading to vary even if the difference between the current and the next is between +/- 50 rpm.