Friday 24 August 2012

Test Rig for Simulating an Electrical Connection at High Temperature

Reason for this Project:
There was a problem in the field with x-ray generator systems breaking down.  The problem appeared to be caused by a poor contact between the x-ray tube and the high voltage cable.  Producing x-rays is a very inefficient process whereby most of the electrical energy is converted into heat and hence the x-ray tube gets very hot.  Overtime it appeared that the contact resistance was going from 0.3 ohm to 1 ohm or greater and that increase of x4 or greater would require the generator to overdrive. (the power output needs to remain steady, the supply voltage is fixed and hence if the resistance increases then the current will need to increase also).

Description:
The project is to simulate the conditions mentioned above and continuously monitor the current whilst the temperature and the connection is varied.  A 1 second clock was developed to allow testing over extended periods of time and then plot the data.

The project uses an AVR mega32 since it was available and had more than enough functions for the job.  The temperature sensor and  current feedback are fed into two of the ADCs which are multiplexed in the software.


  • The interface to the operator is via a terminal and a menu system to choose the test type, test duration and the the set temperature.  The data is captured for review via a spreadsheet and graph.
  • The PC-to-controller link is via a USB cable and the test board includes the FTDI interface.  
  • There are 3 relays to control the START (start/end test), HEATER (on/off of heater element) and IMAX (high current mode for accelerated testing).
  • The temperature sensor (LM94021) is a digital type with selectable gain.  There is a look-up table to convert the raw to actual temperature.
  • There are status LEDs on the board to indicate when the test is running (running = fast flash), and when each of the relays are engaged.









/***************************************************************************************** 
 * Title:           High Voltage Cable Tester
 * Version:         1.00
 * Last Updated:    
 * Target:          ATmega32 with secondary external oscillator for RTC
 *
 * Support E-mail:  dean.evans@fctinternational.com
 *
 * Description  :
 * Program to test a high voltage cable by controlling the temperature and two current
 * settings, one at approx 3.5A which is nominal and the other at approx 5.5A which is for 
 *  worst case.
 * The temperature and current are measured continuously and since the temperature will vary 
 * slowly, you can change the number of continuous measurements for each in the define 
 * TEMP_MEAS_CNT and I_MEAS_CNT.  Typically 10 current and then one temperature.
 *    
 * ADC0 = Temperature
 * ADC1 = Current
 *
 ******************************************************************************************/ 


#include "defines.h"

#include <avr/io.h>    
#include <avr/interrupt.h>   
#include <avr/sleep.h>  
#include <avr/iom32.h>
#include <avr/pgmspace.h>
#include <util/delay.h>

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>


#include <util/delay.h>

#include "uart.h"

#define VERSION "1.0"

#define OUT_DDR DDRD
#define OUT_PORT PORTD

#define GLITCH PD2            /* External INT0 - glitch detect from comparator */
#define START_RELAY PD3   /* Output drive for Test Start Relay - LED 0 */
#define IMAX_RELAY PD4   /* Output drive for HIGH Current Mode relay - LED 1 */
#define PWMOUT PD5   /* PWM Output or on/off control - Output LED 3 */
#define FLASH PD6      /* Output operation indicator - LED 2 */
#define RESET_GLITCH PD7      /* Output pulse to reset the SR latch --- not used */

#define GAIN_DDR  DDRC
#define GAIN_PORT PORTC
#define GS0 PC0               /* Temp sensor gain bit 0 */
#define GS1 PC1               /* Temp sensor gain bit 1 */

#define FAST 1
#define SLOW 0

/* IMPORTANT:  Minimum for either of these is to be 2 since the first measurement is discarded */
#define TEMP_MEAS_CNT 5 /* Number of consecutive reads of temperature */
#define I_MEAS_CNT (5 + TEMP_MEAS_CNT) /* Number of consecutive reads of current, here it is 5 */

#define AVCC 5000 /* AVCC Ref Voltage - milli volts */
#define LUT_OFFSET 10      /* first LUT temp is 10 deg C */
#define I_OFFSET 0       /* accounts for linear offset */
#define INA139_CONST 499   /* See below.  *1000 to convert to integer.  This is accounted for in calc */

/* Vo = Is.Rs.(1000uA/V).Rl 
  Vo = K.Is 
  K = 0.01 x 0.001 x 49.9k = 0.499 
*/

