[SOLVED] problem in reading multiple adc channels

Status
Not open for further replies.
u have to define like this...

#ifndef _XTAL_FREQ
#define _XTAL_FREQ 20000000
#endif
 

You circuit should something like this. I've shorted 3 analog inputs just to show that their inputs will be 0-5V. It can be anything, battery or any other thing.
 

Attachments

  • pic16f676_2.rar
    14.4 KB · Views: 92

OK. That freq thing didn't help. I think there must be some way to tell the compiler that you are using 4 MHz internal osc, so that it compiles to right hex file. Now, it is compiling hex file for 1 MHz, so I'm getting the adc warnings in proteus. I've set 4 MHz freq in proteus. So, you've to find a way to tell the compiler to use 4 MHz clock freq. Instead of all these troubles, you could have used demo version of mikroC. It is very easy to use.

The image you sent shows for setting clk freq for debugging purposes and not for hex file creation.
 
Last edited:

I solved the adc problem. If I enable adc and then selest adc channels then I don't get warnings, but the leds doesn't turn on/off. If I select adc channels first and then turn on the adc, then I get warnings, but the leds turn on/off at the proper voltages. any ways check the hex file with the isis simulation.
 

Attachments

  • ss3.JPG
    163.4 KB · Views: 107
  • pic16f676_.rar
    574 bytes · Views: 94

It's working fine. Check the simulation with both the hex files and reply. Vary the ldr resistance and check. If that proteus link didn't work, then download the demo version of proteus from labcenter.com.
 

Attachments

  • pic16f676_rev3.rar
    14.9 KB · Views: 91

thanks intenetuser2k11.....
mikro c is really a cool compiler and user friendly... and thanks for helping.....

i need to know how interrupt service routine works for multiple adc channels..... since we have only ADIF bit to know the interrupts and how exactly it takes the value
because we cant expect from which channel interrupt will come.....
can u please help me regarding this .... if possible with example....
 

You google for it. You can just use adc, you don't need interrupts. It's simple without interrupts. scan all the channels. Is you RA0 and RA1 channels working? Have you configured CMCON? or are you using other ADC channels?

Check these links...

http://www.electronics-lab.com/blog/?tag=interrupts
http://www.protostack.com/blog/2011/04/analogue-to-digital-conversion-interrupts-on-an-atmega168a/

Code:
[syntax = c]

//Overload, Dusk and Dawn Control

#include<htc.h>
#include<stdlib.h>
#include<stdio.h>

__CONFIG(FOSC_INTRCCLK&PWRTE_ON&BOREN_OFF&WDTE_OFF);

#define solarsense PORTAbits.RC1
#define spulse PORTAbits.RA5
#define olsense PORTCbits.RC2
#define load PORTCbits.RC3
#define solarled PORTCbits.RC4


// Prototypes

void msdelay(unsigned int);
unsigned long int adc(unsigned char source);

// Subroutines

unsigned long int adc(unsigned char source)
{
		
	unsigned long int result = 0;	// 16/32 bit variable to hold the 10 bit A/D result
	
	ADRESL = 0x00;
	ADRESH = 0x00;
	
	switch(source)
	{
		case 'o':
			ADCON0=0x94;
			msdelay(1);
			break;

		case 's':
			ADCON0=0x98;
			msdelay(1);
			break;
			
	}
		ADCON0bits.ADON = 1;
		msdelay(5);
		ADCON0bits.GO = 1;
		while(ADCON0bits.GO);
		ADCON0bits.ADON = 0;
		result = ADRESH;					// copy high byte to result
		result <<= 8;						// shift low byte to 2nd byte
		result |= ADRESL;					// OR result with ADRESL to get both the bytes into one var.
	    return result;						// return the value in result
}

void msdelay(unsigned int time)
		{
			unsigned int i,j;
	
			for(i = 0;i < time;i++);
			for(j = 0;j < 165;j++);
		}

