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 support@ccsinfo.com

zero crossing detector 2VAC
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Aug 17, 2010 4:27 pm     Reply with quote

Aside from your detector problems:
Code:
int8 fanspeedinput[4], fanspeed;

...

fanspeed = bin2bcd(strcat(strcat(fanspeedinput[3],fanspeedinput[2]),
                          strcat(fanspeedinput[1],fanspeedinput[0])));
This is about the most creative code I've seen in a long time, but it isn't going to do what you want it to do. What it does is overwriting memory and most likely corrupting the rest of your program.
This single line of code contains several huge errors and makes it clear to us that you have no knowledge about the difference between a string and a binary value.

What is wrong is that strcat expects a string as an input, that is, a pointer to an array of characters terminated by a zero. You are supplying it a binary value... Ouch. Strcat will search memory until the terminating zero is found and in the process overwrite memory at a random address.

Then when you have created this 'string', you pass it to a function that expects an integer. This is a similar error as before, but now reversed.

And all you wanted to do was to convert the 4 digital inputs to a single binary value. So much code for something that can be done in two basic instructions: input_a() and an '&' operation to filter out the unwanted bits. I leave it to you to figure this out.

O yes, and why are you using bin2bcd() anyway? In the switch statement you are treating the results as a binary value, not as bcd.
deperkin



Joined: 04 Feb 2009
Posts: 83
Location: PA

View user's profile Send private message Send e-mail

B2B
PostPosted: Tue Aug 17, 2010 8:19 pm     Reply with quote

You are correct in that this is a bad approach to checking the inputs...
I do know the difference...

I understand perfectly what you are saying regarding checking the inputs. This was just scrapped together and I obviously did not look at it.

Regarding setting up a timer, I have never had much luck getting this to work correctly (any pointers would be greatly appreciated)...I know how to get a timer to overflow, but the way I am seeing this is that I need to set pin_c2 to low every 1/60 sec. (16666.67 us) for a short period of time, then set it to high for the remaining part of that 1/60 sec.

Am I correct on this?

I was thinking that I would have to invert the edge detect, which is no problem, but working at say 500 kHz clock, how can I get this to overflow at the correct time?

I have removed all of the delays also...

I am thinking the best way to handle proper timing may be to write it up in assembly.

I would rather not use INT_RB, but it is definitely an option. Is there a benefit of using this rather than INT_EXT ?

I had thought I would be able to use INT_EXT and switch the edge detect.

I realize there is alot that I need to learn about programming, and where I fall short is definitely in the area of working with timer interrupts. I never have much luck getting the correct timing. Even trying others examples, I seem to find a much different timing when looking under a scope.

Anyways, Thank you all again for the help. I would really like to find a way to use a PIC and control the speed of an AC motor.

I feel that using a 1Mohm resistor is cheaper and easier for doing a edge detection, and If I could simply get the interrupts to work I can be finished with this part of my project.
deperkin



Joined: 04 Feb 2009
Posts: 83
Location: PA

View user's profile Send private message Send e-mail

updated code
PostPosted: Wed Aug 18, 2010 11:57 am     Reply with quote

Here is an updated code:
Code:
 
#include <18F2550.H>
#include <STDLIB.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, NOPUT, NOLVP, NOMCLR 
#ocs 500 kHz
int16 fanL, fanspeed;

#INT_RB
void AC_isr(){
disable_interrupts(int_RB);
output_low(PIN_C2);
delay_us(fanL);
output_high(PIN_C4);  //LED
}

void main() {   
SET_TRIS_A(0xFF); //PINS A0-A7 are inputs
SET_TRIS_B(0xFF); //PINS B0-B7 are inputs
  while(TRUE){
  enable_interrupts(INT_RB);
  enable_interrupts(GLOBAL);
fanspeed = 0x0F & input_a();
  switch(fanspeed){
   case 10:fanL=0;break;
   case 9: fanL=58;break;
   case 8: fanL=1515;break;
   case 7: fanL=2272;break;
   case 6: fanL=3030;break;
   case 5: fanL=3788;break;
   case 4: fanL=4545; break;
   case 3: fanL=5303;break;
   case 2: fanL=6060;break;
   case 1: fanL=6818;break;
   case 0: fanL=7576; break;
   default: fanL= 0; break;
  }
}
}

