Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] PIC16f675 ADC nEED help on refernece point

Status
Not open for further replies.

cnandha19

Member level 3
Joined
Aug 28, 2015
Messages
59
Helped
1
Reputation
2
Reaction score
1
Trophy points
8
Activity points
604
I read the adc value on corresponding pin but i need to take first value that reads from sensor as refernce value and store temp for 2 sconds and on while second time it mus compared with refernce
 

I'm not sure I understand. Are you saying you take two measurements on the same pin with a two second gap betwen them then compare the values?

Brian.
 
I'm not sure I understand. Are you saying you take two measurements on the same pin with a two second gap betwen them then compare the values?

Brian.

1) Read continuous analog voltage input from sensor. Based on patient’s breathing rate.
(Range- 200mv to 2000 mv )
2) When the input values remain within a range of ±30 mv for 2 seconds, the mean value is chosen as reference (holding point).
3) A red LED glows when reference is obtained.
4) Compare the incoming values with value stored as reference.
5) If the incoming value is still in the same range as the reference, another LED (green) glows indicating that patient is holding his breath.
6) If the incoming values are not in range with reference, green LED turns OFF.
Reference point stored is still there, red LED remains ON.

- - - Updated - - -

i had did lik tis

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
while(1)
    {
         
            ADC_value = GetADCValue(AN2);       // Read ADC value from GP4 pin
           
    
        // ADC_value can have a value from 0 (0v) to 1023(5v) only.
        
 
        __delay_ms(50);
 
 
{
flag=1;
 
if ((ADC_value>=700)  && (flag==1))
{
 
LED=1;
GP0=1; 
__delay_ms(2000);    
 
   //Refernce is obtained Buzzer ON
 
     
LED1=0; //GREEN  
GP0=0; 
}
 
flag=0;
 
 
 if ((ADC_value>=700) && (ADC_value>=500) && (flag==0))
{
LED=1;
__delay_ms(50);
LED1=1;
}
 
 
else if  ((ADC_value>=400) && (ADC_value<=500) && (flag==0))
{
LED=1;
__delay_ms(50);
LED1=0;
}
 
else
{
LED=0;
LED1=0;
 
}

 
Last edited by a moderator:

You need to decide a sampling rate first. That means the number of measurements you are going to take over a fixed period, maybe the 2 seconds you mentioned. You also need to decide how the 2 seconds period is started or whether it is a 'sliding' time window that continuously tracks the measurements over 2 second periods.
Your specific points:

1. Not a problem, those voltages are easy to measure.
2. Do you manually start the 2 seconds or is it a running average of measurements over the previous 2 seconds?
3. Subject to 2 being satisfied this is also easy. Is there a condition that turns the red LED off again?
4. Not a problem.
5. Relies on the voltage having a relatively long time constant or it trigger on instantaneous changes but easy to do.
6. Not a problem.

Basically, you are asking for a device that checks for deviation from an average. You have to decide if the average is over one specific time period or if it 'tracks' the measurements over real time.

Brian.
 
is it correct for No 2 Question


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
unsigned int SampleCount;
     unsigned int ADCSamples[10];
     unsigned int ADC_value = 0;
     unsigned int Average,Average1;
     unsigned int flag;
     
    InitADC(AN2);       // Initialize GP2 as ADC input pin CHANNEL 2
    
 
    while(1)
    {
         
        //  ADC_value = GetADCValue(AN2);       // Read ADC value from  pin GP2 pin
            __delay_ms(2000);
 
for(SampleCount = 0; SampleCount <=10; SampleCount++)
{
__delay_ms(250);
LED=1;
ADCSamples[SampleCount] = GetADCValue(AN2);
 
}
 
Average =((ADCSamples[SampleCount])/20);
 
 
__delay_ms(2000);
LED1=0;
LED=0;
 
for(SampleCount = 0; SampleCount <=10; SampleCount++)
{
__delay_ms(250);
LED=1;
ADCSamples[SampleCount] = GetADCValue(AN2);
 
}
 
Average1 =((ADCSamples[SampleCount])/20);
 
 
__delay_ms(2000);
flag=1;
}
if((Average == Average1) && (flag==1))
{
LED=1;
LED1=1;
}
 
else if((Average >= Average1) && (flag==1))
{
LED=0;
LED1=1;
}

 
Last edited by a moderator:

No, that is wrong for several reasons. It doesn't check for the 2 seconds of stable voltage and the average calculation only uses the last voltage measured.

I am not sure which compiler you are using so I can't give specific code but the principle is this, I presume ten readings per second:

1. declare an array to hold the last 20 readings
2. declare a pointer and set it to the first element in the array.
3. take a voltage measurement and store in the array index of the pointer.
4. increment the pointer (so it points to the next array index) then wait for 100mS.
5. take another measurement. If it is >(previous measurement +30mV) or <(previous measurement - 30mV) increment the pointer, otherwise set it back to zero
6. if the pointer == 20 you have 20 consecutive measurements within +/- 30mV within a 2 second period. If it isn't 20, go back to step 3.

What it is doing is storing each measurement in the array and resetting if the result is out of range. When 20 consecutive 'good' results have been found they will all have been stored in the array and you turn the red LED on.

The next step is to find the average. To do that, sum all the array contents and divide by 20.
Code:
pointer = 20;
while(pointer)
{
total += array[pointer];
pointer--;
}
average = total / 20;

Now you can enter another program loop where you check each measurement to see if it is +/- 30mv of the average and drive the green LED accordingly.

If you want best accuracy in the results, try amplifying the 2V maximum voltage by 2.5 times so it uses the full 5V range of the ADC. It significantly increases the measurment resolution.

Brian.
 
i m using hitech c compiler pls give exact coding
 

Where you are going to write/ store the readings? If you have enough memory, you can store them all in RAM but before you quit, you should save them somewhere, perhaps in a file (SD card or a pendrive).

If timing is critical, I suggest that you concentrate on reading the ADC values regularly and put them out somewhere else; let the other fellow do the processing.

You are trying to do what is expected from a real-time operating system and you need to manage time well.
 

Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Main function
void main()
{
    InitADC(AN2);       // Initialize GP2 as ADC input pin CHANNEL 2    
 
    while(1)
    {
         
        // ADC_value = GetADCValue(AN2);       // Read ADC value from  pin GP2 pin
            __delay_ms(2000);
 
 
unsigned int ADCSamples[3];   
unsigned int i ;
 
for(i = 0; i < 3; i++)
{
ADCSamples[i] = GetADCValue(AN2);
}
 
 
}
}



wheather its crroect for taking 3 adc values in array
 
Last edited by a moderator:

I do not have the Hitech C compiler but basically it looks OK although very inefficient. You have a never ending loop in which you redeclare the array and 'i' over and over again, it would be more sensible to move the two lines
Code:
unsigned int ADCSamples[3];   
unsigned int i ;
outside the loop as there is no need to repeat them. Move them to either before the "void main()" or on the line after it.

Brian.
 
I do not have the Hitech C compiler but basically it looks OK although very inefficient. You have a never ending loop in which you redeclare the array and 'i' over and over again, it would be more sensible to move the two lines
Code:
unsigned int ADCSamples[3];   
unsigned int i ;
outside the loop as there is no need to repeat them. Move them to either before the "void main()" or on the line after it.

Brian.

IS it correct way to get adc value in array format ??


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
unsigned int ADCSamples[3];   
unsigned int first =0 ;
unsigned int ref,ref1;
unsigned int ADC_value;
     
 
// Main function
void main()
{
 
 
    InitADC(AN2);       // Initialize GP2 as ADC input pin CHANNEL 2    
 
    while(1)
    {
         
        // ADC_value = GetADCValue(AN2);       // Read ADC value from  pin GP2 pin
            __delay_ms(2000);
 
 
if(first==0)
{
ADC_value = GetADCValue(AN2); 
ref=ADC_value;
__delay_ms(50);
first++;
}
 
if(first==1)
{
ADC_value = GetADCValue(AN2); 
__delay_ms(50);
ref1=ADC_value;
}
 
 
 
if(ref==ref1)
{
LED=1;
LED1=1;
first=0;
}
 
else if(ref<=ref1)
{
LED=1;
LED=0;
}
else
{
LED=0;
LED1=0;
}
}
}

 
Last edited by a moderator:

I still can't folow what your code does. Based on the description you gave earlier, this code would seem better but I have not tested it at all, I do not have the Hitech compiler to try it so there are probably errors. It should give an idea of how to do it though:
Code:
#define mVLimit 0.03
#define AveragingTime 2000	(2 Secs) mS time to take average over
#define SampleRate 10		mS between averaging samples

#define Tolerance = (mVLimit*1024)/5	//the ADC value for 30mV
#define NumberOfSamples AveragingTime/SampleRate
#define OFF 0
#define ON 1

unsigned int ADCSamples[NumberOfSamples];   
unsigned int ADC_Value;
unsigned int ADC_Total, ADC_Average;
unsigned int UpperLimit, LowerLimit;
unsigned char index = 0;
     
 
// Main function
void main()
{
	RedLED = OFF;
	GreenLED = OFF;
	InitADC(AN2);       // Initialize GP2 as ADC input pin CHANNEL 2    
	ADC_Value = GetADCValue(AN2); // need a first value to make calculation
	
	// get 20 consecutive samples (2 seconds at 10mS intervals) within 'Tolerance' of each other.
	do
	{
		__delay_ms(SampleRate);
		ADCSamples[index] = GetADCValue(AN2); // get next value
		if((ADCSamples[index] > ADC_Value + Tolerance) || (ADCSamples[index] < ADC_Value - Tolerance)) index = 0;
		else index++;
	}while(index < NumberOfSamples);

	// now find their average
	index = NumberOfSamples;
	do
	{
		ADC_Total += ADC_Samples[index--];
	}while(index > 0);
	ADC_Average = ADC_Total / NumberOfSamples;

	RedLED = ON; // show the average has been found
	
	// now loop to see if the present result is close to the average
	UpperLimit = ADC_Average + Tolerance;
	LowerLimit = ADC_Average - Tolerance;
	while(1)
	{
		ADC_Value = GetADCValue(AN2);
		if((ADC_Value > UpperLimit) || (ADC_Value < LowerLimit)) GreenLED = OFF;
		else GreenLED = ON;
		__delay_ms(SampleRate);
	}
}

I made the first three lines '#define' so you can change the values as you wish. Be careful to use sensible numbers, I used the ones you gave but if you increase the averaging time or decrease the time between samples it will make the array size larger and you risk running out of memory.

You will see the program works in three steps:
1. gather enough consecutive readings into the array.
2. calculculate the average value in the array.
3. endless loop checking new readings against the average and operating the green LED accordingly.

Brian.
 
please explain this accord to my 5 th point

while(1)
{
ADC_Value = GetADCValue(AN2);
if((ADC_Value > UpperLimit) || (ADC_Value < LowerLimit)) GreenLED = OFF;
else GreenLED = ON;
__delay_ms(SampleRate);
}
}

1) Read continuous analog voltage input from sensor. Based on patient’s breathing rate.
(Range- 200mv to 2000 mv )
2) When the input values remain within a range of ±30 mv for 2 seconds, the mean value is chosen as reference (holding point).
3) A red LED glows when reference is obtained.
4) Compare the incoming values with value stored as reference.
5) If the incoming value is still in the same range as the reference, another LED (green) glows indicating that patient is holding his breath.
6) If the incoming values are not in range with reference, green LED turns OFF.
Reference point stored is still there, red LED remains ON.
 