//#pragma psect code main=0x100
void main(void)
{
	unsigned long int ssvalue,olvalue;
	unsigned long int lon_value = 409;		//(for 2V)
	unsigned long int htvalue = 665;		//(for 3.25V)
	unsigned long int ltvalue = 563;		//(for 2.75)
	unsigned long int olvoltage = 819;		//(for 4V)
	
	TRISCbits.TRISC1 = 1;					//solar sense	
	TRISAbits.TRISA5 = 0;					//spulse
	TRISCbits.TRISC2 = 1;					//ol sense
	TRISCbits.TRISC3 = 0;					//load
	TRISCbits.TRISC4 = 0;					//solarled
	//ANSEL = 0x41;
	ANSEL = 0x60;
	// Fosc = 4 Mhz, Tosc = 1/Fosc = 0.25us = 250ns
	// Tad = 32 * Tosc = 8us
    // Tad = 8 * Tosc = 2us
    // min Tad = 1.6us 
	// ADCS2-ADCS0 = 001
	// ADCON1 = 00010000 or 0x10
	// ADCON1= 0x10;
	ADCON1= 0x10;

	solarled = 1;						//led ON to show uc working

	while(1)
	{
		

		ssvalue = adc('s');

		if (ssvalue >= ltvalue && ssvalue <= htvalue)
		{
			spulse = 1;
		}
		else
			spulse=0;

		if (ssvalue <= lon_value)
		{
			load = 1;						//light on
		}	
		else
			load = 0;						//light off

		olvalue = adc('o');

		if (olvalue >= olvoltage)
		{
			load = 0;						//light off
		}

	}

}




[/syntax]
 
Last edited:

ADIF bit will be set after every A/D conversion. What are you trying to do? What do you want to inplement?

I think if you check the ststus of ADIF bit, anf if it is set you can change to read the next channel. Like that, on every ADIF set you can switch to next channel.
 
Last edited:

i thought instead of looping we can go for interrupts..... waste of time?????

---------- Post added at 17:09 ---------- Previous post was at 17:05 ----------

can u explain how u made circuit design in isis....
and i want to know if RC2 pin becomes >4V ....RC3 should be zero....
instead of shorting channels can we give two different inputs to each channel....
 

No. As I said earlier, you can chack the status of ADIF bet and switch channels. Tell me what was you actual idea.
 

Right click anywhere in the work sheet and select Placce > Component > From Libraries. In the library choose the comonents and double click in the component pane.. The components gets added to the project. Come out of the library after selecting all the components for that project. The in isis main window, select the component in the list and double click anywhere on the root sheet. The component will be placed. Right click the component for menu. In the right side tool bar. click component mode and darw the wires. To draw wires, start with a click at one terminal and then end with another click at the other terminal.

Now, about the code.

Code:
[syntax = c]

if (ssvalue <= lon_value)
		{
			load = 1;						//light on
		}	
		else
			load = 0;						//light off

		olvalue = adc('o');

		if (olvalue >= olvoltage)
		{
			load = 0;						//light off
		}


[/syntax]

If ssvalue is less than 2V then led RC3 turns ON. else it turns off. If olvalue > 4 v, it turns off. is your circuit turning on if olvalue is > 4V? If yes check the attached file.

Ofcourse, you can give different inputs. I just made that circuit for checking the working of the circuit from one source.
 

Attachments

  • pic16f676_rev3.rar
    14.9 KB · Views: 90

my objective is to check two channels(ol sense and solar sense) as said earlier.....
whenever there is voltage on those pins(with predetermined values) say between 3.25 and 2.75 on solar sense(rc1) channel, spulse(RA5) it should come 'ON'.....
and same pin if it is below 2V, load(rc3) should come ON,
second thing if olsense(rc2) pin is above 4v, load(rc3) should become 0....
 

Check these links.

http://www.youtube.com/watch?v=yt7Bhhvo-hU
http://www.youtube.com/watch?v=J1_Dn8ip5Xs

In you code

Code:
if (ssvalue <= lon_value)
		{
			load = 1;						//light on
		}	
		else
			load = 0;						//light off

		olvalue = adc('o');

		if (olvalue >= olvoltage)
		{
			load = 0;						//light off
		}

If olvalue >= 4V, load will be off, and at the same time if ssvalue becomes < 2V, load turns on. You are using the same led for two parameters. I think there is a logic error. Why don't you use two leds.

