CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

UART -dspic30F6014a
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
arelone



Joined: 06 Dec 2015
Posts: 42

View user's profile Send private message

UART -dspic30F6014a
PostPosted: Mon Dec 26, 2016 11:20 pm     Reply with quote

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: 19568

View user's profile Send private message

PostPosted: Tue Dec 27, 2016 12:41 am     Reply with quote

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: 9255
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Dec 27, 2016 6:40 am     Reply with quote

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: 19568

View user's profile Send private message

PostPosted: Tue Dec 27, 2016 6:48 am     Reply with quote

Actually Temtronic, that is not the case. Very Happy

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: 9255
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Tue Dec 27, 2016 7:07 am     Reply with quote

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

View user's profile Send private message

PostPosted: Wed Dec 28, 2016 5:19 am     Reply with quote

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: 9255
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Dec 28, 2016 6:27 am     Reply with quote

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: 19568

View user's profile Send private message

PostPosted: Wed Dec 28, 2016 8:46 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Dec 29, 2016 6:25 am     Reply with quote

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: 19568

View user's profile Send private message

PostPosted: Thu Dec 29, 2016 8:18 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Dec 29, 2016 11:05 am     Reply with quote

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: 9255
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Thu Dec 29, 2016 1:43 pm     Reply with quote

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: 19568

View user's profile Send private message

PostPosted: Fri Dec 30, 2016 3:11 am     Reply with quote

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

View user's profile Send private message

dspic30f6014a: UART1 & UART 2 communication
PostPosted: Wed May 22, 2019 12:14 am     Reply with quote

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: 19568

View user's profile Send private message

PostPosted: Wed May 22, 2019 1:18 am     Reply with quote

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).
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
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