Jump to content
Sign in to follow this  
Louhimo

Using Boostc To Read Adc Input?

Recommended Posts

Hello again...

 

Okey I am working with a small kind of weather project using PIC16F88, and i understood that whole PORTA is able to take analog input right? So, I am going to buy a temperature sensor and connect it to porta pin 0. But the problem is I don't find any tutorial / code examples how to read ADC values using boost C? Could anyone paste either links to tutorials, or pure code example how can i read adc value and save it to variable?

 

Thanks in advance

Share this post


Link to post
Share on other sites
Hello again...

 

Okey I am working with a small kind of weather project using PIC16F88, and i understood that whole PORTA is able to take analog input right? So, I am going to buy a temperature sensor and connect it to porta pin 0. But the problem is I don't find any tutorial / code examples how to read ADC values using boost C? Could anyone paste either links to tutorials, or pure code example how can i read adc value and save it to variable?

 

Thanks in advance

 

For AD sensors you will need all the PortA pins for the full detection range.

 

Unless there is a reason you want to use AD, there are many nicer to use sensors via OneWire,

I2C, SPI, etc.

The Dallas oneWire sensors are very simple to use and take up one pin as you indicated interest in.

Share this post


Link to post
Share on other sites

Yes i'd like onewire sensor, so i could connnect LCD display to same pic and then i could show the current temperature on the LCD B)

But still the same question: i haven't found any tutorials how to use ADC functions etc :) code example would be nice, ty advance

Share this post


Link to post
Share on other sites

I use one pin for each A2D and read 5 analog values on portA with my 18F252.

This accuracy is as good as the A2D on your chip so why use a one wire sensor?

This is just some clippings so ignore any extra lines.

My delay is probably too long but I have plenty of time in my loop.

volatile bit A2D_not_done@0x0FC2.2;	// bit 2 of adcon0
trisa = 11111111b;	// ALL PORT A inputs
trisb = 11110111b;	// DON'T BUGGER UP PORTB.0 or .3
trisc = 10000000b;	// all Port C outputs except RC7 is RX
// initialize ADC for user inputs
adcon1 = 00000010b;	// 
	// bit 7; 0 = left justify
	// bit 6; adcs2 FOR CLOCK DIVISION
	// bits 5,4; not used
	// bits 3-0; PORT CONFIG; 0010 = AN0...AN4 analog in
	//
// ADCON0 10xxx001
	// BITS 7,6; CLOCK DIVISION /32 if ADCON1,6 = 0
	// BITS 7,6; CLOCK DIVISION /64 if ADCON1,6 = 1
	// BITS 5,4,3; CHANNEL SELECT
	// BIT 2; GO/DONE	
	// BIT 1; NOT USED
	// BIT 0; A/D ON
// finished initializing ADC

// Continuously read setpoint pots
//
//	AN1 = HAPPY	: inside inner gates
//	AN2 = BAND	: between inner & outer gates
//	AN3 = soft_delay : delay before going around loop again
//	AN4 = contrast	: LCD contrast
//	AN5 = REALC	: desired center control point
//
// Read A1 for desired setpoint
adcon0 = 10000001b;			// Read from AN0
delay_us(20);
set_bit(adcon0, 2);			// INNER GATES
while (A2D_not_done);		// Wait for a2d done flag to change
AdRes[1] = adresh;			//	

// Read A2 for desired setpoint
adcon0 = 10001001b;			// Read from AN1
delay_us(20);
set_bit(adcon0, 2);			// OUTER GATES
while (A2D_not_done);		// Wait for a2d done flag to change
AdRes[2] = adresh;			// 	

// Read A3 for desired setpoint
adcon0 = 10010001b;			// Read from AN2
delay_us(20);
set_bit(adcon0, 2);			// SPEED OF LOOP
while (A2D_not_done);		// Wait for a2d done flag to change
AdRes[3] = adresh;			//  

// Read A4 for desired setpoint
adcon0 = 10011001b;			// Read from AN3
delay_us(20);
set_bit(adcon0, 2);			// LCD contrast
while (A2D_not_done);		// Wait for a2d done flag to change
AdRes[4] = adresh;			//  

// Read A5 for desired setpoint
adcon0 = 10100001b;			// Read from AN4
delay_us(20);
set_bit(adcon0, 2);			// CENTER of control gates
while (A2D_not_done);		// Wait for a2d done flag to change
AdRes[5] = adresh;			//

I am using +5V & gnd as references but I have had success using four forward biased diodes as a reference and a resistor beyond to limit current. My sensor saturates at about 3V. Of course a voltage reference is smaller and simpler.

