Embedded Systems and Power Electronics

Total Pageviews

About Me

My photo
I am currently a PhD student at UC Berkeley, following a 6-year journey working at Apple after my undergrad years at Cornell University. I grew up in Dhaka, Bangladesh where my interest in electronics was cultivated, resulting in the creation of this blog.

BTemplates.com

Powered by Blogger.

Oct 26, 2012

Zero crossing detection with PIC16F877A


Zero crossing detection is very important, especially in power control circuits employing thyristors.

I have come across many people struggling with zero crossing detection with PIC microcontroller and thus they cannot fire triacs or SCRs as required.

So, here I have explained a simple method of detecting zero crossing with PIC16F877A, employing only two or three resistors, a bridge rectifier and an optocoupler for the hardware portion of zero cross detection. 

The PIC 16F877A detects the zero crossing using the RB0/INT external interrupt function. I have explained how the zero cross is detected and how the PIC acts upon detection, below.



 
Fig. 1 - Schematic, zero crossing signal and RD0 signals

---------------------------------------------------------------------------------------------------------
Here is the code for PIC16F877A:
(You can download the source file from
https://rapidshare.com/files/604474700/ZeroCrossing.c )
---------------------------------------------------------------------------------------------------------
//Programmer: Syed Tahmid Mahbub
//Compiler: mikroC PRO for PIC v4.60
//Target PIC: PIC16F877A
//Program for zero-cross detection
//---------------------------------------------------------------------------------------------------------
unsigned char FlagReg;
sbit ZC at FlagReg.B0;

void interrupt(){
     if (INTCON.INTF){          //INTF flag raised, so external interrupt occured
        ZC = 1;
        INTCON.INTF = 0;
     }
}

void main() {
     PORTB = 0;
     TRISB = 0x01;              //RB0 input for interrupt
     PORTD = 0;
     TRISD = 0;                 //PORTD all output
     OPTION_REG.INTEDG = 0;      //interrupt on falling edge
     INTCON.INTF = 0;           //clear interrupt flag
     INTCON.INTE = 1;           //enable external interrupt
     INTCON.GIE = 1;            //enable global interrupt
    
     while (1){
           if (ZC){ //zero crossing occurred
              PORTD.B0 = 1; //Send a 1ms pulse
              delay_ms(1);
              PORTD.B0 = 0;
              ZC = 0;
           }
     }
}
---------------------------------------------------------------------------------------------------------

Explanation:




     Fig. 2
     Yellow - AC signal
     Blue - signal on RB0

In yellow (in Figure 2), you can see the input AC voltage (sinusoidal waveform). BR1 rectifies this AC voltage to DC, but since there is no bulk smoothing capacitor, the output is not pure DC, but pulsating DC as shown below.

Fig. 3- The rectified pulsating DC

The output of the bridge rectifier BR1 is DC and current through optocoupler is limited by resistors R1 and R2 (you may use a single resistor instead of 2 if you want, but using 2 resistors distributes the power dissipation and thus generates less heat and lower power per resistor).

So, the optocoupler LED stays on for most of the cycle except when the AC sine wave "crosses zero" (is around zero). While the optocoupler LED is on, the transistor is on and so pulls pin RB0 of PIC16F877A low.

PIC16F877A is coded to enable the external interrupt. An interrupt is generated upon the falling edge of RB0. The diagram below will illustrate what I mean by falling edge.

       Fig.4
       Yellow - signal on RB0
       Blue - signal from RD0

During most of the cycle, the optocoupler LED is on and so RB0 is low. When the optocoupler LED is off as the AC wave is about to cross "zero", RB0 goes high. The transition from low to high on RB0 is a rising edge. When the optocoupler LED is then again turned on as the AC wave crossed the "zero" level (zero crossing), RB0 goes low. This transition from high to low is a falling edge. And upon a falling edge, an interrupt is generated.

When an interrupt is generated, the ZC flag is set (see code above). In the main code, ZC flag is always checked (this is called polling a flag). When ZC flag is set (zero crossing occurred), a 1ms pulse is generated on RD0 (PORTD0) and then the ZC flag is cleared. For example's sake, I have produced a 1ms pulse. You can do whatever you want upon zero-cross detection. The ZC flag is then again continuously polled to check for next interrupt.

You can see all this illustrated in Figures 2, 3 and 4 above.

67 comments:

  1. nice post. can i get ur contact no.

    ReplyDelete
  2. Thanks.

    Send me an email at my email address inferno (dash) rage (at) hotmail (dot) com.

    Or give me your email address.

    And I'll give you my contact number.

    ReplyDelete
    Replies
    1. My email address u27409156@tuks.co.za

      Delete
    2. reply me by email :mohankrishnaejjagiri@gmail.com

      Delete
  3. Hi Tahmid
    Really great work. Keep it up!
    Ur work has been very helpful, Thank you.

    ReplyDelete
    Replies
    1. Thanks!

      I hope my work can help many others like you.

      Regards,
      Tahmid.

      Delete
  4. Tahmid,
    Your explanation is very eloborate, yet very simple.
    Thanks buddy.

    Mitz

    ReplyDelete
    Replies
    1. You're welcome. I'm glad I could be of help!

      Regards,
      Tahmid.

      Delete
  5. hi tahmid

    i want to know about you oscilloscope . is it a multichannel cro software ?
    where from can i get it.

    ReplyDelete
    Replies
    1. It's the digital oscilloscope in Proteus. It's part of the simulation software.

      Regards,
      Tahmid.

      Delete
  6. tahmid

    what is the bootstrap capacitor voltage rating.?
    =high side mosfet rail voltage + vcc ? or low values can be applied ?

    ReplyDelete
    Replies
    1. I assume you're talking about a high-side bootstrap-based drive circuit.

      http://tahmidmc.blogspot.com/2013/01/using-high-low-side-driver-ir2110-with.html

      It has to withstand the low voltage only as it is charged to (VCC - VB) and is discharged for gate driving.

      Use a voltage rating at least 1.5 times the VCC level. That should be fine.

      Regards,
      Tahmid.

      Delete
  7. ok thanks,
    but i have a question about the mosfet switches that
    you are connecting load between the two legs of mosfet
    and at a time only one leg (upper and lower mosfet of same leg) are working and second one is off.....then current will flow where to where.....or what is the direction of current...

    i have asked this question also in edaboard but till date there is no reply.. please explian the mosfet switch operation in detail ...i am confused so much.... TILL DATE..



    if u r comfortable than we can voice chat on gmail..

    captain.shahid.khan@gmail.com

    ReplyDelete
    Replies
    1. First you should read up on full-bridge (also known as H-bridge) topology. Then you can feel free to ask any questions/doubts you have.

      Delete
  8. Assalam o Alaikum tahmid
    i need to ask you something. I am working on a back to back thyristor firing mechanism. I have a PIC18f452 microcontroller board which is powered by a 9V adapter. i am making a zero cross detector circuit by a transformer to step down the 220V to 12V and then feeding to it bridge and repeating the same thing that you did( i.e. bridge rectifier and optocoupler etc.)
    my question is that do i need to make the ground of the zero-cross detector circuit common with the ground of the microcontroller board. i.e. shall i put a jumper wire between ground pin of 7805 IC on the microcontroller board and the ground of the bridge rectifier on the zero cross detector????
    i am currently on the simulations but i have bought the components and will make the hardware after 2 days. i am just worried coz i can't buy the components again due to high prices. it would be very great if you help me in this regard... so that i could not end up burning the components or anything like that :)
    anxiously waiting for your reply.
    regards,
    syed husnain

    ReplyDelete
  9. hai thamid , which is best simulation software (like matlab,orcad...)

    ReplyDelete
    Replies
    1. For electronics (especially PIC/AVR microcontrollers), I would say Proteus. But then again, I haven't used any other simulator and Proteus works brilliant!

      Regards,
      Tahmid.

      Delete
  10. TANK U VERY MUCH ENGR TAHMED, AM GRATEFUL, MY EMAIL IS ogbuuhenry@gmail.com
    pls i need ur contact and email, i still need ur help in many in this field of study, just a young student in university.

    ReplyDelete
  11. can you please show the steps like configuring sine signal - 220v , 50 hz, and configuring other devices.

    you have used Mikro PIC compiler, could you show some steps, how to add a compiler or like that things, i am stuck after designing the circuit, so please tell if need to modify any value or any other info

    ReplyDelete
    Replies
    1. You can get some details on the sine wave settings here: http://tahmidmc.blogspot.com/2013/02/demystifying-use-of-table-pointer-in.html

      Delete
  12. Dear Tahmid..Can we control RPM of AC Motor with +-1 RPM Accuracy. I have a Single Phase shaded Pole AC Motor. Can we achieve this accuracy using Control loop and TRIAC Method.

    ReplyDelete
  13. thank you so much..!! you can connect circuit zero cross to PWM modul of PIC16f877A to control brightness for Incandescent bulbs operate at 220VAC - 50Hz. And use to change the opening angle of Triac...??-- Can u help me..?? Because I need it for my projects.

    ReplyDelete
    Replies
    1. You can't use the regular PWM (as found in the CCP module of the PIC) for controlling the triac and bulb at 50Hz. You'll need to implement phase angle control or pulse skipping modulation in software. Take a look here:

      AC Power Control with Thyristor: Phase Angle Control using triac with PIC16F877A:
      http://www.tahmidmc.blogspot.com/2013/06/power-control-with-thyristor-phase.html

      AC Power Control with Thyristor: Pulse Skipping using triac with PIC16F877A:
      http://tahmidmc.blogspot.com/2013/06/ac-power-control-with-thyristor-pulse.html

      Regards,
      Tahmid.

      Delete
    2. Thank Tahmid so much..!!!!! sites you've shared to help me a lot.

      Delete
  14. This comment has been removed by the author.

    ReplyDelete
  15. tahmid i visit your blog everyday and am always loving it ...on SMPS how can i calculate my inductor value when winding because i dont have the inductor meter . can you explain how i can build it because am very good in embedded system programming. pls reply in my email at "microprogrammer@ymail.com" thanks

    ReplyDelete
  16. Mr. Tahmid

    thank you tuor lesson was very helpfu;; thank you very much but i want ask you a q please

    in the Schematic, zero crossing signal and RD0 signals before the bridge can i use 220 volt or i have to reduse it to 9v ????

    My Email Is ameenyaghshy@gmail.com

    Ameen

    ReplyDelete
    Replies
    1. It can be 220V or it can be 9V. You just have to set the resistors accordingly. So, if you want, you can use 220V. Just use appropriate valued resistors to limit the current and choose resistors with sufficient power rating.

      Delete
  17. Syed
    I have taken the liberty to refer to your page from my instructables page on making an AC dimmer.
    My software is centered around an Arduino, but as the circuit can just as well be used by any other microcontroller, I presumed some of my readers would be interested in your article.
    http://www.instructables.com/id/Arduino-controlled-light-dimmer-The-circuit/

    ReplyDelete
  18. link not found pls put the new link.

    ReplyDelete
  19. Assalamualaikum Tahmid vai...ur code with 16f877a works great.
    i tried it for 18f4550,,,,,,but problem with this command...

    OPTION_REG.INTEDG = 0;

    i tried but couldn't fix it,,,,,any help!!!

    btw.....my project regards a "power factor meter".........for which i need a zero level detector.

    Regards...

    ReplyDelete
    Replies
    1. That bit is to select the triggering edge for external interrupt. You need to find the equivalent for the 18F4550. You should go through the 18F4550 datasheet.

      Delete
  20. Very Useful. Thank you very much

    ReplyDelete
  21. is a great help to all, I could go through the code for the simulation and, Thanksgiving and successes, my email is brillit_057@hotmail.com or jbernaolacampos@gmail.com

    ReplyDelete
  22. is a great help to all, I could go through the code for the simulation and, Thanksgiving and successes, my email is brillit_057@hotmail.com or jbernaolacampos@gmail.com

    ReplyDelete
  23. This comment has been removed by a blog administrator.

    ReplyDelete
  24. আমি আগে কাউকে এতো সহজ করে zero crossing detection বোঝাতে দেখিনি! খুব সহজেই বুঝে গেলাম! thank you so much! আমি triac দিয়ে AC fan speed controller বানাতে চাই। zero crossing detect করে সেটা কিভাবে করবো তা একটু বুঝিয়ে দেবেন প্লিজ? অনেকে কমপ্লেইন করে যে এভাবে light dimmer অথবা fan speed regulator বানালে তা ঠিক মত কাজ করছেনা, মানে ঠিকমত বাড়ছে- কমছেনা। এই সমস্যাটা কি কারনে হতে পারে?

    ReplyDelete
  25. Very impressive blog. Found it today from google while searching for zero crossing.

    Sir, I have two AC power sources. At present I have an analog logic circuit to shift from one AC source to another using a relay or triac.

    Now I wish to use zero cross detect for this purpose. Please help me out if you can.

    I have understood the concept but ain't able to figure out how to proceed.

    arunsingh911@gmail.com

    ReplyDelete
  26. Hello
    I have been trying to work on this.But I couldnt get the proper output.If you have the source code and also the Proteus file is it possible to mail it?If yes I will share my email ID

    ReplyDelete
  27. i need ups technology,can you help me

    ReplyDelete
  28. Hi Tahmid
    Many thanks for the info, your blog is really helpful!

    May I ask you a question? Which optocoupler would you recommend for a zero crossing detector implemented in a 230 VAC Line?

    Regards,

    Gabriel

    ReplyDelete
  29. Hi tehmid

    Brother can you please tell me which optocoupler should I use ??

    Regards
    Rahul
    rahulahuja.eng @gmail.com

    ReplyDelete
    Replies
    1. A standard optocoupler like the 4N35 should be good. When choosing an optocoupler consider the effect of the CTR.

      Delete
    2. Hi Tahmid

      Thanks for your reply. Can you also suggest me the values of R1 & R2 ?? Actually I am a mechanical Engg. and don't know much about electronics.

      Thanks & Regards
      Rahul

      Delete
    3. Hi Tamid Nice post can u pls send ur mail id to my mail id samathasan1@gmail.com currently i am working on ZCD .

      Delete
  30. How can the same be done using 18F4550? What will be the required changes? My project concerns with the triggering of MOSFETs.

    ReplyDelete
  31. Hi Tehmid

    I tried the circuit as you have shown using 8051 controller and triggring BTA12 using moc3021 and speed is also getting reduced. But I am facing one problem. My fan is flickering (giving jerks). I tried a lot my changing the time of triggering and duration between triggering and zcd but unable to solve this problem. Please suggest me what to do ??

    ReplyDelete
  32. Hi Tahmid,

    I found your blog very useful for my project. I used the zero crosspoint to fire the triac to drive an ac induction motor. WE are 60 Hz which means we have 60 cylces per second. My concern is I want to fire the triac on for the first 4cyle and then off for the next 1cyle then On again for the next 4cyles and off for the next one cyle ......and continue this process. which means Im going to chop that 60Hz (60 cyle). how are we going to do that? because unlike your program above its output is choping every cycle. this on and off must be done during the Zero crossing to avoid a noise in the power line, that's why using a delay is not applicable because of the timing of the ON and Off. ON and off must be done during zero crossing.

    ReplyDelete
  33. Hi Tahmid
    i would like to upload the source file but i cant.

    ReplyDelete
  34. Tahmid brother please help me,i wanted take project on your inverter ckt in my final year project. I am worked around your blog over one month. but i did n't find out the schematic circuit diagram diagram. so please kind to the link (or) file to gmail account named sairampaidissetty@gmail.com. or at least reply me as soon as possible. i am witting for reply

    ReplyDelete
  35. hi tahmid
    i want to use zero crossing detector for triggering scr. i am using potentiometer adc but i didn't succeed.please communicate with me.

    ReplyDelete
  36. can any one share the source file of this?

    ReplyDelete
  37. as there is a problem with this source code for downloading it.there fore please help me for providing me the source code with mplab software version.
    thanks

    ReplyDelete
  38. I built a simiar circuit using AVR micro,4n25,MOC3021,BTA16 and the fan speed is controlled in 5 different steps(namely-0,1,2,3,4).In 0,the micro is switching off the MOC3021 so the output is 0.Also in '4',the output of the micro is continuously giving '1',so that the MOC3021 stays on and the fan rotates in full speed.The speed control is done in 1,2 & 3.The speed control works perfectly on pure sine wave AC.But whenever electricity goes off and Inverter power takes place,the speed control malfunctions(Either the fan stops or it generates great hum and rotates very slowly).I saw with a DSO that the inverter is giving square wave output.My question is,is this normal for the circuit to malfunction in square wave(zero cross is happening in square wave also so why is it malfunctioning??)or I am missing something??There is also external snubber attached using 39R and .01uF.Any help is appreciated....Please reply soon.

    ReplyDelete
  39. sir may i know what simulation software you use on this project, can you simulate pic program on this software?

    ReplyDelete
  40. Need HELP
    I used the 4N33 optocoupler and the resistors R1 & R2 of 23k (each of them are two 47k 1/2 Watt mounted in parallel). Proteus simulation shows everything seems to work fine exactely like what you did but after having made the PCB, there is no zero crossing pulse on the output of the optocoupler.

    I've checked everything (circuit, components, program, ...) several times and I found that everything is OK.
    Do you have any idea of what could be wrong that I probably missed?

    Best regards

    ReplyDelete
  41. I tried to replace the 4N33 optocoupler by a 4N25 one and It's working fine now

    ReplyDelete
  42. I have something similar for my project but I have some troubles trying to use 2 interrupts to detect 2 zero crossing signals at the ports RB0,RB1 (PIC18F4550) from a 2phase source. maybe you can helpe. thanks

    here is my code in MikroBasic

    program cross

    dim period as byte
    dim alpha as byte
    dim i, j as byte
    'const angles as byte[6]=(10,45,90,120,150,170)' 180 min voltage 0 max voltage
    sub procedure interrupt
    period=(alpha*8.33)/180
    if (INTCON.INT0IF=1) then
    Vdelay_ms(period) 'shoot positive cycle
    for j=0 to 19
    portd.7=1
    delay_us(5)
    portd.7=0
    delay_us(5)
    next j
    Vdelay_ms(8.33) 'shoot negative cycle
    for j=0 to 19
    portd.7=1
    delay_us(5)
    portd.7=0
    delay_us(5)
    next j
    INTCON.INT0IF=0 'clean external interrupts
    else
    if (INTCON3.INT1IF=1) then
    Vdelay_ms(period) 'shoot positive cycle
    for j=0 to 19
    portd.6=1
    delay_us(5)
    portd.6=0
    delay_us(5)
    next j
    Vdelay_ms(8.33) 'shoot negative cycle
    for j=0 to 19
    portd.6=1
    delay_us(5)
    portd.6=0
    delay_us(5)
    next j
    INTCON3.INT1IF=0 'clean external interrupts
    end if
    end if

    end sub
    main:
    ADCON0.ADON=0
    ADCON1=0X0F
    trisd.7=0 'alpha output phase 1
    trisd.6=0 'alpha output phase 2
    trisb.0=1 'zero crossing phase 1
    trisb.1=1 ''zero crossing phase 2

    portb=0
    portd=0

    INTCON.GIE=1 'Enable global interrupts
    INTCON.INT0IE=1 'Enable external interrupts RB0
    INTCON.INT0IF=0
    INTCON2.INTEDG0=0 'Interrupt on falling edge RB0
    INTCON3.INT1IE=1 'Enable external interrupts RB1
    INTCON3.INT1IF=0
    INTCON2.INTEDG1=0 'Interrupt on falling edge RB1
    while(1)
    alpha=140 'Shooting angle
    wend
    end.

    ReplyDelete
  43. can you help to make same code for pic12f1612?

    ReplyDelete
  44. Hey Tahmid,

    Its too awesome explanation for a amateur like me. I am currently working on the zcd feature of p12f1612, we can reduce the external components and the efforts to detect zc with the help of this. The understanding of the concept was very essential since I was unable to figure out the approach. Thanks buddy this was really helpful.
    Will post the code shortly once I am done.

    ReplyDelete
  45. Hi.... Tahmid, I want to use PIC12F615 instead PIC16F877A. Because, we just wanted two I/O line and one interrupt pin for the whole system. I think it is more suitable to use the controller with less number of pins. Can you just help me to write the code for PIC12F615 for same circuit as it has nor PORTB or PORTD inside.

    My email ID is tushar.mehta.23@gmail.com

    ReplyDelete
  46. Can you please suggest me value and power rating for R1 and R2 with 4n35 on 240VAC?

    ReplyDelete
  47. Hi tahmid I'm from Pakistan..Really love you blog.. Dear I need help in urgent basis. I have some problems in designing smps. Can you leave the reminder message on my emial Yasir.shahzad@kics.edu.pk or give me your email so that i may contact you.. Dear i will keep you in my mind all of my life, thanks

    ReplyDelete
  48. Hi Tahmid,

    I want to count the number of zero crossings let's say 100. on reaching the 100 ZC's I want the program to do something else like connecting the load to normal supply voltage. How can I get out of the continuous loop.

    ReplyDelete