|
|
View previous topic :: View next topic |
Author |
Message |
Sam_40
Joined: 07 Jan 2015 Posts: 127
|
ECCP1 setup for PIC18F4685 [SOLVED] |
Posted: Thu Jun 07, 2018 8:10 pm |
|
|
Hello guys,
I have been working on this project for a while :( I am trying to drive a Half-Bridge Output Driving a Full-Bridge Circuit. The drive is 4 IGBTs like the PIC datasheet PDF page 180 (FIGURE 16-5: EXAMPLES OF HALF-BRIDGE OUTPUT MODE APPLICATIONS.)
The IGBT datasheet shows the MAX t-off and t-fall is 2uS however in the circuit I have (measuring with oscilloscope) from the output falling edge to the IGBT falling edge is about 2.3uS. So I think 4uS is Okay for the dead band? I thought about using smaller than 1mHz or bigger but 1MHz seems to be the best oscillator for this project?
First question: I have two buttons connected RB0 (to increase) and RB1 (to decrease) the frequency? since the frequency can't be 61, 62, 63....400 then using the PR2 8 values above or the closest (if its going to make the duty cycle math easier) is what I am after.
Second question:I also failed to be able to adjust the Duty Cycle of the PWM, I am aware of the CCS function for PWM duty percent, I could not use it successfully.
I only could do that in hard code and I fail to make it adjustable and maintained the set duty cycle while changing the frequency.
To adjust the Duty Cycle I have two buttons connected RB2 (to increase) and RB3 (to decrease) the duty cycle?
Third question: I am using PCM programmer flex_lcd to drive 16x2 LCD
I need to print the Frequency value set in the PIC on first row and the duty cycle set in the PIC on the second row.
I am adjusting the output machine current via SCRs prior to the Main transformer primary coil, so the only thing this PIC has to do is set the frequency, duty cycle and display both of these values.
I was able to make all the above individually working (frequency, duty cycle, buttons, lcd) but could not make them all work together like it should.
I have the board assembled and all the hardware and connection is Okay.
I have tested the oscillator, frequency output A and B and all the IGBTs firing, all good.
Your help would be appreciated,
Code: | #include<18f4685.h>
#fuses EC_IO,NOWDT,NOPROTECT,NOLVP
#use delay(clock=1000000)
#include "flex_lcd.c"
#define P1A PIN_D4
#define P1B PIN_D5
#define P1C PIN_D6
#define P1D PIN_D7
//The ECCP1DEL (Dead-Band Delay) is at address FB7h
#bit ECCP1DEL_bit7 = 0xFB7.7 //PWM Restart Enable bit
#bit ECCP1DEL_bit6 = 0xFB7.6 //PDC6:PDC0: PWM Delay Count bits
#bit ECCP1DEL_bit5 = 0xFB7.5
#bit ECCP1DEL_bit4 = 0xFB7.4
#bit ECCP1DEL_bit3 = 0xFB7.3
#bit ECCP1DEL_bit2 = 0xFB7.2
#bit ECCP1DEL_bit1 = 0xFB7.1
#bit ECCP1DEL_bit0 = 0xFB7.0
//The ECCP1CON (ENHANCED CAPTURE/COMPARE/PWM CONTROL REGISTER)
//is at address FBAh
#byte ECCP1CON = 0xFBA
void setup_eccp1(int8 value)
{
ECCP1CON = value;
switch(value & 0xC0)
{
case CCP_PWM_FULL_BRIDGE:
case CCP_PWM_FULL_BRIDGE_REV:
output_low(P1A);
output_low(P1B);
output_low(P1C);
output_low(P1D);
break;
case CCP_PWM_HALF_BRIDGE:
output_low(P1A);
output_low(P1B);
break;
default:
output_low(P1A);
}
}
//The ECCPR1L (Enhanced Capture/Compare/PWM Register 1 Low Byte)
//is at address FBBh
#byte ECCPR1L = 0xFBB
void set_eccp1_duty(int8 value)
{
ECCPR1L = value;
}
void main()
{
setup_eccp1(CCP_PWM_HALF_BRIDGE | CCP_PWM_H_H);
setup_timer_2(T2_DIV_BY_16, 255, 1);
ECCP1DEL_bit0 = 1; //Set the bit0 for 1 instruction cycle (4uS)
set_eccp1_duty(128); // 50% duty cycle
while(true);
} |
Thank you,
Last edited by Sam_40 on Tue Jun 26, 2018 7:40 pm; edited 2 times in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Jun 08, 2018 2:58 pm |
|
|
You need a main loop. This is one possible outline of what your main
loop should look like:
Code: |
while(TRUE)
{
current_sw_values = read_switches();
if(current_sw_values != previous_sw_values)
{
// calculate which switches have been pressed down, if any.
}
if(any switches pressed) // If any switches were pressed, do this:
{
// Inc or Dec variables based on which switches were pressed.
// Calculate the desired PWM freq and duty cycle.
// Poll the Timer2 interrupt flag until it is set. Then update
// the PWM frequency and duty cycle.
// Update new PWM freq and duty cycle values displayed on lcd.
}
previous_sw_values = current_sw_values;
delay_ms(10); // Debounce delay for switches
} |
|
|
|
Sam_40
Joined: 07 Jan 2015 Posts: 127
|
|
Posted: Thu Jun 14, 2018 6:00 am |
|
|
Thank you PCM Programmer for you reply,
I have been trying to make my project work, I also tried to use your suggestion into my project, I also did some more search for the last few days, no luck so far,
The best I could do was, setup a switch/case statement to set timer2 with the required PR2 for specific frequency and for each of the 8 cases setup variable so I can use to calculate the duty cycle like:
Code: |
case 1:
setup_timer_2(T2_DIV_BY_16, 255, 1);
value = 256;
break; |
However I am having problem with my work flow in CCS C compiler, I would like to ask you and the forum members to help me out, what I need is a functional demo program with these requirments:
* 1MHz crystal oscillator, four switches (RB0-RB4), flex_lcd to drive the 16X2 LCD.
* Read the switches (two for variable X and two for vriable Y).
* Variable X range (1-10).
* Variable Y range (50-80).
* Display X on first line and Y on second line on the LCD.
The above demo code is something I can do, however in your reply, you suggested to me a specific way to read the old switches value and new switches value. I need to see it done in an efficient, correct, simple way so I can implement it in this project and future projects.
Thank you, |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jun 14, 2018 12:07 pm |
|
|
Sam_40 wrote: |
In your reply, you suggested to me a specific way to read the old
switches value and new switches value. I need to see it done in an
efficient, correct, simple way so I can implement it in this project and
future projects.
|
The button() function will handle this for you. This link contains the
button() function and a test program to show how to use it.
http://www.ccsinfo.com/forum/viewtopic.php?t=23837 |
|
|
Sam_40
Joined: 07 Jan 2015 Posts: 127
|
|
Posted: Sat Jun 16, 2018 12:03 pm |
|
|
Hello,
I am having a problems, please help. either P1B high and P1A low, LCD in disco mode , duty cycle auto reset to 50% or 75%. However I can see 80Hz to 400Hz as pressing B0 and B1. No 61Hz? B2 and B3 not working as expected?
Thank you
Last edited by Sam_40 on Tue Jun 26, 2018 7:36 pm; edited 2 times in total |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jun 16, 2018 2:33 pm |
|
|
Quote: | delay_ms(10); /* To decrease DutyCycle */
printf(lcd_putc,"\fFrequency: %u\n", val);
printf(lcd_putc,"DutyCycle: %0.2f", per); |
You're updating the lcd way too often. You don't need to update it
every 10 ms. You need to update if you push a button. So,
You could move those two lines to be at the end (inside the braces) of
each if() statement.
- Or -
You could set a "button pushed" flag variable to TRUE inside each if()
statement. Then add a if() test to see if it's TRUE at the end of the while()
statement, and if TRUE, then execute those two lines. Also, add a line to
clear the flag.
If you don't completely understand method #2, then do #1.
I don't have time right now to do anymore. I have an appt to go to. |
|
|
Sam_40
Joined: 07 Jan 2015 Posts: 127
|
|
Posted: Sat Jun 16, 2018 3:00 pm |
|
|
PCM programmer,
No rush, I did try to put the 2 printf under each of the 4 if statements prior to my last post with no luck.
Please, whenever you have time review my last code and point me in the right direction,
Good luck with your appointment.
Thank you, |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sat Jun 16, 2018 11:41 pm |
|
|
A lot of your problems are caused by using variable types that are too
small. For example, in the code below you are writing 300 or 400
into an int8 variable, but an int8 can only hold from 0 to 255. It will
truncate it and instead of 300, 'val' will be set to only 44.
Quote: |
unsigned int8 frq;
unsigned int8 pr2;
int8 val;
int8 dty=128;
float per=0.5;
.
.
.
case 10:
setup_timer_2(T2_DIV_BY_16, 51, 1);/*300Hz*/
pr2=52;
val=300;
break;
default:
setup_timer_2(T2_DIV_BY_16, 38, 1); /*400Hz*/
pr2=39;
val=400;
break;
|
To fix this and related problems, change the following variables to int16,
as shown in bold below:
Quote: | unsigned int8 frq;
unsigned int16 pr2;
int16 val;
int8 dty=128;
float per=0.5; |
I was able to make the lcd work fine by implementing the "button pressed"
test. Add the lines shown in bold below:
Quote: |
void main()
{
int8 button_pressed = FALSE;
|
Quote: |
// To decrease DutyCycle
if(button(PIN_B3, 0, 50, 10, B3, 1))
{
per -= .05;
if(per <= 0.50)
{
per = 0.50;
}
dty = pr2 * per;
set_pwm1_duty(dty);
button_pressed = TRUE; // Do this in all four if() statements
}
delay_ms(10);
if(button_pressed)
{
printf(lcd_putc,"\fFrequency: %lu\n", val);
printf(lcd_putc,"DutyCycle: %0.2f", per);
button_pressed = FALSE;
}
|
Remember to add button_pressed = TRUE to the bottom of each if() statement.
Why you are using substitute routines to do the ECCP setup ?
What is your CCS compiler version ? Look at the top of the .LST file.
You will see a 4-digit number (only). List of current versions:
http://www.ccsinfo.com/devices.php?page=versioninfo |
|
|
Sam_40
Joined: 07 Jan 2015 Posts: 127
|
|
Posted: Sun Jun 17, 2018 7:22 am |
|
|
Everything is now working except:
1- the two if statements for the button for the duty cycle. When press B2 or B3, the number jumps by itself from 0.5 to 0.75 or .80 then automatically goes to 0.50? I have 10k pull ups on the B0, B1, B2 and B3. Is there anything wrong with my math or settings?
2- The LCD still flickering (the second line), I did all the changes you suggest in your last post.
3- When I started on this project, I couldn't get the dead band to work. I saw one of your posts while searching showing:
Code: | setup_ccp1(CCP_PWM_HALF_BRIDGE | CCP_PWM_H_H, 5); |
The 5 was for the dead band, But I could not make it work? so that is why I am using substitute routines. How can I make it work without the substitute routines? I can't see anything in the PIC header file regarding the dead band? I am only need the half bridge settings.
4- Its 5.021
Thank you PCM programmer, |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Sun Jun 17, 2018 8:35 am |
|
|
re: 'jumping'. That could be explained by 'switch bounce'. Mechanical switches are very bad for bounce (several 1-0-1-0 transitions). You should add a small cap, say .1 mfd across the switch and test.
It's always best to get the hardware 'right' before trying to correct with a 'software solution'.
Jay |
|
|
Sam_40
Joined: 07 Jan 2015 Posts: 127
|
|
Posted: Sun Jun 17, 2018 10:45 am |
|
|
I was able to fix the duty cycle buttons from
to
Code: |
if(per >= 0.80) /* This was the problem */
|
That also fixed the LCD
My new questions:
- When I started on this project, I couldn't get the dead band to work. I saw one of your posts while searching showing:
Code: |
setup_ccp1(CCP_PWM_HALF_BRIDGE | CCP_PWM_H_H, 5);
|
The 5 was for the dead band, But I could not make it work? so that is why I am using substitute routines. How can I make it work without the substitute routines? I can't see anything in the PIC header file regarding the dead band? I am only need the half bridge settings.
How can I improve my code? I thought about add the use fast io and turn all the unused pin to low out puts. Is that needed or does the compiler take care of that? Also is there any changes I need to make to make my code more effecient?
Thank you |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 17, 2018 11:16 am |
|
|
Sam_40 wrote: |
1- the two if statements for the button for the duty cycle. When press B2
or B3, the number jumps by itself from 0.5 to 0.75 or .80 then
automatically goes to 0.50? I have 10k pull ups on the B0, B1, B2 and B3.
Is there anything wrong with my math or settings?
|
It looks to me like another bug in your code. Below, you are adding .05
to 'per' each time. So you should be checking for a limit violation if
the result gets too high. But you've got "less than or equal to" test below.
Quote: |
/* To increase DutyCycle */
if(button(PIN_B2, 0, 50, 10, B2, 1))
{
per += .05;
if(per <= 0.80)
{
per = 0.80;
}
dty = pr2 * per;
set_eccp1_duty(dty);
} |
It really should be this:
If 'per' gets up to 0.80, then don't let it go any higher.
Sam_40 wrote: |
2- The LCD still flickering (the second line).
|
It could be a combination of the screen clearing each time, combined
with the slow PIC clock speed. This is just a guess. So get rid of the
"\f", and add enough spaces at the end of each line to ensure that all
previous text is over-written when you re-write the two lines. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9244 Location: Greensville,Ontario
|
|
Posted: Sun Jun 17, 2018 11:18 am |
|
|
re: improve code...
Use integers or scaled integers instead of floating point variables ! Your code will be a lot smaller AND be a LOT faster( 8-10x or more).
Using fast_io() will make for slightly smaller code and a little bit faster, though be 100% sure of the directions of the I/O pins especially when you make changes(like adding an LED or remapping the LCD pins). with standard_IO() the compiler works out all the 'details' so stuff always works.
Add comments to every line of code. If you code in assembler you'll know why. Heck, 3 months from nw you'll wonder WHY did I do this ?? or WAHT does that mean? Comments are 'free', ie: they do not take up codespace.
Jay |
|
|
Sam_40
Joined: 07 Jan 2015 Posts: 127
|
|
Posted: Sun Jun 17, 2018 11:45 am |
|
|
PCM programmer,
I think you and I were typing at the same time, I did discover my mistake with <= and I did change it to >=, please see my reply prior to yours. The LCD is working fine now.
Would you please see my question regarding the setup_ccp1
I really appreciate all of your help.
Jay,
Thank you for the input, would you please elaborate on
Quote: |
Use integers or scaled integers instead of floating point variables !
|
How can I use it in my code? I only used the float as I thought it made my math easier?
I also would like to wish all the fathers on this forum a Happy Father Day! |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Sun Jun 17, 2018 12:25 pm |
|
|
It looks like deadband delay is not supported by CCS vs. 5.078 for the
18F4685. It should be. I wonder if CCS read this note in the data sheet
and mistakenly took it out for the 18F4685 as well:
Quote: |
Note: Programmable dead-band delay is not
implemented in PIC18F2682/2685 devices
with standard CCP1 modules. |
So it looks like you have to do it with the extra routines.
Regarding floating point execution time, I just ran the MPLAB vs. 8.92
stopwatch program on this line, with the clock set for 1 MHz:
It takes 960 usec. That's about 1 ms per button push.
Since you already have a 10 ms loop delay, 1 ms more for floating point
really won't matter. Save your time for something else.
Last edited by PCM programmer on Sun Jun 17, 2018 12:33 pm; edited 1 time in total |
|
|
|
|
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
|