"UpperLimit" and "LowerLimit" are already calculated as the (average+30mV) and (average-30mV) respectively so they are the boundary values which the ADC reading must lie between if the green LED is to stay bright. ON and OFF are aliases for '1' and '0' respectively to make the program easier to read.

Then it reads:
Get the ADC reading from pin AN2
If the reading (is above the UpperLimit value) or (is less than the LowerLimit value), switch the green LED off,
otherwise it must be within limits so switch the green LED on.
Then wait before repeating the above.

Brian.
 
i m getting the result correctly but if it is not in range means after 2seconds only its updating (i.e Green LED OFF) why this delay ?????

and how i can take again a new refernce point becoause it is in while loop
 

You need to update both the UpperLimit and the the LowerLimit within the loop by recalculating the average ...
 
As I understood the requirement, it takes ONE average over 2 seconds of readings that lie within 30mV of each other. That average is used from then onwards. I asked the question of whether it was a running average but the reply suggested that wasn't the case.

cnandha19 please clarify your requirement.
If a running average is wanted, the code is similar but a new question arises: Does the new average have to be calculated on the same basis that 2 seconds of readings within 30mV have to be used? Please understand that there is a danger in that method, irregular breathing will extend the period needed to find the average and a dead person will pass the test because their breathing rate is constant!

Brian.
 
Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top