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 CCS Technical Support

Simple Zero Crossing Detector

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
edbfmi1



Joined: 18 Jul 2006
Posts: 103

View user's profile Send private message

Simple Zero Crossing Detector
PostPosted: Wed Aug 19, 2015 4:08 pm     Reply with quote

Hello all,
I have something that is driving me crazy.
I am trying to detect the Zero Crossing of the AC Power line.
I have the circuit designed with a 6.2M Ohm resistor coming from the AC line into PIN BO with diodes between VDD and VSS. This gives a fairly nice 0 to 5VDC square wave on PIN B0

I am using PCM V4.140, and a PIC16F716.

The problem I am having is the program is only interrupting when the RB0 interrupt is positive. If I put a breakpoint in the interrupt routines if-else statement it never interrupts in the "else" portion.

I stripped the program to the bare bones.

Any help would be appreciated.

Code:
#include <16F716.h>

// Checksum 5fcd

#fuses XT,NOWDT,NOPROTECT,PUT
#use delay(clock=4000000)
#FILL_ROM 0x00


//#define INTERLOCK_IN PIN_A4
#define Z_CROSS_INPUT PIN_B0
//#define SENSOR PIN_B1
//#define PWR_SW PIN_B2
#define HEARTBEAT PIN_B3
//#define AC PIN_B4
//#define DC_TOP PIN_B5
//#define INTERLOCK_OUT PIN_B6
#define GATE PIN_B7

#BYTE intcon = 0x0B


int8   z_cross_counter;   // Counts number of zero crossings

int8   StatusBits1;
#bit   ac_top = StatusBits1.3      // top half of sinewave
#bit   ac_bottom = StatusBits1.4   // bottom half of sinewave
//#bit   gatehi = StatusBits1.5      // Set when gate is high
//#bit   pwr_on = StatusBits1.6      // Power switch is on   
//#bit   startup = StatusBits1.7


#int_ext
void detect_Z_CROSS()
{
   z_cross_counter++;
   if(input(Z_CROSS_INPUT))
   {
      delay_cycles(1);
      ac_top = TRUE;
      ac_bottom = FALSE;
      output_toggle(HEARTBEAT);
   }
   else
   {
      delay_cycles(1);
      ac_top = FALSE;
      ac_bottom = TRUE;
      output_toggle(HEARTBEAT);
   }
}

void main()
{
   output_low(GATE);
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_EXT);
//   port_b_pullups(false);
   while (1==1)
   {
         delay_cycles(1);
   }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Aug 19, 2015 4:28 pm     Reply with quote

The external interrupt will only occur on one edge, either the positive or
negative edge. You should call the ext_int_edge() function to select the
desired edge. If you don't call it (as in your program), it defaults to the
positive edge.
temtronic



Joined: 01 Jul 2010
Posts: 9244
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Wed Aug 19, 2015 6:09 pm     Reply with quote

I'll assume the 'AC power line' is either 120 or 240 volts. If so you really should NOT tie the PIC directly to it rather use an optocoupler type device for isolation. You could also use a small transformer for this purpose. This is a safety issue. Should (when !) that resistor fails and blows up the PIC, it'll scare you and bam... the DVM you had in your hand is across the room going through the window in far less time that it takes you to read this.


Jay
Ttelmah



Joined: 11 Mar 2010
Posts: 19544

View user's profile Send private message

PostPosted: Thu Aug 20, 2015 3:00 am     Reply with quote

There are quite a lot of circuits that use direct coupling like this.

First thing is though that you need to design the circuit so if a part fails it will fail safe. Simple thing like having a PCB fuse built in the line feeding the resistor, so that if this fails (they do...), the fuse will blow. Chose the clamp diodes to well exceed the rating of the fuse. Also look carefully at the voltage rating of the resistor (most are _not_ mains rated....).

Then though the critical thing. If designing a circuit like this, when working with it, you should be powering it through an isolation transformer. In many countries this is a _requirement_ when working on non-isolated circuits. After it is designed, it can then be encapsulated in a way that meets the insulation requirements for a non isolated circuit, and be 'legal', but this won't save you when designing it....

Then have you done anything like a high voltage 'working' course?. This will teach you basic techniques that reduce the chance of death. Things like avoiding jewellery when working, and putting one hand in your pocket when touching anything, so that there is not an electrical path across your chest, if something does go wrong.

Working safely with mains kit, needs to be done 'both eyes open', with a lot of thought, if it is not going to jump out and 'bite' you.....

To detect both edges, either have the interrupt routine reprogram the detection edge depending on the polarity of the signal, or use the interrupt on chance ability that does detect both edges.

Code:

//For the EXT1 interrupt
#int_ext
void detect_Z_CROSS()
{
   z_cross_counter++;
   if(input(Z_CROSS_INPUT))
   {
      //signal is high so we want to detect falling edge
      ext_int_edge(H_TO_L);
      ac_top = TRUE;
      ac_bottom = FALSE;
      output_toggle(HEARTBEAT);
   }
   else
   {
      ext_int_edge(L_TO_H);
      ac_top = FALSE;
      ac_bottom = TRUE;
      output_toggle(HEARTBEAT);
   }
}

The delay_cycles seems rather pointless - it's going to be perhaps 30 cycles after the edge before it reaches this point....
edbfmi1



Joined: 18 Jul 2006
Posts: 103

View user's profile Send private message

PostPosted: Thu Aug 20, 2015 6:11 am     Reply with quote

Thanks for all the input.
This was just a rough design for proof of concept. The final design does have optical isolation to tie it to the AC mains.

As for the delay_cycles(1);
Quote:
The delay_cycles seems rather pointless - it's going to be perhaps 30 cycles after the edge before it reaches this point....


I use that as a "NOP" for a place to set breakpoints since the compiler does not have a NOP function.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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