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

DAConverter PIC18F13k22 problem

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
kcj



Joined: 05 Oct 2011
Posts: 33

View user's profile Send private message

DAConverter PIC18F13k22 problem
PostPosted: Fri Jan 20, 2012 11:03 am     Reply with quote

Hi All,

I have a question regarding setting up a digital to analogue pin. My project has involved measuring force using a flexiforce sensor and sending the data via xbee to be displayed on a 16x2LCD using PIC18f13k22.

I wanted to use PICO Data logger to record the voltage change as force is applied to the sensor. The data logger requires connecting a wire from the pic to it. The router xbee has a ADC converter built in that i am using to send force data to the Coordinator xbee. The xbee sends a 22 byte package, i am only interested in byte 20,21, which i have transmitted okay and can display on the LCD. But I wanted to convert the digital number into a voltage on a pic pin so i can connect it to the data logger. Trouble is, it turns out PIC8F13K22 does not have a DAC. I have already had all the circuits made, as this is an afterthought idea. I am fairly new to pics and am not sure if there is an alternative idea to solve the problem.

Is there any other way to convert the digital number to a voltage?

Thanks
kcj



Joined: 05 Oct 2011
Posts: 33

View user's profile Send private message

PostPosted: Fri Jan 20, 2012 8:24 pm     Reply with quote

Hi All,

I had an idea that maybe to use a pic with an DAC converter but with the same pins as PIC18F13k22. I have the circuit board made but have not soldered any components yet. Is there an easy way to tell what chips have specific features. ie UART, PWM...etc

Thanks
gpsmikey



Joined: 16 Nov 2010
Posts: 588
Location: Kirkland, WA

View user's profile Send private message

PostPosted: Fri Jan 20, 2012 8:33 pm     Reply with quote

Well, it depends on just what kind of output you want - that chip does have a DAC (although I have not played with it) -- see pg 243 (chapter 20 - "Voltage References") in the data sheet for the chip. It does look like there is a 32 step DAC that can be brought to the outside (but needs a buffer). Not exactly ultra-precision, but what the heck :-)

mikey
_________________
mikey
-- you can't have too many gadgets or too much disk space !
old engineering saying: 1+1 = 3 for sufficiently large values of 1 or small values of 3
Ttelmah



Joined: 11 Mar 2010
Posts: 19520

View user's profile Send private message

PostPosted: Sat Jan 21, 2012 4:12 am     Reply with quote

The other possibility, is to use a PWM output, and an integrator. Accuracy would be limited by the supply rail, and the droop in the driver transistors as you get closer to the rail. Obviously the larger the smoothing capacitor, the better the ripple, but the slower the response.

Best Wishes
kcj



Joined: 05 Oct 2011
Posts: 33

View user's profile Send private message

PostPosted: Sat Jan 21, 2012 11:48 am     Reply with quote

Hi GPS Mikey,

Yes it turns out it does have a DAC on pin 19,18 thanks. The digital numbers the xbee sends will correspond to a voltage range of 0.3v to 1.2v maximum. The CCS manual says to use command setup_DAC() and dac_write() to use the DAC but they are not included in the header file for that PIC. So when I compile I get an error. Is there a way to fix that? I know basic C language and what i know is from the manual.

Hi Ttelmah,

PIC18F13k22 from datasheet has 4 PWM outputs, i have already used 3 PWM pins with the LCD. I use pin5 RC4 to control the contrast with a low pass filter. using code
Code:
setup_timer_2(T2_DIV_BY_16,250,1);  //Timer2 enabled, prescaler of 1, PR1 = 250
setup_ccp1(CCP_PWM);         
set_pwm1_duty(90);

so 1 have 1 pin free, pin 6RC3.
I am just curious but how does the pic know to use this pin,as i have not defined it anywhere. is it in the header file. Also to use another PWM, ie pin6 would i use code

Code:

setup_timer_2(T2_DIV_BY_16,250,1);  //Timer2 enabled, prescaler of 1, PR1 = 250,
setup_ccp1(CCP_PWM);         
set_pwm1_duty(90);
setup_ccp1(CCP_PWM_PLUS_1);
set_pwm2_duty(num1);


