View previous topic :: View next topic |
Author |
Message |
aviarunash
Joined: 15 Nov 2018 Posts: 5
|
18F45K22 ADC vs DAC |
Posted: Tue Dec 18, 2018 1:48 am |
|
|
Hi All
I am not trying anything complex, just working to read the ADC and output it to the DAC with the following code. Running at 64Mhz Internal Clock.
Code: |
#include <18F45K22.h>
#device ADC=8
#include <stdlib.h>
#fuses INTRC_IO,NOWDT,NOPUT,NOBROWNOUT,NOLVP,NOMCLR,NOIESO
#use delay(clock=64M)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,bits=8,stream=STU)
#byte PORTA = 0xF80
unsigned int8 value_adc=0;
long int x=100;
void main() {
set_tris_a(0x08);
set_tris_d(0xF0);
set_tris_b(0x06);
set_tris_c(0xC0);
setup_comparator(NC_NC_NC_NC);
setup_wdt(WDT_OFF);
setup_dac(DAC_VSS_VDD | DAC_OUTPUT);
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(sAN3);
set_adc_channel(3);
while(1)
{
value_adc = read_adc();
delay_us(10);
dac_write(value_adc);
}
} |
The problem what I do face is when I tried to input an amplified audio signal to adc and read the same back on DAC, what I heard was just cracking noise. Decided to check the internals and fed the ADC with 4.99 Volts, Output read on DAC PIN was 4.63 Volts.
What wrong am I making here. Is there any special configurations to be done on this controller to read ADC? I have worked the same on a different controller without much problems. I have some quality issues as the output was on PWM. But nothing like this.
Please advise. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Tue Dec 18, 2018 2:15 am |
|
|
Quote: |
When I tried to input an amplified audio signal to adc and read the same
back on DAC, what I heard was just cracking noise.
|
You have an 8-bit ADC result, but your DAC is only 5-bits. So with a
1:1 write, you are only writing the lower 5 bits of the ADC to the DAC.
This will probably appear as mostly noise. You need to right-shift the
ADC result by 3 bits before sending it to the DAC. Or just divide by 8.
Example:
Code: | dac_write(value_adc/8); |
Quote: | any special configurations to be done on this controller to read ADC?
|
For proper accuracy, you should be using Div by 64, not the internal
ADC clock. Example:
Code: | setup_adc(ADC_CLOCK_DIV_64); |
Both these answers are in the PIC data sheet, in the DAC and ADC sections. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Tue Dec 18, 2018 2:46 am |
|
|
Also
ADC_CLOCK_INTERNAL
Is not recommended for use with a clock speed above 1MHz. Again data
sheet will tell you the recommended clock divisor at 64MHz. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9229 Location: Greensville,Ontario
|
|
Posted: Tue Dec 18, 2018 2:50 pm |
|
|
and....
PIC ADCs are usually POSITIVE DC signal devices NOT AC, so you can't 'read' an analog voltage like a sine wave. You can't read say -2 volts.
Jay |
|
|
aviarunash
Joined: 15 Nov 2018 Posts: 5
|
Thank you |
Posted: Mon Dec 24, 2018 2:42 am |
|
|
Hi All
Thank you for your reply. DAC output is still not good when shifting 3 bits, whereas the PWM output is far more better than DAC. However, I have comeup with an other problem in turning ON/OFF PORTB.3 Digital IO.
Code: |
#include <18F45K22.h>
#device ADC=8
#include <stdlib.h>
#fuses INTRC_IO,NOWDT,NOPUT,NOBROWNOUT,NOLVP,NOMCLR,NOIESO
#use delay(clock=64M)
#byte PORTA = 0xF80
#byte PORTB = 0xF81
#bit RLED=PORTA.3
#bit MAINS = PORTB.1
#bit CUTOFF = PORTB.3
void main() {
set_tris_a(0x00);
set_tris_b(0x00);
setup_comparator(NC_NC_NC_NC);
setup_dac(DAC_OFF);
setup_adc(ADC_OFF);
setup_adc_ports(NO_ANALOGS);
setup_wdt(WDT_OFF);
setup_ccp2(CCP_OFF);
MAINS=1;
while(1)
{
MAINS=0;
CUTOFF=1;
delay_ms(2);
CUTOFF=0;
MAINS=1;
delay_ms(2);
/* - WORKING BLOCK
MAINS=0;
RLED=1;
delay_ms(2);
RLED=0;
MAINS=1;
delay_ms(2);
*/
}
}
|
If I do change CUTOFF to RLED PIN, I have the pulse 2 ms ON/OFF in PORTB.1. But when I use the CUTOFF PIN, I dont see even the PULSE in PORTB.1, assume that PORTB.3 is being reserved and when used, it is behaving abnormally.
Please advice.
NOTE: OUTPUT_HIGH / LOW (PIN_B3) Works fine. Just don't know why it doesn't work when I do it as above. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Dec 24, 2018 12:24 pm |
|
|
Try it with the Latch registers instead of the Port registers. Example:
Code: |
//#byte PORTA = 0xF80
//#byte PORTB = 0xF81
//#bit RLED=PORTA.3
//#bit MAINS = PORTB.1
//#bit CUTOFF = PORTB.3
//---------------------
#byte LATA = getenv("SFR:LATA")
#byte LATB = getenv("SFR:LATB")
#bit RLED = LATA.3
#bit MAINS = LATB.1
#bit CUTOFF = LATB.3
|
If you want to know the reason for doing this, use these search terms
with Google to find articles:
Quote: | site:microchip.com/forums PORTB read modify write |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19518
|
|
Posted: Wed Dec 26, 2018 7:19 am |
|
|
Though limited to 32 levels, the DAC should perform well, _unless_ you are
imposing even a small load on the output. It is a simple resistive divider, so the
output is massively affected by load. Needs an op-amp buffer if any current
is involved at all.
General comments on the posted code.
The clock declaration should say:
#use delay(INTERNAL=64M)
You are 'relying' on the compiler knowing that the fuse is selected for
INT_RC, and that it will automatically generate the correct PLL for this.
Better to tell it this. I think the chip will actually only be running at
16MHz with the selection you post.
The PORT register is the 'input' reads the actual pins. The LAT is the
output latch. It is always better to write to this. The chip is meant to
automatically write to the output latch if you write to the port, but it sounds
as if this is not working for some reason. The CCS output instruction does
write to the output latch not the port. |
|
|
|