Electronic Projects, forums and more.

Go Back   Electronic Circuits Projects Diagrams Free > Electronics Categories > Micro Controllers


Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc.

Reply
 
Tools
Old 9th September 2009, 08:22 PM   #16
Default

try this and tell me what happens:
Code:
#include <pic.h>
#include "pic.h"
#include "delay.h"
#include "math.h" 
#include <stdio.h>
#include <stdlib.h>
  
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(void);
void home_screen(void);
void EnterScreen(void);
void ShowDigits(unsigned char val);
void main(void);



void calc_distance(void);

      

#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;
char temp[8];
int height=50, SensorPos=10;
char input_sw;

 
char mnuPOS;

unsigned char MyVal;
unsigned char MyValLCD[2];
unsigned char MyMaxVal;
unsigned char MyMinVal;



#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(20); //wait for LCD to be ready
	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(20); //wait for LCD to be ready
	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(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)
{   

    OSCCON|=0x60; //set fosc to 4Mhz
	TRISB=0x00; 
	TRISC=0xFC;
    TRISA = 0b10000010; 	// RA7 high imp, RA3 is serial out,
	ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
	ANSELH=0x00;
	lcd_init(); //call LCD initialisation
}

char WaitForInput(void){
char done;
char temp;
done = 0;

while(!done){
    if(!ENTERSETTINGS_SW){
        temp = 1;
        done = 0xff;
    }

    if(!HOME_SW){
        temp = 2;
        done = 0xff;
    }

    if(!INCREASE_SW){
        temp = 3;
        done = 0xff;
    }

    if(!DECREASE_SW){
        temp = 4;
        done = 0xff;
    }
}//end of while
    DelayMs(150);    //debounce
    return temp;
}

void home_screen(void){
	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)
}

void EnterScreen(void){
	lcd_clear();
	lcd_goto_L1();
	lcd_puts(" ENTER/SETTINGS ");
}

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)
{
	// 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

	// convert from 0-99 to 2 decimal digits, 0-99cm
	cm10=0;
	while(math >= 10)
	{
		cm10++;
		math -= 10;
	}
	cm = math;
}
 
void main(void)
{
	init();	// initialise I/O ports, LCD
    //home_screen();

	MyVal = 0;
	MyMinVal = 0;
	MyMaxVal = 99;

while(1){
   	input_sw = WaitForInput();

    switch(input_sw){
      case 1:
      	EnterScreen();
		mnuPOS = 1;
		DelayMS(50);
        break;
      case 2:
		home_screen();
		mnuPOS = 2;
        break;
    }
	
	while(mnuPOS == 1){
   		input_sw = WaitForInput();
		
      switch(input_sw){
		case 1:
			mnuPOS = 2;
			home_screen();
			break;
      	case 3:
			if(MyVal < MyMaxVal)
      			MyVal++;
			ShowDigits(MyVal);
			break;
      	case 4:
			if(MyVal > MyMinVal)
      			MyVal--;
			ShowDigits(MyVal);
        	break;
      }
	}
	
	//Do something here with the new Value which is a decimal in MyVal.
}
 
	 
}
AtomSoft is offline  
Old 9th September 2009, 08:38 PM   #17
Default

Im using the new code you suggested and now

when i power on:


"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and so forth.


when i press home button: infra red liquid level detector is displayed continuously

when i release home button:

"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and so forth.
Code:
when i press increase button: it displays enter/settings on 1st line
                                         then 01                        on 2nd line

                                         it displays enter/settings on 1st line
                                         then 02                        on 2nd line
and continues increasing...
but i need the 1st digit to increase fro 0 to 9 and rollover to 0.

when i release increase button:"enter/settings" is displayed continuously

Code:
when i press decrease button: it displays enter/settings on 1st line
                                         then 02                        on 2nd line

                                         it displays enter/settings on 1st line
                                         then 01                        on 2nd line

                                         it displays enter/settings on 1st line
                                         then 00                       on 2nd line

                                         it displays enter/settings on 1st line
                                         then 00                        on 2nd line
and 00 is the lowest it decreases to
But i need the 2nd digit to decrease from 9 to 0 and rollover to 9.

when i release decrease button:"enter/settings" is displayed continuously


when i press home/settings button:
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and so forth.

when i release home/settings button:
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and so forth.

Last edited by fantabulous68; 9th September 2009 at 08:41 PM.
fantabulous68 is offline  
Old 9th September 2009, 09:21 PM   #18
Default

i think you might have a hardware issue. Are all the buttons pulled high?

As soon as it goes on it should not say anything. It should be blank and you have to press the home button for it to show that "infrared liquid level detector"

Hence why i suggest you uncomment the :