I have the AC (L) connected to a 1MOhm resistor and wired to PIN_B5.

I do get variable speeds with this but it is not consistent.

example: fanspeed set to 4 gives me full speed.
all others give me some variable speed, but with odd vibrations, which makes me think that the phase is not matching.

I do not get a 60Hz output to the motor.

I have switched everything to use a SSR instead of an optocoupler circiut as well.
so I have my SSR wired to pin_C2 now.

I would think, from the wiring and the code, that I should get an output that is a changing duty cycle from the PIC (which i do, but it is not changing like i would expect), and to the motor i would expect a 60Hz signal (which it is not).

overview and circuit:

I have AC(L) connected to 1Mohm resistor at pin B5.
I have an output at pin C2 connected to a SSR.
I have an AC motor and AC(L) connected to the other side of the SSR.

that is the whole circuit.

I interrupt when there is a change in the 60Hz signal, drive C2 low for a short period of time, then drive it high... wait for the next interrupt.

seems simple...

anyone have any idea what could be in error?


THank you again. I really do appreciate all of the help.
Ttelmah



Joined: 11 Mar 2010
Posts: 19260

View user's profile Send private message

PostPosted: Wed Aug 18, 2010 2:40 pm     Reply with quote

In INT_RB, you _must_ read port B.
The interrupt won't clear till you do.
You disable the interrupt, but then enable it on the next loop in main, which wil _immediately_ jump to the handler, since the interrupt will still be set.
Since you are still delaying in the interrupt, read the port as the last thing in the interrupt handler, so that it is cleared at this point, rather than earlier, and possibly becoming set again....

Best Wishes
deperkin



Joined: 04 Feb 2009
Posts: 83
Location: PA

View user's profile Send private message Send e-mail

reading port B
PostPosted: Wed Aug 18, 2010 2:49 pm     Reply with quote

So you think this would help:
Code:

#include <18F2550.H>
#include <STDLIB.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, NOPUT, NOLVP, NOMCLR 
#ocs 500 kHz
int16 fanL, fanspeed;
int8 portB;

#INT_RB
void AC_isr(){
disable_interrupts(int_RB);
output_low(PIN_C2);
delay_us(fanL);
output_high(PIN_C4);  //LED
portB = input_B();
}

void main() {   
SET_TRIS_A(0xFF); //PINS A0-A7 are inputs
SET_TRIS_B(0xFF); //PINS B0-B7 are inputs
  while(TRUE){
  enable_interrupts(INT_RB);
  enable_interrupts(GLOBAL);
fanspeed = 0x0F & input_a();
  switch(fanspeed){
   case 10:fanL=0;break;
   case 9: fanL=58;break;
   case 8: fanL=1515;break;
   case 7: fanL=2272;break;
   case 6: fanL=3030;break;
   case 5: fanL=3788;break;
   case 4: fanL=4545; break;
   case 3: fanL=5303;break;
   case 2: fanL=6060;break;
   case 1: fanL=6818;break;
   case 0: fanL=7576; break;
   default: fanL= 0; break;
  }
}
}

The delay in the interrupt should (if my math is correct) be less then the time it takes to get to the next interrupt.
(i.e. I interrupt and have 1/120th sec till next interrupt = 8333 us)

Thank you by the way for this help.
Ttelmah



Joined: 11 Mar 2010
Posts: 19260

View user's profile Send private message

PostPosted: Wed Aug 18, 2010 3:06 pm     Reply with quote

Yes.

In the demo code as shown, the delay ought to work, _but_ it is likely to cause problems to 'bite you' later, if the code gets more complex.
If you have a delay operation, in the external code, interrupts _will_ be disabled for this. Potentially a problem.
If you use other interrupts (RS232 etc.), these can't be serviced while you are delaying in the first interrupt. Potentially another problem.