Keep the sensor range as large as your reference to get the best accuracy.

Share this post


Link to post
Share on other sites
I use one pin for each A2D and read 5 analog values on portA with my 18F252.

This accuracy is as good as the A2D on your chip so why use a one wire sensor?

 

Your using one pin? Your code says your using 5 pins...

But i am curious, how are you resolving to +/- 0.1 degree with that small a range ...

Share this post


Link to post
Share on other sites
I use one pin for each A2D and read 5 analog values on portA with my 18F252.

This accuracy is as good as the A2D on your chip so why use a one wire sensor?

 

Your using one pin? Your code says your using 5 pins...

But i am curious, how are you resolving to +/- 0.1 degree with that small a range ...

Hi emte,

rfhaley is using 5 sensors for the 5 channel adc and thats why its 5 pins. you can set just 1 pin to adc if you want. I don't know if its a 10bit adc or 12 bit adc. any way he is not using adresl. Very soon i will be posting a thermometer project using LM34 sensor on my thread "Pic Micro programming in Boostc for beginners".

Just not finding enough time.

 

regards,

Raghunathan.

Edited by ra68gi

Share this post


Link to post
Share on other sites
Hi emte,

rfhaley is using 5 sensors for the 5 channel adc and thats why its 5 pins. you can set just 1 pin to adc if you want. I don't know if its a 10bit adc or 12 bit adc. any way he is not using adresl. Very soon i will be posting a thermometer project using LM34 sensor on my thread "Pic Micro programming in Boostc for beginners".

Just not finding enough time.

 

regards,

Raghunathan.

 

yeah, i misread that part ... haste makes waste i guess. B)

 

Upon rereading what i wrote i am wondering what i was thinking ...

But the advantages of using bus based devices is that you can connect more than two to

any given pin, (negative and positive logic device select) and not having to worry about

tracking timing for another set of devices.

 

i'll port one of my ds18S20 projects to boost and send it over, sans-display ... maybe the one

with external eeprom storage for you to browse over.

Share this post


Link to post
Share on other sites
Hi emte,

rfhaley is using 5 sensors for the 5 channel adc and thats why its 5 pins. you can set just 1 pin to adc if you want. I don't know if its a 10bit adc or 12 bit adc. any way he is not using adresl. Very soon i will be posting a thermometer project using LM34 sensor on my thread "Pic Micro programming in Boostc for beginners".

Just not finding enough time.

 

regards,

Raghunathan.

 

yeah, i misread that part ... haste makes waste i guess. :(

 

 

You won't find many more hasteful or wasty than me. B)

Not only do I discard adresl, some of the setpoints are >>3 because I want a fairly small range for some things. This also removes some jitter in the last bit as it requires many more turns of the pot to make the A2D output change. My LCD is only 122 wide so my 'center' needs only 128 choices. My 'gates' either side of center only need a range of 32.

Opposite my 5 A2D & I/O board is my line sensor board talking 50 feet away on RS232.

My optical sensor uses the full 10-bits

//
startpulse(10); 	// Sends SI overlapping CLKOUT pulses to start reading data
for ( i = 0; i < array_size; i++)
{
	ckout();				// clk to next pixel
	set_bit(adcon0, 2);		// read analog input0 until adcon0.2 drops to zero
	while (A2D_not_done);	// Wait for a2d done flag to change
	MAKESHORT(tmp,adresl,adresh);	// store data in array 
	photo[i] = tmp;
} 
ckout();	
}//END

but my display can only handle 8-bit data so I >>2 later. I realize I could shorten things a bit but I like readable code that I can retype easily when I make changes.

I tend to make a lot of silly mistakes so I didn't put an array in MAKESHORT ( or maybe I found that it didn't work).

Share this post


Link to post
Share on other sites

Thank you all for responses, especially rfhaley for the code example, it seems logical :(

But still i'd like to find a small tutorial with examples, because I might find it more useful than just copy/pasting from here B)

Thanks in advance again...

Share this post


Link to post
Share on other sites
Thank you all for responses, especially rfhaley for the code example, it seems logical :(

But still i'd like to find a small tutorial with examples, because I might find it more useful than just copy/pasting from here B)

Thanks in advance again...

:ph34r:

'Tell me, I forget

Show me, I remember

Let me do it for myself, I understand'

:ph34r:

 

I learned what I needed from the data sheet

Read the chapter on Analog Converter, my comments for ADCON are directly from my data sheet. Try to calculate your own conversion delays.

I would rather have somebody get me started with an example though. ;)

Share this post


Link to post
Share on other sites

Microchip's site, Application notes:

AN938 and TB051

 

They are specific to the TC1047 temp sensors, but are generic

enough for anything.

 

Code examples only help partially, its the chip features, or lack

of that affect your code the most.

Share this post


Link to post
Share on other sites
:ph34r:

'Tell me, I forget

Show me, I remember

Let me do it for myself, I understand'

:ph34r:

 

I learned what I needed from the data sheet

Read the chapter on Analog Converter, my comments for ADCON are directly from my data sheet. Try to calculate your own conversion delays.

I would rather have somebody get me started with an example though. B)

 

