Figaro
manufactures sensors that can sniff out various kinds of gases (e.g.
hydrogen, methane, carbon monoxide, etc.). I've designed a simple circuit built around the Figaro
LPM2610 module which will sound an alarm if and when the level of
liquified petroleum gas (LPG) in the kitchen rises above a certain predetermined
level.
I knew the dimensions of the module from the datasheet but when they arrived I
was still quite surprised they're tiny. Nothing against it of course. I
don't want a huge daughter board sitting on my main board.
The surface mount chips are all resistors. No electrostatic discharge
sensitive components here at all. The thermistor is the unmarked black
chip at the upper left corner.
As per datasheet the dark blue bands on the trimpot should be lined up to ensure it's in the calibrated position.
The Figaro module contains the
TGS2610 sensor and various resistors to create two voltage dividers--one for the sensor output and the other for the reference voltage. Whenever sensor voltage V
OUT is equal to the temperature-compensated reference voltage this indicates the LPG concentration in the air is (theoretically) 10% of the lower explosive limit (LEL) of
isobutane. As per the datasheet, butane LEL is 18,000 ppm which is equivalent to 1.8% by volume (although
one website puts it at 16,000 ppm or 1.6%).
In
Application Note for LP Gas Detectors using TGS2610 Figaro provides a wealth of information to get an application up and running. One of the more important tips therein is that the TGS2610 needs a warm up time to get the sensor up to its working temperature. Figaro recommends waiting 2.5 minutes. During this preheating stage the sensor's output is unreliable. In the same AN Figaro suggests circuits to detect heater as well as sensor failures.
According to the datasheet the typical current through the heater @5.0V is 56mA. Although Figaro suggests using a 3.57-ohm current sense resistor to detect heater failure, at the moment what I have are a couple of 2 ohms. 56mA x 2 ohms = 112mV. Therefore, my V
DD has to be around 5.1V to obtain a voltage drop of ~5.0V across the heater. So I configured a power supply using an LM317 voltage regulator to output this value. V
OUT and V
REF were unity-gain buffered while the current sense voltage was gained by 20. Output of the op amps were hooked up to a
Dataq DI-145 to record the values. I then performed a cold start (i.e, the module had not been powered for at least an hour to make sure it's at room temperature).
In the screenshot below you can see that while the heater is ramping up to its working temperature V
OUT gradually settles down (approx 0.3 to 0.4V). This takes >100sec.
Interestingly, voltage across heater current sense resistor spikes upon power up and then exponentially settles. This inrush current suggests that the heater has a cold resistance lower than its hot resistance--just like the filament of an incandescent lamp.
Channel 1: V
OUT
Ch2: V
REF
Ch3: voltage across 2-ohm current sense resistor amplified 20x
Ch4: unused
Vertical: 0.5 volts/div
Horizontal: 5 sec/div
Data acquisition rate: 16 samples/sec
To get a higher resolution and better picture of what's happening during power up I increased the sample rate to the Dataq's maximum of 240/sec.
What's interesting in the image below is how V
OUT stays at nearly zero volt (~20 to 30mV according to Windaq) for around 1 second before climbing. Since this is the voltage across the load resistor (R
L), apparently the semiconductor sensor (R
S) which is in series with R
L has an extremely high resistance at room temperature which drops drops dramatically as it begins to heat up, thus behaving like a negative temperature coefficient (NTC) thermistor. However, its resistance begins to gradually increase as it reaches a certain temperature. Figaro has this
short intro to the construction and operating principles of its sensors
Channel 1: V
OUT
Ch2: V
REF
Ch3: voltage across 2ohm current sense resistor and then amplified by a nominal gain of 20
Ch4: V
DD
Vertical: 0.491 volts/div for Channels 1 to 3, 0.231 V/div for Ch4
Horizontal: 0.33 sec/div
Data acquisition rate: 240 samples/sec
Complete Working Circuit
Given that Figaro AN gives a suggestion on how to detect sensor failure, it must be that this is a distinct possibility. Since I'm using a quad op amp (
MCP609) I decided to make use of what would be an unused device and connected V
OUT to it and then configured it to have the same gain as the amplifier for the heater current sense resistor. Normally the output of this noninverting amplifier would be close to V
DD. However, when the sensor does fail op amp output will be much closer to ground.
Schematic of a fully working LPG detector:
Instead of using comparators as the Figaro AN suggests an MCU with ADC and/or a comparator simplifies the design and affords far more flexibility. The schematic shows the connections given a Microchip
PIC12F615 8-pin microcontroller. The 1K resistors in series with the output of two op amps are only necessary because the MCU pins to which they are connected are also used for in-circuit serial programming. The resistors isolate the op amps during programming. Without them the PICkit2/3 will not be able to properly upload the firmware. A buzzer and an LED provide the alarms.
I've routed V
OUT to one of the MCU's comparator inverting input pin (CIN0- / AN1) and V
REF to the comparator noninverting input pin (CIN+ / AN0). This allows the firmware to use the comparator as well as the ADC to compare the two voltages. Thus, in the firmware below, I have preprocessor directives that allow the user to choose--before compilation--either ADC or voltage comparator.
To make sure the firmware works I initially used simple voltage dividers to emulate the outputs of the Figaro module:
Heater failure was simulated by simply disconnecting the 91-ohm resistor from V
DD . Potentiometer permits testing the full range of V
OUT from 0 to V
DD.
After I was satisfied the firmware was bug-free, I removed all the resistors and plugged the LPM2610 into the breadboard and tested the circuit in the kitchen with the stove disconnected from the mains power so that the stove's spark plug like igniters wouldn't function as I turned the knobs to let gas out. During the test what got me immediately concerned is that it took what seemed a rather high concentration of gas to trigger the sensor. I had to place the breadboard really up close to the stove burner where the gas comes out to get the circuit to trigger the alarm. When the breadboard was a couple of feet away, I had to keep the stove knob depressed for longer than I felt safe (and the smell of gas was getting to me). I had a DMM hooked up to V
OUT so I could monitor it. And from that feedback I felt that 10% LEL was still too high a threshold. Why not lower it to 5% or perhaps even less than that? And while at it why not include a digital display showing how much gas the sensor is detecting? Since that involves a host of mathematical acrobatics I will tackle that project in another blog entry.
One other revelation of note. LPG is usually a mix of butane and propane. At room temperature butane has a
density of ~2.5 kg/m
3, propane ~1.9, and air ~1.2. Since the two gases have higher densities than air (butane being twice as heavy as air) they ought to sink and crawl along the floor. And so that's where I plan to install the circuit when I finish building it. But during the test I got practically the same reading at floor level as before I started letting gas leak out. Instead, and oddly, the sensor was giving a higher reading at half a meter above the stove. It's possible that air currents at the time of the test could have carried the gas upwards. Exit velocity of the gas and its trajectory could be factors too. And there may be other parameters as well of course. Will need to reassess and determine where best to place the sensor circuit.
Firmware
Upon power up there will be a 150-second preheating period indicated by a an audible alert (a short beep once every second). During normal operation the outputs of the LPM2610 is checked four times a second--gas travels and diffuses through the air at a very low speed so there's no need to rapidly poll the sensor. In fact 4 samples/sec may even be considered too fast. During each reading heater and sensor are checked. If voltage across current sense resistor is below a set threshold then the LSb of the16-bit variable VHEAT is set (made = 1). The latest reading
is in the LSb while the oldest reading is in the MSb. If VHEAT = 0xFFFF
and its current state is that heater is ok, then state is now that heater is faulty. A "heater just became faulty" edge trigger is issued. On the other hand, if
VHEAT = 0x0000 and and its current state is that heater is faulty then
state is now that heater is ok. A "heater has just returned to normal operation" edge trigger is issued. Any VHEAT value other than 0x0000 and 0xFFFF is analogous to a bouncing switch contact and no action is taken. All bits in VHEAT are then shifted left with zero getting shifted into the LSb.
To check the integrity of the sensor the value of V
OUT (gained by 20) is checked. If it dips below a set threshold then the
LSb of the16-bit variable VSENSE is set (made = 1). The latest reading
is in the LSb while the oldest reading is in the MSb. If VSENSE = 0xFFFF
and its current state is that sensor is ok, then state is now that
sensor is faulty. A "sensor just became faulty" edge trigger is issued.
On the other hand, if
VSENSE = 0x0000 and and its current state is that sensor is faulty then
state is now that sensor is ok. A "sensor has just returned to normal operation"
edge trigger is issued. Any VSENSE value other than 0x0000 and 0xFFFF is analogous to a bouncing switch contact and no action is taken. All bits in VSENSE are then shifted left with
zero getting shifted into the LSb.
If heater and sensor are both ok (but not if either is faulty), then V
OUT is compared to V
REF. If V
OUT is > V
REF then the LSb of the16-bit variable VLPG is set (made = 1). The latest reading is in the LSb while the oldest reading is in the MSb. If VLPG = 0xFFFF and its current state is that LPG is absent, then state is now that LPG is present. An "LPG present" edge trigger is issued. On the other hand, if VLPG = 0x0000 and and its current state is that LPG is present then state is now that LPG is absent. An "LPG absent" edge trigger is issued. Any VLPG value other than 0x0000 and 0xFFFF is analogous to a bouncing switch contact and no action is taken. All bits in VLPG are then shifted left with zero getting shifted into the LSb.
If either heater or sensor is faulty or if LPG is detected then the appropriate alarm is sounded. The alarm patterns for each of the conditions are as follows:
Heater fault: 100ms beep -> 500ms silence -> 100ms beep -> 4000ms silence -> repeat
Sensor fault: 100ms beep -> 500ms silence -> 100ms beep -> 500ms silence -> 100ms beep -> 4000ms silence -> repeat
LPG detection: 500ms beep -> 500ms silence -> 500ms beep -> 500ms silence -> 2000ms silence -> repeat
Should heater be faulty and for some strange reason reverts to normal, then firmware will enter an infinite loop to let the watchdog timer time out and reset the MCU. This is to force the heater to go through the preheating stage.
/*
Liquified petroleum gas (LPG) detector
When LPG level exceeds a set threshhold audible and visual alarms are activated
When Figaro LPM2610 heater or sensor fault is detected, alarms are activated
Configuration: all enabled except for code protect
Internal oscllator @4MHz, I/0 on clock pins
CONFIG :$2007 : 0x036C
ALARMS/ALERTS:
During power up delay: 25ms beeps every second for around 2.5mins
Heater fault: 100ms beep -> 500ms silence -> 100ms beep -> 4000ms silence -> repeat
Sensor fault: 100ms beep -> 500ms silence -> 100ms beep -> 500ms silence -> 100ms beep -> 4000ms silence -> repeat
LPG detection: 500ms beep -> 500ms silence -> 500ms beep -> 500ms silence -> 2000ms silence -> repeat
LEL = lower explosion limit
LEL of butane = 18,000ppm = 1.8% by volume
For the LPM2610 when Vout = Vref then LPG level is ~10% LEL
*/
// ===========================================================================================
// Values for the following defines can be changed as needed
// ===========================================================================================
//***********************************************
// comment out the following define when done debugging
#define debug
//***********************************************
#ifdef debug
#define powerupdelaysec 10
#else
#define powerupdelaysec 150 // number of seconds to allow heater to reach working temperature during power up reset
// according to datasheet recommended preheating time is 2.5min
#endif
//***********************************************
// comment out the following define if vlpg and vref will be measured by the ADC instead of volt comaparator module
// either ADC or comparator can be used
#define use_comparator
//***********************************************
#define heat_resist_volt 75 // actual millivolts across current sense resistor below which is considered practically zero and therefore indication of heater failure
#define sense_volt 50 // actual millivolts of LM2610 sensor output voltage below which is considered practically zero and therefore indication of sensor failure
#define gain 20 // op amp gain
#define shortbeep_ms 100 // duration of a short beep, in actual milliseconds. maximum of 524ms
#define shortpause_ms 500 // duration of a short pause, in actual milliseconds. maximum of 524ms
#define longpause_ms 4000 // duration of a long pause, in actual milliseconds. *minimum* of 500ms
#define lpg_beep_ms 500 // LPG detected alarm: duration of first beep, in actual milliseconds. maximum of 524ms
#define lpg_pause1_ms 500 // LPG detected alarm: duration of first pause, in actual milliseconds. maximum of 524ms
#define lpg_pause2_ms 2000 // LPG detected alarm: duration of second pause, in actual milliseconds. *mininum* of 500ms
#define reset_beep_ms 25 // power up delay alert: duration of beep, in actual milliseconds. maximum of 524ms
#define reset_pause_ms 1000 // power up delay alert: duration of pause between beeps, in actual milliseconds. *mininum* of 500ms
// ===========================================================================================
// !! WARNING WILL ROBINSON !! DO NOT ALTER THE DEFINES BELOW !!
// ===========================================================================================
#define int1 bit
#define int8 unsigned char
#define int16 unsigned int
#define int32 unsigned long
#define on 1
#define off 0
#define input 1 // for TRISx
#define output 0 // for TRISx
#define analog 1 // for ANSELx
#define digital 0 // for ANSELx
#define hi 1 // switch level high
#define lo 0 // switch level low
#define Vdd 5100 // Vdd voltage
#define heater_threshold heat_resist_volt*gain*1024/Vdd // convert to 10-bit ADC value given ADC ref voltage = Vdd
#define sense_threshold sense_volt*gain*1024/Vdd // convert to 10-bit ADC value given ADC ref voltage = Vdd
// TMR1H initial values for various alarms (Fosc = 4MHz, timer1 prescale = 1:8, TMR1L starts at zero)
#define t1h_shortbeep 256-(shortbeep_ms*1000/(256*8) + 0.5)
#define t1h_shortpause 256-(shortpause_ms*1000/(256*8) + 0.5)
#define t1h_longpause 256-(500*1000/(256*8) + 0.5)
#define longpause_cycles longpause_ms / 500
// TMR1H initial values for LPG detection alarm (Fosc = 4MHz, timer1 prescale = 1:8, TMR1L starts at zero)
#define t1h_lpgbeep 256-(lpg_beep_ms*1000/(256*8) + 0.5)
#define t1h_lpgpause1 256-(lpg_pause1_ms*1000/(256*8) + 0.5)
#define t1h_lpgpause2 256-(500*1000/(256*8) + 0.5)
#define lpg_pause2_cycles lpg_pause2_ms / 500
// TMR1H initial values for power-up delay alert (Fosc = 4MHz, timer1 prescale = 1:8, TMR1L starts at zero)
#define t1h_resetbeep 256-(reset_beep_ms*1000/(256*8) + 0.5)
#define t1h_resetpause 256-(500*1000/(256*8) + 0.5)
#define reset_pause_cycles reset_pause_ms / 500
#define buz GPIO.f5 // buzzer
#define tris_buz TRISIO.f5
#define tris_vref TRISIO.f0 // LPM2610 Vref pin
#define tris_vlpg TRISIO.f1 // LPM2610 Vout pin
#define tris_vsense TRISIO.f2 // LPM2610 Vout pin with gain = 20
#define tris_vheat TRISIO.f4 // voltage across heater current sense resistor with gain = 20
// GP4 is AN3
#define an_vref ANSEL.f0
#define an_vlpg ANSEL.f1
#define an_vsense ANSEL.f2
#define an_vheat ANSEL.f3
#define ch_vref 0 // for use with ADCON0 when selecting analog channel
#define ch_vlpg 1 // for use with ADCON0 when selecting analog channel
#define ch_vsense 2 // for use with ADCON0 when selecting analog channel
#define ch_vheat 3 // for use with ADCON0 when selecting analog channel
#define cmch_vlpg 0 // for use with CMCON0 when selecting comparator channel
#define _lpg_absent 0 // for use with variable statelpg
#define _lpg_present 1 // for use with variable statelpg
#define _heater_ok 0 // for use with variable stateheater
#define _heater_fault 1 // for use with variable stateheater
#define _sensor_ok 0 // for use with variable statesense
#define _sensor_fault 1 // for use with variable statesense
#define none 0 // for use with edge detect
bit stateheater; // status of LPM2610 heater, whether ok or faulty
bit statesense; // status of LPM2610 sensor, whether ok or faulty
bit statelpg; // status of lpg detection, whether detected or not
bit powerreset; // 1 = power up delay in progress; ISR needs this to determine which alarm pattern to sound
enum {heatfaultbegin = 1, heatfaultend} HEATEDGE; // edge detect: 0 = no edge detected, 1 = heater fault has just been detected, 2 = heater fault has just been resolved
enum {sensefaultbegin = 1, sensefaultend} SENSEEDGE; // edge detect: 0 = no edge detected, 1 = sensor fault has just been detected, 2 = sensor fault has just been resolved
enum {lpgdetectbegin = 1, lpgdetectend} LPGEDGE; // edge detect: 0 = no edge detected, 1 = level of LPG in the air has just gone above detection threshold, 2 = level of LPG has just dropped below threshold
enum {_heatbeep1, _heatpause1, _heatbeep2, _heatpause2} STATEHEATALARM;
enum {_sensebeep1, _sensepause1, _sensebeep2, _sensepause2, _sensebeep3, _sensepause3} STATESENSEALARM;
enum {_lpgbeep1, _lpgpause1, _lpgbeep2, _lpgpause2} STATELPGALARM;
enum {_resetbeep1, _resetpause1} STATERESETALARM;
int16 VLPG = 0; // 0x0000 = no lpg detected, 0xFFFF = lpg detected, any other value implies bouncing
int16 VHEAT = 0; // 0x0000 = LPM2610 heater functioning, 0xFFFF = heater fault detected, any other value implies bouncing
int16 VSENSE = 0; // 0x0000 = LPM2610 sensor functioning, 0xFFFF = sensor fault detected, any other value implies bouncing
// ===========================================================================================
// Functions
// ===========================================================================================
void BuzzOn()
{
buz = on;
}
void BuzzOff()
{
buz = off;
}
// turn off buz and led and disable timer
void DisarmAlarm()
{
T1CON.TMR1ON = 0;
INTCON.GIE = 0;
BuzzOff();
}
void ArmAlarm()
{
INTCON.GIE = 1;
TMR1L = 0;
T1CON = 0b110001; // prescale = 1:8, timer1 on
PIR1.TMR1IF = 1;
}
// Figaro LPM2610 needs preheating time during which output signal is unreliable.
void PowerUpDelay()
{
int8 i;
OPTION_REG = 0b10001111; // global weak pull ups disabled, prescaler assigned to WDT, prescale = 1:128
STATERESETALARM = 0;
powerreset = 1;
ArmAlarm();
for (i = 0; i < powerupdelaysec; i++)
{
asm clrwdt // nominal WDT timeout = 18ms without prescale, given WDT prescale = 1:128 WDT = ~2sec
Delay_ms(1000);
}
powerreset = 0;
DisarmAlarm();
OPTION_REG = 0b10000111; // global weak pull ups disabled, prescaler assigned to timer0, prescale = 1:256
// WDT timeout = 18ms
}
void IniReg()
{
GPIO = 0;
ANSEL = 0b1011111; // A/D Conversion Clock = Fosc/16, all four analog channels are analog
tris_buz = output;
WPU = 0; // disable individual pullups
OPTION_REG.NOT_GPPU = 1; // disable global pull up
INTCON.PEIE = 1;
PIE1.TMR1IE = 1;
#ifdef use_comparator
CMCON0 = 0b10000; // comparator off, COUT internal only, COUT logic inverted, CMVin+ connected to CIN+
CMCON0.CMCH = cmch_vlpg; // only one comparator channel is used -- the one connected to Vout of LPM2610
#endif
stateheater = _heater_ok;
statesense = _sensor_ok;
statelpg = _lpg_absent;
}
int16 ADC(int8 channel)
{
ADCON0 = channel << 2; // shift in channel
ADCON0.ADFM = 1; // right justified format
ADCON0.VCFG = 0; // VDD as ref voltage
ADCON0.ADON = 1; // ADC on
Delay_us(20); // datasheet says ADC acquisition time typically takes 12us
ADCON0.GO = 1; // start ADC conversion
while(ADCON0.GO) ; // wait
ADCON0.ADON = 0; // ADC off
return ADRESH*256 + ADRESL;
}
void ReadFigaro()
{
HEATEDGE = none;
SENSEEDGE = none;
LPGEDGE = none;
if (ADC(ch_vheat) < heater_threshold)
++VHEAT;
if (VHEAT == 0xFFFF && stateheater == _heater_ok)
{
HEATEDGE = heatfaultbegin;
stateheater = _heater_fault;
}
else if (!VHEAT && stateheater == _heater_fault)
{
HEATEDGE = heatfaultend;
stateheater = _heater_ok;
}
VHEAT <<= 1;
if (ADC(ch_vsense) < sense_threshold)
++VSENSE;
if (VSENSE == 0xFFFF && statesense == _sensor_ok)
{
SENSEEDGE = sensefaultbegin;
statesense = _sensor_fault;
}
else if (!VSENSE && statesense == _sensor_fault)
{
SENSEEDGE = sensefaultend;
statesense = _sensor_ok;
}
VSENSE <<= 1;
if (stateheater == _heater_ok && statesense == _sensor_ok); // do not read figaro outputs if heater or sensor is faulty
{
// ===========================================================================================
// ADC or comparator can be used to measure vlpg and vref
#ifdef use_comparator
CMCON0.CMON = 1;
Delay_us(10); // datasheet does not specify a settling time but it has a "mode change to output valid time" of 10us. So to be on the safe side allow some delay between comparator turn-on and reading of output
if (CMCON0.COUT)
++VLPG;
CMCON0.CMON = 0; // comparator module consumes >60uA @5V so turn off after reading channel
#else
if (ADC(ch_vlpg) > ADC(ch_vref))
++VLPG;
#endif
// ===========================================================================================
if (VLPG == 0xFFFF && statelpg == _lpg_absent)
{
LPGEDGE = lpgdetectbegin;
statelpg = _lpg_present;
}
else if (!VLPG && statelpg == _lpg_present)
{
LPGEDGE = lpgdetectend;
statelpg = _lpg_absent;
}
VLPG <<= 1;
}
}
void Status()
{
if (LPGEDGE == lpgdetectbegin)
{
STATELPGALARM = 0;
ArmAlarm();
}
else if (LPGEDGE == lpgdetectend)
DisarmAlarm();
if (SENSEEDGE == sensefaultbegin)
{
STATESENSEALARM = 0;
ArmAlarm();
}
else if (SENSEEDGE == sensefaultend)
DisarmAlarm();
if (HEATEDGE == heatfaultbegin)
{
STATEHEATALARM = 0;
ArmAlarm();
}
else if (HEATEDGE == heatfaultend)
while(1) ; // if heater was faulty but somehow fault condition got resolved then restart the MCU
// let WDT timeout reset the MCU so that heater will have preheat time
} // void Status()
void interrupt()
{
int8 COUNT;
if (PIR1.TMR1IF)
{
PIR1.TMR1IF = 0;
if (stateheater == _heater_fault)
{
switch (STATEHEATALARM)
{
default:
case _heatbeep1:
BuzzOn();
TMR1H = t1h_shortbeep;
STATEHEATALARM = _heatpause1;
break;
case _heatpause1:
BuzzOff();
TMR1H = t1h_shortpause;
STATEHEATALARM = _heatbeep2;
break;
case _heatbeep2:
BuzzOn();
TMR1H = t1h_shortbeep;
STATEHEATALARM = _heatpause2;
COUNT = 0;
break;
case _heatpause2:
BuzzOff();
TMR1H = t1h_longpause;
if (++COUNT >= longpause_cycles)
STATEHEATALARM = _heatbeep1;
break;
} // switch (STATEHEATALARM)
} // if (stateheater == _heater_fault)
else if (statesense == _sensor_fault)
{
switch (STATESENSEALARM)
{
default:
case _sensebeep1:
BuzzOn();
TMR1H = t1h_shortbeep;
STATESENSEALARM = _sensepause1;
break;
case _sensepause1:
BuzzOff();
TMR1H = t1h_shortpause;
STATESENSEALARM = _sensebeep2;
break;
case _sensebeep2:
BuzzOn();
TMR1H = t1h_shortbeep;
STATESENSEALARM = _sensepause2;
break;
case _sensepause2:
BuzzOff();
TMR1H = t1h_shortpause;
STATESENSEALARM = _sensebeep3;
break;
case _sensebeep3:
BuzzOn();
TMR1H = t1h_shortbeep;
STATESENSEALARM = _sensepause3;
COUNT = 0;
break;
case _sensepause3:
BuzzOff();
TMR1H = t1h_longpause;
if (++COUNT >= longpause_cycles)
STATESENSEALARM = _sensebeep1;
break;
} // switch (STATESENSEALARM)
} // if (statesense == _sensor_fault)
else if (statelpg == _lpg_present)
{
switch (STATELPGALARM)
{
default:
case _lpgbeep1:
BuzzOn();
TMR1H = t1h_lpgbeep;
STATELPGALARM = _lpgpause1;
break;
case _lpgpause1:
BuzzOff();
TMR1H = t1h_lpgpause1;
STATELPGALARM = _lpgbeep2;
break;
case _lpgbeep2:
BuzzOn();
TMR1H = t1h_lpgbeep;
STATELPGALARM = _lpgpause2;
COUNT = 0;
break;
case _lpgpause2:
BuzzOff();
TMR1H = t1h_lpgpause2;
if (++COUNT >= lpg_pause2_cycles)
STATELPGALARM = _lpgbeep1;
break;
} // switch (STATELPGALARM)
} // if (statelpg == _lpg_present)
else if (powerreset)
{
switch (STATERESETALARM)
{
default:
case _resetbeep1:
BuzzOn();
TMR1H = t1h_resetbeep;
STATERESETALARM = _resetpause1;
COUNT = 0;
break;
case _resetpause1:
BuzzOff();
TMR1H = t1h_resetpause;
if (++COUNT >= reset_pause_cycles)
STATERESETALARM = _resetbeep1;
break;
} // switch (STATERESETALARM)
} // if (powerreset)
} // if (PIR1.TMR1IF)
} // void interrupt()
void main()
{
int8 T0COUNT = 0;
IniReg();
PowerUpDelay();
while(1)
{
asm clrwdt;
if (INTCON.T0IF)
{
INTCON.T0IF = 0;
if (++T0COUNT >= 4) // read sensor approx every quarter second
{
T0COUNT = 0;
ReadFigaro();
Status();
} // if (++T0COUNT >= 4)
} // if (INTCON.T0IF)
} // while(1)
} // void main()