|
|
View previous topic :: View next topic |
Author |
Message |
arelone
Joined: 06 Dec 2015 Posts: 42
|
UART -dspic30F6014a |
Posted: Fri May 24, 2019 3:04 am |
|
|
Hi,
I am wondering when I try to read 4.788V from multichannel ADCs. Only channel AN0 seems working, for others it displays -16.000. Why is this happening? Does the dspic require delay to read from other ADCs? or I missed to declare/ insert include files in the code? I tried to insert delay (50us) in reading from ADCs but the problem remains. Any ideas?
Regards
Arelone
Here is the output in the hyper terminal:
4752.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
-16.000
9.999
Code: |
#include <30F6014A.h>
#include <float.h>
#include <string.h>
#fuses HS, NOWDT, NOPROTECT, PUT64, BORV27
//correct - Power On Reset Timer value 64ms, Brownout reset at 2.7V
#use delay(clock=20000000) //20 MHz crystal
//#use rs232(baud=9600,UART2)
#define LED PIN_B10
//#define VSS_VDD
#define WDT_OFF=0
#use rs232(baud=9600,UART2)
void main()
{
setup_adc_ports(sAN0 | sAN1 | sAN2 | sAN3 | sAN4 | sAN5 | sAN6 | sAN7 | sAN8 | sAN9 | sAN10 | sAN11 | sAN12 | sAN13 | sAN14 | sAN15, VSS_VDD);
setup_adc(ADC_CLOCK_DIV_64 | ADC_TAD_MUL_2);
setup_adc_ports(ALL_ANALOG);
// Built-in A/D setup function
setup_adc(ADC_CLOCK_INTERNAL);
// Built-in A/D setup function
const int8 channel_1[]=1,2,3,4,5,6,7,8,9,10,11,12,13;
int16 ADC_value1[sizeof(channel_1)];
int32 value;
float voltage[sizeof(channel_1)];
//int32 voltage[sizeof(channel_1)];
//I/O ports configurations(1:input, 0:output)
set_tris_a(0x0000); //set port_a as output
set_tris_b(0xFFFF); //set port_b as analog input/ADC
set_tris_c(0x0000); //set port_c as output
set_tris_d(0x0000); //set port_d as output
set_tris_f(0x0000); //set port_f as output
set_tris_g(0x0000); //set port_g as output
output_a(0x0000); //clear port_a to all 0s
output_c(0x0000); //clear port_c to all 0s
output_d(0xFFFF); //clear port_d to all 1s-portD dafault at HIGH state
output_f(0x0000); //clear port_f to all 0s
output_g(0x0000); //clear port_g o all 0s
while(TRUE)
{
//read from chnnel 0, 0++ (1,2,3...7)
for (value=0;value<sizeof(channel_1);value++)
{
set_adc_channel(channel_1[value]);
delay_us(50);
ADC_value1[value]=read_adc();
delay_us(50);
voltage[value] = (ADC_value1[value]);
}
//display value from channels 0...7
for (value=0;value<sizeof(channel_1);value++)
{
//printf("%4.3f",voltage[value]);
printf("%4.3f\r\n",voltage[value]);
}
//printf("9.999");
printf("9.999\r\n");
}
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Fri May 24, 2019 5:59 pm |
|
|
OK I don't use that PIC but some comments
1) The PIC ADC returns bits NOT a floating voltage so this line
printf("%4.3f\r\n",voltage[value]);
doesn't make any sense to me.
2) -16.00 could be the float equal to the ADC being >VDD. Again the ADC is monopolar and should NEVER give a -ve value.
3) Your code seems really, really complicated.
IE.. for (value=0;value<sizeof(channel_1);value++)
Simply select an ADC pin, read it, display it, delay then select another pin..........
4) If you've got say 8 ADC pins make for(value=0;value<9;value++) is a LOT easier to read and understand, at least to this fossil.
5) ALWAYS add 'ERRORS' to the #USE RS232( ...options...) |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19551
|
|
Posted: Fri May 24, 2019 10:38 pm |
|
|
and, you have not got a line specifying the ADC value size to be returned.
#device ADC=12
Without this, the default is normally for the ADC value to be returned
left lustified, so when put into a signed int16, any value above half range
will give a -ve return. |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
|
Posted: Wed Jun 26, 2019 1:15 am |
|
|
Hi,
I compiled the code with CCS C ver. 5.010 with a new dspic30F6014a chip using UART1 or UART2 and it works accordingly.
Below I attached code for getting delay of 1us using internal clock (7.37MHz x16) and read analog samples from multi-channel ADC. I verified with an oscilloscope and the pulses created are approximately 1us. However during the operation, the chip becomes warm. Is this normal? or is there any better examples to create the 1us delay?.
Can someone explain to me the relationship between ADC frequency & TAD particularly in my case which using internal clock. How to calculate the acquisition time and no. of samples for the 12 bits ADC for each channel? Is it possible to setting the ADC to read 1 sample per channel? Any examples that I can make as reference?
Regards
Code: |
#include <30F6014A.h>
#device ADC=12
#include <float.h>
#include <string.h>
#fuses FRC_PLL16, NOWDT, NOPROTECT, PUT64, BORV27 //7.37MHz x16
#use delay(clock=117920000,internal)
#use rs232(baud=9600,UART1,ERRORS)
void main()
{
set_TRIS_C(0x0000);
set_TRIS_D(0x0000);
SETUP_ADC(adc_OFF);
setup_adc_ports(ALL_ANALOG);
setup_adc_ports(sAN0 |sAN1|sAN2|sAN3|sAN4|sAN5|sAN6|sAN7|sAN8|sAN9|sAN10|sAN11|sAN12|sAN13|sAN14|sAN15, VSS_VDD);
setup_adc(ADC_CLOCK_DIV_64 | ADC_TAD_MUL_2);
setup_adc(ADC_CLOCK_INTERNAL);
// Built-in A/D setup function
output_high(PIN_C2);
output_high(PIN_C3);
output_high(PIN_C4);
output_high(PIN_G6);
output_high(PIN_G7);
output_high(PIN_D8);
output_high(PIN_D9);
output_high(PIN_D10);
output_high(PIN_D11);
output_high(PIN_G15);
//setup_adc_ports(ALL_ANALOG);
// Build-in A/D setup function
signed int32 ert_adc_value_5;
signed int32 ert_adc_value_6;
signed int32 ert_adc_value_7;
signed int32 ert_adc_value_8;
signed int32 ert_adc_value_9;
signed int32 ert_adc_value_10;
signed int32 ert_adc_value_11;
signed int32 ert_adc_value_12;
signed int32 ert_adc_value_13;
signed int32 ert_voltages_5;
signed int32 ert_voltages_6;
signed int32 ert_voltages_7;
signed int32 ert_voltages_8;
signed int32 ert_voltages_9;
signed int32 ert_voltages_10;
signed int32 ert_voltages_11;
signed int32 ert_voltages_12;
signed int32 ert_voltages_13;
while(TRUE)
{
//TR1 as transmitter
output_high(PIN_C1); //excitation signal 328kHz at TR1
delay_us(2);
output_low(PIN_C1);
delay_us(1);
output_high(PIN_C1);
delay_us(2);
output_low(PIN_C1);
delay_us(49); // delay 54.4us
output_low(PIN_C2); // ch 5
output_low(PIN_D8); // ch 13
delay_us(8); // delay 62.4us
output_low(PIN_C3); // ch 6
output_low(PIN_D9); // ch 12
delay_us(6); // delay 68.8us
output_low(PIN_C4); // ch 7
output_low(PIN_D10); // ch 11
delay_us(3); // delay 72.0us
output_low(PIN_G6); // ch 8
output_low(PIN_D11); // ch 10
delay_us(1); // delay 72.8us
output_low(PIN_G7); // ch 9
//sample at TR5
output_low(PIN_G15);
set_adc_channel(4); //read from channel 0
delay_us(10); //delay is required after setting channel and bef.read
ert_adc_value_5=read_adc(); //starts conversion & store it in value
ert_voltages_5=(ert_adc_value_5)*5000/4096;// last result of last conversion
printf("Ch05=%u\r\n",ert_voltages_5);
//sample at TR6
set_adc_channel(5); //read from channel 0
delay_us(10); //delay is required after setting channel and bef.read
ert_adc_value_6=read_adc(); //starts conversion & store it in value
ert_voltages_6=(ert_adc_value_6)*5000/4096;// last result of last conversion
printf("Ch06=%u\r\n",ert_voltages_6);
//sample at TR7
set_adc_channel(6); //read from channel 0
delay_us(10); //delay is required after setting channel and bef.read
ert_adc_value_7=read_adc(); //starts conversion & store it in value
ert_voltages_7=(ert_adc_value_7)*5000/4096;// last result of last conversion
printf("Ch07=%u\r\n",ert_voltages_7);
//sample at TR8
set_adc_channel(7); //read from channel 0
delay_us(10); //delay is required after setting channel and bef.read
ert_adc_value_8=read_adc(); //starts conversion & store it in value
ert_voltages_8=(ert_adc_value_8)*5000/4096;// last result of last conversion
printf("Ch08=%u\r\n",ert_voltages_8);
//sample at TR9
set_adc_channel(8); //read from channel 0
delay_us(10); //delay is required after setting channel and bef.read
ert_adc_value_9=read_adc(); //starts conversion & store it in value
ert_voltages_9=(ert_adc_value_9)*5000/4096;// last result of last conversion
printf("Ch09=%u\r\n",ert_voltages_9);
//sample at TR10
set_adc_channel(9); //read from channel 0
delay_us(10); //delay is required after setting channel and bef.read
ert_adc_value_10=read_adc(); //starts conversion & store it in value
ert_voltages_10=(ert_adc_value_10)*5000/4096;// last result of last conversion
printf("Ch10=%u\r\n",ert_voltages_10);
//sample at TR11
set_adc_channel(10); //read from channel 0
delay_us(10); //delay is required after setting channel and bef.read
ert_adc_value_11=read_adc(); //starts conversion & store it in value
ert_voltages_11=(ert_adc_value_11)*5000/4096;// last result of last conversion
printf("Ch11=%u\r\n",ert_voltages_11);
//sample at TR12
set_adc_channel(11); //read from channel 0
delay_us(10); //delay is required after setting channel and bef.read
ert_adc_value_12=read_adc(); //starts conversion & store it in value
ert_voltages_12=(ert_adc_value_12)*5000/4096;// last result of last conversion
printf("Ch12=%u\r\n",ert_voltages_12);
//sample at TR13
set_adc_channel(12); //read from channel 0
delay_us(10); //delay is required after setting channel and bef.read
ert_adc_value_13=read_adc(); //starts conversion & store it in value
ert_voltages_13=(ert_adc_value_13)*5000/4096;// last result of last conversion
printf("Ch13=%u\r\n",ert_voltages_13);
output_high(PIN_G15);
output_high(PIN_C2);
output_high(PIN_C3);
output_high(PIN_C4);
output_high(PIN_G6);
output_high(PIN_G7);
output_high(PIN_D8);
output_high(PIN_D9);
output_high(PIN_D10);
output_high(PIN_D11);
}
}//end main
|
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Wed Jun 26, 2019 4:55 am |
|
|
While I don't use that PIC, I offer some comments..
1) Yes, the PIC will get warm. If YOU did 117 million pushups in a second, you'd be warm too ! CMOS devices are very low poer 'at rest', it's during 'transitions' (0>1>0, 0>1,1>0) that they consume power. Power = heat.
2) I was curious about your program and I think you're trying to read several ultrasonic sensors with analog outputs ? IF so, post the make/model info.
3) You should have two tasks. 1 acquire the ADC readings, 2 - display them. You could be getting sensor glitches but without knowing what sensors you're using, it's hard to help.
4) analog can be tricky to get 'right', especially over 8 bits AND fast. You need proper PCB design (layout, caps, traces, filtering, etc.) as well as shielding from sensors to PCB. A STABLE PSU is required as well as a precision Vref. That way 1.2345 volts is ALWAYS 1.2345 and not 1.2346 or 1.2344.
5) You need to read the ADC section of the datasheet to understand the ADC. As well, check Microchip's website for 'apnotes'. They have dozens. read them all, especially the older ones so you can 'see' how it works.
Jay |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
UART -dspic30F6014a |
Posted: Fri Oct 18, 2019 6:41 pm |
|
|
Hi,
I need some help here. I'm trying to use the PLL clock multiplier settings for the attached program. I'm using 20MHz oscillator. Before this I was using #fuses HS,...#use delay (clock=20000000) statement and the ADC works as expected however I am not getting 1us pulse, the best I can get is 1.42us. I decided to tried the PLL options with #FUSES HS2_PLL4,...(20MHz/2 * 4=40MHz) #use delay (clock=20000000). Now i can get approximately 1.088us but the measurement data received from UART are unreadable characters. Please help.
Arelone
Code: |
#include <30F6014A.h>
#device ADC=12
#include <float.h>
#include <string.h>
#fuses HS2_PLL4,NOWDT, NOPROTECT, PUT64, BORV27,
#use delay(clock=20000000) //20MHz MHz crystal used
#use rs232(baud=9600,UART1,ERRORS)
void main()
{
set_TRIS_C(0x0000);
set_TRIS_D(0x0000);
SETUP_ADC(adc_OFF);
setup_adc_ports(ALL_ANALOG);
setup_adc_ports(sAN0 |sAN1|sAN2|sAN3|sAN4|sAN5|sAN6|sAN7|sAN8|sAN9|sAN10|sAN11|sAN12|sAN13|sAN14|sAN15, VSS_VDD);
setup_adc(ADC_CLOCK_DIV_64 | ADC_TAD_MUL_2);
setup_adc(ADC_CLOCK_INTERNAL);
// Built-in A/D setup function
//setup_adc_ports(ALL_ANALOG);
// Build-in A/D setup function
signed int32 ert_adc_value_5;
signed int32 ert_adc_value_6;
signed int32 ert_adc_value_7;
signed int32 ert_adc_value_8;
signed int32 ert_adc_value_9;
signed int32 ert_adc_value_10;
signed int32 ert_adc_value_11;
signed int32 ert_adc_value_12;
signed int32 ert_adc_value_13;
signed int32 ert_voltages_5;
signed int32 ert_voltages_6;
signed int32 ert_voltages_7;
signed int32 ert_voltages_8;
signed int32 ert_voltages_9;
signed int32 ert_voltages_10;
signed int32 ert_voltages_11;
signed int32 ert_voltages_12;
signed int32 ert_voltages_13;
while(TRUE)
{
output_high(PIN_D4);
delay_us(1);
output_low(PIN_D4);
delay_us(2);
output_high(PIN_D4);
delay_us(1);
output_low(PIN_D4);
delay_us(2);
//sample at TR5
set_adc_channel(4); //read from channel 4
delay_us(20); //delay is required after setting channel and bef.read
//read_adc(ADC_START_ONLY);
ert_adc_value_5=read_adc(); //starts conversion & store it in value
ert_voltages_5=(ert_adc_value_5)*5000/4096;// last result of last conversion
printf("Ch05=%u\n\r",ert_voltages_5);
output_high(PIN_C2);
//sample at TR6
set_adc_channel(5); //read from channel 5
delay_us(20); //delay is required after setting channel and bef.read
//read_adc(ADC_START_ONLY);
ert_adc_value_6=read_adc(); //starts conversion & store it in value
ert_voltages_6=(ert_adc_value_6)*5000/4096;// last result of last conversion
printf("Ch06=%u\r\n",ert_voltages_6);
output_high(PIN_C3);
//sample at TR7
set_adc_channel(6); //read from channel 6
delay_us(20); //delay is required after setting channel and bef.read
//read_adc(ADC_START_ONLY);
ert_adc_value_7=read_adc(); //starts conversion & store it in value
ert_voltages_7=(ert_adc_value_7)*5000/4096;// last result of last conversion
printf("Ch07=%u\r\n",ert_voltages_7);
//sample at TR8
set_adc_channel(7); //read from channel 7
delay_us(20); //delay is required after setting channel and bef.read
//read_adc(ADC_START_ONLY);
ert_adc_value_8=read_adc(); //starts conversion & store it in value
ert_voltages_8=(ert_adc_value_8)*5000/4096;// last result of last conversion
printf("Ch08=%u\r\n",ert_voltages_8);
//sample at TR9
set_adc_channel(8); //read from channel 8
delay_ms(10); //delay is required after setting channel and bef.read
//read_adc(ADC_START_AND_READ);
ert_adc_value_9=read_adc(); //starts conversion & store it in value
ert_voltages_9=(ert_adc_value_9)*5000/4096;// last result of last conversion
printf("Ch09=%u\r\n",ert_voltages_9);
//sample at TR10
set_adc_channel(9); //read from channel 9
delay_ms(10); //delay is required after setting channel and bef.read
//read_adc(ADC_START_ONLY);
ert_adc_value_10=read_adc(); //starts conversion & store it in value
ert_voltages_10=(ert_adc_value_10)*5000/4096;// last result of last conversion
printf("Ch10=%u\r\n",ert_voltages_10);
//sample at TR11
set_adc_channel(10); //read from channel 10
delay_us(20); //delay is required after setting channel and bef.read
//read_adc(ADC_START_ONLY);
ert_adc_value_11=read_adc(); //starts conversion & store it in value
ert_voltages_11=(ert_adc_value_11)*5000/4096;// last result of last conversion
printf("Ch11=%u\r\n",ert_voltages_11);
//sample at TR12
set_adc_channel(11); //read from channel 11
delay_us(20); //delay is required after setting channel and bef.read
//read_adc(ADC_START_ONLY);
ert_adc_value_12=read_adc(); //starts conversion & store it in value
ert_voltages_12=(ert_adc_value_12)*5000/4096;// last result of last conversion
printf("Ch12=%u\r\n",ert_voltages_12);
//sample at TR13
set_adc_channel(12); //read from channel 12
delay_us(20); //delay is required after setting channel and bef.read
//read_adc(ADC_START_ONLY);
ert_adc_value_13=read_adc(); //starts conversion & store it in value
ert_voltages_13=(ert_adc_value_13)*5000/4096;// last result of last conversion
printf("Ch13=%u\r\n",ert_voltages_13);
printf("Ch99=9888\r\n");
}
//}
//}
}//end main |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19551
|
|
Posted: Sat Oct 19, 2019 12:33 am |
|
|
You have two set_adc_ports, and setup_adc instructions. Only the last
will actually be respected. A second instruction overrides the first.
The first actually shows an important feature. The use of TAD_MUL.
This allows you to program the ADC to automatically perform the delay
before reading.
Now in fact on a DSPIC like this it is possible to scan a set of analog
inputs automatically, with programmed timings between
samples. However you are trying to exceed the capabilities of the PIC. The
maximum sample rate on this chip is 200K samples/second (5uSec), and
this only if you have the 'best' clock selected (to give Tad=334nSec). Using
the default internal clock will be just 666KHz typically, and with this a single
conversion will take 21uSec. Using your 20MHz Fosc, the fastest conversion
possible is 133KHz, so 7.5uSec per conversion. |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
UART -dspic30F6014a |
Posted: Sat Oct 19, 2019 10:50 am |
|
|
Hi,
Thank you for the explanation. But I still confusing on this matter and correct me if my understanding are wrong.
In my case if I want to use 40MHz obtained from (HS/2)*4 what is the minimum TAD here? is it 334nSec?
Another thing is, I could not correlate if I obtained the FOSC, TCY,actual TAD, and sampling time = 1TAD + 14 TAD, how to relate these values in setup_ADC options (CLK_DIV_? & TAD_MUL_?). Sorry again for lack of knowledge in programming.
Arelone. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19551
|
|
Posted: Sat Oct 19, 2019 1:43 pm |
|
|
No, You'd need to use a clock that is a multiple of 6MHz to get the fastest
conversion. The best you can get from 40MHz, is using a divisor of 7,
which will give a Tad of 350nSec and a conversion time of 5.25uSec.
190476 conversions per second. |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
UART -dspic30F6014a |
Posted: Wed Oct 23, 2019 8:46 am |
|
|
Hi,
Thanks for the knowledge Ttelmah. Now I can run the code smoothly. Here is the corrected hardware code.
Code: |
#fuses NOWDT, NOPROTECT, PUT64, BORV27
#use delay (clock=58982400, xtal=7372800)
|
Arelone |
|
|
|
|
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
|