No no no and no ;)

Of course I do not wan't a ready code with correct timings etc. but what I want is the normal code which would explain a bit those functions i need to use etc. things? Yes i do find some tutorials using Pic Micro Assembly, but i guess they also integrated some functions to boostc so i could use C instead of assembly. And as i begged a code example, i just meant a code which could possible introduce those needed functions with correct parameters for me :(

I don't want to be the one who copies everything from the internet. I am the one who wants to LEARN, as simple as that!

Share this post


Link to post
Share on other sites
No no no and no B)

Of course I do not wan't a ready code with correct timings etc. but what I want is the normal code which would explain a bit those functions i need to use etc. things? Yes i do find some tutorials using Pic Micro Assembly, but i guess they also integrated some functions to boostc so i could use C instead of assembly. And as i begged a code example, i just meant a code which could possible introduce those needed functions with correct parameters for me :(

I don't want to be the one who copies everything from the internet. I am the one who wants to LEARN, as simple as that!

 

A block diagrams is in the application note i listed in the last post, here is the url:

http://ww1.microchip.com/downloads/en/AppNotes/00938_a.pdf Page 10

Its generic enough to get an overall idea.

 

As for library specific functions, read the header files. Myself, as i expect a lot of others,

rarely use the stock libraries as they are not usually usable in a lot of applications.

But if development time is an issue stock libraries are an invaluable resource, as are

your own tweaked libraries.

Share this post


Link to post
Share on other sites

just a reminder:

microcontrollers will not accept negative AC voltages (they might get damage --> based from my experience). try to use level shifter or a clipper. And another thing, put bypass capacitors in your PIC's regulator. here is a helpful link:

Share this post


Link to post
Share on other sites
just a reminder:

microcontrollers will not accept negative AC voltages (they might get damage --> based from my experience). try to use level shifter or a clipper. And another thing, put bypass capacitors in your PIC's regulator. here is a helpful link:

 

(two more small cents)

 

The standard solution is to use ~1uF cap between the input to the PIC and ground, this will drain any

negative voltage instead of harming the PIC.

 

If you like the cheap option you could just use one diode and half-wave rectify it, but remember you

would now need to take into account the drop accross the diode. This will also allow you to use the

pin for something else when your not using it for AD ... as long as you do not exceed the PIV which

is unlikely since that would damage the PIC before the diode.

Share this post


Link to post
Share on other sites

Maybe this will help us both out. I'm using a PIC16F88 to read in an A/D value. I have it set up to use the RC oscillator (INTRC) so that it runs as 31.25 kHz (I need to use it as a nanoWatt device).

 

Here's my small bit of code:

#include <system.h>

#pragma DATA _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_ON & _BODEN_ON & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_CLKOUT
#pragma DATA _CONFIG2, _IESO_ON & _FCMEN_ON

// Set 20MHz clock frequency                      
#define CLOCK      31250
#pragma CLOCK_FREQ CLOCK

#define ON  0
#define OFF 1


// Globals
volatile bit adc_on @ADCON0.ADON;  // A/D conversion on bit
volatile bit adc_go @ADCON0.GO; // A/D conversion status bit

void main()
{
 unsigned char wait;
 long analog;

 // Set up the Analog selection register
 ansel = 0x01;  // 1=Analog, 0=Digital  RA0 as analog
 trisa = 0x01;  // 1=input, 0=output    RA0 as input (for analog)

 // Set up A/D Control Register 1
 set_bit(   adcon1, ADFM );  // A/D right justified
 clear_bit( adcon1, ADCS2 );  // A/D clock /2
 clear_bit( adcon1, VCFG1 );  // set to use AVdd  AVss
 clear_bit( adcon1, VCFG0 );  

 // Set up A/D Control Register 0
 set_bit(   adcon0, ADCS1 );  // Tad = Frc derived from the internal A/D RC oscillator
 set_bit(   adcon0, ADCS0 );
 clear_bit( adcon0, CHS2 );  // Channel 0
 clear_bit( adcon0, CHS1 );
 clear_bit( adcon0, CHS0 );
 
 trisb = 0x00;  // 1=input, 0=output 

 wait = 10;

 while( 1 ) {
   adc_on = 1; // Turn on the A/D converter
   delay_ms( 1 );
   adc_go = 1;  // Start the conversion of ch0
   while( adc_go )  // wait for it to finish
    ;
     
   MAKESHORT( analog, adresl, adresh );  // Grab the A/D conversion
   adc_on = 0; // Turn off the A/D converter
   delay_ms( wait );    
   
 }
 

}

 