num1 is the digital number, From my understanding the PWM is a digital signal switching on-off. The amount of time the signal is high is the pulse width. The time taken for high then low is the pulse period. If the pulse has a 50% cycle then is high 50% of the time the low 50%. I f you know the duty cycle controlled by set_pwm1_duty(90) in code and multiply it by the output high voltage then you know Vout.

So for me to use num1 in code for the duty cycle would work okay???.

I cant test this out using my pic this weekend due to me not having my kit here, so any additional knowledge would be great and any corrections as well.

Thanks
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Jan 21, 2012 9:45 pm     Reply with quote

Quote:
Yes it turns out it does have a DAC on pin 19,18 thanks.

The datasheet says it's only on pin 19. It's also not an official DAC.
It's part of the Comparator Vref module.

Quote:

The CCS manual says to use command setup_DAC() and dac_write() to
use the DAC but they are not included in the header file for that PIC. So
when I compile I get an error.

That's because it's not an official DAC. You must use the setup_vref()
function to control it. Also, you will need an opamp voltage follower
as a buffer on the Cvref output pin. Look at this diagram in the data
sheet for an example:
Quote:
FIGURE 20-2: VOLTAGE REFERENCE OUTPUT BUFFER EXAMPLE

Data sheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/41365E.pdf
If you need more help on the circuit, Google for: Opamp Voltage Follower

But unfortunately, CCS still doesn't have any support for setup_vref() for
the 18F13K22 even in vs. 4.128.

I think this substitute setup_vref() routine might work, if it's modified.
http://www.ccsinfo.com/forum/viewtopic.php?t=43155&start=6

Here is the modified version. I haven't tested this in hardware so I don't
know if works, but it has a good chance to work.
Code:

#include<18F13K22.h>
#fuses INTRC_IO,NOWDT,NOPLLEN
#use delay(clock=4M)
   
#define VREF_A0      0x20  // Output the DAC voltage on pin A0
#define VREF_ENABLE  0x80
// Note: Use 'FALSE' as parameter to disable the Vref.

void setup_vref(int8 value)
{
#byte REFCON0 = 0xFBA
#byte REFCON1 = 0xFBB
#byte REFCON2 = 0xFBC

REFCON0 = 0;      // Disable fixed Vref
REFCON1 = value & 0xA0;  // Enable/disable the Vref and the DAC OE pin.
REFCON2 = value & 0x1F;  // Set Vref level from 0-31 (0 to +5v)
}

//==============================================
void main()
{
// Example: Enable Vref voltage of 2.65 volts.
// Vref = 5v * (17/32) = 2.65v
setup_vref(VREF_ENABLE | VREF_A0 | 17);

// Example: Disable Vref voltage.
setup_vref(FALSE);

while(1);
}
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Sat Jan 28, 2012 8:14 pm     Reply with quote

Quote:
The only problem is I used a voltage follower circuit to buffer the output voltage from the pin, but the PICO data scope displays the square signal of the PWM.

I am new to electronics so I was wondering how do I convert the square wave into a readable wave for the data logger.


Does the PICO datalogger record time or voltage?

If you want the datalogger to see voltage you need a low pass filter to turn the PWM into a dc voltage. You have 3 basic options:

1) A multipole filter just below the PWM frequency. This costs space, money and power, but gives fast response to input changes.

2) 1 or 2 poles at a frequency much lower then the PWM frequency. This is likely cheaper and smaller but gives slow response to input changes.

3) A few poles of filtering and synchronizing the PICO logger digitized to the PWM clock. This is good only if the PICO logger clock is accessible.
_________________
The search for better is endless. Instead simply find very good and get the job done.
kcj



Joined: 05 Oct 2011
Posts: 33

View user's profile Send private message

PostPosted: Sun Jan 29, 2012 7:20 am     Reply with quote

Hello SherpaDoug,


I am using the PICO datalogger to record voltage change against time. I have no problem recording the output voltage from the router xbee circuit, it is a line on the graph that changes when force is applied to the sensor.