FILE uart_str = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW);

/*
 * Bits that are set inside interrupt routines, and watched outside in
 * the program's main loop.
 */
volatile struct {
   uint8_t rtc_int : 1;
   uint8_t adc_int : 1;
uint8_t test_end : 1;
   uint8_t new_temp_data : 1;
   uint8_t start : 1;               /* flag for start/stopping test */
} flags;

struct Counter{
   uint8_t timer0_OVF;   /* overflow counter timer 0 */
   uint8_t flash;   /* used in timer0 ovf to flash led - I am alive */
   uint8_t glitch;      /* counts each occurrence where the current drops below a threshold*/
} counter;

typedef struct {      /* all time parameters */
uint8_t second;  
uint8_t minute;
uint8_t hour; 
uint16_t set_hour;
uint8_t set_minute;                                    
} time;

 time t; 
  
static volatile enum Test 
 {
NORMAL, 
HIGH, 
COMBINED
} selected_test; 


 /* define globals */
volatile uint8_t flash_on_val; /* on time mult 10ms */
volatile uint8_t flash_off_val; /* off time mult 10ms */

volatile uint16_t adc_raw;   /* contains ADCW for both temp and I conversion */

volatile uint8_t sp_temp;   /* set point for temperature */
volatile uint8_t pv_temp;
volatile uint32_t mV_temp;   /* measured temperature */
volatile uint32_t pv_I;   /* measured current */
volatile uint32_t last_I;

/* prototypes */
static void ioinit(void);
ISR(TIMER0_OVF_vect);
ISR(TIMER2_OVF_vect);
ISR(ADC_vect);
void setTest(void);
void setTestTime(void);
void setTemperature(void);
void initTime(void);
char displaySelection(void);
void initTest(void);
void flashRate(uint8_t);
void temperature_ctrl(uint8_t t);
void runTest(void);
uint8_t searchLUT(uint16_t v);
uint8_t getInput(void);
void printResults(void);


/* stored in RAM since we have enough space.  Could store in PROGMEM but you have to init */
/* every const into the PROGMEM */
const uint16_t LM94021_LUT[]  = {
2500, 2486, 2473, 2459, 2446, 2433, 2419, 2406, 2392, 2379, /* 10 - 19 deg C */
2365, 2352, 2338, 2325, 2311, 2298, 2285, 2271, 2258, 2244, /* 20 - 29 */
2231, 2217, 2204, 2190, 2176, 2163, 2149, 2136, 2122, 2108, /* 30 - 39 */
2095, 2081, 2067, 2054, 2040, 2026, 2012, 1999, 1985, 1971, /* 40 - 49 */
1958, 1944, 1930, 1916, 1902, 1888, 1875, 1861, 1847, 1833, /* 50 - 59 */
1819, 1805, 1791, 1777, 1763, 1749, 1735, 1721, 1707, 1693, /* 60 - 69 */
1679, 1665, 1651, 1637, 1623, 1609, 1595, 1581, 1567, 1553, /* 70 - 79 */
1539, 1525, 1511, 1497, 1483, 1469, 1544, 1441, 1427, 1413, /* 80 - 89 */
1399, 1385, 1371, 1356, 1342, 1328, 1314, 1300, 1286, 1272, /* 90 - 99 */
1257, 1243, 1229, 1215, 1201, 1186, 1172, 1158, 1144, 1130, /* 100 - 09 */
1115, 1101, 1087, 1073, 1058, 1044, 1030, 1015, 1001,  987, /* 110 - 19 */
973,  958,  944,  929,  915,  901,  886,  872,  858,  843, /* 120 - 29 */
829,  814,  800,  786,  771,  757,  742,  728,  713,  699, /* 130 - 39 */
684,  670,  655,  640,  626,  611,  597,  582,  568,  553, /* 140 - 49 */
538 /* 150 */  
};
                                             