However, when I try to debug it with the Variable PSU attached to RA0, it never breaks out of the while() loop

Share this post


Link to post
Share on other sites
However, when I try to debug it with the Variable PSU attached to RA0, it never breaks out of the while() loop

 

This probably will not work:

while( adc_go )  // wait for it to finish
  ;

Try not to put comments before the semicolon.

 

You will have to look at the other AD threads but there are a few issues trying to simulate

AD in SourceBoost i belive.

 

If you have the hardware setup, just run the code and dump out raw results to your serial port.

Share this post


Link to post
Share on other sites

emte and dknovick

This probably will not work:

while( adc_go )  // wait for it to finish
 ;

Try not to put comments before the semicolon.

The comment does not affect this code, leave the comments or delete them - it makes no difference;)

 

You will have to look at the other AD threads but there are a few issues trying to simulate  AD in SourceBoost i belive.

The ADC simulation under SourceBoost IDE simulator is correct for PIC16F877A ADC and devices with a compatible ADC. So if your device does not have a compatible ADC it won't work as you expect.

 

Regards

Dave

Share this post


Link to post
Share on other sites

Good to know about both those.

Never used a 16F88 myself, so i've no idea if its compatable or not.

Share this post


Link to post
Share on other sites
The ADC simulation under SourceBoost IDE simulator is correct for PIC16F877A ADC and devices with a compatible ADC. So if your device does not have a compatible ADC it won't work as you expect.

So, how would be know if it has a compatible ADC?

Share this post


Link to post
Share on other sites
If you have the hardware setup, just run the code and dump out raw results to your serial port.

Haven't had the time to dig into serial stuff yet (that's next).

Share this post


Link to post
Share on other sites
So, how would be know if it has a compatible ADC?

I guess I answered my own question, the code seems to work in hardware. I blink an LED after the while loop... and, well, the LED blinks. Next up, hooking a pot to the input to see if I can turn the LED on at a certain voltage.

Share this post


Link to post
Share on other sites
If you have the hardware setup, just run the code and dump out raw results to your serial port.

Haven't had the time to dig into serial stuff yet (that's next).

 

Serial is probably the simplest thing to do with your PIC (providing you have a MAX232 or simular

connected). Just initialize it at the baudrate and dump your output into txreg, very handy for

debugging runtime issues instead of using an ICD.

Share this post


Link to post
Share on other sites
Serial is probably the simplest thing to do with your PIC (providing you have a MAX232 or simular

connected). Just initialize it at the baudrate and dump your output into txreg, very handy for

debugging runtime issues instead of using an ICD.

In that case, I'll definitely look into it. I still do some things old-school.

Share this post


Link to post
Share on other sites
Maybe this will help us both out.  I'm using a PIC16F88 to read in an A/D value.  I have it set up to use the RC oscillator (INTRC) so that it runs as 31.25 kHz (I need to use it as a nanoWatt device).

 

Here's my small bit of code:

    adc_go = 1;  // Start the conversion of ch0
   while( adc_go )  // wait for it to finish
   ;
     
   MAKESHORT( analog, adresl, adresh );  // Grab the A/D conversion
   adc_on = 0; // Turn off the A/D converter
   delay_ms( wait );    
   
 }
 

}

 

However, when I try to debug it with the Variable PSU attached to RA0, it never breaks out of the while() loop

 

Hi guys,

I had just completed the thermometer project using Pic16f72. I will soon be posting it in my thread "pic micro programming in boostC for beginners. I am yet to write the detailed description for the circuit connections & its functioning.

I will post the code here, see if its useful for you. Unlike many programs in BoostC which use set_bit clear_bit macros, i straight away write the config bits into the respective SFR. Have look at this code.

#include <system.h>
#pragma CLOCK_FREQ 4000000  // config clock to 4mhz.

// Set configuration fuse.

