|
|
View previous topic :: View next topic |
Author |
Message |
kcj
Joined: 05 Oct 2011 Posts: 33
|
DAConverter PIC18F13k22 problem |
Posted: Fri Jan 20, 2012 11:03 am |
|
|
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
|
|
Posted: Fri Jan 20, 2012 8:24 pm |
|
|
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
|
|
Posted: Fri Jan 20, 2012 8:33 pm |
|
|
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: 19552
|
|
Posted: Sat Jan 21, 2012 4:12 am |
|
|
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
|
|
Posted: Sat Jan 21, 2012 11:48 am |
|
|
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
|
|
Posted: Sat Jan 21, 2012 9:45 pm |
|
|
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
|
|
Posted: Sat Jan 28, 2012 8:14 pm |
|
|
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
|
|
Posted: Sun Jan 29, 2012 7:20 am |
|
|
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
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
|
|
Posted: Mon Jan 30, 2012 9:22 am |
|
|
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
|
PWM modes |
Posted: Mon Jan 30, 2012 10:09 am |
|
|
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 |
|
|
|
|
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
|