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

generate 120kHz + zerocrossing detect+emergency
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Moeini



Joined: 08 Aug 2006
Posts: 9

View user's profile Send private message Yahoo Messenger

generate 120kHz + zerocrossing detect+emergency
PostPosted: Wed Sep 06, 2006 1:09 am     Reply with quote

Hi
I want to send Data from a transmitter board to a receiver every 3 second.
kindly attend to following explanations :
1- my PIC is 16f877a
2- my crystal is 7.67375MHz
3- a binary '1' is represented by a 1ms burst of 120kHz at the zero crossing point of the AC line and a binary '0' by the absence of 120kHz.
please guide me about the above mentioned early and point out me errors of this.
Best Regards.


Last edited by Moeini on Mon Sep 11, 2006 3:46 am; edited 1 time in total
ckielstra



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

View user's profile Send private message

PostPosted: Wed Sep 06, 2006 11:53 am     Reply with quote

First some comments:
1) When posting code use the 'code' feature to preserve layout and formatting of your code, this makes it easier for us to read and will get you more responses. The feature works by clicking the code button before pasting your source code and click it again when finished.
2) Keep your posted program as small as possible. Don't post the standard CCS header file, we already have it.
3) For copyright reasons you are not allowed to post the CCS header files in a public forum like this.
4) Describe your problem in more details. Tell what you expect to happen. What is working and what not? What have you tried to fix the problem, etc., etc.

Without knowing the problem in your code I spotted many lines like
Code:
xout=1; //enable 120kHz out put.
delay_ms(1);
xout=1; //disable 120kHz out put.     // <-- Most likely you meant xout=0 ???
This can't be right. Setting xout will either enable or disable the 120kHz output, not both. Fix this error in at least 4 places.
Moeini



Joined: 08 Aug 2006
Posts: 9

View user's profile Send private message Yahoo Messenger

120khz burst with 1ms long
PostPosted: Thu Sep 07, 2006 9:19 am     Reply with quote

Hi
Thanks for your attention to my question.

i want to generate the 120 kHz carrier with an external oscillator circuit. A single I/O pin would be used to enable or disable the oscillator circuit output. The CCP1 module is used in PWM mode to produce a 120 kHz square wave .
After initialization, CCP1 is continuously enabled and the Trisc bit for the pin is used to gate the PWM output. When the trisc bit is set, the pin is an input and the 120kHz signal is not presented to the pin . When the trisc bit is clear , the pin is an output and the 120kHz signal coupled to the AC line.
But:
In my code long of 120kHz burst is not 1 ms.


Last edited by Moeini on Wed Sep 13, 2006 4:43 am; edited 3 times in total
Ttelmah
Guest







PostPosted: Thu Sep 07, 2006 9:57 am     Reply with quote

General comment, if you want real help, you need to 'pare' the question down to the minimum. If you are saying, that this program:
Code:

#byte   trisc=0x87
#bit    Xout=trisc.2

void main() {
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_1,15,1);
   setup_ccp1(CCP_PWM);
   set_pwm1_duty(32L);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);

   while(1)  {
       xout=0;
       delay_ms(1);
       xout=1;
       delay_ms(1);
   }
}

Does not give 1mSec bursts of the 120KHz tone, then post a short program like this to ask the question, rather than your lump of code.
Now as a comment I would use 'fast_io' on portC, before attempting to control the TRIS like this. Otherwise since the compiler thinks that it is controlling the TRIS, while you are also doing so, especially on portC, where the compiler maintains a ghost register on some chip versions, there may be problems. However this should not apply to what you show.
The point being made earlier by abother poster, is that quite a few places in your code, have you unneccesarily setting the TRIS bit twice to the same value. Why?.
There is also a potential problem in some areas like:
Code:

while(!input(PIN_B0));//wait 3 half cycles of ac line .
while(!input(PIN_B0));
while(!input(PIN_B0));


This will only wait for _one_ half cycle of the mains. When B0, goes high, it'll drop straight through all three tests.

Best Wishes
ckielstra



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

View user's profile Send private message

PostPosted: Thu Sep 07, 2006 10:02 am     Reply with quote

