 |
 |
View previous topic :: View next topic |
Author |
Message |
suspiciousdeveloper
Joined: 02 Mar 2025 Posts: 4
|
Having issues while trying to use ADC |
Posted: Sun Mar 02, 2025 3:52 pm |
|
|
Compiler Version: V5.118
MCU: 33CH128MP202-I/SS
Hey there, while trying to use ADC the code seems to be getting stuck whenever the read_adc() function is called. Tried multiple methods but no luck, appreciate any help provided. Code is attached below:
Code: | #include <33CH128MP202.h>
#device adc=12 // Ensure 12-bit ADC resolution
#fuses NOWDT, HS // Disable watchdog, high-speed oscillator
#use delay(crystal=10mhz, clock=180000000)
// UART1 Configuration
#pin_select U1TX = PIN_B6
#pin_select U1RX = PIN_B5
#use rs232(UART1, STREAM=UART1, baud=9600, xmit=PIN_B6, rcv=PIN_B5, ERRORS)
// ADC Configuration
#define ADC_CHANNEL 0 // **Try AN0 Instead of AN4**
#define VREF 3.3 // Reference Voltage
#define ADC_MAX 4095 // 12-bit ADC max value
#define PIN_LED PIN_B7 // **LED for debugging**
void blink_led() {
int i;
for (i = 0; i < 5; i++) { // **Blink LED 5 times before ADC setup**
output_toggle(PIN_LED);
delay_ms(500);
}
}
// **Initialize ADC (With Debugging and Reset)**
void init_adc() {
fprintf(UART1, "Initializing ADC...\r\n");
setup_adc_ports(sAN0); // Ensure AN0 is analog
delay_ms(5);
setup_adc(ADC_CLOCK_DIV_64); // **Try a more stable clock setting**
set_adc_channel(ADC_CHANNEL); // Select AN0
delay_ms(10); // Allow ADC to stabilize
// **Check if ADC Module is Enabled**
if (!adc_done()) {
fprintf(UART1, "ERROR: ADC is NOT READY! ADC module may be OFF.\r\n");
} else {
fprintf(UART1, "ADC Initialized Successfully.\r\n");
}
}
// **Read ADC Value with Debugging**
unsigned int16 read_adc_value() {
unsigned int16 adc_result;
int timeout = 5000;
fprintf(UART1, "Starting ADC Conversion...\r\n");
set_adc_channel(ADC_CHANNEL); // Select correct channel
delay_us(10); // Small delay before conversion
// **Use ADC_START_ONLY to Prevent Hanging**
read_adc(ADC_START_ONLY);
// **Timeout Protection**
while (!adc_done() && timeout > 0) {
delay_us(10);
timeout--;
}
if (timeout == 0) {
fprintf(UART1, "ERROR: ADC Conversion Timed Out!\r\n");
return 0;
}
adc_result = read_adc(ADC_READ_ONLY);
fprintf(UART1, "DEBUG: read_adc() returned: %u\r\n", adc_result);
return adc_result;
}
// **Main Function**
void main() {
unsigned int16 temp_adc;
float voltage;
delay_ms(100); // Allow MCU to stabilize
fprintf(UART1, "\r\nBOOTING SYSTEM...\r\n");
blink_led(); // **Confirm MCU is running**
init_adc(); // **Initialize ADC**
while (TRUE) {
fprintf(UART1, "Trying to read ADC...\r\n");
temp_adc = read_adc_value(); // Get ADC reading
voltage = (temp_adc / (float)ADC_MAX) * VREF; // Convert ADC value to voltage
fprintf(UART1, "ADC Read: %u | Voltage: %.2fV\r\n", temp_adc, voltage);
delay_ms(1000); // Read every second
}
}
|
|
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9425 Location: Greensville,Ontario
|
|
Posted: Sun Mar 02, 2025 5:50 pm |
|
|
ok ,curious like my cat...FYI I've never used it but...
THAT PIC appears to be 'dual core' . If so I assume YOU have to configure what pins are ADC and where they go --> PIC #1, --> PIC #2
first though , I'd get the clock set to something reasonable, say 10MHz for test purposes AND run the '1Hz LED' program to confirm it runs....
when 'happy' have main()
do....
read ADC
send data to PC
delay 500ms
...forever
CONFIRM this works, put pot on input,vary, result should 'follow' wiper.
bottom line..go back to basics, build on code that works.
forget about 'floating point' too !!
query... is that PIC rated for 180 MHz operation at 3 volt VDD ? |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19730
|
|
Posted: Mon Mar 03, 2025 6:13 am |
|
|
He is rather pushing the core. It is rated for 180MHz, but only over a limited
supply and temperature range.
There are lots of extra complexities with these chips:
First the ADC clock source is not being specified. By default will be 'SYSTEM'.
Then, he needs to specify which ADC channel to use. On this ADC, there
are multiple SAR's feeding the single dedicated core on the master chip.
By default it will read all enabled channels, but he has none enabled. |
|
 |
