Freescale Semiconductor Application Note AN1950 Rev 4, 11/2006 Water Level Monitoring by: Michelle Clifford, Applications Engineer Sensor Products, Tempe, AZ INTRODUCTION Many washing machines currently in production use a mechanical sensor for water level detection. Mechanical sensors work with discrete trip points enabling water level detection only at those points. The purpose for this reference design is to allow the user to evaluate a pressure sensor for not only water level sensing to replace a mechanical switch, but also for water flow measurement, leak detection, and other solutions for smart appliances. This system continuously monitors water level and water flow using the temperature compensated MPXM2010GS pressure sensor in the low cost MPAK package, a dual op-amp, and the MC68HC908QT4, eight-pin microcontroller. SYSTEM DESIGN Pressure Sensor The pressure sensor family has three levels of integration — Uncompensated, Compensated and Integrated. For this design, the MPXM2010GS compensated pressure sensor was selected because it has both temperature compensation and calibration circuitry on the silicon, allowing a simpler, yet more robust, system circuit design. An integrated pressure sensor, such as the MPXV5004G, is also a good choice for the design eliminating the need for the amplification circuitry. measuring is between 0–40 cm. This corresponds to a pressure range of 0–4 kPa. Therefore, the MPXM2010GS was selected for this system. The sensor sensitivity is 2.5 mV/kPa, with a full-scale span of 25 mV at the supply voltage of 10 VDC. The full-scale output of the sensor changes linearly with supply voltage, so a supply voltage of 5 V will return a full-scale span of 12.5 mV. (VS actual / VS spec) * VOUT full-scale spec = VOUT full-scale (5.0 V/ 10 V) x 25 mV = 12.5 mV Since this application will only be utilizing 40 percent of the pressure range, 0–4kPa, our maximum output voltage will be 40 percent of the full-scale span. VOUT FS * (Percent FS Range) = VOUT max 12.5 mV * 40% = 5.0 mV The package of the pressure sensor is a ported MPAK package. This allows a tube to be connected to the sensor and the tube is connected to the bottom of the tub. This isolates the sensor from direct contact with the water. The small size and low cost are additional features making this package a perfect fit for this application. Figure 2. A Ported Pressure Sensor Figure 1. Water Level Reference Design Featuring a Pressure Sensor The height of most washing machine tubs is 40 cm, therefore the water height range that this system will be © Freescale Semiconductor, Inc., 2006. All rights reserved. Table 1. MPXM2010D OPERATING CHARACTERISTICS (VS = 10 VDC, TA = 25°C unless otherwise noted, P1 > P2) Characteristic Symbol Min Typ Max Unit Pressure Range POP 0 — 10 kPa Supply Voltage VS — 10 16 Vdc Supply Current IO — 6.0 – mAdc Full Scale Span VFSS 24 25 26 mV Voff -1.0 — 1.0 mV DV/DP — 2.5 — mV/kPa — -1.0 — 1.0 %VFSS Offset Sensitivity Linearity Amplifier Induced Errors The sensor output needs to be amplified before being inputted directly to the microcontroller through an eight-bit A/D input pin. To determine the amplification requirements, the pressure sensor output characteristics and the 0-5 V input range for the A/D converter had to be considered. The amplification circuit uses three op-amps to add an offset and convert the differential output of the MPXM2010GS sensor to a ground-referenced, single-ended voltage in the range of 0–5.0 V. The pressure sensor has a possible offset of ±1 mV at the minimum rated pressure. To avoid a nonlinear response when a pressure sensor chosen for the system has a negative offset (VOFF), we added a 5.0 mV offset to the positive sensor output signal. This offset will remain the same regardless of the sensor output. Any additional offset the sensor or op-amp introduces is compensated for by software routines invoked when the initial system calibration is done. To determine the gain required for the system, the maximum output voltage from the sensor for this application had to be determined. The maximum output voltage from the sensor is approximately 12.5 mV with a 5.0 V supply since the full-scale output of the sensor changes linearly with supply voltage. This system will have a maximum pressure of 4 kPa at 40 cm of water. At a 5.0 V supply, we will have a maximum sensor output of 5 mV at 4 kPa of pressure. To amplify the maximum sensor output to 5.0 V, the following gain is needed: Gain = (Max Output needed) / (Max Sensor Output and Initial Offset) = 5.0 V / (0.005 V + 0.005) = 500 The gain for the system was set for 500 to avoid railing from possible offsets from the pressure sensor or the op-amp. The Voltage Outputs from the sensor are each connected to a non-inverting input of an op-amp. Each op-amp circuit has the same resistor ratio. The amplified voltage signal from the negative sensor lead is VA. The resulting voltage is calculated as follows: VA = (1+R8/R6) * V4 = (1+10/1000) * V4 The amplified voltage signal from the positive sensor lead is VB. This amplification adds a small gain to ensure that the positive lead, V2, is always greater than the voltage output from the negative sensor lead, V4. This ensures the linearity of the differential voltage signal. VB = (1+R7/R5) * V2 – (R7/R5) * VCC = (1+10/1000) * V2 + (10/1000)*(5.0 V) = (1.001) * V2 + 0.005 V The difference between the positive sensor voltage, VB, and the negative sensor voltage, VA is calculated and amplified with a resulting gain of 500. VC = (R12/R11) * (VB – VA) = (500 K/1K) * (VB – VA) = 500 * (VB – VA) The output voltage, VC, is connected to a voltage follower. Therefore, the resulting voltage, VC, is passed to an A/D pin of the microcontroller. The range of the A/D converter is 0 to 255 counts. However, the A/D Values that the system can achieve are dependent on the maximum and minimum system output values: Count = (VOUT – VRL) / ( VRH – VRL) x 255 where VXdcr = Transducer Output Voltage VRH = Maximum A/D voltage VLH = Minimum A/D voltage Count (0 mm H20) = (2.5 – 0) / (5.0 – 0) * 255 = 127 Count (40 mm H20) = (5.0 – 0) / (5.0 – 0) * 255 = 255 Total # counts = 255 – 127 = 127 counts. The resolution of the system is determined by the mm of water represented by each A/D count. As calculated above, the system has a span of 226 counts to represent water level up to and including 40 cm. Therefore, the resolution is: Resolution = mm of water / Total # counts = 400mm/127 counts = 3.1 mm per A/D count = (1.001) * V4 AN1950 2 Sensors Freescale Semiconductor R6 10K V4sensor R8 10Ω 6 5 - 7 VA R12 500K + VCC R11 1K 13 R7 10Ω VCC 12 R9 1K R5 10K V2sensor 2 3 - 1 + C5 0.1µF VC 14 4 - 9 10 8 VOUT + 11 R10 500K VB + Figure 3. Amplification Scheme Microprocessor To provide the signal processing for pressure values, a microprocessor is needed. The MCU chosen for this application is the MC68HC908QT4. This MCU is perfect for appliance applications due to its low cost, small eight-pin package, and other on-chip resources. The MC68HC908QT4 provides: a four-channel, eight-bit A/D, a 16-bit timer, a trimmable internal timer, and in-system FLASH programming. The central processing unit is based on the high performance M68HC08 CPU core and it can address 64 Kbytes of memory space. The MC68HC908QT4 provides 4096 bytes of user FLASH and 128 bytes of random access memory (RAM) for ease of software development and maintenance. There are five bi-directional input/output lines and one input line shared with other pin features. The MCU is available in eight-pin as well as 16-pin packages in both PDIP and SOIC. For this application, the eight-pin PDIP was selected. The eight-pin PDIP was chosen for a small package, eventually to be designed into applications as the eight-pin SOIC. The PDIP enables the customer to reprogram the software on a programming board and retest. Display Depending on the quality of the display required, water level and water flow can be shown with two LEDs. If a higher quality, digital output is needed, an optional LCD interface is provided on the reference board. Using a shift register to hold display data, the LCD is driven with only three lines outputted from the microcontroller: an enable line, a data line, and a clock signal. The two LEDs are multiplexed with the data line and clock signal PTA3 PTA4 PTA5 HC908QT4 R2 1K A B CLK HC164 R3 1K EN RS RW LCD DB0 DB1 DB2 DB3 DB4 DB5 DB6 DB7 Figure 4. Multiplexed LCD Circuit Multiplexing of the microcontroller output pins allows communication of the LCD to be accomplished with three pins instead of eight or 11 pins of I/O lines usually needed. With an eight-bit shift register, we are able to manually clock in eight bits of data. The enable line (EN) is manually accepted when eight bytes have been shifted in, telling the LCD the data on the data bus is available to execute. The LEDs are used to show pressure output data by displaying binary values corresponding to a pressure range. Leak detection, or water-flow speed, is displayed by blinking a green LED at a speed relating to the speed of water flow. The red LED displays the direction of water flow. Turning the red LED off signifies water flowing into the tub. Turning the red LED on signifies water flowing out of the tub, or alternatively, there is a leak. Digital values for water height, rate of water flow, and calibration values are displayed if an LCD is connected to the board AN1950 Sensors Freescale Semiconductor 3 OTHER This system is designed to run on a 9.0 V battery. It contains a 5.0 V regulator to provide 5.0 V to the pressure sensor, microcontroller, and LCD. The battery is mounted on the back of the board using a space saving spring battery clip. Table 2. Parts List Ref. Qty Description Value Vendor Part No. U2 1 Pressure Sensor 1 Freescale MPXM2010GS C1 1 Vcc Cap 0.1µf Generic — C2 1 Op-Amp Cap 0.1µf Generic — C3 1 Shift Register Cap 0.1µf Generic — D1 1 Red LED — Generic — D2 1 Green LED — Generic — S2, S3 2 Pushbuttons — Generic — U1 1 Quad Op-Amp — ADI AD8544 U3 1 Voltage Regulator 5.0 V Fairchild LM78L05ACH U4 1 Microcontroller 8-pin Freescale MC68HC908QT4 R1 1 ¼ W Resistor 22 K Generic — R2 1 ¼ W Resistor 2.4 K Generic — R3, R6 2 ¼ W Resistor 1.2 M Generic — R4, R5 2 ¼ W Resistor 1.5 K Generic — R7, R8 2 ¼ W Resistor 10 K Generic — R9, R10 2 ¼ W Resistor 1.0 K Generic — U6 1 LCD (Optional) 16 x 2 Seiko L168200J000 U5 1 Shift Registor — Texas Instruments 74HC164 Smart Washer Software This application note describes the first software version available. However, updated software versions may be available with further functionality and menu selections. Software User Instructions When the system is turned on or reset, the microcontroller will flash the selected LED and display the program title on the LCD for five seconds, or until the select (SEL) button is pushed. Then the menu screen is displayed. Using the select (SEL) pushbutton, it is easy to scroll through the menu options for a software program. To run the water level program, use the select button to highlight the Water Level option, then press the enter (ENT) pushbutton. The Water Level program will display current water level, the rate of flow, a message if the container is Filling, Emptying, Full, or Empty, and a scrolling graphical history displaying data points representing the past forty level readings. The Water Level is displayed by retrieving the digital voltage from the internal A/D Converter. This voltage is converted to pressure in millimeters of water and then displayed on the LCD. buttons on system power-up enters the calibration mode. At this point, the calibration menu is displayed with the previously sampled offset voltage. To recalibrate the system, expose the sensor to atmospheric pressure and press the SEL button (PB1). At this point, the zero offset voltage will be sampled and saved to a location in the microcontroller memory. To obtain the second calibration point, place the end of the plastic tube from the pressure sensor to the bottom of a container holding 40 mm of water. Then press the ENT button (PB2). The voltage output will be sampled, averaged and saved to a location in memory. To exit the calibration mode, press the SEL (PB1) button. Calibration and Calibration Software To calibrate the system, a two-point calibration is performed. The sensor will take a calibration point at 0 mm and at 40 mm of water. Depressing both the SEL and ENT Figure 5. Water Level System Set-Up for Demonstration AN1950 4 Sensors Freescale Semiconductor Converting Pressure to Water Level Hydrostatic pressure being measured is the pressure at the bottom of a column of fluid caused by the weight of the fluid and the pressure of the air above the fluid. Therefore, the hydrostatic pressure depends on the air pressure, the fluid density and the height of the column of fluid. P= Pa + ρ g ∆h where P = pressure Pa = pressure ρ = mass density of fluid g = 9.8066 m/s^2 h = height of fluid column To calculate the water height, we can use the measured pressure with the following equation, assuming the atmospheric pressure is already compensated for by the selection of the pressure sensor being gauge: ∆h = P \ ρ g The function first clears the 40 pressure readings it updates for the Graphical History. The history then enters the loop first displaying eight special characters, each containing five data points of water level history. The function adcbyta is called to obtain the current averaged A/D value. The function LfNx is called to convert the A/D value to a water level. It is then compared to the calibration points, the maximum and minimum points, to determine if the container is full or empty. If true, then it displays the corresponding message. The current water level is compared to the previous read and displays the message filling if it has increased, emptying if it has decreased, and steady if it has not changed. The water level calculation has to be converted to decimal in order to display it in the LCD. To convert the water level calculation to decimal, the value is continually divided with the remainder displayed to the screen for each decimal place. To display the Rate of Water Flow, the sign of the value is first determined. If the value is negative, the one's complement is taken, a negative sign is displayed, and then the value is continually divided to display each decimal place. If the number is positive, a plus sign. Software Function Descriptions Level Function Main Function The Level function initializes the graphics characters. Once this is complete, it continues looping to obtain an average A/D reading, displaying the Water Level, the Water Flow, and a Graphical History until simultaneously depressing both PB1 and PB2 to return to the main function. The function first clears the 40 pressure readings it updates for the Graphical History. The history then enters the loop first displaying eight special characters, each containing five data points of water level history. The function adcbyta is called to obtain the current averaged A/D value. The function LfNx is called to convert the A/D value to a water level. It is then compared to the calibration points, the maximum and minimum points, to determine if the container is full or empty. If true, then it displays the corresponding message. The current water level is compared to the previous read and displays the message filling if it has increased, emptying if it has decreased, and steady if it has not changed. The water level calculation has to be converted to decimal in order to display it in the LCD. To convert the water level calculation to decimal, the value is continually divided with the remainder displayed to the screen for each decimal place. To display the Rate of Water Flow, the sign of the value is first determined. If the value is negative, the one's complement is taken, a negative sign is displayed, and then the value is continually divided to display each decimal place. If the number is positive, a plus sign is displayed to maintain the display alignment and the value is continually divided to display each decimal place. The most complicated part of this function is updating the graphics history display. The characters for the 16x2 LCD chosen for this reference design are 8x5 pixels by default. Therefore, each special character that is created will be able to display five water level readings. Since the height of the special character is eight pixels, each vertical pixel position will represent a water level in increments of 20 mm. The main function calls an initialization function Allinit calls a warm-up function, Warmup, to allow extra time for the LCD to initialize, then checks if buttons PB1 and PB2 are depressed. If they are depressed concurrently, it calls a calibration function Calib. If they are not both pressed, it enters the main function loop. The main loop displays the menu, moves the cursor when the PB1 is pressed and enters the function corresponding to the highlighted menu option when PB2 is depressed. Calibration Function The calibration function is used to obtain two calibration points. The first calibration point is taken when the head tube is not placed in water to obtain the pressure for 0 mm of water. The second calibration point is obtained when the head tube is placed at the bottom of a container with a height of 160 mm. When the calibration function starts, a message appears displaying the A/D values for the corresponding calibration points currently stored in the flash. To program new calibration points, press PB1 to take 256 A/D readings at 0 mm of water. The average is calculated and stored in a page of flash. Then the user has the option to press PB1 to exit the calibration function or obtain the second calibration point. To obtain the second calibration point, the head tube should be placed in 160 mm of water, before depressing PB2 to take 256 A/D readings. The average is taken and stored in a page of flash. Once the two readings are taken, averaged, and stored in the flash, a message displays the two A/D values stored. Level Function The Level function initializes the graphics characters. Once this is complete, it continues looping to obtain an average A/D reading, displaying the Water Level, the Water Flow, and a Graphical History until simultaneously depressing both PB1 and PB2 to return to the main function. Resolution = (H1 – H0) / D AN1950 Sensors Freescale Semiconductor 5 where H1 and H2 are the maximum and minimum water levels respectively and D is the possible datapoints available per character. Resolution = (160mm– 0mm) / 8.0 = 20 mm / data point. The graphical history is displayed using the eight special characters. To update the graphics, all the characters have to be updated. The characters are updated by first positioning a pixel for the most recent water level reading in the first column of the first character. Then the four right columns of the first character are shifted to the right. The pixel in the last column of that character is carried to the first column of the next character. This column shifting is continued until all 40 data points have been updated in the eight special characters. LfNx Function The LfNx function calculates the water level from the current A/D pressure reading. The A/D Pressure value is stored in Register A before this function is called. Using the A/D value and the calibration values stored in the flash, the water level is calculated from the following function: RBRA: = (NX –N1) * 160 / (N2 – N1), where NX is the current A/D Value N1 is the A/D Value at 0 mm H20 N2 is the A/D Value at 160 mm H20 To simplify the calculation, the multiplication is done first. Then the function NdivD is called to divide the values. NdivD Function The NdivD function performs a division by counting successive subtractions of the denominator from the numerator to determine the quotient. The denominator is subtracted from the numerator until the result is zero. If there is an overflow, the remainder from the last subtraction is the remainder of the division. wrflash and ersflsh Functions The wrflash and ersflsh functions are used to write to and erase values from the flash. For more information regarding flash functionality, refer to Section Four, Flash Memory from the MC68HC908QY4/D Databook. ALLINIT Function The Allinit function disables the COP for this version of software, sets the data direction bits, and disables the data to the LCD and turns off the LCD enable line. It also sets up the microcontroller's internal clock to half the speed of the bus clock. See Section 15, Computer Operating Properly, of the MC68908QT4 datasheet for information on utilizing the COP module to help software recover from runaway code. bintasc Function The binasc function converts a binary value to its ascii representation. A/D Functions The A/D functions are used to input the amplified voltage from the pressure sensor from channel 0 of the A/D converter. The function adcbyti will set the A/D control register, wait for the A/D reading and load the data from the A/D data register into the accumulator. The function adcbyta is used to obtain an averaged A/D reading by calling adcbyti 256 times and returning the resulting average in the accumulator. LCD Functions The LCD hardware is set up for multiplexing three pins from the microcontroller using an eight-bit shift register. Channels three, four, and five are used on port A for the LCD enable (E), the LCD reset (RS), and the shift register clock bit, respectively. The clock bit is used to manually clock data from channel four into the eight-bit shift register. This is the same line as the LCD RS bit because the MSB of the data is low for a command and high for data. The RS bit prepares the LCD for instructions or data with the same bit convention. When the eight bits of data are available on the output pins of the shift register, the LCD enable (E) is toggled to receive the data. The LCD functions consist of an initialization function lcdinit which is used once when the system is started and five output functions. The functions lcdcmdo and lcdchro both send a byte of data. The function shiftA is called by both lcdcmdo and lcdchro to manually shift eight bits of data into the shift register. The function lcdnibo converts the data to binary before displaying. The lcdnibo displays a byte of data by calling lcdnibo for each nibble of data. The function lcdnibo enables strings to be easily added to the software for display. The function accepts a comma- delimited string of data consisting of 1–2 commands for clearing the screen and positioning the cursor. It then continues to output characters from the string until the @ symbol is found, signally the end of the string. CONCLUSION The water level reference design uses a MPXM2010GS pressure sensor in the low cost MPAK package, the low cost, eight-pin microcontroller, and a quad op-amp to amplify the sensor output voltage. This system uses very few components, reducing the overall system cost. This allows for a solution to compete with a mechanical switch for water level detection but also offer additional applications such as monitoring water flow for leak detection, and the other applications for smart washing machines. WARMUP Function The Warmup function alternates the blinking of the two LEDs ten times. This gives the LCD some time to warm up. Then the function warmup calls the LCD initialization function, lcdinit. AN1950 6 Sensors Freescale Semiconductor SOFTWARE LISTING ;NitroWater 2.0 24Jan03 ;-------------; ;Water Level Reference Design ;**************************** ; - uses 908QT4 (MC68HC908QT4) and MPAK (MPXM2010GS) ; CALIB: 2-point pressure calibration (0mm and 160mm) ; LEVEL: displays water level, flow, and graphics ; UNITS: allows user to select between cm and inches ; ;__________________________________________________________ ram equ $0080 ;memory pointers rom equ $EE00 vectors equ $FFDE ;__________________________________________________________ porta equ $00 ;registers ddra equ $04 config2 equ $1E config1 equ $1F tsc equ $20 tmodh equ $23 icgcr equ $36 adscr equ $3C adr equ $3E adiclk equ $3F flcr equ $FE08 flbpr equ $FFBE ;__________________________________________________________ org $FD00 ;flash variables N1 db $96 ;1st calibration pt. = 0mm org $FD40 N2 db $F6 ;2nd calibration pt. = 160mm org $FD80 ;__________________________________________________________ org vectors dw cold ;ADC dw cold ;Keyboard dw cold ;not used dw cold ;not used dw cold ;not used dw cold ;not used dw cold ;not used dw cold ;not used dw cold ;not used dw cold ;not used dw cold ;TIM Overflow dw cold ;TIM Channel 1 dw cold ;TIM Channel 0 dw cold ;not used dw cold ;IRQ dw cold ;SWI dw cold ;RESET ($FFFE) ;__________________________________________________________ org ram BB ds 1 ;variables flshadr ds 2 flshbyt ds 1 memSP ds 2 mem03 ds 2 AN1950 Sensors Freescale Semiconductor 7 CNT ds 1 Lgfx ds 1 weath ds 1 UnitType ds 1 UnitDiv ds 1 UnitEmpt ds 1 UnitFull ds 1 ram0 ds 1 NC ds 1 NB ds 1 NA ds 1 DC ds 1 DB ds 1 DA ds 1 MB ds 1 MA ds 1 OB ds 1 OA ds 1 RB ds 1 RA ds 1 P0C ds 1 P0B ds 1 P0A ds 1 NPTR ds 1 ramfree ds 80 ;used both for running RAM version of wrflash & storing 40 readings ;__________________________________________________________ ;__________________________________________________________ ;__________________________________________________________ org rom cold: rsp ;reset SP if any issues (all interrupt vectors point here) jsr ALLINIT ;general initialization jsr WARMUP ;give LCD extra time to initialize brset 1,porta,nocalib brset 2,porta,nocalib jmp CALIB ;only do calibration if SEL & ENT at reset nocalib: ldhx #msg01 ;otherwise skip and show welcome messages jsr lcdstro ;"Reference Design" msg jsr del1s ;wait 1s ldhx #msg01a ;"Water Level" msg jsr lcdstro jsr del1s ;wait 1s initCM: ldhx #$A014 sthx UnitType ldhx #$039E sthx UnitEmpt MENU: jsr clr lda jsr luke: ;initialize default units to cm ($A0=cm, $3F=in) ;UnitType set to $A0; UnitDiv set to $14 ;UnitEmpt set to $03; UnitFull set to $9E ldhx #msg01b lcdstro ;Menu msg RA ;menu choice=0 to begin with #$0D lcdcmdo ;blink cursor on menu choice ldx RA ;get current menu choice clrh lda menupos,x ;and look up corresponding LCD address jsr lcdcmdo ;reposition cursor AN1950 8 Sensors Freescale Semiconductor warm: brclr 1,porta,PB1 ;check for SEL brclr 2,porta,PB2 ;or for ENT bclr 4,porta ;otherwise bset 5,porta ;turn on "SEL" LED jsr del100ms ;delay bset 4,porta ;toggle LEDs bclr 5,porta ;"ENT" now on: means choice is SEL ***or*** ENT jsr del100ms ;delay and repeat until SEL or ENT bra warm PB1: inc RA ;***SEL*** toggles menu choices lda RA cmp #$02 ;menu choices are $00 and $01 bne PB1ok clr RA ;back to $00 when all others have been offered PB1ok: bclr 4,porta bclr 5,porta ;LEDs off jsr del100ms ;wait a little bit brclr 1,porta,PB1ok ;make sure they let go of SEL bra luke PB2: bclr 4,porta ;***ENT*** confirms menu choice bclr 5,porta ;LEDs off lda RA ;get menu choice bne skip00 jmp LEVEL ;do ===LEVEL=== if choice=$01 skip00: jmp UNITS ;do ===UNITS=== if choice=$00 ;__________________________________________________________ ;__________________________________________________________ CALIB: lda #$01 jsr lcdcmdo clr ram0 ldhx #msg05 ;===CALIB=== 2-point calibration jsr lcdstro ;Calibration current values lda N1 ;0mm jsr lcdbyto lda #'/' jsr lcdchro lda N2 ;160mm jsr lcdbyto bset 4,porta bset 5,porta ;LEDs on lego1: brclr 1,porta,lego1 lego2: brclr 2,porta,lego2 bclr 4,porta bclr 5,porta ;LEDs off when both SEL & ENT are released jsr del1s jsr del1s ;wait 2s ldhx #msg05a jsr lcdstro ;show instructions waitPB1: brset 2,porta,no2 ;if ENT is not pressed, skip jmp nocalib ;if ENT is pressed then cancel calibration no2: brclr 1,porta,do1st ;if SEL is pressed then do 1st point cal bra waitPB1 ;otherwise wait for SEL or ENT do1st: ldhx #msg05b ;1st point cal: show values jsr lcdstro clr CNT ;CNT will count 256 A/D readings clr RB clr RA ;RB:RA will contain 16-bit add-up of those 256 values AN1950 Sensors Freescale Semiconductor 9 do256: lda #$C9 jsr lcdcmdo ;position LCD cursor at the right spot lda CNT deca jsr lcdbyto ;display current iteration $FF downto $00 lda #':' jsr lcdchro jsr adcbyti ;get reading add RA sta RA lda RB adc #$00 sta RB ;add into RB:RA (16 bit add) jsr lcdbyto ;show RB lda RA jsr lcdbyto ;then RA dbnz CNT,do256 ;and do 256x lsl RA ;get bit7 into carry bcc nochg ;if C=0 then no need to round up inc RB ;otherwise round up nochg: lda RB ;we can discard RA: average value is in RB ldhx #N1 ;point to flash location jsr wrflash ;burn it in! ldhx #msg05c ;ask for 160mm jsr lcdstro waitPB2: brset 2,porta,waitPB2 ;wait for ENT ldhx #msg05d ;2nd point cal: show values jsr lcdstro clr CNT ;ditto as 1st point cal clr RB clr RA do256b: lda #$C9 jsr lcdcmdo lda CNT deca jsr lcdbyto lda #':' jsr lcdchro jsr adcbyti add RA sta RA lda RB adc #$00 sta RB jsr lcdbyto lda RA jsr lcdbyto dbnz CNT,do256b lsl RA bcc nochg2 inc RB nochg2: lda RB cmp N1 ;compare N2 to N1 bne validcal ;if different, we are OK ldhx #msg05e ;otherwise warn of INVALID CAL! jsr lcdstro jsr del1s jsr del1s jsr del1s ;wait 2s jmp CALIB ;try cal again AN1950 10 Sensors Freescale Semiconductor validcal: ldhx #N2 jsr wrflash ;burn N2 into flash ldhx #msg05 ;and display new current cal values from flash jsr lcdstro lda N1 ;0mm value jsr lcdbyto lda #'/' jsr lcdchro lda N2 ;160mm value jsr lcdbyto jsr del1s jsr del1s jmp nocalib ;done! ;__________________________________________________________ ;__________________________________________________________ LEVEL: lda #$01 ;===LEVEL=== main routine: displays level, flow & graphics jsr lcdcmdo ;clear screen lda #$0C jsr lcdcmdo ;cursor off lda #$88 ;position cursor at LCD graphics portion jsr lcdcmdo ;(2nd half of first line) clra ;and write ascii $00 through $07 fillgfx: jsr lcdchro ;which contain the graphics related to inca ;40 different readings cmp #$08 ;do all 8 bne fillgfx LVL: ldhx #ramfree ;point to 40 pressure readings lda #$28 ;count down from 40 purge: clr 0,x ;clear all those locations incx ;next (H cannot change: we are in page0 RAM) dbnza purge jsr adcbyta ;get averaged A/D reading (i.e. NX) jsr LfNx ;convert to level and sta Lgfx ;store in "Level graphics" LVLwarm: bset 4,porta bset 5,porta ;LEDs on during this cycle ldhx #ramfree ;point to 40 pressure readings mov #$27,RA ;count down from 39 shiftgfx: lda 1,x ;take location+1 sta 0,x ;and move to location+0, i.e. shift graphics left incx ;next X (once again: we are in page 0, no need to worry about H) dbnz RA,shiftgfx ;do this 39x jsr adcbyta jsr LfNx mov RA,OA ;get averaged A/D reading (i.e. NX) ;LX:=(NX-N1)*ConversionValue/(N2-N1) ;store result in OA clr RB ;RB will contain graphic pixels (default=$00) cmp UnitEmpt ;if <UnitEmpty (preset value = empty or almost) bcs Lzero ;then "empty" (no pixels) cmp UnitFull ;if >=UnitFull (preset value = full or almost) bcc Lsat ;then "full" (pixel $80=bit 7) clrh ;otherwise determine one of 8 graphic values ldx UnitDiv ;UnitDiv is roughly full range/8 div ;in order to give 8 values mov #$01,RB ;but now value has to be converted to pixel AN1950 Sensors Freescale Semiconductor 11 cmp #$01 ;if result is $01 beq Lzero ;then display it directly makeRB lsl RB ;otherwise shift 1 pixel bit to the right place dbnza makeRB ;by counting down result of division bra Lzero Lsat: mov #$80,RB ;if full then position highest pixel Lzero: lda RB ldhx #ramfree+$27 ;last of the 40 sta 0,x ;put it at then end of the 40 bytes (new value), all others were shifted left clr weath ;weath will contain dynamic change based also on value of RB lda RB beq donew ;if RB=$00 then weath=$00: "empty" cmp #$80 bne notfull ; mov #$01,weath ;if $80 then weath=$01: "full" bra donew notfull mov #$02,weath ;prepare for "steady" if L(i)=L(i-1) lda OA ;get current level value L(i) cmp Lgfx ;compare to previous level value L(i-1) beq donew mov #$03,weath ;"filling" if L(i)>L(i-1) bcc donew mov #$04,weath ;"emptying" otherwise donew: lda OA ;current level L(i) sub Lgfx ;minus previous level L(i-1) sta MA ;establishes rate: L(i)-L(i-1) mov RA,Lgfx ;update L(i-1) ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - golevel: lda #$80 ;******** now let's display the level in decimal ******** jsr lcdcmdo ;start on 1st character of 1st line lda OA ;get current level value clrh ldx #$64 ;and divide by 100 div bne over100 ;if result is >0 then handle "hundreds" lda #$20 ;otherwise display space (remove leading 0) jsr lcdchro bra lnext over100: jsr lcdnibo ;display "hundreds" digit lnext: pshh pula ;move remainder into A clrh ldx #$0A ;divide by 10 div jsr lcdnibo ;display "tens" digit lda #'.' jsr lcdchro ;display decimal point pshh pula jsr lcdnibo ;and first decimal lda UnitType ;check for cm ($A0) vs. in (#3F) cmp #$3F beq dsplIN dsplCM: lda #'c' jsr lcdchro lda #'m' AN1950 12 Sensors Freescale Semiconductor jsr lcdchro bra goflow ;display "cm" for centimeters dsplIN: lda #'i' jsr lcdchro lda #'n' jsr lcdchro ;display "in" for inches ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - goflow: lda #$C0 ;******** now let's display the flow in decimal ******** jsr lcdcmdo ;position cursor on 1st character 2nd line lda MA ;get flow lsla ;test sign of rate (in MA) bcc positiv ;if positive, then it's easy lda MA coma inca sta MA cmp #$64 bcs not2lo lda #'<' jsr lcdchro lda #$63 sta MA bra goconv ;otherwise 1's complement of MB ;check to see if >100 ;if not we are OK ;otherwise display that we exceeded min rate ;that LCD can display (<9.9) ;force value to 99 not2lo: lda #'-' jsr lcdchro bra goconv positiv: lda MA cmp #$64 bcs not2hi lda #'>' jsr lcdchro lda #$63 sta MA bra goconv ;display that minus sign ;check to see if >100 ;if not we are OK ;otherwise display that we exceeded max rate ;that LCD can display (>9.9) ;force value to 99 not2hi: lda #'+' jsr lcdchro goconv: lda MA clrh ldx #$0A div jsr lcdnibo lda #'.' jsr lcdchro pshh pula jsr lcdnibo lda UnitType cmp #$3F beq dsplINf ;display the plus sign (to keep alignment) ;get flow ;and divide by 10 ;display "tens" digit ;display decimal point ;and first decimal ;check for cm ($A0) vs. in (#3F) dsplCMf: lda #'c' jsr lcdchro lda #'m' bra reusef AN1950 Sensors Freescale Semiconductor 13 dsplINf: lda #'i' jsr lcdchro lda #'n' reusef: jsr lcdchro lda #'/' jsr lcdchro lda #'s' jsr lcdchro ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - gfxupdt: lda #$40 ;======== Graphics Update: tough stuff =========== jsr lcdcmdo ;prepare to write 8 bytes into CGRAM starting at @ $40 ldhx#ramfree;point to 40 pressure readings (this reuses wrflash RAM) mov #$08,DA ;DA will count those 8 CGRAM addresses cg8: lda 0,x sta NC lda 1,x sta NB lda 2,x sta NA lda 3,x sta DC lda 4,x staDB;readings 0-4 go into NC,NB,NA,DC,DB and will form 1 LCD special character mov #$08,RA ;RA will count the 8 bits fill:clrRB;start with RB=0, this will eventually contain the data for CGRAM rol NC rolRB rol NB rolRB rol NA rolRB rol DC rolRB rol DB rolRB;rotate left those 5 values and use carry bits to form RB (tough part) lda RB jsrlcdchro;and put it into CGRAM dec RA ;do this 8 times to cover all 8 bits bne fill incx incx incx incx incx ;now point to next 5 values for next CGRAM address (5 values per character) dec DA ;do this for all 8 CGRAM characters bne cg8 ldaweath;get weather variable and decide which message to display cmp #$04 bne try3210 ldhx #msg02e ;if $04 bra showit try3210: cmp #$03 bne try210 ldhx #msg02d ;if $03 bra showit try210: cmp #$02 AN1950 14 Sensors Freescale Semiconductor bne try10 ldhx #msg02c ;if $02 bra showit try10: cmp #$01 bne try0 ldhx #msg02b ;if $01 bra showit try0: ldhx #msg02a ;otherwise this one showit: jsr lcdstro jsr del1s ;1s between pressure/altitude readings brset 1,porta,contin ;exit only if SEL brset 2,porta,contin ;and ENT pressed together jmp MENU contin: jmp LVLwarm ;__________________________________________________________ LfNx: sub N1 ;*** PX=f(NX,N2,N1) *** ldx UnitType ;$A0=160 for cm, $3F=63 for in mul sta NA stx NB clr NC ;NCNBNA:=(NX-N1)* (conversion value: 160 or 63) lda sub sta clr clr jsr N2 N1 DA DB DC NdivD ;RBRA:=(NX-N1)*(conversion value)/(N2-N1) lda RA cmp #$C8 ;check to see if result is negative bcs noovflw ;if <$C8 we are OK ovflw: clr RA ;otherwise force level to 0! noovflw: lda RA rts ;__________________________________________________________ NdivD: clr RA ;RBRA:=NCNBNA/DCDBDA clr RB ;destroys NCNBNA and DCDBDA keepatit: lda RA add #$01 sta RA lda RB adc #$00 sta RB ;increment RB:RA lda NA sub DA sta NA lda NB sbc DB sta NB lda NC sbc DC sta NC ;NC:NB:NA:=NC:NB:NA-DC:DB:DA bcc keepatit ;keep counting how many times until overflow lda RA sub #$01 sta RA lda RB sbc #$00 sta RB ;we counted once too many, so undo that AN1950 Sensors Freescale Semiconductor 15 lsr DC ror DB ror DA ;divide DC:DB:DA by 2 lda NA add DA sta NA lda NB adc DB sta NB lda NC adc DC sta NC ;and add into NC:NB:NA lsla bcs nornd ;if carry=1 then remainder<1/2 of dividend lda RA add #$01 sta RA lda RB adc #$00 sta RB ;otherwise add 1 to result nornd: rts ;__________________________________________________________ ;__________________________________________________________ UNITS: brclr 2,porta,UNITS ;let go of ENT first lda #$01 ;===UNITS=== Allows user to select units: inches or cm jsr lcdcmdo ;clear screen ldhx jsr jsr clr lda jsr uluke: #msg03 lcdstro ;Unit Choice menu del100ms RA ;menu choice=0 to begin with #$0D lcdcmdo ;blink cursor on menu choice ldx RA ;get current menu choice clrh lda menupos,x ;and look up corresponding LCD address jsr lcdcmdo ;reposition cursor uwarm: brclr 1,porta,uPB1 ;check for SEL brclr 2,porta,uPB2 ;or for ENT bclr 4,porta ;otherwise bset 5,porta ;turn on "SEL" LED jsr del100ms ;delay bset 4,porta ;toggle LEDs bclr 5,porta ;"ENT" now on: means choice is SEL ***or*** ENT jsr del100ms ;delay and repeat until SEL or ENT bra uwarm uPB1: inc RA ;***SEL*** toggles menu choices lda RA cmp #$02 ;menu choices are $00 and $01 bne uPB1ok clr RA ;back to $00 when all others have been offered uPB1ok: bclr 4,porta bclr 5,porta ;LEDs off jsr del100ms ;wait a little bit brclr 1,porta,uPB1ok ;make sure they let go of SEL bra uluke AN1950 16 Sensors Freescale Semiconductor uPB2: bclr 4,porta ;***ENT*** confirms menu choice bclr 5,porta ;LEDs off lda RA ;get menu choice bne SelIN SelCM: ldhx #$A014 ;initialize default units to cm ($A0=cm, $3F=in) sthx UnitType ;UnitType set to $A0; UnitDiv set to $14 ldhx #$039E sthx UnitEmpt ;UnitEmpt set to $03; UnitFull set to $9E lda #$01 jsr lcdcmdo ;clear LCD ldhx #msg03a jsr lcdstro ;and show choice selection to be cm jsr del1s ;wait 1s jmp LEVEL ;let's do LEVEL now... SelIN: ldhx #$3F08 ;initialize default units to in ($A0=cm, $3F=in) sthx UnitType ;UnitType set to $3F; UnitDiv set to $08 ldhx #$033D sthx UnitEmpt ;UnitEmpt set to $03; UnitFull set to $3D lda #$01 jsr lcdcmdo ;clear LCD ldhx #msg03b jsr lcdstro ;and show choice selection to be in jsr del1s ;wait 1s jmp LEVEL ;let's do LEVEL now... ;__________________________________________________________ ;__________________________________________________________ ;__________________________________________________________ ;******************************************************************** ;******************************************************************** ;******** GENERAL Routines ****************************************** ;******************************************************************** ;******************************************************************** ;-------- INITIALIZATION Routines ----------------------------------; ALLINIT: initializes HC08, sets I/O, resets LCD and LEDs ; ------ALLINIT: bset 0,config1 ;disable COP mov #$38,ddra ;PTA0=MPAK,PTA1=SEL,PTA2=ENT,PTA3=E,PTA4=RS,PTA5=clk mov #$30,adiclk ;ADC clock /2 bclr 3,porta ;E=0 bclr 4,porta ;grn=OFF; RS=0 bclr 5,porta ;red=OFF; CLK=0 rts ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; WARMUP: waits half a second while it flashes LEDs, and allows LCD to get ready ; -----WARMUP: bclr 4,porta bclr 5,porta ;LEDs off lda #$0A ;prepare to do this 10x tenx: jsr del25ms ;delay bclr 4,porta bset 5,porta ;alternate on/off jsr del25ms bset 4,porta bclr 5,porta ;and off/on dbnza tenx ;10 times so the LCD can get ready (slow startup) jsr lcdinit ;now initialize it AN1950 Sensors Freescale Semiconductor 17 bclr 4,porta bclr 5,porta ;LEDs off rts ;-------- WRITE TO EEPROM Routines ---------------------------------; wrflash: burns A into flash at location pointed by H:X ; ------wrflash: sthx flshadr ;this is the address in the flash sta flshbyt ;and the byte we want to put there tsx sthx memSP ;store SP in memSP, so it can be temporarily used as a 2nd index register ldhx #ramfree+1 ;SP now points to RAM (remember to add 1 to the address!!!, HC08 quirk) txs ;SP changed (careful not to push or call subroutines) ldhx #ersflsh ;H:X points to beginning of flash programming code doall: lda 0,x ;get 1st byte from flash sta 0,sp ;copy it into RAM aix #$0001 ;HX:=HX+1 ais #$0001 ;SP:=SP+1 cphx #lastbyt ;and continue until we reach the last byte bne doall ldhx memSP ;once done, restore the SP txs jsr ramfree ;and run the subroutine from RAM, you cannot write the flash while rts ;running a code in it, so the RAM has to take over for that piece ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ;*************** THE FOLLOWING CODE WILL BE COPIED INTO AND WILL RUN FROM RAM ****** ersflsh: lda #$02 ;textbook way to erase flash sta flcr lda flbpr clra ldhx flshadr sta 0,x bsr delayf lda #$0A sta flcr bsr delayf lda #$08 sta flcr bsr delayf clra sta flcr bsr delayf pgmflsh: lda #$01 ;textbook way to program flash sta flcr lda flbpr clra ldhx flshadr sta 0,x bsr delayf lda #$09 sta flcr bsr delayf lda flshbyt ldhx flshadr sta 0,x bsr delayf lda #$08 sta flcr bsr delayf clra sta flcr AN1950 18 Sensors Freescale Semiconductor bsr delayf rts delayf: ldhx #$0005 ;wait 5x20us mov #$36,tsc ;stop TIM & / 64 sthx tmodh ;count H:X x 20us bclr 5,tsc ;start clock delayfls: brclr 7,tsc,delayfls rts ;this RTS will move from RAM back into EEPROM lastbyt: nop ;*************** END OF CODE THAT WILL BE COPIED INTO AND WILL RUN FROM RAM ****** ;-------- DELAY Routines -------------------------------------------; del1s: generates a 1s delay ; ----del1s: pshh pshx ldhx #$C350 ;1 second delay=$C350=50000 x 20us bra delmain ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; del100ms: generates a 100ms delay ; -------del100ms: pshh pshx ldhx #$1388 bra delmain ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; del50ms: generates a 50ms delay ; ------del50ms: pshh pshx ldhx #$09C4 bra delmain ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; del25ms: generates a 25ms delay ; ------del25ms: pshh pshx ldhx #$04E2 bra delmain ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; del5ms: generates a 5ms delay ; -----del5ms: pshh pshx ldhx #$00FA bra delmain ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; del1ms: generates a 1ms delay ; -----del1ms: pshh pshx ldhx #$0032 bra delmain ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; del100us: generates a 100us delay ; ----del100us: pshh pshx ldhx #$0005 bra delmain ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - AN1950 Sensors Freescale Semiconductor 19 ; delmain: main delay routine; generates delay equal to H:X x 20us ; ------delmain: mov #$36,tsc ;stop TIM & / 64 sthx tmodh ;count H:X x 20us bclr 5,tsc ;start clock delwait: brclr 7,tsc,delwait ;wait for end of countdown pulx pulh rts ;this RTS serves for all delay routines! ;-------- A/D Routines ---------------------------------------------; adcbyti: gets single A/D reading from PTA0 and returns it in A ; ------adcbyti: mov #$00,adscr ;ADC set to PTA0 brclr 7,adscr,* ;wait for ADC reading lda adr ;result in adr rts ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; adcbyta: gets averaged A/D reading from PTA0 and returns it in A ; ------adcbyta: clr CNT ;average 256 readings clr RB ;will be addint them up clr RA ;in RB:RA do256a: bsr adcbyti add RA sta RA lda RB adc #$00 sta RB ;16-bit add into RB:RA dbnz CNT,do256a ;do all 256 lsl RA ;if RA<$80 bcc nochga ;then RB result is correctly rounded inc RB ;otherwise round off to next value nochga: lda RB rts ;-------- LCD Routines ---------------------------------------------; lcdinit: initializes LCD ; ------lcdinit: lda #$3C ;set 8-bit interface, 1/16 duty, 5x10 dots bsr lcdcmdo lda #$0C ;display on, cursor off, blink off bsr lcdcmdo lda #$06 ;increment cursor position, no display shift bsr lcdcmdo lda #$01 ;clear display bsr lcdcmdo rts ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; lcdcmdo: sends a command to LCD ; ------lcdcmdo: bsr shiftA bclr 4,porta ;RS=0 for command bset 3,porta bclr 3,porta ;toggle E bsr del5ms ;some commands require 2ms for LCD to execute rts ;so let's play it safe ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; lcdchro: sends a character (data) to LCD ; ------lcdchro: bsr shiftA bset 4,porta ;RS=1 for data AN1950 20 Sensors Freescale Semiconductor bset 3,porta bclr 3,porta ;toggle E bsr del100us ;data only requires 40us for LCD to execute rts ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; shiftA: shifts A into shift register and provides 8-bits to LCD ; -----shiftA: psha mov #$08,BB ;will be shifting 8 bits all8: lsla ;get bit bcc shift0 ;if bit=0 then shift a 0 shift1: bset 4,porta ;otherwise shift a 1 bra shift shift0: bclr 4,porta ;bit 4 is data to shift register shift: bclr 5,porta ;bit 5 is shift register clock bset 5,porta bclr 5,porta ;toggle CLK dbnz BB,all8 ;do all 8 bits pula rts ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; lcdnibo: displays 1 character (0-9,A-F) based on low-nibble value in A ; ------lcdnibo: psha ;convert 4 bits from binary to ascii add #$30 ;add $30 (0-9 offset) cmp #$39 ;is it a number (0-9) ? bls d0to9b ;if so skip add #$07 ;else add $07 = total of $37 (A-F offset) d0to9b: bsr lcdchro pula rts ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; lcdbyto: displays 2 characters based on hex value in A ; ------lcdbyto: psha psha ;remember A (for low nibble) lsra ;shift right 4 times lsra lsra lsra bsr lcdnibo ;high nibble pula and #$0F bsr lcdnibo ;low nibble pula rts ;- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ; lcdstro: displays message ending in '@', but also sends commands to LCD ; ------lcdstro: psha lda 0,x lcon: cmp #$80 ;if ASCII >=$80 bhs iscmd cmp #$1F ;or <=$1F then bls iscmd ;assume it is a command to LCD isdta: bsr lcdchro ;otherwise it is data to LCD reuse1: aix #$0001 ;next character lda 0,x ;indexed by x cmp #$40 ;continue until bne lcon ;character = '@' AN1950 Sensors Freescale Semiconductor 21 pula ;we are done bclr 4,porta ;so bclr 5,porta ;turn off LEDs rts iscmd: bsr lcdcmdo bra reuse1 ;-------- ROM DATA: contains all LCD messages ----------------------msg01 db $01,$80,'*MPAK & 908QT4* ' db $C0,'Reference Design','@' msg01a db $01,$80,'Water Level & ' db $C0,'Flow v2.0','@' msg01b db $01,$80,'1:Level/Flow ' db $C0,'2:Set Units ','@' msg05 db $01,$80,'* Calibration! *' db $C0,'Curr lo/hi:','@' msg05a db $01,$80,'1st point: 0mm' db $C0,'SEL:cal ENT:quit','@' msg05b db $01,$80,'Calibrating... ' db $C0,' 0mm: ','@' msg05c db $01,$80,'2nd point: 160mm' db $C0,'ENT:continue ','@' msg05d db $01,$80,'Calibrating... ' db $C0,' 160mm: ','@' msg05e db $01,$80,'INVALID ' db $C0,'CALIBRATION! ','@' msg02a db $C8,' EMPTY','@' msg02b db $C8,' FULL','@' msg02c db $C8,' steady','@' msg02d db $C8,' H20 in','@' msg02e db $C8,' H20 out','@' msg03 db $01,$80,'1: unit=cm H20 ' db $C0,'2: unit=in H20 ','@' msg03a db $80,'Unit is now: cm','@' msg03b db $80,'Unit is now: in','@' menupos db $80,$C0 end REFERENCES Baum, Jeff, “Frequency Output Conversion for MPX2000 Series Pressure Sensors,” Application Note AN1316/D. Hamelain, JC, “Liquid Level Control Using a Pressure Sensor,” Application Note AN1516/D. AN1950 22 Sensors Freescale Semiconductor NOTES AN1950 Sensors Freescale Semiconductor 23 How to Reach Us: Home Page: www.freescale.com Web Support: http://www.freescale.com/support USA/Europe or Locations Not Listed: Freescale Semiconductor, Inc. Technical Information Center, EL516 2100 East Elliot Road Tempe, Arizona 85284 +1-800-521-6274 or +1-480-768-2130 www.freescale.com/support Europe, Middle East, and Africa: Freescale Halbleiter Deutschland GmbH Technical Information Center Schatzbogen 7 81829 Muenchen, Germany +44 1296 380 456 (English) +46 8 52200080 (English) +49 89 92103 559 (German) +33 1 69 35 48 48 (French) www.freescale.com/support Japan: Freescale Semiconductor Japan Ltd. Headquarters ARCO Tower 15F 1-8-1, Shimo-Meguro, Meguro-ku, Tokyo 153-0064 Japan 0120 191014 or +81 3 5437 9125 [email protected] Asia/Pacific: Freescale Semiconductor Hong Kong Ltd. Technical Information Center 2 Dai King Street Tai Po Industrial Estate Tai Po, N.T., Hong Kong +800 2666 8080 [email protected] For Literature Requests Only: Freescale Semiconductor Literature Distribution Center P.O. Box 5405 Denver, Colorado 80217 1-800-441-2447 or 303-675-2140 Fax: 303-675-2150 [email protected] AN1950 Rev. 4 11/2006 Information in this document is provided solely to enable system and software implementers to use Freescale Semiconductor products. There are no express or implied copyright licenses granted hereunder to design or fabricate any integrated circuits or integrated circuits based on the information in this document. Freescale Semiconductor reserves the right to make changes without further notice to any products herein. Freescale Semiconductor makes no warranty, representation or guarantee regarding the suitability of its products for any particular purpose, nor does Freescale Semiconductor assume any liability arising out of the application or use of any product or circuit, and specifically disclaims any and all liability, including without limitation consequential or incidental damages. “Typical” parameters that may be provided in Freescale Semiconductor data sheets and/or specifications can and do vary in different applications and actual performance may vary over time. All operating parameters, including “Typicals”, must be validated for each customer application by customer’s technical experts. Freescale Semiconductor does not convey any license under its patent rights nor the rights of others. Freescale Semiconductor products are not designed, intended, or authorized for use as components in systems intended for surgical implant into the body, or other applications intended to support or sustain life, or for any other application in which the failure of the Freescale Semiconductor product could create a situation where personal injury or death may occur. Should Buyer purchase or use Freescale Semiconductor products for any such unintended or unauthorized application, Buyer shall indemnify and hold Freescale Semiconductor and its officers, employees, subsidiaries, affiliates, and distributors harmless against all claims, costs, damages, and expenses, and reasonable attorney fees arising out of, directly or indirectly, any claim of personal injury or death associated with such unintended or unauthorized use, even if such claim alleges that Freescale Semiconductor was negligent regarding the design or manufacture of the part. Freescale™ and the Freescale logo are trademarks of Freescale Semiconductor, Inc. All other product or service names are the property of their respective owners. © Freescale Semiconductor, Inc. 2006. All rights reserved.