But the data recorder wont pick up the PWM signal the pic produces.
A low pass filter just below the PWM frequency u say. I am not quite sure how i would calculate that using a software PWM and timer 1 i uses to calculate the RCvalues. Any ideas?
Here is my code- I posted it in another thread which is locked now. That thread had the same subject as this one..sorry Rolling Eyes
Code:

#include <18f13k22.h>
#fuses HS,NOBROWNOUT,NOWDT,PUT,STVREN,NOFCMEN,NOMCLR,NOXINST,NOPLLEN   
#use delay(clock=20M)                           // setup clock timer
#use rs232(baud=9600,UART1,ERRORS)              //Hardware PIC18F UART setup

#include <Flex_lcd.c>

#define preload 65458
#define PICO1 pin_A2
#define PICO2 pin_C0

//**************************************************************************************************
//Global variables
//**************************************************************************************************


int sensor1_duty,sensor2_duty;
int Intcount,i;
int buffer [24];
int byte1,byte11;
int data19,data20,data21,data22;
int16 num1,num2,num3,num4;
float sensor1,sensor2;
float volts1,volts2;

//************************************************************************************************

#INT_TIMER1
void timer_irq()
{
    set_timer1(preload);
   
   if (Intcount < 255)
    {     
      if (Intcount == sensor1_duty)
       {
         output_low(PICO1);
       }   
      if (Intcount == sensor2_duty)
       {
         output_low(PICO2);
       }   
    }
   
   else if(Intcount == 255)
    {
      Intcount = 0;
      output_high(PICO1);
      output_high(PICO2);   
    }   
    Intcount++;
}

void main()
{

lcd_init();
  //Timer 2 used to create a PWM to control contrast on LCD
  setup_timer_2(T2_DIV_BY_16,250,1);  //Timer2 enabled, PR2 = 250, prescaler of 1
  setup_ccp1(CCP_PWM);     
  set_pwm1_duty(90);
  //Timer 1 interupt used to create software PWM
  setup_timer_1(T1_INTERNAL | T1_DIV_BY_4);
  enable_interrupts(INT_TIMER1);
  enable_interrupts(GLOBAL);
 
while(1)
  {   
     if (kbhit(true))
    {       
         //retrieves the bytes   
          byte1 = getc();         

            //First byte in a 22byte packet xbee sends is always 0x7E
            if (byte1 == 0x7E)
            {
                //reads the 24 bytes
                 for(i=0;i<24;i++)
                    {                 
                      byte1 = getc();
                      buffer[i]=byte1;
                    } 
                      byte11=buffer[11];
            }
           
                     //LSB of Router1 64 Bit address(unique to router1)00 13 A2 00 40 71 6E EF
                     if (byte11 == 0x71)
                         {
                         //buffer 20-24 contain force data for 1-2 sensors
                           data19=buffer[20];
                           data20=buffer[21];
                           data21=buffer[22];
                           data22=buffer[23];
                                         
                         //converts the 10 bit number in integer
                           num1=((data19*256)+data20);
                           num2=((data21*256)+data22);
                           num3=num1/10;
                           num4=num2/10;

                         //Formulea calculated in excell relating force data to volts                 
                         //and bytes xbee sends       
                          volts1=(0.0012*num1);                   
                          volts2=(0.0012*num2);
                                             
                          printf(lcd_putc, "\fSensor1  %4.2f\n", volts1); 
                          printf(lcd_putc, "\Sensor2  %4.2f\n", volts2);                 
                          sensor1_duty = num3;
                          sensor2_duty = num4;
                          Intcount = 0;                     
                         }   
    }
      else
    printf(lcd_putc, "\fNo Connection\n");
     delay_ms(400);   
  }
}

Thanks
kcj



Joined: 05 Oct 2011
Posts: 33

View user's profile Send private message

PostPosted: Mon Jan 30, 2012 9:22 am     Reply with quote

Hi All,

I have a general question regarding PWM and CCP. I am using PIC 18F13k22 which has one CCP1 but 4 PWM pins, namely P1A,P1B,P1C and P1D, can each of the pin be used as a PWM output.

The header file has quite a few commands namely
Code:

////////////////////////////////////////////////////////////////// CCP
// CCP Functions: SETUP_CCPx, SET_PWMx_DUTY
// CCP Variables: CCP_x, CCP_x_LOW, CCP_x_HIGH
// Constants used for SETUP_CCPx() are:

