+ Post New Thread
Results 1 to 8 of 8
  1. #1
    Member level 2
    Points: 1,312, Level: 8

    Join Date
    Apr 2013
    Posts
    49
    Helped
    0 / 0
    Points
    1,312
    Level
    8

    Reading more than one analog value is a problem

    Hello all,

    I can read one analog value in one channel just fine. But using two or more seems to be a problem. It seems the ADRES(ult) register does not get refreshed with the new value from the second channel. I am thinking that capacitor in the ADC is not discharged. Can you please help. The code is as listed below.
    Code:
    void ADC_Init();
    
    unsigned int  ADC_Read(unsigned int);
    
     void main()
     { 
    
    	int a, b;
    	float voltage;
    
    	TRISBbits.TRISB3 = 0; 
    	TRISBbits.TRISB2 = 0; 
    	TRISBbits.TRISB1 = 0;
    	PORTB = 0;
    
    	
    	OSCCON = 0x72;			//	set internal oscillator at 8 MHz
    	
    
    	while(1)
    		{
    			ADC_Init();	
    			ADCON0 = 0b00001101;	//	select channel1(AN3) and power on A/D Module (ADON =1)	   		
    			a = ADC_Read(3);
                		ADCON0 = 0b00010101;	//	select channel1(AN5) and power on A/D Module (ADON =1)
                		b = ADC_Read(5);	//	Read another channel
    		
    			
    			if (a > b)
    				{
    				    PORTBbits.RB1 = 1;
    				     
    				}
    			else
    				{
    					PORTBbits.RB1 = 0;
    				
                    }
      }
    
    void ADC_Init()
    	{
    		TRISA  = 0xFF;		//	initialise PortA as input Port
    		PORTA  = 0;
            	ADCON2 = 0b10111110;	//	1 Right justified; 010 == 20*T_ad; 010 = F_osc/64
    		ADCON1 = 0b00000101;	//	AN0 and AN1 set as Analog Inputs
    		ADRESH = 0;
    		ADRESL = 0;
    	}
    
    
    unsigned int ADC_Read(unsigned int channel)
    	{
    		unsigned int d;
    		ADCON0bits.GO = 1;	//	Set the GO 
    		while(ADCON0bits.GO == 1)
    		{
    			d = (ADRESH*256)|(ADRESL);
    		}
    		return(d);
    	}

    •   AltAdvertisment

        
       

  2. #2
    Super Moderator
    Points: 78,118, Level: 68
    Achievements:
    7 years registered
    Awards:
    2nd Helpful Member
    betwixt's Avatar
    Join Date
    Jul 2009
    Location
    Aberdyfi, West Wales, UK
    Posts
    12,784
    Helped
    4271 / 4271
    Points
    78,118
    Level
    68

    Re: Reading more than one analog value is a problem

    Your prognosis is almost correct. You don't need to discharge the ADC S&H capacitor but you do need to give it time to adapt to the voltage from the new channel, especially if you are not driving the ADC inputs from a low impedance. Try adding a short delay between selecting channel and taking the measurement. It is explained in all the PIC data sheets.

    I'm a little worried about your ADC_Read() routine, you should be waiting for the 'GO' bit to clear before reading the ADC results rather than continuously reading them until it clears. You might also need an 'int' cast on the registers when you combine them into 'd'. You also seem to ignore the channel selection value passed to the routine.

    Brian.
    PLEASE - no friends requests or private emails, I simply don't have time to reply to them all.
    It's better to share your questions and answers on Edaboard so we can all benefit from each others experiences.


    1 members found this post helpful.

  3. #3
    Super Moderator
    Points: 28,814, Level: 41
    andre_teprom's Avatar
    Join Date
    Nov 2006
    Location
    Brazil
    Posts
    8,587
    Helped
    1087 / 1087
    Points
    28,814
    Level
    41
    Blog Entries
    6

    Re: Reading more than one analog value is a problem

    Furthermore, it is not expected to have the ADC_Init() function inside the while(1) loop.
    Run it just once, before the endless loop.
    --------------------------------------------------------------------------------------------------
    Part of the world that you live in, You are the part that you're giving ( Renaissance )



    •   AltAdvertisment

        
       

  4. #4
    Member level 2
    Points: 1,312, Level: 8

    Join Date
    Apr 2013
    Posts
    49
    Helped
    0 / 0
    Points
    1,312
    Level
    8

    Re: Reading more than one analog value is a problem

    Hello all,

    I still seem to be having a problem reading the second analog value. I am using PIC18F4550 and MPLAB IDE 8.56 and XC18 compiler. I am also using two analog inputs both are square wave from function generator, both have duty cycle at 50% and 4V as Vpp and both have 2.5V DC offset to eliminate negative input to PIC. But one signal is at 1 Hz given to AN3 and the other is 10 Hz given to AN5.

    It seems that when the positive edge of the first is sensed then the second one is not sampled. The code and oscilloscope results are as below. Please tell me how to fix it.

    Code:
    void ADC_Init();
    
     void main()
     { 
    
    	int a, b;
    
        	PORTA  = 0;
            TRISA  = 0xFF;	//	initialise PortA as input Port
    		
            ADCON2 = 0b10010010;	//	1 Right justified;  010 == 4*T_ad; 010 = F_osc/32
    	ADCON1 = 0b00000101;	//	AN0 and AN1 set as Analog Inputs
    	ADRESH = 0;
    	ADRESL = 0;
      		
      	PORTB = 0;
    	TRISBbits.TRISB3 = 0; 
    	TRISBbits.TRISB2 = 0; 
    	TRISBbits.TRISB1 = 0;
    	
    	PORTC = 0;
    	TRISCbits.TRISC2 = 0; 
    	
    	OSCCON = 0b01000110;			//	set internal oscillator at 8 MHz
    	
    	ADC_Init();
    
    	while(1)
    		{
                  			ADCON0 = 0b00001101; // select channel1(AN3) and power on A/D Module (ADON =1)      
    				ADCON0bits.GO = 1;   // start conversion  
     				while (ADCON0bits.GO == 1) continue; // wait until conversion is complete  
     				a = ((int)ADRESH << 8)|ADRESL; // save value to variable  
    				Delay10TCY();
    			
    				ADCON0 = 0b00010101;	//	select channel1(AN5) and power on A/D Module (ADON =1)
    				ADCON0bits.GO = 1;   // start conversion  
     				while (ADCON0bits.GO == 1) continue; // wait until conversion is complete  
     				b = ((int)ADRESH << 8)|ADRESL; // save value to variable  
    				Delay10TCY();
    			if (a <= 512)
    				{
    				  	LATBbits.LATB1 = 1;
    				 }
    			else
    				{
    					LATBbits.LATB1 = 0;
    				}
              		 if (b <= 512)
    				{
    					LATCbits.LATC2 = 1;   
    				}
    			else
    				{
    					LATCbits.LATC2 = 0;
    				}
    		} 
     }
    
    void ADC_Init()
    	{
    		TRISA  = 0xFF;	//	initialise PortA as input Port
    		PORTA  = 0;
            	ADCON2 = 0b10111110;	//	1 Right justified; 010 == 20*T_ad; 010 = F_osc/64
    		ADCON1 = 0b00000101;	//	AN0 and AN1 set as Analog Inputs
    		ADRESH = 0;
    		ADRESL = 0;
    	}
    Click image for larger version. 

Name:	20180711_133507.jpg 
Views:	1 
Size:	342.6 KB 
ID:	147814



  5. #5
    Super Moderator
    Points: 78,118, Level: 68
    Achievements:
    7 years registered
    Awards:
    2nd Helpful Member
    betwixt's Avatar
    Join Date
    Jul 2009
    Location
    Aberdyfi, West Wales, UK
    Posts
    12,784
    Helped
    4271 / 4271
    Points
    78,118
    Level
    68

    Re: Reading more than one analog value is a problem

    The program flow looks wrong to me. Try removing the 'continue' instructions completely, you want it to wait until 'GO' is zero then move to reading the result, something like this:

    while(ADCON0bits.GO == 1); // so it doesn't pass this point until 'GO' = 0.

    Also check the delays in the data sheet, they probably want to be in the tens or hundreds of uS not just a few cycles. Put the delay between selecting the channel and setting the GO bit so the S&H has time to adapt before you take the measurement.

    Brian.
    PLEASE - no friends requests or private emails, I simply don't have time to reply to them all.
    It's better to share your questions and answers on Edaboard so we can all benefit from each others experiences.


    1 members found this post helpful.

  6. #6
    Member level 2
    Points: 1,312, Level: 8

    Join Date
    Apr 2013
    Posts
    49
    Helped
    0 / 0
    Points
    1,312
    Level
    8

    Re: Reading more than one analog value is a problem

    Hello all,

    Please tell me if my code is right or wrong. I can't figure out why it is not working. By my logic it should but it is not. I have gone over it like 10 times. Thanks a million. Also can somebody tell me how to use the CODE tags the right way. The Code window stills takes up a lot of space and the lines are not numbered. Thanks again.

    Code:
    #pragma config PLLDIV = 5         // PLL Prescaler Selection bits (No prescale (4 MHz oscillator input drives PLL directly))
    #pragma config CPUDIV = OSC1_PLL2 // System Clock Postscaler Selection bits ([Primary Oscillator Src: /1][96 MHz PLL Src: /2])
    #pragma config USBDIV = 2         // USB Clock Selection bit (used in Full-Speed USB mode only; UCFG:FSEN = 1) (USB clock source comes directly from the primary oscillator block with no postscale)
     
    // CONFIG1H
    #pragma config FOSC = HSPLL_HS  // Oscillator Selection bits (HS oscillator, PLL enabled (HSPLL))
    
    #include 
    #include 
    
    unsigned int adc_data[2];
    unsigned char analog_selected = 1;
    
    void interrupt(){
      if (PIR1bits.ADIF) 
    	{
        	PIR1bits.ADIF=0; // clear AD interrupt flag
        	switch (analog_selected)
    	  {
          		case 0:
    			adc_data[0] = (ADRESH << 8) | ADRESL; // read data from channel 0
            		analog_selected = 1; // return channel 1
            		ADCON0 = 0b11000101; // select channel 1;
    				if (adc_data[0] >= 512)
    					{
    						LATBbits.LATB2 = 1;   
    					}
    				else
    					{
    						LATBbits.LATB2 = 0;
    					}
            	     break;
          		case 1:
            		adc_data[1] = (ADRESH << 8) | ADRESL; // read data from channel 1
            		analog_selected--;   // decrease channel index
            		ADCON0 = 0b11000001; // select channel 0
    	
    				if (adc_data[1] >= 512)
    					{
    				  	   LATCbits.LATC2 = 1;   
    					}
    				else
    					{
    					   LATCbits.LATC2 = 0;
    					}		 
            	    break;
           	}
        Nop();		// wait acquisition time for next sample to be available for sample and hold
        Nop();
        Nop();	
        ADCON0bits.GO = 1;  // start conversion again
      }
    }
    
     void main()
     { 
    
    	int a, b;
    	unsigned int i=0, temp;
    	int first = 1;
      	
    	PORTA  = 0;		   	
            TRISA  = 0xFF;		//	initialise PortA as input Port
    		
            ADCON2 = 0b10001110;	//	1 Right justified;  001 == 2*T_ad; 110 = F_osc/64
    	ADCON1 = 0b00001100;	//	AN0 and AN1 set as Analog Inputs
    	ADRESH = 0;
    	ADRESL = 0;
      		
      	PORTB = 0;
    	TRISBbits.TRISB3 = 0; 
    	TRISBbits.TRISB2 = 0; 
    	TRISBbits.TRISB1 = 0;
    	
    	PORTC = 0;
    	TRISCbits.TRISC2 = 0; 
    	
    	OSCCON = 0b01000110;			//	set internal oscillator at 8 MHz
    	
    	while(1)
    		{
                  	ADCON0 = 0b11000001; // select channel0(AN0) and power on A/D Module (ADON =1)      
    		ADCON0bits.GO = 1;   // start conversion  
    			
     			while (ADCON0bits.GO == 1)  // wait until conversion is complete
    				{  
    				     if(first == 1)
                                           {	
    					adc_data[0] = (ADRESH << 8) | ADRESL; // read dadta from channel 0
            				
            				ADCON0 = 0b11000101; // select channel 1
    					  if (adc_data[0] >= 512)
    						{
    				  		  LATBbits.LATB2 = 1;
    				 		}
    					  else
    						{
    						  LATBbits.LATB2 = 0;
    						} 
    					 first = 0;					
    					}
                                       interrupt();
    				}		
    		} 
     }



    •   AltAdvertisment

        
       

  7. #7
    Super Moderator
    Points: 28,814, Level: 41
    andre_teprom's Avatar
    Join Date
    Nov 2006
    Location
    Brazil
    Posts
    8,587
    Helped
    1087 / 1087
    Points
    28,814
    Level
    41
    Blog Entries
    6

    Re: Reading more than one analog value is a problem

    As Brian said, just add a ";" after the code

    while (ADCON0bits.GO == 1)
    --------------------------------------------------------------------------------------------------
    Part of the world that you live in, You are the part that you're giving ( Renaissance )


    1 members found this post helpful.

  8. #8
    Super Moderator
    Points: 78,118, Level: 68
    Achievements:
    7 years registered
    Awards:
    2nd Helpful Member
    betwixt's Avatar
    Join Date
    Jul 2009
    Location
    Aberdyfi, West Wales, UK
    Posts
    12,784
    Helped
    4271 / 4271
    Points
    78,118
    Level
    68

    Re: Reading more than one analog value is a problem

    Listen.... Brian is always right! (well... most times)

    I find the easiest way to add the code tags is to do it manually. Just type this:
    before the code and without the quotes or spaces "[ C O D E ]"
    and after the code add "[ / C O D E ]" Note the extra '/' to turn code mode off.

    I had to add the spaces or the Forum would have used it as real code tags!

    Brian.
    PLEASE - no friends requests or private emails, I simply don't have time to reply to them all.
    It's better to share your questions and answers on Edaboard so we can all benefit from each others experiences.


    1 members found this post helpful.

--[[ ]]--