As I said before, far better to use a timer. Program this to 'tick' in some interval that suits you (master clock/8 say). Then in INT_RB, output low your first pin, load the timer with the constant needed to make it run for the period you require, clear it's interrupt, enable it's interrupt, and exit immediately without a delay.
When the timer interrupts, turn off it's interrupt, and set the second output pin. Exit immediately.

This way the hardware timer, handles your timing, rather than you sitting waiting, and your code outside, can be doing other things...

Best Wishes
deperkin



Joined: 04 Feb 2009
Posts: 83
Location: PA

View user's profile Send private message Send e-mail

many thanks
PostPosted: Wed Aug 18, 2010 5:07 pm     Reply with quote

Thank you!

I will try this. I have never had much luck getting the timers to interrupt at the correct (calculated) time however, and since this needs to be consistent I am not confident I can get it to work, however I will try.
That approach would be much better.

I do not plan on adding any additional code, and this PIC would be dedicated to only AC speed control.

I have tried the code and still cannot get it to work well however.


Thank you again.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 18, 2010 5:45 pm     Reply with quote

I'm curious about how you get 500 KHz as your oscillator speed.
What's your crystal frequency ? (and your compiler version)
deperkin



Joined: 04 Feb 2009
Posts: 83
Location: PA

View user's profile Send private message Send e-mail

500 Khz speed
PostPosted: Wed Aug 18, 2010 8:48 pm     Reply with quote

the 500 kHz seems to be fast enough for me...

I tried a 4Mhz, but found that 500k is a good speed.

is there any difficulty with that speed?

I am programming with 4.093 pcwhd compiler

i am not using an external clock...

i do have the AC line wired to t0CKI with a 2Mohm resistor and diode to Vdd, but am not using it in the code at the moment.

is there a better way to just use this input as an oscillator and use T0CKI??

I cant seem to get good interrupts using timers, and i know there is alot I have to learn in this respect, but I would just like to use a PIC for a simple fan speed controller. I dont need to be as accurate as an FOC, and i thought about going to an IGBT driver (if anyone has any recommended P/Ns i would appreciate that).

I tried using an optocoupler for my zero-crossing, and may come back to that soon, but for now I am just connecting the AC straight to the PIC using a 1Mohm resistor.

I feel instead of going low for a short period of time, then delaying, then going high... i should switch this and go high, then delay, then go low (??)

i currently have this PIC connected to a Crydom 2410 SSR.
is that a bad choice? i know it is more expensive they making a circuit, but i can afford it for now and dont want to spend alot of time on this part of the design.

Thanks again.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 18, 2010 9:56 pm     Reply with quote

Quote:
I am not using an external clock...

I compiled your latest program with vs. 4.093 and these are the config bits:
Code:
Configuration Fuses:
   Word  1: 0000   XT NOIESO NOFCMEN PLL1 CPUDIV1 NOUSBDIV
   Word  2: 1E1F   BROWNOUT NOWDT BORV20 NOPUT WDT32768 NOVREGEN
   Word  3: 0300   PBADEN CCP2C1 NOMCLR NOLPT1OSC
   Word  4: 0081   STVREN NODEBUG NOLVP NOXINST
   Word  5: C00F   NOPROTECT NOCPD NOCPB
   Word  6: E00F   NOWRT NOWRTD NOWRTC NOWRTB
   Word  7: 400F   NOEBTR NOEBTRB

It's using the XT fuse, which only works with an external crystal,
resonator, or oscillator. You imply that you're using the internal
oscillator, but the config bits would have to be set for INTRC or
INTRC_IO and they're not. The reason I brought this up is because
you said the program still doesn't work, and the fuses and clock speed
settings looked a little weird to me.
deperkin



Joined: 04 Feb 2009
Posts: 83
Location: PA

View user's profile Send private message Send e-mail

external resonator
PostPosted: Thu Aug 19, 2010 6:58 am     Reply with quote

So from what I understand now, which i did not know before, is that I should remove the XT ?

would I then need to set the other bits?

Thank you btw, this is helpful.
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 Previous  1, 2
Page 2 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