Quote:
In my code long of 120kHz burst is not 1 ms.
Please post your #fuses, #delay and #include lines as well. This will tell us the processor you are using, the clock speed and configuration settings.
Looking at your current timer2 setup it looks like you are using a 7.68MHz crystal, is this correct?

Code:
        while(!input(PIN_B0));//wait 3 half cycles of ac line .
        while(!input(PIN_B0));
        while(!input(PIN_B0));
This will not wait for 3 AC cycles, but only 1. When the first test succeeds it immediately does the second test and will succeed, same for the third test. Add a small (1ms) delay between the tests.

I'm not familiar with the X10 protocol, but I understand that you have to send the same command twice as a primitive error checking mechanism. You are sending two different commands.
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Fri Sep 08, 2006 8:40 am     Reply with quote

To wait three half cycles I would do something like this:
Code:
        while(!input(PIN_B0));//wait 3 half cycles of ac line .
        while(input(PIN_B0));
        while(!input(PIN_B0));
        while(input(PIN_B0));
        while(!input(PIN_B0));

_________________
The search for better is endless. Instead simply find very good and get the job done.
Moeini



Joined: 08 Aug 2006
Posts: 9

View user's profile Send private message Yahoo Messenger

PostPosted: Sun Sep 10, 2006 11:09 pm     Reply with quote

1)
In output of my circuit duration of 120khz burst is 200uS in place of 1mS.
2)
[quote]
Please post your #fuses, #delay and #include lines as well.

Code:

#include <16F877A.h>
//#device ICD=TRUE
#device adc=8
#fuses NOWDT,RC, NOPUT, NOPROTECT, NODEBUG, BROWNOUT, LVP, NOCPD, NOWRT
#use delay(clock=7673750,RESTART_WDT)

3)
[quote]
'fast_io' on portC
i am not unerstand means of the top line please explain for me about it.
4)
do you know that what can write this code with use of interrupt for making 1ms delay?


thanks a lot for your guidance
ckielstra



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

View user's profile Send private message

PostPosted: Mon Sep 11, 2006 2:38 am     Reply with quote

Quote:
1)
In output of my circuit duration of 120khz burst is 200uS in place of 1mS.
Check Table 17-3 of the PIC16F877A datasheet. When clocking the PIC in RC mode the maximum allowed frequency is 4MHz, your 7.67MHz is to high and most likely the PIC is running unstable.

A side note: you are specifying the frequency as 7673750Hz. Do you realize standard ceramic capacitors have a 5% tolerance? Add to this the stray capacitance of your circuit, tolerance of the resistor, humidity and temperature effects and you end up with a total tolerance of minimal 10%. If 7.6MHz was allowed for a PIC in RC mode, it would be clocking somewhere between 6.9 and 8.5MHz. Specifying the frequency with as many digits as you give is suggesting an accuracy that you will never achieve.

Quote:
4)
do you know that what can write this code with use of interrupt for making 1ms delay?
Why do you want to use interrupts? I like to keep my programs as simple as possible and interrupts will complicate things a lot.
Moeini



Joined: 08 Aug 2006
Posts: 9

View user's profile Send private message Yahoo Messenger

PostPosted: Tue Sep 12, 2006 11:03 am     Reply with quote

Hi
Thank you for your attention.
In the output of my circuit (in proteus software) there is a 120kHz burst that is created every 10ms and move on the osciloscope area continuously. It means that it starts from the begining of the osciloscope area and it passes and it repeats again from the begining of the osciloscope area and we dont know what it is.
In my code if we want to send "0110", the time delay between first digit and second one must be 10ms and the time delay between the second one and the third one must be 20ms and between third one and fourth one must be 30ms.
But in the proteus analysis the time delay is 10ms!
Please tell me if there is a problem in my code or my consequent from the output figure is wrong.
ckielstra



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

View user's profile Send private message

PostPosted: Tue Sep 12, 2006 3:28 pm     Reply with quote

I think I spotted another error in your code, you are mixing the lines
Code:
while(!input(PIN_B0))
and
Code:
while(input(PIN_B0))
My guess is that you meant to use only one of these versions through all your code. I don't know your hardware setup so I don't know which version is the correct one.