Do you want RC3 (load) to be off when ssvalue < 2V and olvalue > 4V?
 
Last edited:

OK. I modified the code and compiled. You can check the simulation with the attached file. There is a small bug in isis. The pins RC1 and RC2 are interchanged internally. The code you write for RC1 is sensed by RC2 and the code you write for RC2 is sensed by RC1. It is a bug with the proteus.
 

Attachments

  • pic16f676_rev4.rar
    15.8 KB · Views: 83

OK. In your circuit, there is an o/p "S Pulse". What is it? Is it an LED?

Code:
[syntax]

//Overload, Dusk and Dawn Control

#include<htc.h>
#include<stdlib.h>
#include<stdio.h>

__CONFIG(FOSC_INTRCCLK&PWRTE_ON&BOREN_OFF&WDTE_OFF);

#define solarsense PORTAbits.RC1
#define spulse PORTAbits.RA5
#define olsense PORTCbits.RC2
#define load PORTCbits.RC3
#define solarled PORTCbits.RC4


// Prototypes

void msdelay(unsigned int);
unsigned long int adc(unsigned char source);

// Subroutines

unsigned long int adc(unsigned char source)
{
		
	unsigned long int result = 0;	// 16/32 bit variable to hold the 10 bit A/D result
	
	ADRESL = 0x00;
	ADRESH = 0x00;
	
	switch(source)
	{
		case 'o':
			ADCON0=0x94;
			msdelay(1);
			break;

		case 's':
			ADCON0=0x98;
			msdelay(1);
			break;
			
	}
		ADCON0bits.ADON = 1;
		msdelay(5);
		ADCON0bits.GO = 1;
		while(ADCON0bits.GO);
		ADCON0bits.ADON = 0;
		result = ADRESH;					// copy high byte to result
		result <<= 8;						// shift low byte to 2nd byte
		result |= ADRESL;					// OR result with ADRESL to get both the bytes into one var.
	    return result;						// return the value in result
}

void msdelay(unsigned int time)
		{
			unsigned int i,j;
	
			for(i = 0;i < time;i++);
			for(j = 0;j < 165;j++);
		}

//#pragma psect code main=0x100
void main(void)
{
	unsigned long int ssvalue,olvalue;
	unsigned long int lon_value = 409;		//(for 2V)
	unsigned long int htvalue = 665;		//(for 3.25V)
	unsigned long int ltvalue = 563;		//(for 2.75)
	unsigned long int olvoltage = 819;		//(for 4V)
	
	TRISCbits.TRISC1 = 1;					//solar sense	
	TRISAbits.TRISA5 = 0;					//spulse
	TRISCbits.TRISC2 = 1;					//ol sense
	TRISCbits.TRISC3 = 0;					//load
	TRISCbits.TRISC4 = 0;					//solarled
	//ANSEL = 0x41;
	ANSEL = 0x60;
	// Fosc = 4 Mhz, Tosc = 1/Fosc = 0.25us = 250ns
	// Tad = 32 * Tosc = 8us
    // Tad = 8 * Tosc = 2us
    // min Tad = 1.6us 
	// ADCS2-ADCS0 = 001
	// ADCON1 = 00010000 or 0x10
	// ADCON1= 0x10;
	ADCON1= 0x10;

	solarled = 1;						//led ON to show uc working

	while(1)
	{
		

		ssvalue = adc('s');

		if (ssvalue >= ltvalue && ssvalue <= htvalue)
		{
			spulse = 1;
		}
		else
			spulse=0;

		//if (ssvalue <= lon_value)
		//{
			//load = 1;						//light on
		//}	
		//else
			//load = 0;						//light off

		olvalue = adc('o');

		//if (olvalue >= olvoltage)
		//{
			//load = 0;						//light off
		//}

		if (ssvalue <= lon_value && olvalue < olvoltage)
		{
			load = 1;
		}
		else if (olvalue >= olvoltage)
		{
			load = 0;
		}

	}

}



[/syntax]

OK. I got it S PULSE is an LED.
 
Last edited:

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…