|
|
View previous topic :: View next topic |
Author |
Message |
boham Guest
|
ADC using PIC18F4520 |
Posted: Fri Feb 29, 2008 1:11 pm |
|
|
Hi all, I have been searching (hopefully well enough) about this but I was planning on using an external ADC to send the bits to my pic for processing but I found out researching that the PIC will do this for me.
I am not sure where I can find info on creating an ADC with this PIC. I am fairly new to PIC programming so bear with me. Any help would be greatly appreciated.
Thanks. |
|
|
boham Guest
|
|
Posted: Fri Feb 29, 2008 1:13 pm |
|
|
Oh one more quick question that I think the answer is no but I have to ask anyway:
Can the PIC do D/A? |
|
|
jma_1
Joined: 08 Feb 2005 Posts: 147 Location: Wisconsin
|
|
Posted: Sun Mar 02, 2008 12:16 pm |
|
|
Greetings boham,
The datasheet for the 18F4520 device is listed on the web page :
http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&nodeId=1335&dDocName=en010297
The analog to digital conversion has many examples provide by CCS and postings in the forum. There should even be examples posted by CCS on their website -> compiler information / api / etc. Look for functions like setup_port(), set_adc_channel, read_adc(), etc.
You might be able to use PWM output and filter the signal to get an approximate analog output. This might not be flexible enough depending on your analog ouptut requirements.
Cheers,
jma
A better approach would be to use the SPI or I2C and interface a standalone DAC chip. |
|
|
boham Guest
|
|
Posted: Wed Mar 12, 2008 4:26 pm |
|
|
OK, here's what I have so far:
Code: | #include <18F4520.h>
#device ADC=8 //set for 8 bit A/D
#use delay(clock=10000000)
#fuses HS,NOWDT
#include <math.h>
//define the A/D control register
#BYTE ADCON0 = 0x1F
int16 ch1_result; //variable to hold A/D readings
#DEFINE Vres 0.019608
//define the button press for transmit
#define BUTTON_PRESSED (!input(PIN_A4))
#int_AD
void AD_isr(){
//possibly could use "if(ADCON0){"
if (((ADCON0 & 0x38) >> 3) == 1){ //must be channel 1
ch1_result = read_adc(); //get 8-bit reading for ch 1
}
ADCON0 |= 0x4; //Restart A/D (sets the GO bit to start conversion)
//If the program was not interrupt-based, the GO bit
//could be interrogated to determine when the conversion
//was completed.
}//AD_isr()
void output_bits(){
//Vres=((ch1_result*5.0)/255.0)*1000; //calculation of voltage on ADC channel
int step;
step = floor(ch1_result / Vres);
createBinary(step, ticker);
// outputloop
}
void createBinary(int number, int ticker) {
int remainder;
if(number <= 1) {
//output to a pin
OUTPUT_TO_A_PIN //output to pin A0-A7
}
else{
//output to a pin
remainder = number%2;
createBinary(remainder);
OUTPUT_TO_A_PIN //output to pin A0-A7
}
}
void main(){
setup_adc_ports(ALL_ANALOG); //Use internal reference all analog channels active
setup_adc(ADC_CLOCK_DIV_32); //Divide Fosc by 32 to get below clock maximum
//Divisor = Fosc/635 KHz = 10MHz / 625KHz = 16
//The next higher divisor is 32 so it must be used
enable_interrupts(INT_AD); //Unmask A/D interrupt
enable_interrupts(global); //Enable all unmasked interrupts
set_adc_channel(1); //Choose channel 1
ADCON0 |= 0x4; //Start A/D process
while(TRUE){
//If the button is pressed, then start sending bits to Bluetooth
if(BUTTON_PRESSED){
output_bits();
}//if
//else, just wait for a button to be pressed to transmit
}//main while loop
}//main() |
I want an 8 bit A/D from 0V-5V.
5 Volts to 8 bits gives me a Vresolution ~ .01960784V for every bit.
So .01960784 VDc is a 1 in my case which does HEX2DEC = 00000001
1.969908 VDc is a 100 which does HEX2DEC = 01100100
and so on to 255 which is 5.003708 Vdc
so what I have done here is when the analog voltage is read, convert it to a hex based on a number you can see what I did with the floor function to get approximate.
Basically, I am receiving an Analog signal, converting it to an 8 Bit binary number and sending the binary number to the outputs of the PIC to be received by a bluetooth transceiver.
Am I on the right track?
You can see in my createBinary function: OUTPUT_TO_A_PIN where I am not too sure where to go from there.
Am I completely off track or am I close? Thank you all for your help! |
|
|
Ttelmah Guest
|
|
Posted: Wed Mar 12, 2008 4:56 pm |
|
|
Don't use the ADC interrupt.
The _only_ reasons to use this, are:
1) You are triggering the ADC conversion with the CCP.
2) You are using the 'sleep' ability of the processor while the ADC conversion is being done, and you need the interrupt to wake the processor.
As it stands, the ADC conversion, will take about 90 instruction times, and you will be spending all your time in the interrupt (the overhead associated with the interrupt handler is a total of about 60 instructions, add the time in the handler itself, and you have no time to do anything much else....). Also, the ADC, has a acquisition requirement _between_ samples, and retriggering the ADC in the interrupt, will almost certainly not give enough time for this. Being in this interrupt so much of the time, will almost certainly also interfere with timings needed for the data output...
To trigger the interrupt (if you want to do what you are doing), use the CCS function read_adc(ADC_START_ONLY). Basically, you are using C, and should use C functions, unless you have very good reasons to do things directly. This helps portability in the future.
If you want repeated automatic acquisitions, use a _timer_ interrupt at a much lower frequency. Otherwise, just use the normal read_adc function.
The PIC ADC, is slightly unusual, in that because of where the actual 'switch' points occur, the steps should be considered as being Vref/1024, rather than Vref/1023 (in your case Vref/256, rather than Vef/255). There is an application note in the Microchip website about this.
Remember floating point arithmetic is _slow_. You are giving your result in integer mV, so do the maths in integer:
Code: |
int16 result;
result = ((int32)(read_adc())*5000)/256;
|
You don't need be fiddling around with floor, and fp maths at all...
Remember that the standard 'RS232' serial routines, output a byte in serial bitwise format on a pin. The bluetooth transmitter, is almost certain to expect either standard async serial othis type, or something like SPI (for which again, there is hardware present...).
Best Wishes |
|
|
[email protected] Guest
|
|
Posted: Sat Apr 12, 2008 2:33 am |
|
|
Try looking at this site for some example code: qwikandlow.com
My professor wrote a book about using the 18f452 and the code should work on the newer one. There is also a pdf book available for download.
I'm gonna be working on programming some similar stuff with a pic18f4520 this weekend and next week, so send me an email if you have any questions, I'd be glad to help out and i like looking at other code to get new ideas.
Mike - [email protected]
(put NOT-SPAM in the subject line in case I have to filter that address if bots pick it up) |
|
|
stereo Guest
|
|
Posted: Wed Jan 06, 2010 2:18 am |
|
|
What is the software to compile the code here? I'm using mplab ide v7.6. Looking at the code in this forum, I think it is not supported if I use the code.
Anyway, I have problem displaying decimal point of the reading voltage on the lcd screen. Instead of 4.99v, it displays 499v.
And how can I measure current and display it on the lcd screen? |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jan 06, 2010 2:04 pm |
|
|
This is the CCS C compiler forum for PIC microcontrollers . If you're
using a different C compiler such as Hi-Tech, CC5X, FED, SourceBoost,
C18, etc., then you need to go to the forum for your compiler. Most
compilers have a forum. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|