View previous topic :: View next topic |
Author |
Message |
baris_akinci
Joined: 10 Mar 2016 Posts: 17 Location: Ankara
|
pwm and normal output on same pin for 16f628a |
Posted: Thu Mar 10, 2016 2:49 am |
|
|
Hello CCS forum members, sorry maybe this is simple question but I couldn't find a solution while although I searched for days.
I want to make "if condition" program. I mean when a signal comes from RF line, the state will move to the other one. I have done until here but I couldn't achive PWM part I tried both PWM (ON/OFF in us) and CCP module but failed. If I am missing, please let me now.
I use -INT OSC, - same LED for normal output and pwm output
Code: |
#include <16F628A.h>
#FUSES INTRC_IO, NOWDT, NOPUT, NOMCLR, NOBROWNOUT, NOLVP
#use fast_io(a)
#use fast_io(b)
#use delay(internal=4000000)
#use rs232(baud=2400,xmit=PIN_B2,rcv=PIN_B1,ERRORS)
#priority rda,rtcc
#define LED1 pin_a0
#define LED2 pin_a1
#define LED3 pin_a2
#define LED4 pin_a3
char c[10];
int durum=0;
int index = 0;
int inc=0;
int kapat=0;
int aktif=0;
int second=0;
int minute=15;
int hour=0;
#int_timer0
void second_counter(void)
{
set_timer0(57);
int bytee;
if(bytee==20)
{
second++;
bytee=0;
if(second==60)
{
minute++;
if(minute % 5 ==0)
second =1;
else
second=0;
if(minute==60)
{
hour++;
second=25;
minute=0;
if(hour==24)
hour=0;
}
}
}
else
bytee++;
}
#int_rda
void RDA_isr(void)
{
disable_interrupts(int_rda); //RDA kesmesi routine'inde mecburi olarak yazılması gerekiyor, haberleşme devamı olduğu için sonsuz kesme olmaması adına yapılır
if(durum == 0)
{
c[index] = getch();
if(c[index] =='X') //senkron verisi geldi mi? //şifreleme olarak 0xA1, 0xD1, tarzında da gönderilebilir,alıcıda bu şekilde aranabilir daha sağlıklı filtremelem yapılabilir
{
durum = 1;
index++; // geldiyse komut verisi için indexi arttır.
}
}
if(durum == 1)
{
c[index] = getch();
if(c[index] =='A') //komut geldi mi
{
inc++;
durum = 0; //işlem bitince yeniden senkron aramak için durumu 0 la.
}
if (c[index] == 'B')
{
inc=inc-1; // başka bi işlem yap
durum = 0;
}
if (c[index] == 'K')
{
kapat++; // başka bi işlem yap
durum = 0;
}
if (inc==6) {aktif=1;}
else aktif=0;
index = 0; // komut işlendi indexi 0 yapki senkron verisini dizinin 1.elemanına alabilesin.
}
enable_interrupts(int_rda); //
}
void sim1() {
// police light
int i=0;
output_high(LED1);output_high(LED2); for(i=0;i<70;i++) {delay_ms(1); }
output_low(LED1);output_low(LED2); for(i=0;i<70;i++) {delay_ms(1); }
output_high(LED1);output_high(LED2); for(i=0;i<70;i++) {delay_ms(1); }
output_low(LED1);output_low(LED2); for(i=0;i<70;i++) {delay_ms(1); }
output_high(LED1);output_high(LED2); for(i=0;i<70;i++) {delay_ms(1); }
output_low(LED1);output_low(LED2); for(i=0;i<200;i++) {delay_ms(1); }
output_high(LED3);output_high(LED4); for(i=0;i<70;i++) {delay_ms(1); }
output_low(LED3);output_low(LED4); for(i=0;i<70;i++) {delay_ms(1); }
output_high(LED3);output_high(LED4); for(i=0;i<70;i++) {delay_ms(1); }
output_low(LED3);output_low(LED4); for(i=0;i<70;i++) {delay_ms(1);}
output_high(LED3);output_high(LED4); for(i=0;i<70;i++) {delay_ms(1); }
output_low(LED3);output_low(LED4); for(i=0;i<200;i++) {delay_ms(1); }
}
void sim2() {
// LED animation 2
int b=0;
output_high(LED1); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED1); for(b=0;b<50;b++){delay_ms(1); }
output_high(LED2); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED2);for(b=0;b<50;b++){delay_ms(1); }
output_high(LED3); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED3);for(b=0;b<50;b++){delay_ms(1); }
output_high(LED4); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED4);for(b=0;b<50;b++){delay_ms(1); }
for(b=0;b<150;b++){delay_ms(1); }
output_high(LED4); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED4);for(b=0;b<50;b++){delay_ms(1); }
output_high(LED3); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED3);for(b=0;b<50;b++){delay_ms(1); }
output_high(LED2); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED2);for(b=0;b<50;b++){delay_ms(1); }
output_high(LED1); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED1);for(b=0;b<50;b++){delay_ms(1); }
}
void sim3() {
// LED animation 3
int h=0;
for(h=0;h<250;h++){delay_ms(1); }
output_toggle(LED1);output_toggle(LED2);output_toggle(LED3);output_toggle(LED4);
for(h=0;h<250;h++){delay_ms(1); }
output_toggle(LED1);output_toggle(LED2);output_toggle(LED3);output_toggle(LED4);
}
void sim4() {
// LED animation 4
int a=0;
output_high(LED1); output_high(LED2);output_low(LED3);output_low(LED4);
for(a=0;a<250;a++){delay_ms(1); }
output_low(LED1); output_low(LED2);output_high(LED3);output_high(LED4);
for(a=0;a<250;a++){delay_ms(1); }
}
void sim5() {
// LED animation 5
int d=0;
output_high(LED1); output_high(LED3);output_low(LED2);output_low(LED4);
for(d=0;d<250;d++){delay_ms(1); }
output_low(LED1); output_low(LED3);output_high(LED2);output_high(LED4);
for(d=0;d<250;d++){delay_ms(1); }
}
void sim6() {
// PWM code will be here, fade ON/OFF slowly
}
void main()
{
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
set_timer0(60);
enable_interrupts(int_timer0);
enable_interrupts(int_rda);
enable_interrupts(GLOBAL);
set_tris_a(0x00);
while(TRUE)
{
if(inc==1) {
while(inc==1) {sim1();}
enable_interrupts(int_rda); // interrupt işleminde kapattığımız kesmeyi burada tekrardan aktif ediyoruz
}
else if(inc==2) {
while (inc==2){sim2();}
enable_interrupts(int_rda);
}
else if(inc==3) {
while (inc==3){sim3();}
enable_interrupts(int_rda);
}
else if(inc==4) {
while (inc==4){sim4();}
enable_interrupts(int_rda);
}
else if(inc==5) {
while (inc==5){sim5();}
enable_interrupts(int_rda);
}
else if (inc==6) {
while (inc==6) {sim6(); }
enable_interrupts(int_rda);
}
else if(inc==7) inc=1;
else if(inc==0) inc=6;
else inc=inc;
}
}
|
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Mar 10, 2016 3:11 am |
|
|
Lots of little comments first:
bytee in the interrupt should be _static_. Otherwise it can potentially be overwritten (in fact the compiler will not, but it is bad programming).
Don't disable INT_RDA in the serial interrupt. Pointless. All interrupts are disabled by the hardware.
It's very inefficient to access the byte each time from an indexed array. It takes typically about 15 instructions to access an array element, but only one or two to access a simple variable. So your code will be smaller and faster, if you just code like:
Code: |
#int_rda
void RDA_isr(void)
{
int8 latest;
latest=getch();
c[index]=latest;
if (durum==0)
{
if (latest=='X')
{
durum=1;
index++;
}
//etc..
|
With the five locations you access the array in the routine, this will save about 50 instructions!. Also makes the interrupt faster as well.
One other comment on the interrupt. Add code to ensure that index can never go beyond 9. Otherwise if (for instance), you accidentally received eleven 'X' characters, you will be overwriting other variables.
Then on your problem. Why bother?.....
Setup the PWM once in the main code. Then if you want the output to be 'off', just code the duty as 0, while if you want it 'on' just code the duty as 1024.
So:
Code: |
#define PWM_HIGH set_pwm1_duty(1024)
#define PWM_LOW set_pwm1_duty(0)
//Then at start of main
setup_CCP1(CCP_PWM);
setup_timer2(T2_DIV_BY_1,249,1); //whatever suits your timing
PWM_LOW;
//then to turn the pin high just use
PWM_HIGH;
|
|
|
|
baris_akinci
Joined: 10 Mar 2016 Posts: 17 Location: Ankara
|
pwm and normal output on same pin for 16f628a |
Posted: Thu Mar 10, 2016 3:30 am |
|
|
Ttelmah wrote: | Lots of little comments first:
Then on your problem. Why bother?.....
Setup the PWM once in the main code. Then if you want the output to be 'off', just code the duty as 0, while if you want it 'on' just code the duty as 1024.
So:
Code: |
#define PWM_HIGH set_pwm1_duty(1024)
#define PWM_LOW set_pwm1_duty(0)
//Then at start of main
setup_CCP1(CCP_PWM);
setup_timer2(T2_DIV_BY_1,249,1); //whatever suits your timing
PWM_LOW;
//then to turn the pin high just use
PWM_HIGH;
|
|
thank you for instant reply and analysing my project. I will definitelly take into account your advices. but, as for my question, there are 4 output as you see and this outputs are working seperatelly sometimes in which animation they are. your suggestion is just for one output for all 4 outputs. but I need seperated outputs at the same time. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Mar 10, 2016 4:57 am |
|
|
OK. It should work normally if you disable the PWM.
So:
setup_CCP1(CCP_OFF);
The reason you are having problems, is because you are specifying fast_io, which then means _you_ have to control TRIS. Nowhere are you setting TRIS to '0' for the pin. |
|
|
baris_akinci
Joined: 10 Mar 2016 Posts: 17 Location: Ankara
|
pwm and normal output on same pin for 16f628a |
Posted: Thu Mar 10, 2016 7:38 am |
|
|
[img]
resim yükleme servisi
you can see my project for better understanding. Is there a way to connect all led's to CCP module of 16f628a? because teher is only one output and if I connect all to here, then the LEDs are going short circuit! I think, only one solution is remaining, generating softaware pwm, not CCP module. I tried this by the way but failed!![/b] |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Mar 10, 2016 8:33 am |
|
|
You do it the 'other way up'. You have the PWM output drive a common collector transistor to give the _ground_ to all the LED's. Then for any LED you want 'on', you set the output bit that drives it. You can set the intensity by changing the PWM.
Why on earth are you fiddling around with two PIC's. You have spare inputs on one, use them. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Mar 10, 2016 9:04 am |
|
|
In your OP you sound like you're running out of pins.
So why create problems using the same pins twice when you've got spares?
Also why have you got diodes D5-8 in series with the LEDs? The LEDs are diodes!
Depending on the number of brightness levels you want you may be able to use software PWM on all four LEDs.
That way they can have different intensities.
Mike |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Thu Mar 10, 2016 10:28 am |
|
|
Me thinks this is existentially a Proteus/ISIS project. The screen shot doth influence my sentiment. Object reality may be denied us all, including the OP...... |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Thu Mar 10, 2016 10:57 am |
|
|
What irks me is the 'messy ' schematic. It should be easy to follow the 'flow' or logic of the product by the layout, which isn't the case here. Horizontal grounds just don't make life easy !
As for the diodes in the LEDs... they do drop the Vout of the PIC by about .7 so you _could_ eliminate the 100r curent limit resistors. While not good practise I have done similar _creative_ hardware in the past.
Jay |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Mar 10, 2016 12:41 pm |
|
|
Please tell us:-
Is this a REAL HARDWARE project or Proteus/ISIS?
Mike |
|
|
baris_akinci
Joined: 10 Mar 2016 Posts: 17 Location: Ankara
|
pwm and normal output on same pin for 16f628a |
Posted: Thu Mar 10, 2016 1:01 pm |
|
|
I think I was misunderstood here. I used two pics because I made Rf communication between 2 pics via RS232 (433 MHz TX-RX device).
this was my mistake because I forget to delete diodes before uploading it. I used them because I tried to use CCP module but all leds were short circuit as below!
[img]
resim yükleme servisi
So, my main question again; I want to make if state LED simulation(sim1,sim2,sim3,..). there are normal outputs (5v) from sim1 to sim5 but for sim6 I want PWM (fading on/off until another signal comes). I tried hardware CCP module but failed, I tried also SPWM but failed again. I need your help at this point.
thank you
Code: | void sim1() {
// police light
int i=0;
output_high(LED1);output_high(LED2); for(i=0;i<70;i++) {delay_ms(1); }
output_low(LED1);output_low(LED2); for(i=0;i<70;i++) {delay_ms(1); }
output_high(LED1);output_high(LED2); for(i=0;i<70;i++) {delay_ms(1); }
output_low(LED1);output_low(LED2); for(i=0;i<70;i++) {delay_ms(1); }
output_high(LED1);output_high(LED2); for(i=0;i<70;i++) {delay_ms(1); }
output_low(LED1);output_low(LED2); for(i=0;i<200;i++) {delay_ms(1); }
output_high(LED3);output_high(LED4); for(i=0;i<70;i++) {delay_ms(1); }
output_low(LED3);output_low(LED4); for(i=0;i<70;i++) {delay_ms(1); }
output_high(LED3);output_high(LED4); for(i=0;i<70;i++) {delay_ms(1); }
output_low(LED3);output_low(LED4); for(i=0;i<70;i++) {delay_ms(1);}
output_high(LED3);output_high(LED4); for(i=0;i<70;i++) {delay_ms(1); }
output_low(LED3);output_low(LED4); for(i=0;i<200;i++) {delay_ms(1); }
}
void sim2() {
// LED animation 2
int b=0;
output_high(LED1); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED1); for(b=0;b<50;b++){delay_ms(1); }
output_high(LED2); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED2);for(b=0;b<50;b++){delay_ms(1); }
output_high(LED3); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED3);for(b=0;b<50;b++){delay_ms(1); }
output_high(LED4); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED4);for(b=0;b<50;b++){delay_ms(1); }
for(b=0;b<150;b++){delay_ms(1); }
output_high(LED4); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED4);for(b=0;b<50;b++){delay_ms(1); }
output_high(LED3); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED3);for(b=0;b<50;b++){delay_ms(1); }
output_high(LED2); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED2);for(b=0;b<50;b++){delay_ms(1); }
output_high(LED1); for(b=0;b<50;b++){delay_ms(1); }
output_low(LED1);for(b=0;b<50;b++){delay_ms(1); }
}
void sim3() {
// LED animation 3
int h=0;
for(h=0;h<250;h++){delay_ms(1); }
output_toggle(LED1);output_toggle(LED2);output_toggle(LED3);output_toggle(LED4);
for(h=0;h<250;h++){delay_ms(1); }
output_toggle(LED1);output_toggle(LED2);output_toggle(LED3);output_toggle(LED4);
}
void sim4() {
// LED animation 4
int a=0;
output_high(LED1); output_high(LED2);output_low(LED3);output_low(LED4);
for(a=0;a<250;a++){delay_ms(1); }
output_low(LED1); output_low(LED2);output_high(LED3);output_high(LED4);
for(a=0;a<250;a++){delay_ms(1); }
}
void sim5() {
// LED animation 5
int d=0;
output_high(LED1); output_high(LED3);output_low(LED2);output_low(LED4);
for(d=0;d<250;d++){delay_ms(1); }
output_low(LED1); output_low(LED3);output_high(LED2);output_high(LED4);
for(d=0;d<250;d++){delay_ms(1); }
}
void sim6(unsigned int tR) {
output_high(LED1);
delay_us(tR);
output_low(LED1);
delay_us(100-tR);
}
void main()
{
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256);
set_timer0(60);
enable_interrupts(int_timer0);
enable_interrupts(int_rda);
enable_interrupts(GLOBAL);
set_tris_a(0x00);
while(TRUE)
{
if(inc==1) {
while(inc==1) {sim1();}
enable_interrupts(int_rda); // interrupt işleminde kapattığımız kesmeyi burada tekrardan aktif ediyoruz
}
else if(inc==2) {
while (inc==2){sim2();}
enable_interrupts(int_rda);
}
else if(inc==3) {
while (inc==3){sim3();}
enable_interrupts(int_rda);
}
else if(inc==4) {
while (inc==4){sim4();}
enable_interrupts(int_rda);
}
else if(inc==5) {
while (inc==5){sim5();}
enable_interrupts(int_rda);
}
else if (inc==6) {
while (inc==6) {
unsigned int tR;
for(tR=1;tR<100;tR=tR+1)
{sim6(tR);}
enable_interrupts(int_rda);
}
}
else if(inc==7) inc=1;
else if(inc==0) inc=6;
else inc=inc;
|
|
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Mar 10, 2016 5:49 pm |
|
|
Now you're getting me confused.
In your OP you seemed to want ALL the LEDs to connect to the PWM.
Now (in sim6) you only seem to want LED1 to fade.
Please tell us:-
1) How many LEDS do you want to PWM?
2) Do the LEDs all need to PWM in step with each other?
3) Are you wanting to gradually both increase and decrease brightness?
4) How many brightness levels do you want?
AND, most importantly, answer my previous question
Is this REAL hardware or Proteus/ISIS simulation?
Mike |
|
|
baris_akinci
Joined: 10 Mar 2016 Posts: 17 Location: Ankara
|
pwm and normal output on same pin for 16f628a |
Posted: Fri Mar 11, 2016 12:47 am |
|
|
thank you for reply Mike, yes I try to do real hardware but for some test and improvement, I make the ISIS file simple. my last post for sim6() is just to see whether I achieved PWM or not, If I had done, I would have been increased for all LEDs, this was just trying!
for your questions;
all 4 LEDs I want PWM at the same time, yes I want gradually increase/decrease the brighness of LEDs until another signal comes, brightness level depens on how good seemed on eye in real LED. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Fri Mar 11, 2016 3:03 am |
|
|
The ways to do this are:
1) Software PWM.
2) Multiplexing.
With the latter, you connect _all_ the LED's to one PWM output at one end (so their grounds, with a suitable driver transistor), and the other ends to the four chip outputs.
Then you have a choice. If the LED's can all dim together, this is all that is needed. If the LED's want to be different, you multiplex. Sequence is:
Set required power level on PWM for LED1. Turn on it's output. Wait for perhaps 200th second. Then turn off LED1, set level for LED2, turn on LED2. Wait another 200th second. Repeat for LED3, and 4. Then go back to the start. You actually run the LED's with 4* the current you want them to have, but each is only on for 1/4 the time. You can then set the PWM level for each separately. Advantage of this is that the actual PWM is done fast, and it is only the multiplex that needs an interrupt, so something like 200Hz is adequate.
Conversely, software PWM, can be done with your existing hardware, but will need a fast interrupt if you are not to get flickering. The fewer the number of 'levels' you need the easier this is. The code library has basic code for three LED's at:
<http://www.ccsinfo.com/forum/viewtopic.php?t=30139&highlight=software+pwm> |
|
|
baris_akinci
Joined: 10 Mar 2016 Posts: 17 Location: Ankara
|
pwm and normal output on same pin for 16f628a |
Posted: Mon Mar 14, 2016 7:39 am |
|
|
Thank you for reply Ttelmah. what I learned from your refer's topic is that the way to do SPWM is to make many ON/OFF succecivelly in microseconds and we can fading the LEDs by changing their internal period ON/OFF situation's. therefore I made the following code part for sim6() Code: | void sim6(void) { // pwm function sub-function
static int m=0;
for (m=5;m<255;m=m+5) {
if(m<255) {
output_high(LED1);output_high(LED2);output_high(LED3);output_high(LED4);
delay_us(m);
output_low(LED1);output_low(LED2);output_low(LED3);output_low(LED4);
delay_us(256-m);
if(m>=255) {
for(m=255;m>5;m=m-5) {
output_high(LED1);output_high(LED2);output_high(LED3);output_high(LED4);
delay_us(m);
output_low(LED1);output_low(LED2);output_low(LED3);output_low(LED4);
delay_us(256-m);
}
}
}
}
}
|
but I failed, because I just see the LEDs ON/OFF fastly!! not fading(gradually ON/OFF).
second issue by the way, this code part has to wait for arrival of its counter (counter is generated by rf signal and change the state from sim1(),sim2(),sim3(),...,sim6()). but when I give the power to the board, sim6() automatically starts :S
thank you for your help in advance.. |
|
|
|