In order to make your code easier to read I suggest you introduce a macro
Code:
#define WAIT_ZERO_CROSSING     while (!input(PIN_B0));



With all the given suggestions for improvements I have no clue as to what your current program looks like. Please incorporate all suggestions and post your most recent program code.
Moeini



Joined: 08 Aug 2006
Posts: 9

View user's profile Send private message Yahoo Messenger

PostPosted: Wed Sep 13, 2006 4:42 am     Reply with quote

Hi
for detection of all zerocrossing point must be determined falling edge and rising edge. therefore i think that use of both while(!input(PIN_B0)) and while(input(PIN_B0)) is required.
my code with most recent details is:

Code:
#include <16F877A.h>
//#device ICD=TRUE
#device adc=8
#fuses NOWDT,HS, NOPUT, NOPROTECT, NODEBUG, BROWNOUT, LVP, NOCPD, NOWRT
#use delay(clock=7673750,RESTART_WDT)
include <ide.h>
#byte   trisc=0x87
#bit    Xout=trisc.2
int i=0;

void start_code();
void send_one();
void send_zero();
void send_house();
void send_unit();
void send_command();


void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_1,15,1);
   setup_ccp1(CCP_PWM);
   set_pwm1_duty(32L);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   lcd_init();
   lcd_gotoxy(1,1);
   lcd_putc("X10 MODULE");

   while(1)
   {
      output_low(PIN_A1);//turn on LED for 0.5sec.
      delay_ms(500);
      output_high(PIN_A1);
     
      if(i>=3)  //transmit code every 3 seconds.
       {
        i=0;
        start_code();
        send_house();
        send_cammand();
        while(!input(PIN_B0));//wait 3 half cycles of ac line .
        while(input(PIN_B0));
        while(!input(PIN_B0));
        while(input(PIN_B0));
        while(!input(PIN_B0));
        start_code();
        send_house();
        send_command();
       }
     i++;
   }
}


/********************************
* SEND ZERO
* Effect:
 * this function will send a "0" bit using X-10
 * a "1" bit will follow on the next half-cycle
 * as a check
********************************/
void send_zero()
{
   while(!input(PIN_B0));//wait for zero crossing.
   xout=1;  //disable 120kHz out put.because Xout is an input pin.(#bit Xout=trisc.2)
   delay_ms(1);
   xout=1;  //disable 120kHz out put.( in reality do nothing.)

   while(input(PIN_B0));
   xout=0;    //enable 120kHz out put.because Xout is an output pin.
   delay_ms(1);
   xout=1;
}

/*********************************
*SEND ONE
*Effect:
* this function will send a "1" bit using X-10
* a "0" bit will follow on the next half-cycle
* as a check
**********************************/
void send_one()
{
   while(!input(PIN_B0));
   xout=0;
   delay_ms(1);
   xout=1;
   while(input(PIN_B0));
   xout=1;
   delay_ms(1);
   xout=1;
}

/*****************************************
*START CODE
*Effect:
* this function will send  "1110" bits using X-10
* without compliment of bit on the next half-cycle
******************************************/
void start_code()
{
   while(!input(PIN_B0));
   xout=0;
   delay_ms(1);
   xout=1;
   while(input(PIN_B0));
   xout=0;
   delay_ms(1);
   xout=1;
   while(!input(PIN_B0));
   xout=0;
   delay_ms(1);
   xout=1;
   while(input(PIN_B0));
   xout=1;
   delay_ms(1);
   xout=1;
}

void  send_house()
{
   send_zero();
   send_one();
   send_one();
   send_zero();
}

void  send_unit()
{
   send_zero();
   send_one();
   send_one();
   send_zero();
   send_zero();
}


void  send_command()
{
   send_zero();
   send_zero();
   send_zero();
   send_one();
   send_one();
}

please give me your email to send for you figures of my hardware and etc.

Best Regards
ckielstra



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

View user's profile Send private message

PostPosted: Fri Sep 15, 2006 6:42 pm     Reply with quote

To the other people following this thread: Moeini is using a slightly modified version of the Microchip X10 Application Note AN236. The zero crossing detection hardware in this setup is very simple, just a 5M resistor to the 110Vm using a technique described in AN521

