![]() | ![]() | ![]() |
| | #136 | |
|
I was advised by Noggin: Quote:
Code: #include <pic.h>
#include "pic.h"
#include "delay.h"
#include "math.h"
#include <stdio.h>
#include <stdlib.h> //
#define FALSE 0
#define TRUE 1
struct filter_type {
unsigned int accumulator;
unsigned int output;
unsigned char shift_value;
unsigned char initialized;
} ;
struct filter_type adc_filter;
void userMenu(char pos); //
void FloatToStr(float , char[]);
void DelayMs(unsigned char);
void lcd_cmd(unsigned char);
void lcd_data(unsigned char);
void lcd_clear(void);
void lcd_puts(const char[]);
void lcd_goto_L1(void);
void lcd_goto_L2(void);
void lcd_cursor(unsigned char);
void lcd_init(void);
void init(void);
char WaitForInput(char expire);
unsigned char user_input(void);
void home_screen(void);
void EnterHeight(void);
void EnterScreen(void);
void ShowDigits(unsigned char val);
void calc_distance(void);
void main(void);
unsigned char cm2LCD;
unsigned char posneg;
unsigned char LLHigh, LLLow;
unsigned int LiquidLevel;
#define LCD_RS RC0 //LCD RS pin
#define LCD_EN RC1 //LCD EN pin
#define LCD_STROBE() LCD_EN = 1; asm("nop"); asm("nop"); LCD_EN = 0
unsigned char cm10; //
unsigned char cm; //
unsigned int math; // used for voltage calculations
unsigned char NumDec;
unsigned char NumSep[2];
unsigned char i,j,k;
unsigned char height=50;
unsigned char range=10;
unsigned char area;
char input_sw;
char mnuPOS;
unsigned char MyVal;
unsigned char MyValLCD[2];
unsigned char MyMaxVal;
unsigned char MyMinVal;
unsigned long bres; // for bresenham 2-second timer system
unsigned char ;
#define HOME_SW RC2 //HOME switch
#define INCREASE_SW RC3 //INCREASE switch
#define DECREASE_SW RC4 //DECREASE switch
#define ENTERSETTINGS_SW RA4 //ENTERSETTINGS switch
///////////////////////CONVERT FLOAT TO STRING///////////////////
// This function was taken from the CAVR library. It was modified slightly
// to suit our design.
void FloatToStr(float n, char str[])
{
float scale;
unsigned char d,f;
f=0;i=0;
if (n<0.0) {n=-n; str[f]='-'; f++;};
n=n+0.005;
scale=1.0;
while (n>=scale) {scale=scale*10.0; ++i;};
if (i==0) {str[f]='0'; f++;}
else
while (i--)
{
scale=floor(0.5+scale/10.0);
d=(unsigned char) (n/scale);
str[f]=d+'0';
n=n-scale*d;
f++;
};
str[f]='.';
f++;
for (j=0;j<=1;j++) //2 decimal points
{
n=n*10.0;
d=(unsigned char) n;
str[f]=d+'0';
n=n-d;
f++;
};
str[f]='\0';
}
///////////////////END CONVERT FLOAT TO STRING///////////////////
/////////////////////////////DELAY///////////////////////////////
void DelayMs(unsigned char cnt)
{
#if XTAL_FREQ <= 2MHZ
do {
DelayUs(996);
} while(--cnt);
#endif
#if XTAL_FREQ > 2MHZ
unsigned char p;
do {
p = 4;
do {
DelayUs(250);
} while(--p);
} while(--cnt);
#endif
}
void DelayS(unsigned char cnt)
{
for (j=0; j<(cnt*10); j++)
DelayMs(100);
}
///////////////////////////DELAY END/////////////////////////////
//////////////////////////////LCD SETUP//////////////////////////
/* send a command to the LCD */
void lcd_cmd(unsigned char c)
{
DelayMs(2); //wait for LCD to be ready shorter delay
LCD_RS = 0; //write instruction
PORTB = (c & 0xF0); //load upper nibble on LCD data lines
LCD_STROBE(); //send instruction to LCD
PORTB = ((c << 4) & 0xF0); //load upper nibble on LCD data lines
LCD_STROBE(); //send instruction to LCD
}
/* send data to the LCD */
void lcd_data(unsigned char c)
{
DelayMs(2); //wait for LCD to be ready shorter delay
PORTB = 0x00;
LCD_RS = 1; //write data
PORTB |= (c & 0xF0); //load upper nibble on LCD data lines
LCD_STROBE(); //send instruction to LCD
PORTB &= 0x00; //load upper nibble on LCD data lines
PORTB |= ( (c << 4) & 0xF0);
LCD_STROBE(); //send instruction to LCD
}
/*Clear the LCD*/
void lcd_clear(void)
{
lcd_cmd(0x01); //command to clear LCD
}
/*write a string of chars to the LCD*/
void lcd_puts(const char s[])
{
j = -1;
while(s[++j]!=('\0')) // send characters until null character reached
lcd_data(s[j]);
}
/*go to beginning of line 1*/
void lcd_goto_L1(void)
{
lcd_cmd(0b10000000); // command to go to line 1
}
/*go to beginning of line 2*/
void lcd_goto_L2(void)
{
lcd_cmd(0b11000000); // command to go to line 2
}
/*move cursor "x" positions to the right*/
void lcd_cursor(unsigned char x)
{
lcd_cmd(((x)&0x7F)|0x80);
}
/*initialise the LCD - put into 4 bit mode*/
void lcd_init(void)
{
LCD_RS = 0;
LCD_EN = 0;
DelayMs(20); //wait for LCD startup
lcd_cmd(0x02);
lcd_cmd(0x28); // 4-bit mode
lcd_cmd(0x08); // display off
lcd_cmd(0x01); // clear display
lcd_cmd(0x0C); // disp. on, cursor off, cursor blink off
lcd_cmd(0x06); // entry mode
lcd_cmd(0x80); // initialise DDRAM address to zero
}
//////////////////////////LCD SETUP END//////////////////////////
void init(void)
{
// setup the PIC 16f690
OSCCON = 0x72; // internal osc, 8MHz
PORTA = 0;
TRISA = 0b10010010; // RA7 high imp, RA3 is serial out, RA4 button input
PORTB = 0; // PORTB not used
WPUB = 1; // PORTB pullups ON
RABPU = 0;
/* Init ADC */
ADCON0 = 0b10000101; // bit 7 right justify,analogue channel select bits bits5-2 0001=AN1,ADC ON, RA1 is ADC input
ADCON1 = 0b00100000; //bits6-4 fosc/32
ADON=1; // turn on the A2D conversion module
ANSEL=0x02; //set RA1 as analog input for GP2 sensor
ANSELH=0x00;
T1CON = 0b00010001; // TMR1 is ON, 1:2 prescale, =1MHz
T2CON = 0b00000101; // TMR2 is ON, 1:4 prescale, =1MHz
MyVal = 0; //initializn these variables here
MyMinVal = 0;
MyMaxVal = 99;
TRISB=0x00;
TRISC=0xFC;
lcd_init(); //call LCD initialisation
}
//EDITED this a bit. now if expire input is set it will leave loop with a 0
//instead of rechecking this will be useful for display your measured data and
//waiting for user to exit.
char WaitForInput(char expire){
char done;
char temp;
done = 0;
temp = 0;
while(!done){
if(!ENTERSETTINGS_SW){
while(ENTERSETTINGS_SW);
temp = 1;
done = 0xff;
}
if(!HOME_SW){
while(HOME_SW);
temp = 2;
done = 0xff;
}
if(!INCREASE_SW){
while(INCREASE_SW);
temp = 3;
done = 0xff;
}
if(!DECREASE_SW){
while(DECREASE_SW);
temp = 4;
done = 0xff;
}
if(expire == 1) break;
}//end of while
DelayMs(150); //debounce
return temp;
}//
void Init_Filter( struct filter_type *filter, unsigned char shift )
{
filter->initialized = FALSE;
filter->shift_value = shift;
}
void Update_Filter( struct filter_type *filter, unsigned int new_value )
{
if (filter->initialized != TRUE)
{
filter->output = new_value;
filter->accumulator = new_value << filter->shift_value;
filter->initialized = TRUE;
}
else
{
filter->accumulator -= filter->output;
filter->accumulator += new_value;
filter->output = filter->accumulator >> filter->shift_value;
}
}
void userMenu(char pos){
unsigned int delaytime = 100000; // 100ms CHANGE THIS FOR YOUR BELOW DELAY
lcd_clear();
lcd_goto_L1();
switch(pos){
case 0:
lcd_puts(" HEIGHT ");
break;
case 1:
lcd_puts(" RANGE ");
break;
case 2:
lcd_puts(" SURFACE AREA ");
break; //
case 3:
lcd_puts(" MEASURED ");
while(WaitForInput(1) != 2){ //Wait for user to press enter to leave loop
// wait for 2 seconds, uses TMR1 free running at 1Mhz
while(!TMR1IF) // wait for TMR1 overflow
TMR1IF = 0; // clear overflow flag
bres += 65536; // add 65536uS to bres value
if(bres >= delaytime ) // if reached 2 seconds!
{
bres -= delaytime ; // subtract 2 seconds, keep error
// read the ADC voltage RA1 (Sharp GP2 sensor)
// Whenever you read your adc, just call Update_Filter( &adc_filter, adc_value ).
GODONE=1; // initiate conversion on the channel 0
while(GODONE) continue; // Wait convertion done
Update_Filter( &adc_filter, adc_value );
calc_distance(); // convert ADC value to distance
lcd_goto_L2(); //Only change line 2
//
if(posneg == 'p')
lcd_data('+');
else
lcd_data('-');
//
lcd_data(LLHigh);
lcd_data(LLLow);
lcd_puts(" [cm] "); //comment this out if you want
}
}
lcd_goto_L1();
lcd_puts(" Loading Home ");
lcd_goto_L2();
lcd_puts(" ");
DelayS(1);
break;
}
if(pos == 3) return;
lcd_goto_L2();
lcd_puts("Press Up/Down"); //home screen message (line 2)
}
// New Menu System
void EnterHeight(void){
lcd_clear();
lcd_goto_L1();
lcd_puts(" ENTER HEIGHT ");
lcd_goto_L2();
lcd_puts("Press Up/Down"); //home screen message (line 2)
}
void EnterScreen(void){
lcd_clear();
lcd_goto_L1();
lcd_puts(" [cm] ");
}
void ShowDigits(unsigned char val){
MyValLCD[0] = val /10; //returns the quotient (if temp = 35 the result is 3)
MyValLCD[1] = val % 10; //Returns remainder (if temp = 35 the result is 5)
MyValLCD[0] += 0x30; //to ASCII
MyValLCD[1] += 0x30; //to ASCII
EnterScreen();
lcd_goto_L2();
lcd_data(MyValLCD[0]); //to LCD
lcd_data(MyValLCD[1]); //to LCD
}
void calc_distance(void)
{
unsigned int tmp;
unsigned int mathKeep; // used for voltage calculations backup
// from the transeiver datasheet the analog voltage is
// the inverse of distance, so distance can be calculated
// d = (1 / volts) then just scaled to suit the transeiver
// load ADC value in 16bit math var
//Wherever you perform a calculation on the ADC value, use adc_filter.output instead.
// math = ADRESH;
math=adc_filter.output;
math = (math * 256);
// math += ADRESL;
math +=adc_filter.output;
// now invert it; (1 / volts) use (6050 / volts) for scaling
math = (6050 / math);
if(math >= 2) math -=2; // fix linear error (-2)
if(math > 99) math = 99; // max limit at 99cm
//Create a copy of math for more use
mathKeep = math;
//LiquidLevel=height-;
// convert from 0-99 to 2 decimal digits, 0-99cm
cm10=0;
while(math >= 10)
{
cm10++;
math -= 10;
}
cm = math;
math = mathKeep; //Now our original data is back and can be used.
//This will check if negative
LiquidLevel=height-math;
//
posneg = 'p';
if((LiquidLevel < 0) || (LiquidLevel > 0xFF00)){
LiquidLevel = -LiquidLevel ;
posneg = 'n';
}
//
//if below zero which will be in the 0xFFFF range i just chose any 0xFFxx number :D
//LiquidLevel is higher than 09 so spilt the variable LiquidLevel into 2 //
LLHigh = ( LiquidLevel / 10 ) + '0'; //
LLLow = ( LiquidLevel % 10 ) + '0'; //
}
//
unsigned char user_input(void) //This will return what we want
{
char done = 0;
MyVal = 0; //Start on 0
while(done == 0){
input_sw = WaitForInput(0);
switch(input_sw){
case 1:
done = 0xff; //This tells us the user finished entering
lcd_goto_L1();
lcd_puts(" OK "); //home screen message (line 1)
break;
case 3:
if(MyVal < MyMaxVal)
MyVal++;
EnterScreen();
ShowDigits(MyVal);
break;
case 4:
if(MyVal > MyMinVal)
MyVal--;
EnterScreen();
ShowDigits(MyVal);
break;
default:
break;
}
}
DelayMs(250);
DelayMs(250);
return MyVal;
}
void home_screen(void){
mnuPOS = 0;
lcd_clear();
lcd_goto_L1();
lcd_puts("INFRARED LIQUID"); //home screen message (line 1)
lcd_goto_L2();
lcd_puts("LEVEL DETECTOR"); //home screen message (line 2)
input_sw = 0; //Reset the value
while(input_sw != 1) //Wait until enter is pressed
input_sw = WaitForInput(0);
userMenu(0);
DelayMs(2); //shorter delay
height = user_input(); //The HEIGHT var will have the myVal
userMenu(1);
DelayMs(2); //shorter delay
range = user_input(); //The HEIGHT var will have the myVal
userMenu(2);
DelayMs(2); //shorter delay
area = user_input(); //The HEIGHT var will have the myVal
//
userMenu(3);
DelayMs(2); //shorter delay
input_sw = 0; //Reset the value
}
//*********************************************************
/* Junebug_Serial4.c RomanBlack.com 19th July 2009.
uses "zero error 1 second timer"
system to generate a 2 second interval, then every
2 seconds it reads an analog voltage from a
Sharp GP2 distance sensor and converts it to decimal
distance, then sends that data to a LCD
Code for MikroC, config handled by MikroC compiler;
_INTI02_OSC_1H
_WDT_OFF_2H
-MCLRE_ON_3H
_LVP_OFF_4L
_PWRT_ON_2L
*/
//*********************************************************
void main(void)
{
init(); // initialise I/O ports, LCD
while(1){
home_screen();
}
}
Im a bit unsure about: Code: //Wherever you perform a calculation on the ADC value, use adc_filter.output instead.
// math = ADRESH;
math=adc_filter.output;
math = (math * 256);
// math += ADRESL;
math +=adc_filter.output; Can adc_filter.output be broken up into a high & low value then assigned to math? OR do i assign adc_filter output directly to math as is??
__________________ Learn without thinking begets ignorance. Think without learning is dangerous. | ||
| |
| | #137 |
|
What is adc_value? You might need to replace that. I hate structures heh The issue is you do math on 2 parts Low and Hi. Not sure what the structure accomplishes heh
__________________ AtomSofts eBay Store AtomSoftTech: C18 TIPS & TRICKS v9 PDF Nokia 6100 Driver/Software My Name: Jason Lopez http://atomsofttech.info/ | My YouTube Videos! My Favorite Store: dipmicro Electronics | |
| |
| | #138 | |||||
| Quote:
i tested the project on liquids & responded: ME:The readings are fluctuating.....not very stable especially for water.... Noggin:This should help reduce fluctuations. Increase the shift value to increase noise rejection, but it will slow the response. Code: Code:
typdef struct filter_type
{
Uint16 accumulator;
Uint16 output;
Uint8 shift_value;
Uint8 initialized;
};
filter_type adc_filter;
void Init_Filter( filter_type *filter, Uint8 shift )
{
filter->initialized = FALSE;
filter->shift_value = shift;
}
void Update_Filter( filter_type *filter, Uint16 new_value )
{
if (filter->initialized != TRUE)
{
filter->output = new_value;
filter->accumulator = new_value << filter->shift_value;
filter->initialized = TRUE;
}
else
{
filter->accumulator -= filter->output;
filter->accumulator += new_value;
filter->output = filter->accumulator >> filter->shift_value;
}
}
Quote:
Quote:
Quote:
Quote:
load ADC value in 16bit math var---->So ADRESH and ADRESL contain the adc values im sure.
__________________ Learn without thinking begets ignorance. Think without learning is dangerous. | ||||||
| |
| | #139 |
|
To average the readings you should make a nice simple variable like: unsigned int adc_temp[3]; Then take about 3 readings placing the data in each var using a loop with a delay.. Code: for(x=0;x<3;x++){
GODONE=1;
while(GODONE) continue;
adc_temp[x] = (ADRESH << 4) | ADRESL;
DelayMs(100);
}
//Now average the readings
adc_actual = (adc_temp[0] + adc_temp[1] + adc_temp[2]) / 3;
__________________ AtomSofts eBay Store AtomSoftTech: C18 TIPS & TRICKS v9 PDF Nokia 6100 Driver/Software My Name: Jason Lopez http://atomsofttech.info/ | My YouTube Videos! My Favorite Store: dipmicro Electronics Last edited by AtomSoft; 22nd September 2009 at 11:58 AM. | |
| |
| | #140 |
|
Ok that seems like a more simple way to average the readings...I will try it out later tonight on the sensor...Thanks AtomSoft
__________________ Learn without thinking begets ignorance. Think without learning is dangerous. | |
| |
| | #141 |
|
Im trying to use your method of averaging, i included it in RED highlight below....but i keep getting a pointer error...Could you please tell me what im doing wrong? Code: math = ADRESH; math = (math * 256); math += ADRESL; Code: #include <pic.h>
#include "pic.h"
#include "delay.h"
#include "math.h"
#include <stdio.h>
#include <stdlib.h> //
void userMenu(char pos); //
void FloatToStr(float , char[]);
void DelayMs(unsigned char);
void lcd_cmd(unsigned char);
void lcd_data(unsigned char);
void lcd_clear(void);
void lcd_puts(const char[]);
void lcd_goto_L1(void);
void lcd_goto_L2(void);
void lcd_cursor(unsigned char);
void lcd_init(void);
void init(void);
char WaitForInput(char expire);
unsigned char user_input(void);
void home_screen(void);
void EnterHeight(void);
void EnterScreen(void);
void ShowDigits(unsigned char val);
void calc_distance(void);
void main(void);
unsigned char cm2LCD;
unsigned char posneg;
unsigned char LLHigh, LLLow;
unsigned int LiquidLevel;
#define LCD_RS RC0 //LCD RS pin
#define LCD_EN RC1 //LCD EN pin
#define LCD_STROBE() LCD_EN = 1; asm("nop"); asm("nop"); LCD_EN = 0
unsigned char cm10; //
unsigned char cm; //
unsigned int math,adc_temp,adc_actual; // used for voltage calculations
unsigned char NumDec;
unsigned char NumSep[2];
unsigned char i,j,k,x;
//char temp[8];
//[/b]
unsigned char height=50;
unsigned char range;
unsigned char area;
unsigned char SensorPos=10;
//[/b] New Vars
char input_sw;
char mnuPOS;
unsigned char MyVal;
unsigned char MyValLCD[2];
unsigned char MyMaxVal;
unsigned char MyMinVal;
unsigned long bres; // for bresenham 2-second timer system
unsigned char ;
#define HOME_SW RC2 //HOME switch
#define INCREASE_SW RC3 //INCREASE switch
#define DECREASE_SW RC4 //DECREASE switch
#define ENTERSETTINGS_SW RA4 //ENTERSETTINGS switch
///////////////////////CONVERT FLOAT TO STRING///////////////////
// This function was taken from the CAVR library. It was modified slightly
// to suit our design.
void FloatToStr(float n, char str[])
{
float scale;
unsigned char d,f;
f=0;i=0;
if (n<0.0) {n=-n; str[f]='-'; f++;};
n=n+0.005;
scale=1.0;
while (n>=scale) {scale=scale*10.0; ++i;};
if (i==0) {str[f]='0'; f++;}
else
while (i--)
{
scale=floor(0.5+scale/10.0);
d=(unsigned char) (n/scale);
str[f]=d+'0';
n=n-scale*d;
f++;
};
str[f]='.';
f++;
for (j=0;j<=1;j++) //2 decimal points
{
n=n*10.0;
d=(unsigned char) n;
str[f]=d+'0';
n=n-d;
f++;
};
str[f]='\0';
}
///////////////////END CONVERT FLOAT TO STRING///////////////////
/////////////////////////////DELAY///////////////////////////////
void DelayMs(unsigned char cnt)
{
#if XTAL_FREQ <= 2MHZ
do {
DelayUs(996);
} while(--cnt);
#endif
#if XTAL_FREQ > 2MHZ
unsigned char p;
do {
p = 4;
do {
DelayUs(250);
} while(--p);
} while(--cnt);
#endif
}
void DelayS(unsigned char cnt)
{
for (j=0; j<(cnt*10); j++)
DelayMs(100);
}
///////////////////////////DELAY END/////////////////////////////
//////////////////////////////LCD SETUP//////////////////////////
/* send a command to the LCD */
void lcd_cmd(unsigned char c)
{
DelayMs(2); //wait for LCD to be ready shorter delay
LCD_RS = 0; //write instruction
PORTB = (c & 0xF0); //load upper nibble on LCD data lines
LCD_STROBE(); //send instruction to LCD
PORTB = ((c << 4) & 0xF0); //load upper nibble on LCD data lines
LCD_STROBE(); //send instruction to LCD
}
/* send data to the LCD */
void lcd_data(unsigned char c)
{
DelayMs(2); //wait for LCD to be ready shorter delay
PORTB = 0x00;
LCD_RS = 1; //write data
PORTB |= (c & 0xF0); //load upper nibble on LCD data lines
LCD_STROBE(); //send instruction to LCD
PORTB &= 0x00; //load upper nibble on LCD data lines
PORTB |= ( (c << 4) & 0xF0);
LCD_STROBE(); //send instruction to LCD
}
/*Clear the LCD*/
void lcd_clear(void)
{
lcd_cmd(0x01); //command to clear LCD
}
/*write a string of chars to the LCD*/
void lcd_puts(const char s[])
{
j = -1;
while(s[++j]!=('\0')) // send characters until null character reached
lcd_data(s[j]);
}
/*go to beginning of line 1*/
void lcd_goto_L1(void)
{
lcd_cmd(0b10000000); // command to go to line 1
}
/*go to beginning of line 2*/
void lcd_goto_L2(void)
{
lcd_cmd(0b11000000); // command to go to line 2
}
/*move cursor "x" positions to the right*/
void lcd_cursor(unsigned char x)
{
lcd_cmd(((x)&0x7F)|0x80);
}
/*initialise the LCD - put into 4 bit mode*/
void lcd_init(void)
{
LCD_RS = 0;
LCD_EN = 0;
DelayMs(20); //wait for LCD startup
lcd_cmd(0x02);
lcd_cmd(0x28); // 4-bit mode
lcd_cmd(0x08); // display off
lcd_cmd(0x01); // clear display
lcd_cmd(0x0C); // disp. on, cursor off, cursor blink off
lcd_cmd(0x06); // entry mode
lcd_cmd(0x80); // initialise DDRAM address to zero
}
//////////////////////////LCD SETUP END//////////////////////////
void init(void)
{
// setup the PIC 16f690
OSCCON = 0x72; // internal osc, 8MHz
PORTA = 0;
TRISA = 0b10010010; // RA7 high imp, RA3 is serial out, RA4 button input
PORTB = 0; // PORTB not used
WPUB = 1; // PORTB pullups ON
RABPU = 0;
/* Init ADC */
ADCON0 = 0b10000101; // bit 7 right justify,analogue channel select bits bits5-2 0001=AN1,ADC ON, RA1 is ADC input
ADCON1 = 0b00100000; //bits6-4 fosc/32
ADON=1; // turn on the A2D conversion module
ANSEL=0x02; //set RA1 as analog input for GP2 sensor
ANSELH=0x00;
T1CON = 0b00010001; // TMR1 is ON, 1:2 prescale, =1MHz
T2CON = 0b00000101; // TMR2 is ON, 1:4 prescale, =1MHz
MyVal = 0; //initializn these variables here
MyMinVal = 0;
MyMaxVal = 99;
TRISB=0x00;
TRISC=0xFC;
lcd_init(); //call LCD initialisation
}
//EDITED this a bit. now if expire input is set it will leave loop with a 0
//instead of rechecking this will be useful for display your measured data and
//waiting for user to exit.
char WaitForInput(char expire){
char done;
char temp;
done = 0;
temp = 0;
while(!done){
if(!ENTERSETTINGS_SW){
while(ENTERSETTINGS_SW);
temp = 1;
done = 0xff;
}
if(!HOME_SW){
while(HOME_SW);
temp = 2;
done = 0xff;
}
if(!INCREASE_SW){
while(INCREASE_SW);
temp = 3;
done = 0xff;
}
if(!DECREASE_SW){
while(DECREASE_SW);
temp = 4;
done = 0xff;
}
if(expire == 1) break;
}//end of while
DelayMs(150); //debounce
return temp;
}//
void userMenu(char pos){
unsigned int delaytime = 100000; // 100ms CHANGE THIS FOR YOUR BELOW DELAY
lcd_clear();
lcd_goto_L1();
switch(pos){
case 0:
lcd_puts(" HEIGHT ");
break;
case 1:
lcd_puts(" RANGE ");
break;
case 2:
lcd_puts(" SURFACE AREA ");
break; //
case 3:
lcd_puts(" MEASURED ");
while(WaitForInput(1) != 2){ //Wait for user to press enter to leave loop
// wait for 2 seconds, uses TMR1 free running at 1Mhz
while(!TMR1IF) // wait for TMR1 overflow
TMR1IF = 0; // clear overflow flag
bres += 65536; // add 65536uS to bres value
if(bres >= delaytime ) // if reached 2 seconds!
{
bres -= delaytime ; // subtract 2 seconds, keep error
// read the ADC voltage RA1 (Sharp GP2 sensor)
for(x=0;x<3;x++){
GODONE=1; // initiate conversion on the channel 0
while(GODONE) continue; // Wait convertion done
adc_temp[x] = (ADRESH << 4) | ADRESL;
DelayMs(100);
}
//Now average the readings
adc_actual = (adc_temp[0] + adc_temp[1] + adc_temp[2]) / 3;
calc_distance(); // convert ADC value to distance
lcd_goto_L2(); //Only change line 2
//
if(posneg == 'p')
lcd_data('+');
else
lcd_data('-');
//
lcd_data(LLHigh);
lcd_data(LLLow);
lcd_puts(" [cm] "); //comment this out if you want
}
}
lcd_goto_L1();
lcd_puts(" Loading Home ");
lcd_goto_L2();
lcd_puts(" ");
DelayS(1);
break;
}
if(pos == 3) return;
lcd_goto_L2();
lcd_puts("Press Up/Down"); //home screen message (line 2)
}
// New Menu System
void EnterHeight(void){
lcd_clear();
lcd_goto_L1();
lcd_puts(" ENTER HEIGHT ");
lcd_goto_L2();
lcd_puts("Press Up/Down"); //home screen message (line 2)
}
void EnterScreen(void){
lcd_clear();
lcd_goto_L1();
lcd_puts(" [cm] ");
}
void ShowDigits(unsigned char val){
MyValLCD[0] = val /10; //returns the quotient (if temp = 35 the result is 3)
MyValLCD[1] = val % 10; //Returns remainder (if temp = 35 the result is 5)
MyValLCD[0] += 0x30; //to ASCII
MyValLCD[1] += 0x30; //to ASCII
EnterScreen();
lcd_goto_L2();
lcd_data(MyValLCD[0]); //to LCD
lcd_data(MyValLCD[1]); //to LCD
}
void calc_distance(void)
{
unsigned int tmp;
unsigned int mathKeep; // used for voltage calculations backup
// from the transeiver datasheet the analog voltage is
// the inverse of distance, so distance can be calculated
// d = (1 / volts) then just scaled to suit the transeiver
// load ADC value in 16bit math var
math = ADRESH;
math = (math * 256);
math += ADRESL;
// now invert it; (1 / volts) use (6050 / volts) for scaling
math = (6050 / math);
if(math >= 2) math -=2; // fix linear error (-2)
if(math > 99) math = 99; // max limit at 99cm
//Create a copy of math for more use
mathKeep = math;
//LiquidLevel=height-;
// convert from 0-99 to 2 decimal digits, 0-99cm
cm10=0;
while(math >= 10)
{
cm10++;
math -= 10;
}
cm = math;
math = mathKeep; //Now our original data is back and can be used.
//This will check if negative
LiquidLevel=height-math;
//
posneg = 'p';
if((LiquidLevel < 0) || (LiquidLevel > 0xFF00)){
LiquidLevel = -LiquidLevel ;
posneg = 'n';
}
//
//if below zero which will be in the 0xFFFF range i just chose any 0xFFxx number :D
//LiquidLevel is higher than 09 so spilt the variable LiquidLevel into 2 //
LLHigh = ( LiquidLevel / 10 ) + '0'; //
LLLow = ( LiquidLevel % 10 ) + '0'; //
}
//
unsigned char user_input(void) //This will return what we want
{
char done = 0;
MyVal = 0; //Start on 0
while(done == 0){
input_sw = WaitForInput(0);
switch(input_sw){
case 1:
done = 0xff; //This tells us the user finished entering
lcd_goto_L1();
lcd_puts(" OK "); //home screen message (line 1)
break;
case 3:
if(MyVal < MyMaxVal)
MyVal++;
EnterScreen();
ShowDigits(MyVal);
break;
case 4:
if(MyVal > MyMinVal)
MyVal--;
EnterScreen();
ShowDigits(MyVal);
break;
default:
break;
}
}
DelayMs(250);
DelayMs(250);
return MyVal;
}
void home_screen(void){
mnuPOS = 0;
lcd_clear();
lcd_goto_L1();
lcd_puts("INFRARED LIQUID"); //home screen message (line 1)
lcd_goto_L2();
lcd_puts("LEVEL DETECTOR"); //home screen message (line 2)
input_sw = 0; //Reset the value
while(input_sw != 1) //Wait until enter is pressed
input_sw = WaitForInput(0);
userMenu(0);
DelayMs(2); //shorter delay
height = user_input(); //The HEIGHT var will have the myVal
userMenu(1);
DelayMs(2); //shorter delay
range = user_input(); //The HEIGHT var will have the myVal
userMenu(2);
DelayMs(2); //shorter delay
area = user_input(); //The HEIGHT var will have the myVal
//
userMenu(3);
DelayMs(2); //shorter delay
input_sw = 0; //Reset the value
//Waits for user to press ENTER to show home screen
/*
"enter height"
call enter/settings (which is now user input function in new code)
height=MyVal
"enter range"
call user_input
range=MyVal
"enter surface area"
call user_input
area=MyVal
*/
}
//*********************************************************
/* Junebug_Serial4.c RomanBlack.com 19th July 2009.
uses "zero error 1 second timer"
system to generate a 2 second interval, then every
2 seconds it reads an analog voltage from a
Sharp GP2 distance sensor and converts it to decimal
distance, then sends that data to a LCD
Code for MikroC, config handled by MikroC compiler;
_INTI02_OSC_1H
_WDT_OFF_2H
-MCLRE_ON_3H
_LVP_OFF_4L
_PWRT_ON_2L
*/
//*********************************************************
void main(void)
{
init(); // initialise I/O ports, LCD
while(1){
home_screen();
/*// wait for 2 seconds, uses TMR1 free running at 1Mhz
while(!TMR1IF) // wait for TMR1 overflow
TMR1IF = 0; // clear overflow flag
bres += 65536; // add 65536uS to bres value
if(bres >= 2000000) // if reached 2 seconds!
{
bres -= 2000000; // subtract 2 seconds, keep error
// read the ADC voltage RA1 (Sharp GP2 sensor)
GODONE=1; // initiate conversion on the channel 0
while(GODONE) continue; // Wait convertion done
calc_distance(); // convert ADC value to distance
// LiquidLevel=height-;
// lcd_clear(); // Using the new menu you can erase or
// lcd_data(cm10 + '0');
// lcd_data(cm + '0');
// lcd_goto_L2();
// lcd_puts("[cm] "); //comment this out if you want
*/
}
}
__________________ Learn without thinking begets ignorance. Think without learning is dangerous. Last edited by fantabulous68; 24th September 2009 at 08:41 AM. | |
| |
| | #142 |
|
im going to try the 2 methods suggested to see which gives me a more accurate measurement... Methods being: 1. Your Averaging of 3 adc values 2. Noggins Digital filter
__________________ Learn without thinking begets ignorance. Think without learning is dangerous. | |
| |
| | #143 |
|
You need to change the declaration to, Code: unsigned int math,adc_temp[3],adc_actual; // used for voltage calculations Code: adc_temp[x] = (ADRESH << 4) | ADRESL; Code: adc_temp[x] = (ADRESH << 8) | ADRESL; | |
| |
| | #144 |
|
Thanks Pommie
__________________ Learn without thinking begets ignorance. Think without learning is dangerous. | |
| |
| | #145 |
|
How do i split adc_actual into a high and low so i can assign it to math in the calc_distance function? Code: // load ADC value in 16bit math var math = ADRESH; math = (math * 256); math += ADRESL; Code: #include <pic.h>
#include "pic.h"
#include "delay.h"
#include "math.h"
#include <stdio.h>
#include <stdlib.h> //
void userMenu(char pos); //
void FloatToStr(float , char[]);
void DelayMs(unsigned char);
void lcd_cmd(unsigned char);
void lcd_data(unsigned char);
void lcd_clear(void);
void lcd_puts(const char[]);
void lcd_goto_L1(void);
void lcd_goto_L2(void);
void lcd_cursor(unsigned char);
void lcd_init(void);
void init(void);
char WaitForInput(char expire);
unsigned char user_input(void);
void home_screen(void);
void EnterHeight(void);
void EnterScreen(void);
void ShowDigits(unsigned char val);
void calc_distance(void);
void main(void);
unsigned char cm2LCD;
unsigned char posneg;
unsigned char LLHigh, LLLow;
unsigned int LiquidLevel;
#define LCD_RS RC0 //LCD RS pin
#define LCD_EN RC1 //LCD EN pin
#define LCD_STROBE() LCD_EN = 1; asm("nop"); asm("nop"); LCD_EN = 0
unsigned char cm10; //
unsigned char cm; //
unsigned int math,adc_temp[3],adc_actual; // used for voltage calculations
unsigned char NumDec;
unsigned char NumSep[2];
unsigned char i,j,k,x;
//char temp[8];
unsigned char height=50;
unsigned char range;
unsigned char area;
unsigned char SensorPos=10;
// New Vars
char input_sw;
char mnuPOS;
unsigned char MyVal;
unsigned char MyValLCD[2];
unsigned char MyMaxVal;
unsigned char MyMinVal;
unsigned long bres; // for bresenham 2-second timer system
unsigned char ;
#define HOME_SW RC2 //HOME switch
#define INCREASE_SW RC3 //INCREASE switch
#define DECREASE_SW RC4 //DECREASE switch
#define ENTERSETTINGS_SW RA4 //ENTERSETTINGS switch
///////////////////////CONVERT FLOAT TO STRING///////////////////
// This function was taken from the CAVR library. It was modified slightly
// to suit our design.
void FloatToStr(float n, char str[])
{
float scale;
unsigned char d,f;
f=0;i=0;
if (n<0.0) {n=-n; str[f]='-'; f++;};
n=n+0.005;
scale=1.0;
while (n>=scale) {scale=scale*10.0; ++i;};
if (i==0) {str[f]='0'; f++;}
else
while (i--)
{
scale=floor(0.5+scale/10.0);
d=(unsigned char) (n/scale);
str[f]=d+'0';
n=n-scale*d;
f++;
};
str[f]='.';
f++;
for (j=0;j<=1;j++) //2 decimal points
{
n=n*10.0;
d=(unsigned char) n;
str[f]=d+'0';
n=n-d;
f++;
};
str[f]='\0';
}
///////////////////END CONVERT FLOAT TO STRING///////////////////
/////////////////////////////DELAY///////////////////////////////
void DelayMs(unsigned char cnt)
{
#if XTAL_FREQ <= 2MHZ
do {
DelayUs(996);
} while(--cnt);
#endif
#if XTAL_FREQ > 2MHZ
unsigned char p;
do {
p = 4;
do {
DelayUs(250);
} while(--p);
} while(--cnt);
#endif
}
void DelayS(unsigned char cnt)
{
for (j=0; j<(cnt*10); j++)
DelayMs(100);
}
///////////////////////////DELAY END/////////////////////////////
//////////////////////////////LCD SETUP//////////////////////////
/* send a command to the LCD */
void lcd_cmd(unsigned char c)
{
DelayMs(2); //wait for LCD to be ready shorter delay
LCD_RS = 0; //write instruction
PORTB = (c & 0xF0); //load upper nibble on LCD data lines
LCD_STROBE(); //send instruction to LCD
PORTB = ((c << 4) & 0xF0); //load upper nibble on LCD data lines
LCD_STROBE(); //send instruction to LCD
}
/* send data to the LCD */
void lcd_data(unsigned char c)
{
DelayMs(2); //wait for LCD to be ready shorter delay
PORTB = 0x00;
LCD_RS = 1; //write data
PORTB |= (c & 0xF0); //load upper nibble on LCD data lines
LCD_STROBE(); //send instruction to LCD
PORTB &= 0x00; //load upper nibble on LCD data lines
PORTB |= ( (c << 4) & 0xF0);
LCD_STROBE(); //send instruction to LCD
}
/*Clear the LCD*/
void lcd_clear(void)
{
lcd_cmd(0x01); //command to clear LCD
}
/*write a string of chars to the LCD*/
void lcd_puts(const char s[])
{
j = -1;
while(s[++j]!=('\0')) // send characters until null character reached
lcd_data(s[j]);
}
/*go to beginning of line 1*/
void lcd_goto_L1(void)
{
lcd_cmd(0b10000000); // command to go to line 1
}
/*go to beginning of line 2*/
void lcd_goto_L2(void)
{
lcd_cmd(0b11000000); // command to go to line 2
}
/*move cursor "x" positions to the right*/
void lcd_cursor(unsigned char x)
{
lcd_cmd(((x)&0x7F)|0x80);
}
/*initialise the LCD - put into 4 bit mode*/
void lcd_init(void)
{
LCD_RS = 0;
LCD_EN = 0;
DelayMs(20); //wait for LCD startup
lcd_cmd(0x02);
lcd_cmd(0x28); // 4-bit mode
lcd_cmd(0x08); // display off
lcd_cmd(0x01); // clear display
lcd_cmd(0x0C); // disp. on, cursor off, cursor blink off
lcd_cmd(0x06); // entry mode
lcd_cmd(0x80); // initialise DDRAM address to zero
}
//////////////////////////LCD SETUP END//////////////////////////
void init(void)
{
// setup the PIC 16f690
OSCCON = 0x72; // internal osc, 8MHz
PORTA = 0;
TRISA = 0b10010010; // RA7 high imp, RA3 is serial out, RA4 button input
PORTB = 0; // PORTB not used
WPUB = 1; // PORTB pullups ON
RABPU = 0;
/* Init ADC */
ADCON0 = 0b10000101; // bit 7 right justify,analogue channel select bits bits5-2 0001=AN1,ADC ON, RA1 is ADC input
ADCON1 = 0b00100000; //bits6-4 fosc/32
ADON=1; // turn on the A2D conversion module
ANSEL=0x02; //set RA1 as analog input for GP2 sensor
ANSELH=0x00;
T1CON = 0b00010001; // TMR1 is ON, 1:2 prescale, =1MHz
T2CON = 0b00000101; // TMR2 is ON, 1:4 prescale, =1MHz
MyVal = 0; //initializn these variables here
MyMinVal = 0;
MyMaxVal = 99;
TRISB=0x00;
TRISC=0xFC;
lcd_init(); //call LCD initialisation
}
//EDITED this a bit. now if expire input is set it will leave loop with a 0
//instead of rechecking this will be useful for display your measured data and
//waiting for user to exit.
char WaitForInput(char expire){
char done;
char temp;
done = 0;
temp = 0;
while(!done){
if(!ENTERSETTINGS_SW){
while(ENTERSETTINGS_SW);
temp = 1;
done = 0xff;
}
if(!HOME_SW){
while(HOME_SW);
temp = 2;
done = 0xff;
}
if(!INCREASE_SW){
while(INCREASE_SW);
temp = 3;
done = 0xff;
}
if(!DECREASE_SW){
while(DECREASE_SW);
temp = 4;
done = 0xff;
}
if(expire == 1) break;
}//end of while
DelayMs(150); //debounce
return temp;
}//
void userMenu(char pos){
unsigned int delaytime = 100000; // 100ms CHANGE THIS FOR YOUR BELOW DELAY
lcd_clear();
lcd_goto_L1();
switch(pos){
case 0:
lcd_puts(" HEIGHT ");
break;
case 1:
lcd_puts(" RANGE ");
break;
case 2:
lcd_puts(" SURFACE AREA ");
break; //
case 3:
lcd_puts(" MEASURED ");
while(WaitForInput(1) != 2){ //Wait for user to press enter to leave loop
// wait for 2 seconds, uses TMR1 free running at 1Mhz
while(!TMR1IF) // wait for TMR1 overflow
TMR1IF = 0; // clear overflow flag
bres += 65536; // add 65536uS to bres value
if(bres >= delaytime ) // if reached 2 seconds!
{
bres -= delaytime ; // subtract 2 seconds, keep error
// read the ADC voltage RA1 (Sharp GP2 sensor)
for(x=0;x<3;x++){
GODONE=1; // initiate conversion on the channel 0
while(GODONE) continue; // Wait convertion done
adc_temp[x] = (ADRESH << 8) | ADRESL;
DelayMs(100);
}
//Now average the readings
adc_actual = (adc_temp[0] + adc_temp[1] + adc_temp[2]) / 3;
calc_distance(); // convert ADC value to distance
lcd_goto_L2(); //Only change line 2
//
if(posneg == 'p')
lcd_data('+');
else
lcd_data('-');
//
lcd_data(LLHigh);
lcd_data(LLLow);
lcd_puts(" [cm] "); //comment this out if you want
}
}
lcd_goto_L1();
lcd_puts(" Loading Home ");
lcd_goto_L2();
lcd_puts(" ");
DelayS(1);
break;
}
if(pos == 3) return;
lcd_goto_L2();
lcd_puts("Press Up/Down"); //home screen message (line 2)
}
// New Menu System
void EnterHeight(void){
lcd_clear();
lcd_goto_L1();
lcd_puts(" ENTER HEIGHT ");
lcd_goto_L2();
lcd_puts("Press Up/Down"); //home screen message (line 2)
}
void EnterScreen(void){
lcd_clear();
lcd_goto_L1();
lcd_puts(" [cm] ");
}
void ShowDigits(unsigned char val){
MyValLCD[0] = val /10; //returns the quotient (if temp = 35 the result is 3)
MyValLCD[1] = val % 10; //Returns remainder (if temp = 35 the result is 5)
MyValLCD[0] += 0x30; //to ASCII
MyValLCD[1] += 0x30; //to ASCII
EnterScreen();
lcd_goto_L2();
lcd_data(MyValLCD[0]); //to LCD
lcd_data(MyValLCD[1]); //to LCD
}
void calc_distance(void)
{
unsigned int tmp;
unsigned int mathKeep; // used for voltage calculations backup
// from the transeiver datasheet the analog voltage is
// the inverse of distance, so distance can be calculated
// d = (1 / volts) then just scaled to suit the transeiver
// load ADC value in 16bit math var
math = ADRESH;
math = (math * 256);
math += ADRESL;
// now invert it; (1 / volts) use (6050 / volts) for scaling
math = (6050 / math);
if(math >= 2) math -=2; // fix linear error (-2)
if(math > 99) math = 99; // max limit at 99cm
//Create a copy of math for more use
mathKeep = math;
//LiquidLevel=height-;
// convert from 0-99 to 2 decimal digits, 0-99cm
cm10=0;
while(math >= 10)
{
cm10++;
math -= 10;
}
cm = math;
math = mathKeep; //Now our original data is back and can be used.
//This will check if negative
LiquidLevel=height-math;
//
posneg = 'p';
if((LiquidLevel < 0) || (LiquidLevel > 0xFF00)){
LiquidLevel = -LiquidLevel ;
posneg = 'n';
}
//
//if below zero which will be in the 0xFFFF range i just chose any 0xFFxx number :D
//LiquidLevel is higher than 09 so spilt the variable LiquidLevel into 2 //
LLHigh = ( LiquidLevel / 10 ) + '0'; //
LLLow = ( LiquidLevel % 10 ) + '0'; //
}
//
unsigned char user_input(void) //This will return what we want
{
char done = 0;
MyVal = 0; //Start on 0
while(done == 0){
input_sw = WaitForInput(0);
switch(input_sw){
case 1:
done = 0xff; //This tells us the user finished entering
lcd_goto_L1();
lcd_puts(" OK "); //home screen message (line 1)
break;
case 3:
if(MyVal < MyMaxVal)
MyVal++;
EnterScreen();
ShowDigits(MyVal);
break;
case 4:
if(MyVal > MyMinVal)
MyVal--;
EnterScreen();
ShowDigits(MyVal);
break;
default:
break;
}
}
DelayMs(250);
DelayMs(250);
return MyVal;
}
void home_screen(void){
mnuPOS = 0;
lcd_clear();
lcd_goto_L1();
lcd_puts("INFRARED LIQUID"); //home screen message (line 1)
lcd_goto_L2();
lcd_puts("LEVEL DETECTOR"); //home screen message (line 2)
input_sw = 0; //Reset the value
while(input_sw != 1) //Wait until enter is pressed
input_sw = WaitForInput(0);
userMenu(0);
DelayMs(2); //shorter delay
height = user_input(); //The HEIGHT var will have the myVal
userMenu(1);
DelayMs(2); //shorter delay
range = user_input(); //The HEIGHT var will have the myVal
userMenu(2);
DelayMs(2); //shorter delay
area = user_input(); //The HEIGHT var will have the myVal
//
userMenu(3);
DelayMs(2); //shorter delay
input_sw = 0; //Reset the value
//Waits for user to press ENTER to show home screen
/*
"enter height"
call enter/settings (which is now user input function in new code)
height=MyVal
"enter range"
call user_input
range=MyVal
"enter surface area"
call user_input
area=MyVal
*/
}
//*********************************************************
/* Junebug_Serial4.c RomanBlack.com 19th July 2009.
uses "zero error 1 second timer"
system to generate a 2 second interval, then every
2 seconds it reads an analog voltage from a
Sharp GP2 distance sensor and converts it to decimal
distance, then sends that data to a LCD
Code for MikroC, config handled by MikroC compiler;
_INTI02_OSC_1H
_WDT_OFF_2H
-MCLRE_ON_3H
_LVP_OFF_4L
_PWRT_ON_2L
*/
//*********************************************************
void main(void)
{
init(); // initialise I/O ports, LCD
while(1){
home_screen();
}
}
__________________ Learn without thinking begets ignorance. Think without learning is dangerous. | |
| |
| | #146 |
|
You can just do, math=adc_actual; Mike. | |
| |
| | #147 |
|
Try : Code: // load ADC value in 16bit math var math = (adc_actual >> 8) & 0x00FF; math = (math * 256); math += adc_actual & 0x00FF;
__________________ AtomSofts eBay Store AtomSoftTech: C18 TIPS & TRICKS v9 PDF Nokia 6100 Driver/Software My Name: Jason Lopez http://atomsofttech.info/ | My YouTube Videos! My Favorite Store: dipmicro Electronics | |
| |
| | #148 | |
| Quote:
I prefer this technique; it only needs to take 1 new reading, then averages that with the 3 previous readings. Code: GODONE=1;
while(GODONE) continue;
adc_temp[x] = (ADRESH << 8) | ADRESL;
x++;
x = (x & 0x03); //(or bcf x,2 or x.F2=0 on a better compiler)
adc_actual = (adc_temp[0] + adc_temp[1] + adc_temp[2]
+ adc_temp[3] +2) / 4;
Last edited by Mr RB; 24th September 2009 at 07:45 PM. | ||
| |
| | #149 |
|
if your taking 1 new reading and average it with last actual reading then you might have big error there not in code but actual data If reading 1 was 10 CM If reading 2 was 9 CM If new reading is 2 CM Your average is: 10 + 9 + 2 + 2 = 23 / 4 = 5.75 Now is that anything near the 2 that was read ? also change : adc_temp[x] = (ADRESH << 4) | ADRESL; to adc_temp[x] = (ADRESH << 8) | ADRESL;
__________________ AtomSofts eBay Store AtomSoftTech: C18 TIPS & TRICKS v9 PDF Nokia 6100 Driver/Software My Name: Jason Lopez http://atomsofttech.info/ | My YouTube Videos! My Favorite Store: dipmicro Electronics Last edited by AtomSoft; 24th September 2009 at 11:17 AM. | |
| |
| | #150 |
|
Sure, but in most cases you read the sensor constantly, as part of a timed loop process. So the 4 readings in the circular buffer are always the 4 most recent readings. Then whenever you need to "read" the filtered ADC value you just average the readings that are already in the circular buffer. | |
| |
|
| Tags |
| display, lcd, pushbutton, reading |
| Thread Tools | |
| Display Modes | |
| |
Similar | ||||
| Title | Starter | Forum | Replies | Latest |
| Substituting a 16x2 LCD display for 16x1 LCD display? | Dawny | Electronic Projects Design/Ideas/Reviews | 19 | 11th October 2008 09:58 AM |
| Pushbutton Slow & Repeating Pulse | btanner | Electronic Projects Design/Ideas/Reviews | 1 | 22nd January 2008 06:18 PM |
| Is this display burned out? (Sony MD LCD Display) | Amphr_Moth | General Electronics Chat | 4 | 28th October 2007 07:47 PM |
| how to display '-' & '+' range number on LCD? | meera83 | Micro Controllers | 8 | 5th July 2007 09:56 AM |
| lcd display with hd44780 display driver | ANUPAMA | Micro Controllers | 2 | 7th April 2004 02:58 PM |