#define CCP_PWM                         0xC
#define CCP_PWM_PLUS_1                  0x1c 
#define CCP_PWM_PLUS_2                  0x2c
#define CCP_PWM_PLUS_3                  0x3c
#word   CCP_1       =                   getenv("SFR:CCPR1L")
#byte   CCP_1_LOW   =                   getenv("SFR:CCPR1L")
#byte   CCP_1_HIGH  =                   getenv("SFR:CCPR1H")
// OR in one of the following to use timer 3 with a CCP unit
#define  T3_CCP2       0x8

// The following should be used with the ECCP unit only (or these in)
#define CCP_PWM_H_H                     0x0c
#define CCP_PWM_H_L                     0x0d
#define CCP_PWM_L_H                     0x0e
#define CCP_PWM_L_L                     0x0f

#define CCP_PWM_FULL_BRIDGE             0x40
#define CCP_PWM_FULL_BRIDGE_REV         0xC0
#define CCP_PWM_HALF_BRIDGE             0x80

#define CCP_SHUTDOWN_ON_COMP1           0x100000
#define CCP_SHUTDOWN_ON_COMP2           0x200000
#define CCP_SHUTDOWN_ON_COMP            0x300000
#define CCP_SHUTDOWN_ON_INT0            0x400000
#define CCP_SHUTDOWN_ON_COMP1_INT0      0x500000
#define CCP_SHUTDOWN_ON_COMP2_INT0      0x600000
#define CCP_SHUTDOWN_ON_COMP_INT0       0x700000

#define CCP_SHUTDOWN_AC_L               0x000000
#define CCP_SHUTDOWN_AC_H               0x040000
#define CCP_SHUTDOWN_AC_F               0x080000

#define CCP_SHUTDOWN_BD_L               0x000000
#define CCP_SHUTDOWN_BD_H               0x010000
#define CCP_SHUTDOWN_BD_F               0x020000

#define CCP_SHUTDOWN_RESTART            0x80000000 

#define CCP_PULSE_STEERING_A            0x01000000
#define CCP_PULSE_STEERING_B            0x02000000
#define CCP_PULSE_STEERING_C            0x04000000
#define CCP_PULSE_STEERING_D            0x08000000
#define CCP_PULSE_STEERING_SYNC         0x10000000

#word   CCP_2       =                   getenv("SFR:CCPR2L")
#byte   CCP_2_LOW   =                   getenv("SFR:CCPR2L")
#byte   CCP_2_HIGH  =                   getenv("SFR:CCPR2H")
#word   CCP_3       =                   getenv("SFR:CCPR3L")
#byte   CCP_3_LOW   =                   getenv("SFR:CCPR3L")
#byte   CCP_3_HIGH  =                   getenv("SFR:CCPR3H")
#word   CCP_4       =                   getenv("SFR:CCPR4L")
#byte   CCP_4_LOW   =                   getenv("SFR:CCPR4L")
#byte   CCP_4_HIGH  =                   getenv("SFR:CCPR4H")

Which can be used, i have looked in the manual and other sources but have yet to find a meaning for the function of most of these codes? Is there another source that has a descriptive meaning of them?

The main question is how do you individually control a PWM PIN. i used code
Code:

setup_timer_2(T2_DIV_BY_16,250,1);  //Timer2 enabled, PR2 = 250, prescaler of 1
  setup_ccp1(CCP_PWM);     
  set_pwm1_duty(90);

which changed P1A very well. I have tried many different varieties to change P1B..etc but have not been successful.

Thanks
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PWM modes
PostPosted: Mon Jan 30, 2012 10:09 am     Reply with quote

Quote:

I have a general question regarding PWM and CCP. I am using PIC 18F13k22 which has one CCP1 but 4 PWM pins, namely P1A,P1B,P1C and P1D, can each of the pin be used as a PWM output.


The microchip data sheet tells you EXACTLY what you can, and cannot, do with the 4 PWM outputs. Which outputs are active depends on the selected mode. Essentially the active outputs all run at the same frequency, with mode dependent duty ratios.

Mike
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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