I don't have time now to study all details but it looks like the zero crossing detection should work. Only problem I can see is that your implementation is waiting for a specific edge to happen before sending the first data bit. This is tricky, with a small delay in your program you will miss an edge and introduce an unwanted delay of two zero crossings ( = 2 unwanted zero bits in X10 protocol). Also check if your positive / negative edge sequence is correct for the total bit sequence (very tricky right now and you might consider a more advanced approach).

Change the LVP fuse to NOLVP, you are not using an low voltage programmer. Setting this fuse in a circuit where the LVP pin is used as a normal I/O pin will lead to erratic behaviour.

Quote:
In the output of my circuit (in proteus software) there is a 120kHz burst that is created every 10ms and move on the osciloscope area continuously. It means that it starts from the begining of the osciloscope area and it passes and it repeats again from the begining of the osciloscope area and we dont know what it is.
This might have to do with your scope settings. When set to continuous trigger mode the scope will overlay each previous pattern and you will see a pattern of only 120kHz bursts. Maybe when looking carefully at the scope you can see the graph of the zero-line as well?
Moeini



Joined: 08 Aug 2006
Posts: 9

View user's profile Send private message Yahoo Messenger

PostPosted: Mon Sep 18, 2006 12:43 am     Reply with quote

Quote:

with a small delay in your program you will miss an edge and introduce an unwanted delay

For prevent of this, what do I do ?
Quote:
check if your positive / negative edge sequence is correct for the total bit sequence

Please explain more.
best regards
ckielstra



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

View user's profile Send private message

PostPosted: Mon Sep 18, 2006 12:22 pm     Reply with quote

Moeini wrote:
Quote:

with a small delay in your program you will miss an edge and introduce an unwanted delay

For prevent of this, what do I do ?
A quick and dirty approach is to ensure you have no long delays when transmitting data, i.e. no delay_ms calls and no printf statements. Before or after transmitting you can do all the slow things but just make sure you don't call any of these functions when transmitting. That said, I don't like quick-and-dirty because in two weeks I forgot this special requirement and am spending two days looking for the bug elsewhere. A better approach would be to transmit the data under interrupt control: first prepare your whole data stream and then have it transmitted in the background. More work, but you don't have to worry about other functions messing up your timing.


Moeini wrote:
Quote:
check if your positive / negative edge sequence is correct for the total bit sequence

Please explain more.
Your current implementation is very sensitive for the correct sequence of rising and falling edges of the zero-crossing detector. I was just wondering if your program was working correctly in this respect. For example like after sending the Start Code would it matter if the next data to be send was a 0 or 1? I didn't want to spend time checking this and left it for you to check. My first impression is that there is no problem.
Moeini



Joined: 08 Aug 2006
Posts: 9

View user's profile Send private message Yahoo Messenger

PostPosted: Tue Sep 19, 2006 12:13 pm     Reply with quote

Hi.
i wrote the code with use of overflow interrupt of timer0
to time the duration of the 1ms 120kHz burst and external interrupt
for zero crossing detect. please study it and tell me its errors.
Best Regards

Code:
  #include <CCS T1.h>

   #define Falling 1
   #define Rising  0
   #byte   trisc=0x87
   #bit    Xout=trisc.2
   #byte   status=0x3
   #bit    carry=status.0
   int1    X10TxFlag;
   int1    RxBit,TxBit;
   int1    TxCommandFlag=1,SecondTxFlag;
   int     TXData3=0,TxData2=0,TxData1=0,TxData0=0;
   int     NumTxBit,count,w,i;
   int     TxHouse,TxUnit,TxFunction;
   int1      ext_edge=Falling;
   VOID    InitX10Tx();
   void    RotateTxData(w);