Code:
void main(void)
{
	init();	// initialise I/O ports, LCD
        home_screen(); 

Last edited by AtomSoft; 9th September 2009 at 09:23 PM.
AtomSoft is offline  
Old 9th September 2009, 09:30 PM   #19
Default

Maybe the configuration bits in MPLAB are not set corrrectly???that would affect the micro right. im using momentary push button switches....
fantabulous68 is offline  
Old 9th September 2009, 09:31 PM   #20
Default

im going to uncomment home and c what happens. When i tried your new code....home is uncommented and the same remarks apply.

Last edited by fantabulous68; 9th September 2009 at 09:33 PM.
fantabulous68 is offline  
Old 9th September 2009, 09:35 PM   #21
Default

heh replacing time:
Code:
    TRISA = 0b10000010; 	// RA7 high imp, RA3 is serial out,
heh in your init: you should put this
Code:
    TRISA = 0b10010010; 	// RA7 high imp, RA3 is serial out, RA4 button input 

Last edited by AtomSoft; 9th September 2009 at 09:36 PM.
AtomSoft is offline  
Old 9th September 2009, 09:39 PM   #22
Default

oscillator external RC clockout
watchdog timer off
power up timer off
master clear enable external
code protect off
data ee ee protect off
brown out detect BOD enabled, sboren disabled
internal external switchover mode enabled
monitor clock fail-safe enabled
fantabulous68 is offline  
Old 9th September 2009, 09:41 PM   #23
Default

what pic are you using?
AtomSoft is offline  
Old 9th September 2009, 09:47 PM   #24
Default

i replaced the TRISA line but:


when i power on:


"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and so forth.


when i press home button: infra red liquid level detector is displayed continuously

when i release home button:

"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and
"infrared liquid level detector is displayed" then it clears and
"enter/settings" is displayed continuously then it clears and so forth.

BUT now also sumtimes when i hold down the home button for long:

the screen remains blank until i release it again
fantabulous68 is offline  
Old 9th September 2009, 09:50 PM   #25
Default

im using the pic 16f690.
fantabulous68 is offline  
Old 9th September 2009, 09:54 PM   #26
Default

ok. What are you using to program it? CCS or something?

try this:
Code:
#include <pic.h>
#include "pic.h"
#include "delay.h"
#include "math.h" 
#include <stdio.h>
#include <stdlib.h>
  
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(void);
void home_screen(void);
void EnterScreen(void);
void ShowDigits(unsigned char val);
void main(void);



void calc_distance(void);

      

#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;
char temp[8];
int height=50, SensorPos=10;
char input_sw;

 
char mnuPOS;

unsigned char MyVal;
unsigned char MyValLCD[2];
unsigned char MyMaxVal;
unsigned char MyMinVal;



#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(20); //wait for LCD to be ready
	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(20); //wait for LCD to be ready
	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(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)
{   

    OSCCON|=0x60; //set fosc to 4Mhz

	TRISB=0x00; 
	TRISC=0xFC;
    TRISA = 0b10010010; 	// RA7 high imp, RA3 is serial out,

	ANSEL=0x02;            //set RA1 as analog input for GP2 sensor
	ANSELH=0x00;
	lcd_init(); //call LCD initialisation
}

char WaitForInput(void){
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;
    }
}//end of while
    DelayMs(150);    //debounce
    return temp;
}

void home_screen(void){
	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)
}

void EnterScreen(void){
	mnuPOS = 0;
	input_sw = 0;
	lcd_clear();
	lcd_goto_L1();
	lcd_puts(" ENTER/SETTINGS ");
}

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)
{
	// 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

	// convert from 0-99 to 2 decimal digits, 0-99cm
	cm10=0;
	while(math >= 10)
	{
		cm10++;
		math -= 10;
	}
	cm = math;
}

void main(void)
{
	init();	// initialise I/O ports, LCD
    home_screen();

	MyVal = 0;
	MyMinVal = 0;
	MyMaxVal = 99;

while(1){
	input_sw = 0;
   	input_sw = WaitForInput();

    switch(input_sw){
      case 1:
      	EnterScreen();
		mnuPOS = 1;
		DelayMS(50);
        break;
      case 2:
		home_screen();
		mnuPOS = 2;
        break;
    }
	
	while(mnuPOS == 1){
		input_sw = 0;
   		input_sw = WaitForInput();
		
      switch(input_sw){
		case 1:
			mnuPOS = 2;
			home_screen();
			break;
      	case 3:
			if(MyVal < MyMaxVal)
      			MyVal++;
			ShowDigits(MyVal);
			break;
      	case 4:
			if(MyVal > MyMinVal)
      			MyVal--;
			ShowDigits(MyVal);
        	break;
      }
	}
	
	//Do something here with the new Value which is a decimal in MyVal.
}
 
	 
}
AtomSoft is offline  
Old 9th September 2009, 10:03 PM   #27
Default

im using the pic kit 2 demo board with mplab ide v8.01-hi-tech universal toolsuite:hi tech ansi c compiler pic lite....whats ccs???hehe

Last edited by fantabulous68; 9th September 2009 at 10:05 PM.
fantabulous68 is offline  
Old 9th September 2009, 10:08 PM   #28
Default

the new code it gives an error:

Error [499] ; 0. undefined symbol:
_DelayMS(ctest.obj)

ok i corrected it....MS to Ms

Last edited by fantabulous68; 9th September 2009 at 10:10 PM.
fantabulous68 is offline  
Old 9th September 2009, 10:13 PM   #29
Default

ok i ran the new code and:

when i power up:

infrared liquid level detector is displayed and its stable....not being repeated.


however pressing the buttons has no effect
fantabulous68 is offline  
Old 9th September 2009, 10:49 PM   #30
Default

Ok the way this works is to enter settings you need to press enter then use increase and decrease.

What happens when you press enter? nothing?
AtomSoft is offline  
Reply

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



All times are GMT. The time now is 09:56 AM.


Electronic Circuits  |  Learning Electronics
eXTReMe Tracker