/************************************************************************/
/*                       MAIN                                           */
/************************************************************************/
int main(void)   
{  
uart_init();                          
ioinit();
flashRate(SLOW);

stdout = stdin = &uart_str;

printf_P(PSTR("\n\nWelcome to the HV Cable Test program - ")); 
fprintf(stdout,"Version %s\n\n",VERSION);

while(1) // do forever
{
      char next;
do /* set up test parameters */
{
setTest(); /* selects the normal or high current test*/
setTestTime(); /* selects the test time */
setTemperature(); /* selects temperature */
next = displaySelection(); /* displays selection and waits for confirmation or starts over*/

} while (next != 'y');
printf_P(PSTR("\n*** Don't forget to start capture!!! ***\n"));
_delay_ms(750);

initTest(); /* inits timer, turns on appropriate relays, flasher freq increased for test running*/
runTest(); /* reads adc and updates values to UART, checks for current time == end time */
}

} /*  END MAIN  */

/************************************************************************/
/* Runs the test reading ADC, converting to eng units and controlling   */
/************************************************************************/
void runTest(void)
{
while(flags.start == 1 )
{

static uint8_t first_temp_meas = TRUE;
static uint8_t first_I_meas = TRUE;
static uint8_t meas_counter = 0; /* allows more measures of current*/
volatile static uint8_t last_sec;

/* ADC Measurement */
if(flags.adc_int == 1) /* ADC result ready */
{
flags.adc_int = 0; /* reset flag for next ADC - NB gets set in ADC interrupt*/
ADCSRA |= _BV(ADSC) ; /* start next conversion  */
if (++meas_counter <= TEMP_MEAS_CNT) /* reading for temp */
{
if (first_temp_meas == TRUE)  /* skip first result*/
first_temp_meas = FALSE;
else
{
mV_temp =   AVCC * (uint32_t) adc_raw / 1023; // * OFFSET; /* milliVolt temporary */
flags.new_temp_data = 1;
//pv_I = 0; // for debug
if (meas_counter == TEMP_MEAS_CNT) /* last reading so change for current */
{
first_temp_meas = TRUE;
ADMUX |= _BV(MUX0); /* set for current next reading */
}
}

else /* this is current reading */
{
if (first_I_meas == TRUE)  /* skip first result*/
first_I_meas = FALSE;
else
{
pv_I = (AVCC  * (uint32_t)adc_raw * 1000 / 1023 / INA139_CONST)  - I_OFFSET; /* converts to mV */
//mV_temp = 0;  //debug
if (meas_counter == I_MEAS_CNT) /* last reading so change for temperature */
{
meas_counter = 0;
first_I_meas = TRUE;
ADMUX &= ~(_BV(MUX0)); /* select temperature for next reading */
}
}
}
}

  /* ONLY if NEW temperature measurement, convert to deg C and then control output */
if (flags.new_temp_data)
{
flags.new_temp_data = 0;
pv_temp = searchLUT((uint16_t)mV_temp) + LUT_OFFSET;   /* searches sensor LUT and converts to deg C */
  temperature_ctrl(pv_temp); /* regulates heater on and off */
}
  
  // 
      if(flags.rtc_int == 1)
  {
  flags.rtc_int = 0;
  printResults();     
  }



      // if current varies by +-10% from last reading then print to screen
if ((pv_I < last_I * 0.90) || (pv_I > last_I * 1.1))
{
fprintf(stdout,"%03d:%02d:%02d  Temperature(degC) = %u \tCurrent(mA) = %u ***\tGlitch = %01d\n"
  ,t.hour,t.minute,t.second,pv_temp,(uint16_t)pv_I, counter.glitch);
last_I = pv_I;
}


if(flags.test_end == 1)  /* end of test? */
{
flags.test_end = 0; flags.start = 0 ; /* reset flags and exit while loop */

OUT_PORT &= ~(_BV(START_RELAY) | _BV(IMAX_RELAY) | _BV(PWMOUT)); // turn off all outputs
flashRate(SLOW); /* set indicator to slow flash */
printf_P(PSTR("*** END OF TEST ***\n"));
}
} // end of while (start == 1)
}


void printResults(void)
{

//if (t.second % 2 == 0) /* update every 2 seconds */     
//{
//if (t.second != last_sec )
//{
fprintf(stdout,"%03d:%02d:%02d  Temperature(degC) = %u \tCurrent(mA) = %u\tGlitch = %01d\n"
,t.hour,t.minute,t.second,pv_temp,(uint16_t)pv_I, counter.glitch);
last_I = pv_I;
//}
//last_sec = t.second;
//}

}


/************************************************************************/
/* Initializes the IO and enables interrupts                            */
/************************************************************************/
static void ioinit(void) 
{
OUT_DDR = _BV(START_RELAY) | _BV(IMAX_RELAY)  | _BV(PWMOUT) | _BV(FLASH) | _BV(RESET_GLITCH)  ; // set outputs
OUT_PORT &= ~(_BV(START_RELAY) | _BV(IMAX_RELAY)  | _BV(PWMOUT)); // turn off (LEDs) to start
GAIN_DDR = _BV(GS0) | _BV(GS1);
   // INT0 setup for detecting current glitches
   MCUCR = _BV(ISC00) | _BV(ISC01);       /* rising edge of INT0 */
   GICR |= _BV(INT0);                     /* Enable INT0 */

// Timer0 Setup
TCCR0 = _BV(CS01) | _BV(CS00); // divide by 64 
TCNT0 = 100; // count of 156 gives 10ms overflow

// Timer2 Setup
    TIMSK &= ~((1<<TOIE2)|(1<<OCIE2));       //Disable TC0 interrupt
    ASSR = _BV(AS2);                         //set Timer/Counter2 to be asynchronous from the CPU clock 
                                             //with a second external clock(32,768kHz)driving it.  

    TCCR2 = _BV(CS22) | _BV(CS20); //prescale the timer to be clock source / 128 to make it
        //exactly 1 second for every overflow to occur

    while(ASSR & TCN2UB);           //Wait until TC0 is updated
    TIMSK = _BV(TOIE0) | /*_BV(TOIE1) |*/ _BV(TOIE2);        //set 8-bit Timer/Counter0 Overflow Interrupt Enable  

ADMUX = _BV(MUX0) ; /* current  */  
ADCSRA = _BV(ADEN)| _BV(ADIE) | _BV(ADPS1) | _BV(ADPS0); /* Pre-scalar /8 gives 125kHz, adc enable , enable interrupt,*/

/*  NOTE: MUX0 defaults to 0 i.e. ADC0 is selected.  Setting MUX0 selects ADC1 */
                       
    sei();                     //set the Global Interrupt Enable Bit 
}

/************************************************************************/
/*  Regulates temperature with very simple on/off control               */
/************************************************************************/
void temperature_ctrl(uint8_t t)
{
if ( t < sp_temp)
OUT_PORT |= _BV(PWMOUT); /* switch on heater */
else if (t > sp_temp)
OUT_PORT &= ~_BV(PWMOUT); /* switch off heater */

}

/************************************************************************/
/* Initializes the test parameters and turns on the ADC etc             */
/************************************************************************/
void initTest(void)
{
initTime();                /* set time to zero */
counter.glitch = 0;          /* reset glitch counter */

GAIN_PORT = _BV(GS0) | _BV(GS1);    /* Set temp sensor gain bits to high */

if (selected_test == HIGH)
{
OUT_PORT &= ~_BV(PWMOUT); // turn off PWM led
OUT_PORT |= (_BV(IMAX_RELAY) | _BV(START_RELAY));  // turn on
}
else
{
OUT_PORT &= ~(_BV(IMAX_RELAY) | _BV(PWMOUT)); // turn off Imax LED
OUT_PORT |= _BV(START_RELAY); // turn on Start relay LED2
}
flags.start = 1;

ADCSRA |= _BV(ADSC); /* Start ADC conversion */
flashRate(FAST);
}

/************************************************************************/
/* Counts glitches from comparator and then resets                      */
/************************************************************************/
ISR(INT0_vect)
{
++counter.glitch;

OUT_PORT |= _BV(RESET_GLITCH);      /* reset SR circuit */
OUT_PORT &= ~_BV(RESET_GLITCH);     /* ~11us pulse */

fprintf(stdout,"%03d:%02d:%02d  Temperature(degC) = %u \tCurrent(mA) = %u \tGlitch = %01d ***\n"
,t.hour,t.minute,t.second,pv_temp,(uint16_t)pv_I, counter.glitch);
}

/************************************************************************/
/* Measures the current and temperature                                 */
/************************************************************************/
ISR(ADC_vect)
{
adc_raw = ADCW ;
flags.adc_int = 1;
}

/************************************************************************/
/* Used for various flash rates of mode indicator                       */
/************************************************************************/
ISR(TIMER0_OVF_vect)
{
TCNT0 = 100;
//++counter.timer0_OVF;
if(++counter.timer0_OVF == flash_on_val) // 100ms
OUT_PORT &= ~_BV(FLASH); // active Low - switch ON LED
else if(counter.timer0_OVF == flash_off_val) // 1900ms
{
OUT_PORT |= _BV(FLASH); // switch OFF LED
counter.timer0_OVF = 0; // reset
}
}

/************************************************************************/
/* 1 second clock for hr, min and sec.                                  */
/* Checks for end of test and sets flag                                 */
/************************************************************************/
ISR(TIMER2_OVF_vect) 
{    
flags.rtc_int = 1; // used for timing of outputing data
    if (++t.second==60)        //keep track of time
    {
        t.second=0;
        if (++t.minute==60) 
        {
            t.minute=0;
            ++t.hour;
        }
    } 
/* flag to check for test timeout */
if (t.hour == t.set_hour && t.minute == t.set_minute && (t.minute > 0 || t.hour > 0))
flags.test_end = 1;
}   

/************************************************************************/
/* Binary Search function for arrays.  This is set for a sorted array   */
/* where the ordered sort is from high to low.  To change for low to    */
/* high you would set the while ( low >= high )                         */
/* RETURNS: the array position NOT THE VALUE                            */
/************************************************************************/
uint8_t searchLUT(uint16_t v)
{
uint8_t low = 0;
uint8_t high = (sizeof(LM94021_LUT)/ sizeof(*LM94021_LUT)) - 1;

while (low <= high && high < 255)   
{
uint8_t mid = (low + high) / 2;
int16_t diff = LM94021_LUT[mid] - v;
if (diff == 0) 
  return mid;
else if (diff > 0)      /* LM94021_LUT[mid] < temp*/
  low = mid + 1;
else 
  high = mid - 1;
}
return low;
}

/************************************************************************/
/*  sets all the time parameters to zero                                */
/************************************************************************/
void initTime(void)
{
t.second = 0;
t.minute = 0;
t.hour = 0;


/************************************************************************/
/* Prompts the user for a time and stays in a loop until a valid entry  */
/************************************************************************/
void setTestTime(void)
{
char buf[20];
while(1) 
{
printf_P(PSTR("\nEnter the test time in the following format (hhh:mm) : "));
if(fgets(buf, sizeof buf -1, stdin) != NULL)
{
         if (sscanf(buf,"%d%*c%d",&t.set_hour,&t.set_minute)>0)
  {
     if (t.set_hour <= 999 || t.set_minute <= 59) 
        break;
  }
}
  printf_P(PSTR("*** Error: Try again Example 24:23 is 24 hrs 23 min ***\n"));

}

/************************************************************************/
/* Prompts the user for test required and stays in loop until a valid   */
/* entry                                                                */
/************************************************************************/
void setTest(void)
{
//uint8_t num;
char buf[20];
while(1) 
{
printf_P(PSTR("\nSelect from the following:\n"));
printf_P(PSTR("1. Normal Current Test\n")); 
printf_P(PSTR("2. High Current Test\n")); 
printf_P(PSTR("3. Combination Test (*** NOT ENABLED YET ***)\n"));
printf_P(PSTR("\nSelect > "));
//num = uart_getchar(stdin);

if (fgets(buf,sizeof buf - 1, stdin) != NULL)
{
         if (tolower(buf[0]) > '0' && tolower(buf[0]) < '3') 
     break;
  else
  {
     printf_P(PSTR("*** Error:  Enter 1 or 2 ***\n\n"));
  }  
}

//printf("num = %c\n",num);


switch (tolower(buf[0])) 
{
case '1':
selected_test = NORMAL;
break;
case '2':
selected_test = HIGH;
break;
case '3':
selected_test = COMBINED;
break;
default:
printf_P(PSTR("I am in default\n"));
break;
}
}




/************************************************************************/
/* Displays selection and asks for confirm to continue                  */
/************************************************************************/
char displaySelection(void)
{
char buf[5];
uint8_t cnt = 0;
if (selected_test == NORMAL)
printf_P(PSTR("\nTest Selected : Normal Current Test\n"));
else if(selected_test == HIGH)
printf_P(PSTR("\nTest Selected : High Current Test\n"));
else if(selected_test == COMBINED)
printf_P(PSTR("\nTest Selected : Combination of Normal and HIgh Current Test\n"));
printf("Time selected : %d hours %d minutes\n",t.set_hour,t.set_minute);
printf("Temp Set Point : %u deg C\n",sp_temp);
printf_P(PSTR("\nWould you like to continue (y/n) :  "));
fgets(buf, sizeof buf - 1, stdin);
   while(++cnt < 5)          
{
if (tolower(buf[0]) == 'y' || tolower(buf[0]) == 'n')
  return buf[0];
else 
{
printf("buf[0] = %c\n",buf[0]);
         printf_P(PSTR("\nInput error (y/n)  :  ")); 
fgets(buf, sizeof buf - 1, stdin);
}
}
return 'n';
}

/************************************************************************/
/* Requests set temperature and stays in loop until valid response      */
/************************************************************************/
void setTemperature(void)
{
while(1) 
{
printf_P(PSTR("Enter the temperature set point (deg C) : "));
scanf("%d",&sp_temp);
if (sp_temp > 20 && sp_temp < 200) break;
printf_P(PSTR("*** Temperature must be between 20 and 200 deg C ***\n"));

}

//
/************************************************************************/
/* Sets the flash rate of the mode indicator                            */
/************************************************************************/
void flashRate(uint8_t r)
{
if (r) { // fast
flash_on_val = 5; /* 50 ms ON */
flash_off_val = 10; /* 200 ms OFF */
} else { // slow
flash_on_val = 5; /* 20 ms ON */ 
flash_off_val = 190; /* 1900 ms OFF */
}
}

Thursday 23 August 2012

AVR Code for ADC conversion from a Water Flow Sensor to LCD16*2





/*
 * Water_Flow_Sensor.c
 *
 * Created: 3/03/2012 5:55:20 PM
 *  Author: Dean
 *
 * Water flow sensor to measure the flow rate from a Proteus flow switch;
 *
 * 0.8 - 9.5 L/min
 * Analogue Input 0 - 5V ADC0
 * POWERTIP PC1602-H LCD 16*2
 *
 * INT0 - RESET BUTTON - resets the MAX and MIN
 *
 * DISPLAY READOUT
 *  ________________
 * |FLOW  3.63 L/MIN|
 * |MIN 2.81MAX 4.93|
 * |________________|
 */


#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>

#include "defines.h"
#include "lcd_lib.h"
#include "a2d.h"

// declared in a2d.h and used to indicate adc interrupt
extern volatile unsigned char a2dCompleteFlag;


// prototypes
void set_display(void);
ISR(INT0_vect); // resets max and min


// globals
volatile u16 gmax = 0; // start at lowest value
volatile u16 gmin = 1024; // start at highest value


int main(void) {

u16 iflow; // holds adc raw data for flow
float fflow; // float conversion of above
char buffer[8]; // reserve memory
char* str = buffer; // string for flow value to LCD


MCUCR |= _BV(ISC01);  // falling edge of INT0
GICR |= _BV(INT0); // enable INT0
LCDinit();
a2dInit();

set_display(); // set all the display static readings
a2dStartConvert();

while(1){
if (a2dCompleteFlag){
iflow = ADCW;
a2dCompleteFlag = FALSE; // set ready for next conversion
a2dStartConvert(); // start ADC

fflow = 0.0093 * (float)iflow;  // 9.5L/min / 1024 = 0.0093

dtostrf(fflow,3,2,str);
LCDGotoXY(5,0);
LCDstring(str);

if (iflow < gmin) { // update max or min if changed
gmin = iflow;
LCDGotoXY(4,1);
LCDstring(str);
} else if(iflow > gmax){
gmax = iflow;
LCDGotoXY(12,1);
LCDstring(str);
}
}
}
}

ISR(INT0_vect){
gmax = 0; // reset max and min
gmin = 1024;
}


void set_display(void){
LCDclr();
LCDcursorOFF();
LCDGotoXY(3,0);
LCDstring("WATER FLOW");
LCDGotoXY(2,1);
LCDstring("SENSOR V1.0");

_delay_ms(1000);
LCDclr();
LCDhome();
LCDstring("FLOW       L/MIN");
LCDGotoXY(0,1);
LCDstring("MIN     MAX");
}