temtronic
Joined: 01 Jul 2010 Posts: 9425 Location: Greensville,Ontario
|
|
Posted: Mon Mar 03, 2025 6:43 am |
|
|
yeesh.... sounds like a 'fun' PIC to deal with !
Kinda wondered why the 'warp speed' for the clock, especially for testing .
I KNOW board layout,wiring,etc. is critical to get more than 10 bits of good data from a 12 bit ADC. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19730
|
|
Posted: Mon Mar 03, 2025 7:49 am |
|
|
Yes, they are getting fun.
The design is very much optimised to using the ADC triggered from something
like the PWM. You specify the channels you want, and when it gets the
trigger it automatically samples the specified channels.
The results are stored in buffers for each channel number.
The ADC won't sample without a channel setup enabled. I think this
is what he is missing. These are the CNVCHSEL bits. He has to perform
a channel setup as well as the basic ADC setup. |
|
 |
suspiciousdeveloper
Joined: 02 Mar 2025 Posts: 4
|
|
Posted: Mon Mar 03, 2025 11:33 am |
|
|
temtronic wrote: | ok ,curious like my cat...FYI I've never used it but...
THAT PIC appears to be 'dual core' . If so I assume YOU have to configure what pins are ADC and where they go --> PIC #1, --> PIC #2
first though , I'd get the clock set to something reasonable, say 10MHz for test purposes AND run the '1Hz LED' program to confirm it runs....
when 'happy' have main()
do....
read ADC
send data to PC
delay 500ms
...forever
CONFIRM this works, put pot on input,vary, result should 'follow' wiper.
bottom line..go back to basics, build on code that works.
forget about 'floating point' too !!
query... is that PIC rated for 180 MHz operation at 3 volt VDD ? |
Hey, thanks for the response, yea the MCU works fine with 180MHz as well. I tried lowering it down to 10MHz as you said but there was no change.  |
|
 |
