|
|
View previous topic :: View next topic |
Author |
Message |
Moeini
Joined: 08 Aug 2006 Posts: 9
|
generate 120kHz + zerocrossing detect+emergency |
Posted: Wed Sep 06, 2006 1:09 am |
|
|
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
|
|
Posted: Wed Sep 06, 2006 11:53 am |
|
|
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
|
120khz burst with 1ms long |
Posted: Thu Sep 07, 2006 9:19 am |
|
|
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
|
|
Posted: Thu Sep 07, 2006 9:57 am |
|
|
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
|
|
Posted: Thu Sep 07, 2006 10:02 am |
|
|
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
|
|
Posted: Fri Sep 08, 2006 8:40 am |
|
|
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
|
|
Posted: Sun Sep 10, 2006 11:09 pm |
|
|
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
|
|
Posted: Mon Sep 11, 2006 2:38 am |
|
|
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
|
|
Posted: Tue Sep 12, 2006 11:03 am |
|
|
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
|
|
Posted: Tue Sep 12, 2006 3:28 pm |
|
|
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
|
|
Posted: Wed Sep 13, 2006 4:42 am |
|
|
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
|
|
Posted: Fri Sep 15, 2006 6:42 pm |
|
|
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
|
|
Posted: Mon Sep 18, 2006 12:43 am |
|
|
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
|
|
Posted: Mon Sep 18, 2006 12:22 pm |
|
|
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
|
|
Posted: Tue Sep 19, 2006 12:13 pm |
|
|
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 |
|
|
|
|
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
|