#pragma DATA _CONFIG, _XT_OSC & _WDT_OFF & _CP_OFF & _PWRTE_OFF

//A function to get adc value from pic's built-in adc.
void a_d(void);

//A function for 7-segment display to display "0°C-99°C".
void seven_segment1(void);

//A function for 7-segment display to dispaly "0-150".
void seven_segment2(void);

//A function to get segment values for hundreds & tens.
unsigned char get_value1(unsigned char x);

//A function to get segments value for units.
//units display module is inverted so as to display degree celsius,
//with decimal point at top of the display.
unsigned char get_value2(unsigned char y);

/*Variable adc is made global for easy access,
which is used in main().*/
unsigned char adc;

//Variable temperature is made global for easy access.
unsigned char temperature;

void main()
{  
 trisa=255;      //set porta as output. 
 trisb=0;        //set porb.0 as input & rest of the pins as output.
 trisc=0;        //set all portc pins as output pins.
 portc=0;        //make all portc pins low.
 portb=0;        //zero all portb pins.
 adcon1=1;       // make RA0,RA1,RA2 pins as analog inputs & RA3 as +ref.
 adcon0=0b01000001; //choose Fosc/8,RA0/AN0 as channel(0),go/done=0,adon=1.
 unsigned int sample;  //sample var holds the adc sample value.
 unsigned char b0;     //for loop var.   
 while( 1 )            //Infinite loop.
 {
 sample=0;             //initialize the sample to zero.
 for(b0=0;b0<20;b0++)  //take 20 adc samples.
 {
 a_d();                //call function a_d().
 sample += adc;        
 }
 temperature=sample/20;  //take average of 20 samples.
 if(temperature<99)      //call seven_segment1 if temperature is less
 seven_segment1();       //than 99 else  call seven_segment2.
 else
 seven_segment2();   
 }
 }
 
void a_d(void)  //adc routine.
{ 
 adc=0; 
 adcon0.2=1;           //start ad convertion.
 while(adcon0.2==1)     //check if conversion is complete.
 {
 
 }
 adc=adres;           //if conversion is over, load adc value.
}
 


void seven_segment1(void)    //seven_segment1 routine.
{
 unsigned char b0;          //b0 as for loop counter.
 unsigned char tens;    //holds the tens value to be displayed 
 unsigned char units;   //holds the units value.
 tens=temperature/10;       //find the tens value.
 units=temperature%10;      //find the units value.
 for(b0=0;b0<250;b0++)      //loop it 250 times to see.
 {
 portb=get_value1(tens);   //place the segment value of tens on portb
 portc.0=1;                //turn on transistor(H). 
 delay_ms(1);              //keep it on for 1ms.
 portc.0=0;                //turn off transistor(H).
 portb=get_value1(units);  //place the segment value of units.
 portc.1=1;                //turn on transistor(T).
 delay_ms(1);              //keep it on for 1ms.
 portc.1=0;                //turn it off.
 portb=0xD5;        //place character "°C" to represent degree celsius.  
 portc.2=1;         //turn on transistor(U).
 delay_ms(1);       //keep it on for 1ms.
 portc.2=0;         //turn it off.
 }
}

void seven_segment2(void)  //seven_segment2 routine.
{
 unsigned char b0;        //same as above with the only difference
 unsigned char hundreds;  //in the units segment which in this case
 unsigned char tens;      // will display the units value instead of
 unsigned char units;     // character "C". i wish to remind you that
 hundreds=temperature/100;      //the this display is inverted & so
 tens=(temperature%100)/10;     //requires a diffrent set of segment
 units=temperature%10;     //values.This we do by calling get_value2
 for(b0=0;b0<250;b0++)
 {
 portb=get_value1(hundreds);
 portc.0=1;
 delay_ms(1);
 portc.0=0;
 portb=get_value1(tens);
 portc.1=1;
 delay_ms(1);
 portc.1=0;
 portb=get_value2(units);
 portc.2=1;
 delay_ms(1);
 portc.2=0;
 }
}

unsigned char get_value1(unsigned char x)
{
unsigned char segments[10]={0xDE,0x50,0xE6,0xF4,0x78,0xBC,0xBE,0x54,0xFE,0xFC};
return segments[x];
} 

unsigned char get_value2(unsigned char y)
{
unsigned char segments[10]={0xDE,0x0A,0xE6,0xAE,0x3A,0xBC,0xFC,0x8A,0xFE,0xBE};
return segments[y];
}

Raghunathan

Edited by ra68gi

Share this post


Link to post
Share on other sites

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...