suspiciousdeveloper
Joined: 02 Mar 2025 Posts: 4
|
|
Posted: Mon Mar 03, 2025 11:37 am |
|
|
Ttelmah wrote: | Yes, they are getting fun.
The design is very much optimised to using the ADC triggered from something
like the PWM. You specify the channels you want, and when it gets the
trigger it automatically samples the specified channels.
The results are stored in buffers for each channel number.
The ADC won't sample without a channel setup enabled. I think this
is what he is missing. These are the CNVCHSEL bits. He has to perform
a channel setup as well as the basic ADC setup. |
Hey I couldn't find any other functions than adc_set_channel() which I am already using, can you please help regarding else I need to do? |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19730
|
|
Posted: Mon Mar 03, 2025 12:18 pm |
|
|
The ADC channel number there is not the channel number for the sampling.
If you look at the functions you are already using they offer channel
selections as an option. You need to setup a channel with these. |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19730
|
|
Posted: Tue Mar 04, 2025 3:05 am |
|
|
Problem here is the use of the word 'channel'.
On traditional ADC's, the 'channel' had one meaning, the input number
to be read. On this chip it has two meanings....
There is the analog channel, and the ADC sample channel. The analog
channel is the historic meaning. The sample channel, it which of the five
internal input channels it is actually to read.
Now if you look at the data sheet, these are the CNVCHSEL bits. It tells
you that when doing a software triggered read, it'll read the sample channel
that has this bit set. If none of these bits are set, it won't actually perform
a read.
Now the .h file makes this more confusing, by calling both these numbers
'channel'. It is right I suppose, since this is what they are called in the
data sheet, but doesn't help you to understand that these are separate....
Personally I think they should have changed the names so the one
in set_adc_channel, was called perhaps an_channel, and the ones in
read_adc, and add_done, were called perhaps samp_chan.
The key point here is that a sample channel has to be set.
So if you change adc_done(), to adc_done(1), this then is using sample
channel 1, similarly if you change the read_adc commands, to:
read_adc(ADC_START_ONLY,1);
and
read_adc(ADC_READ_ONLY,1);
This then says to set the bottom CNVCHSEL bit to work with this channel.
Now the data sheet says:
Quote: |
CNVCHSEL [5:0]: Channel Number Selection for Software Individual Channel Conversion Trigger bits
These bits define a channel to be converted when the CNVRTCH bit is set.
|
The point is it won't actually do a conversion, unless one of these bits is
set. If you look at the listing, if you use the '1' as shown, it sets the bottom
one of these bits, so the software trigger should then know what it has
to convert.
I've only use this ADC with triggered sampling, but noted when looking
at the setups, that this bit needed to be set and worked out that this was
what did it.
I must admit I was surprised that the default didn't set a bit without this.... |
|
 |
suspiciousdeveloper
Joined: 02 Mar 2025 Posts: 4
|
|
Posted: Thu Mar 06, 2025 2:32 pm |
|
|
Ttelmah wrote: | Problem here is the use of the word 'channel'.
On traditional ADC's, the 'channel' had one meaning, the input number
to be read. On this chip it has two meanings....
There is the analog channel, and the ADC sample channel. The analog
channel is the historic meaning. The sample channel, it which of the five
internal input channels it is actually to read.
Now if you look at the data sheet, these are the CNVCHSEL bits. It tells
you that when doing a software triggered read, it'll read the sample channel
that has this bit set. If none of these bits are set, it won't actually perform
a read.
Now the .h file makes this more confusing, by calling both these numbers
'channel'. It is right I suppose, since this is what they are called in the
data sheet, but doesn't help you to understand that these are separate....
Personally I think they should have changed the names so the one
in set_adc_channel, was called perhaps an_channel, and the ones in
read_adc, and add_done, were called perhaps samp_chan.
The key point here is that a sample channel has to be set.
So if you change adc_done(), to adc_done(1), this then is using sample
channel 1, similarly if you change the read_adc commands, to:
read_adc(ADC_START_ONLY,1);
and
read_adc(ADC_READ_ONLY,1);
This then says to set the bottom CNVCHSEL bit to work with this channel.
Now the data sheet says:
Quote: |
CNVCHSEL [5:0]: Channel Number Selection for Software Individual Channel Conversion Trigger bits
These bits define a channel to be converted when the CNVRTCH bit is set.
|
The point is it won't actually do a conversion, unless one of these bits is
set. If you look at the listing, if you use the '1' as shown, it sets the bottom
one of these bits, so the software trigger should then know what it has
to convert.
I've only use this ADC with triggered sampling, but noted when looking
at the setups, that this bit needed to be set and worked out that this was
what did it.
I must admit I was surprised that the default didn't set a bit without this.... |
Thanks for the help, I got it working. Can you guide me on how to use ADC with Interrupts on this specific model? I already tried the basic ADC_START_ONLY in main code and calling ADC_READ_ONLY in isr but it doesnt seem to work  |
|
 |
Ttelmah
Joined: 11 Mar 2010 Posts: 19730
|
|
Posted: Fri Mar 07, 2025 12:28 am |
|
|
Using interrupts with manual triggering would just waste time. Where
interrupts are useful, is when the ADC is started by an external event.
So (for example) the PWM, or a timer.
I would suggest you setup a Tacq in the ADC setup. This way the ADC
will automatically wait to acquire when sampling, so you can just read
without having to wait after selecting a channel. |
|
 |
|
|
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
|