#int_EXT
EXT_isr()
{
/********************TransmitX10Bit*****************************/
/*performed at every ZeroCrossing.
/*if TxBit=1,enable 120khz output for 1ms otherwise, do nothing.
/***************************************************************/
   if(TxBit ==0)//TxBit=transmitted bit at every zerocrossing.
   RxBit=0;
   else
   {
    Xout=0;    //enable 120khz output.
    enable_interruptS(INT_timer0);// Timer0 is used to time the duration of the 1ms 120kHz burst.
    RxBit=1;//(This assures reception of own transmission)
   }

   TxBit=0;

/****************** X10Tx() ************************/
/*Transmit 22 bits of data out of TXData registers
/*Rotate by 10 to reposition TXData
/*Transmit 28 bits of data out of TXData registers
/*for secend Transmission that 6 bits is zero
/*for determine end of packet
/***************************************************/
   if(X10TxFlag==1)//if transmission isnot complete perform the below operations:
   {
    TxBit=bit_test(TxData3,7);
    carry=TxBit;
      #asm
    rlf TxData0,f
    rlf TxData1,f
    rlf TxData2,f
    rlf TxData3,f
    #endasm
    NumTxBit--;
    if(NumTxBit ==0)  //Have all the bits been sent?
    {
     if(SecondTxFlag==0)//Yes, was this the second transmission?
      {
        SecondTxFlag=1;//No, set up for second transmission and
                      //Set the flag to indicate second transmission.
        w=10;
        RotateTxData(w);//Reposition data at left end of buffer.
        NumTxBit=28;    //Send 22 bits again.(with 6 zero bits at end.)
      }
      else
      X10TxFlag=0;    //clear X10TxFlag,to introduce that last transmit is done.
    }
   }

/*******************ToggleInterruptEdge***********************/
/*Toggles interrupt edge so that interrupt are generated
/*on both rising and falling zero-crossings on RB0/INT pin.
/*************************************************************/

   if (ext_edge == Falling)
    ext_int_edge(L_TO_H);
   else
    ext_int_edge(H_TO_L);
    ext_edge++;
}

#int_TIMER0
TIMER0_isr()
{
   Xout=1; // disable 120khz output,for End X10 Envelope.
   disable_interrupts(INT_timer0);
}



void main()
{

   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_8);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_1,15,1);
   setup_ccp1(CCP_PWM);
   set_pwm1_duty(32L);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_EXT);//Enable external Interrupt for ZeroCrossing points Detection.
   enable_interrupts(INT_TIMER0);//Enable Timer0 Overflow Interrupt.
   enable_interrupts(GLOBAL);
   ext_int_edge(H_TO_L);// initiation ZeroCrossing Detect
   enable_interrupts(INT_ext);
   InitX10Tx();
   //lcd_init();
   TxHouse=01101001;//load TxHouse with housecode=A
   TxUnit=01101001; //load TxUnit with unitcode=1
   TxFunction=01011001;//load TxFunction with Function=on
}

/*********************RotateTxData()**************************/
/*Rotates data in TxData register to left by number in Wreg
/*************************************************************/
void RotateTxData(w)
{
   count=w;
   for (i=0;i<w;i++)
   {
   carry=bit_test(Txdata3,7);
   #asm
   rlf TxData0,f
   rlf TxData1,f
   rlf TxData2,f
   rlf TxData3,f
   #endasm
   }
}
/**************************InitX10Tx()************************************/
/* prepare whole data stream for transmission,with the folloing sequence:
/*startcode/housecode/unitcode or functioncode
/*************************************************************************/
VOID InitX10Tx()
{
   TxData3=0b00001110;   //load TxData3 with start code.
   TxData2=TxHouse;      //load TxData2 with house code.
   if(TxCommandFlag==1)  //is the transmit command flag set?
   {
    TxData1=TxFunction;  //yes,then prepare to transmit command.
    TxData0=0b10000000;//load suffix for command into TxData0.
   }
   else
   {
    TxData1=TxUnit;      //no,then prepare to transmit an address.
    TxData0=0b01000000;//load suffix for unit address into TxData0.
   }
   w=4;
   RotateTxData(w); //rotate the TxData registers 4 times to
   //the left to prepare for transmission.with this action the extra zero bits go to end of Txdata0(LSB bits)
   NumTxBit=22;   //set number of bites to transmit.
   SecondTxFlag=0;//clear SecondTxFlag because this is first transmisson.
   X10TxFlag=1;   // Set the X10TxFlag to begin transmission.
}


Last edited by Moeini on Wed Sep 20, 2006 2:21 am; edited 1 time in total
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 1, 2  Next
Page 1 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