|
|
View previous topic :: View next topic |
Author |
Message |
arelone
Joined: 06 Dec 2015 Posts: 42
|
UART -dspic30F6014a |
Posted: Mon Dec 26, 2016 11:20 pm |
|
|
Hi,
I'm using compiler ver.5.0.1, 20MHz osc and dspic30f6014a to read from ADC using UART1. My computer is loaded with win10 and the program was successfully compiled. I tried to observe the ADC output with the hyper terminal however no values are displayed. I tested with pic18F4580 and the ADC values are displayed accordingly. The settings at the com properties are as follows:
Bits per second: 9600
Data bits:8
Parity: None
Stop bits:1
Flow control: Hardware
Has anyone experienced the same problem?
Code: |
#include <dspic30f6014A uart 9600 wo start char.h>
#use rs232(baud=9600, xmit=PIN_F3,rcv=PIN_F2,Bits=8, ERRORS)
#fuses FRC, NOWDT, NOPROTECT, PUT64, BORV27 //correct - Power On Reset Timer value 64ms, Brownout reset at 2.7V
#define LED PIN_B10
//#device ADC=8
int z;
void main()
{
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[] = 0, 1, 2, 3, 4, 5, 6, 7;
int16 ADC_value[sizeof(channel)];
int8 value;
int16 voltage[sizeof(channel)];
while(TRUE)
{
for(z = 0; z < 1; z++)
{
// read from 8 channels ADC
for(value = 0; value < sizeof(channel); value++) // Read from 8 adc channels
{
output_high(LED);
set_adc_channel(channel[value]);
ADC_value[value] = read_adc(); // ADC readings
voltage[value] = ADC_value[value] * (5000 / 255); // Convert ADC data to mV
}
// Print all ADC data
for(value = 0; value < sizeof(channel); value++) // Display 8 voltage values
{
printf("%4.3w\r\n", voltage[value]); //format data in .000
}
printf("9\r\n"); //'9' is display at each end of 8 values
}
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Tue Dec 27, 2016 12:41 am |
|
|
CCS compiler versions are in the form x.xxx
Look at the .lst file where this is found.
If your compiler really has a low number (below perhaps 5.012), then this is a beta compiler at best.
You don't show your clock setup. You say 20MHz, but have FRC selected. Old rule is before trying to do anything on a chip do a basic 'flash an LED' test, and make sure your clock settings are giving the correct oscillation speed.
Then with the ADC, you must wait for Tacq, between selecting a channel and reading it. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Tue Dec 27, 2016 6:40 am |
|
|
as welll this..
setup_adc(ADC_CLOCK_INTERNAL);
is wrong for 16/18 PICs, probably not correct for 30s as well.
also this...
printf("%4.3w\r\n", voltage[value]);
why not also display the channel with the voltage ?
this would show you a) com interface is running correctly as text 'channel' is seen and b) program is looping as number goes 1,2,3...8 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Tue Dec 27, 2016 6:48 am |
|
|
Actually Temtronic, that is not the case.
It's wrong on all the PIC16's and 18's, where the internal oscillator is not recommended if you are working above 1Mhz, unless you put the PIC to sleep when you use the ADC, but on the DsPIC's, this advice is no longer there. They instead say the internal oscillator 'must be used' if you are putting the chip to sleep, and comment that it will not give the fastest sampling rates supported, but no longer have the warning about using it when running normally.
So, probably better not to, but no longer 'not recommended' on these later chips.
Hope you had a good Christmas. I now need about a week to recover.... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Tue Dec 27, 2016 7:07 am |
|
|
Too many PICs... too little time
I know the 30s are a different 'breed' of PICs and assumed(wrongly) that the ADC section was the same. I have seen here that the 'clock section' can be 'fun' to decode so the 1Hz LED program is critical to get 'up and running'.
I gave up trying to see if the newest PICs are better...I like the older,time tested ones, that don't come with 600+ 'must read' pages and more fuses than instructions.
Only got rain here(southern Ontario), though Winterpeg,MB got 35cm ( 14 INCHES) of snow yesterday.
Better them than me.
Jay |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
|
Posted: Wed Dec 28, 2016 5:19 am |
|
|
Hi,
Thank you for the posts. I make some corrections as advised :
in *.c file
a) #fuses FRC... changed to #fuses HS...
b) #use delay(clock=20000000)
c) #use rs232(baud=9600, ...) changed to#use rs232(baud=9600,UART1)
Code: | #include <dspic30f6014A uart 9600 wo start char.h>
#use rs232(baud=9600,UART1)
#fuses HS, NOWDT, NOPROTECT, PUT64, BORV27 //correct - Power On Reset Timer value 64ms, Brownout reset at 2.7V
#define LED PIN_B10
#use delay(clock=20000000) //20 MHz crystal
int z;
void main()
{
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[] = 0, 1, 2, 3, 4, 5, 6, 7;
int16 ADC_value[sizeof(channel)];
int8 value;
int16 voltage[sizeof(channel)];
while(TRUE)
{
for(z = 0; z < 1; z++)
{
// read from 8 channels ADC
for(value = 0; value < sizeof(channel); value++) // Read from 8 adc channels
{
output_high(LED);
set_adc_channel(channel[value]);
ADC_value[value] = read_adc(); // ADC readings
voltage[value] = ADC_value[value] * (5000 / 255); // Convert ADC data to mV
}
// Print all ADC data
for(value = 0; value < sizeof(channel); value++) // Display 8 voltage values
{
printf("%4.3w\r\n", voltage[value]); //format data in .000
}
printf("9\r\n"); //'9' is display at each end of 8 values
}
}
}
|
in *.h file
a) I add #device ADC=12
Code: |
#include <30F6014A.h>
#FUSES NOWDT //No Watch Dog Timer
#FUSES CKSFSM //Clock Switching is enabled, fail Safe clock monitor is enabled
#FUSES NOBROWNOUT //No brownout reset
#device ADC=12 //Receive full 12-bits ADC for dsPIC30F6014A
#device ICSP=1
#use delay(crystal=20000000)
|
the output
--1--)--0--0--0
--1--Œ--0--0--0
--1--o--0--0--0
--1--X--0--0--0
--1--@--0--0--0
--1--a--0--0--0
--1--@--0--0--0
9
--1--g--0--0--0
--1--b--0--0--0
--1--¼--0--0--0
--1--»--0--0--0
--1--•--0--0--0
--1--‡--0--0--0
--1----0--0--0
--1--~--0--0--0
9
--1--g--0--0--0
--1--p--0--0--0
--1--·--0--0--0
--1--»--0--0--0
--1--¤--0--0--0
--1--‡--0--0--0
--1--¨--0--0--0
Now there are unreadable characters display from 8 ADC channels on the hyper terminal screen. Any clues why is this happening? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Wed Dec 28, 2016 6:27 am |
|
|
hmm.. there a re a few things you should do to make 'debugging' a lot easier!
1) You only display 7 channels of readings ! Comments say 8 are read and displayed.
So instead of your print line I'd print the channel number as well as the data. This way you KNOW what channel and data are being read and displayed.
2) Bad display is either a) bad ADC data or b) bad display formatting
To show this, I'd modify the print line to include the raw ADC value as well as the channel and formatted voltage.
Something like
Code: | printf("ADC chnl % raw data %x voltage %4.3 \r\n",value,ADC_value[channel],voltage[value]); |
Syntax might not be right doing this fast.
The point is you NEED to display the raw data as well as the computed to locate where the 'garbage' is coming from.
Since the number '9' does print the connection/baudrate seems to be correct. I would change '9' to 'End of loop' or similar text so that you KNOW what it means though.
You should also have a 'start of loop header'....
All these debugging starements can be deleted once you get the problem solved.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Wed Dec 28, 2016 8:46 am |
|
|
I repeat this comment already made:
"Old rule is before trying to do anything on a chip do a basic 'flash an LED' test, and make sure your clock settings are giving the correct oscillation speed. "
Also the sequence for a PIC should always be:
Include PIC processor file.
Any #device lines here.
Fuses
Clock statement
RS232 and any other setup lines
Then include libraries.
The #USE RS232 should not be done till _after_ the clock is set.
It looks like your PIC is _not_ clocking at the speed you think it is.
What is the stuff on the end of the processor include line?.
Code: |
#include <pic30f6014A.h>
#fuses HS, NOWDT, NOPROTECT, PUT64, BORV27
#use delay(clock=20000000) //20 MHz crystal code]
#use rs232(baud=9600,UART1,ERRORS)
#define LED PIN_B10
//then include any libraries and have your main code.
|
Doing it in any other order is dangerous. #USE RS232 _relies_ on the clock being setup. Library code _relies- on things like the UART already being setup. etc. etc.. |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
|
Posted: Thu Dec 29, 2016 6:25 am |
|
|
Hi Ttelmah,
Thanks for the advice. I already make the necessary changes. To display the adc values in floating point I added:
#include <float.h>
and make changes to:
float voltage [sizeof(channel)];
printf("%4.3f\r\n", voltage[value]);
Now the values display are in x.xxx.But I noticed all values are at 5.000V. I connect adc3 to 0V and it displays 0.061V. Is this normal? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Thu Dec 29, 2016 8:18 am |
|
|
First, your scaling is actually wrong. You don't want to divide by 255.
This is an old bit of 'history'. On the first 8bit ADC's, you had 256 'levels', and therefore 255 'risers' between them. So you had to divide by 255. Now early microprocessors made the PIC look like a 'mainframe', and this was hugely unwanted maths. So Texas launched an 8bit ADC with a different transfer function. On this, it behaved as if it actually had 257 'levels', but stopped at the 256'th, never giving the extra level. So using a 5v Vref, it would give an output of 255 about 30mV below the 5v level, and would not go any higher. This is the scaling used by 99.99% of modern ADC's. The key thing is it means that the correct division is 256, not 255, and it'll never actually 'get to' displaying the Vref voltage (5v).
Now, don't use float. Your initial approach was right, you were just getting it wrong (and also trying to go for more accuracy than the chip can give - especially since you are only working with 8bit from the ADC).
The scaling required is:
Code: |
ADC_value[value] = read_adc(); // ADC readings
voltage[value] = (( (int32)ADC_value[value] * 5000)+127)/256;
//Then
printf("%5.3Lw\r\n", voltage[value]);
|
However you really only need use *500, and %4.2. You are trying to display a digit more than you really 'have'...
The problem is that your maths was overflowing. Think about it. 5000*255 = 127500 - would this fit in an int16?.
However there is then the separate 'issue' of just how noise free your signals actually are, and how well the ground pins are routed. It sounds as if you have some mV of noise on one of the rails. Possibly the supply (since you are using this as the ADC reference).
The ADC actually transitions to giving a '1' out, just half a step from the zero voltage input. This is why there is the 127 offset in the above. So it behaves as if the bottom 'step' is just half width.
As a comment, even if using float, you don't want/need float.h. Float.h, provides the high level functions (like sin/cos etc.), the basic float maths does not want/need this.
Then separately, you are not telling the chip what to use as the Vref.
setup_adc_ports(ALL_ANALOG, VSS_VDD); //to use the supply as Vref
I suspect this is the reason for the current problem, it is probably selecting to use the Vref pins, and the ADC will not work properly without a Vref....
If you want accuracy though use a separate Vref. |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
|
Posted: Thu Dec 29, 2016 11:05 am |
|
|
Hi,
Thanks for the detail explanation. It takes time for me to understand. What if I change the adc to 12-bit adc? is this correct conversion for 12-bit ADC.
voltage[value] = (((int32)ADC_value[value] *5000)+2048)/4096; then the value will be 5000.5 which is incorrect.
Back to the original code with 8-bit ADC. Must +Vref (5.0V) -Vref (0V) connected at all times?
The output in the hyper terminal screen display as follows w/o connected the +Vref and -Vref.
--3--3--0
--1--Ã--0--0--0
--3--3--0
--3--3--0
--3--3--0
--3--3--0
--3--3--0
--3--3--0
--3--3--0
--3--3--0
--3--3--0
--3--3--0
--3--3--0
--3--3--0
9
--3--3--0
--3--3--0
--3--3--0
--1--Ã--0--0--0
--3--3--0
--3--3--0
--3--3--0
--3--3--0 |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9221 Location: Greensville,Ontario
|
|
Posted: Thu Dec 29, 2016 1:43 pm |
|
|
as I said in a previous reply....
The point is you NEED to display the raw data as well as the computed to locate where the 'garbage' is coming from.
right now you have NO idea WHY the numbers are bad
possible reasons are
0) EMI
1) bad sensor
2) bad wiring
3) bad PIC
4) bad code
5) it's Friday
really you HAVE to display the RAW ADC data
NO amount of code will fix a bad sensor.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Fri Dec 30, 2016 3:11 am |
|
|
That is the point of the VSS_VDD in this:
setup_adc_ports(ALL_ANALOG, VSS_VDD);
Tells the chip to use the supply as it's Vref.
However using the supply, you will be 'lucky' to get even 7bits of useable data. To use 12bits, requires a _really_ good stable and smooth Vref.
No, the value given will be 4999
4095 - maximum value from the ADC
*5000 = 20475000
+2048 = 20477048
/4096 = 4999 (integer).
Also look at:
<http://www.planetanalog.com/document.asp?doc_id=527531>
This shows the transfer function for an 'ideal' 3bit ADC. Note how the actual output value stops at '111', but the line of the graph is as if it went to 1000, but stops one bit below this. The PIC ADC behaves like this, except it is actually offset 0.5bit 'downwards'. |
|
|
arelone
Joined: 06 Dec 2015 Posts: 42
|
dspic30f6014a: UART1 & UART 2 communication |
Posted: Wed May 22, 2019 12:14 am |
|
|
Hi,
I have problem to communicate with UART1 in the dcpic30F6014a chip. I test attached code with UART 2 there is no issue. The issue is my circuit board is connected to the UART1 and if change it to UART2 it will be a tedious task and if possible I want to avoid it. I am using CCS C ver 5.0.1.0. What did I missed here? Any advice why I cannot get any data from UART1?
Regards
Arelone
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;
//const int8 channel_2[]=2,3,4,5,6,7,8,9,10,11,12,13,14;
//const int8 channel_3[]=3,4,5,6,7,8,9,10,11,12,13,14;
//const int8 channel_4[]=4,5,6,7,8,9,10,11,12,13,14;
//const int8 channel_5[]=5,6,7,8,9,10,11,12,13,14;
//const int8 channel_6[]=6,7,8,9,10,11,12,13,14;
//const int8 channel_7[]=7,8,9,10,11,12,13,14;
//const int8 channel_8[]=8,9,10,11,12,13,14;
//const int8 channel_9[]=9,10,11,12,13,14;
//const int8 channel_10[]=10,11,12,13,14;
//const int8 channel_11[]=11,12,13,14;
//const int8 channel_12[]=12,13,14;
//const int8 channel_13[]=13,14;
//const int8 channel_14[]=14;
int16 ADC_value1[sizeof(channel_1)];
//int16 ADC_value2[sizeof(channel_2)];
//int16 ADC_value3[sizeof(channel_3)];
//int16 ADC_value4[sizeof(channel_4)];
//int16 ADC_value5[sizeof(channel_5)];
//int16 ADC_value6[sizeof(channel_6)];
//int16 ADC_value7[sizeof(channel_7)];
//int16 ADC_value8[sizeof(channel_8)];
//int16 ADC_value9[sizeof(channel_9)];
//int16 ADC_value10[sizeof(channel_10)];
//int16 ADC_value11[sizeof(channel_11)];
//int16 ADC_value12[sizeof(channel_12)];
//int16 ADC_value13[sizeof(channel_13)];
//int16 ADC_value14[sizeof(channel_14)];
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]);
ADC_value1[value]=read_adc();
voltage[value] = (ADC_value1[value]/4096)*5000;
}
//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");
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19499
|
|
Posted: Wed May 22, 2019 1:18 am |
|
|
I'd have to say compiler.
I'm not sure if your compiler is 5.001 or 5.010, but in either case these are
'low beta' versions of the version 5 compiler (the former was 'alpha' at best). |
|
|
|
|
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
|