|
|
View previous topic :: View next topic |
Author |
Message |
young
Joined: 24 Jun 2004 Posts: 285
|
|
Posted: Thu Feb 24, 2005 8:26 am |
|
|
Hi Humberto:
here is the code that I changed according to your advised bit by bit manchester data transmitting, please have a check if I am doing correct, specially about the timing
Code: |
/*********************************************************/
/* */
/* Send Manchester data bit by bit */
/* */
/*********************************************************/
#if defined(__PCM__)
#include <16F819.h>
#include <stdio.h>
#include <stdlib.h>
#fuses HS,WDT,NOPROTECT
//#device ADC=10
#use delay(clock=10000000)
#use rs232(baud=2400, parity=N, xmit=PIN_A0)
#define M_Tx_Pin PIN_A1
void SEND_DATA(BYTE txbyte)
{
int i,j,b,me;
b = txbyte;
for (i=0; i<2; i++)
{
delay_ms(10);
me = 0; // manchester encoded txbyte
for (j=0 ; j<4; j++) {
me >>=2;
if (bit_test(b,0) )
me |= 0b01000000; // 1->0
else
me |= 0b10000000; // 0->1
b >>=1;
}
//send data bit by bit through M_Tx_Pin for every 416.66 ms
for(i=0;i<8;i++)
{
//putc(me);
if(bit_test(me,i))
output_high(M_Tx_Pin);
else
output_low(M_Tx_Pin);
delay_us(417);
}
}
}
//
void remoteprintf(char *c)
{
int8 i,length;
length=strlen(c);
//premable data to init TWS
for(i=0;i<4;i++)
{
output_low(M_Tx_Pin);
delay_us(417);
}
// send data
for (i=0; i<length;i++)
SEND_DATA(c[i]);
//send stop
for(i=0;i<4;i++)
{
output_high(M_Tx_Pin);
delay_us(417);
}
}
void main()
{
char data[]="I am flying!";
setup_port_a(ADC_OFF);
set_tris_a(0xf3);
setup_CCP1(CCP_OFF);
setup_timer_1(T1_DISABLED);
enable_interrupts(global);
while(1)
{
remoteprintf(data);
}
}
|
|
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu Feb 24, 2005 9:15 am |
|
|
Imanjl wrote:
Quote: |
I put a scope probe on the rx output of rf module and the waveform was
a continuous 01010101 bit with this pattern if we route this pin to PIC RX
input It always fills the buffer and aslo generate RDA interrupt that is
unwantted ..
|
I wrote:"To detect the data you need to know what is the iddle state of Rx
output in the RWS434 receiver."
1)Receiver Iddle state = no RF present
2)I never mention to enable RDA interrupt. To receive this kind of signal,
you must write a software handler.
3)As you see, DATA info has a transition in every bit. The idea to send the
sequence 0000 is to detect a LOW STATE 4 times longer than a
LOW in the DATA frame and validate it as a START.
Sending the sequence 1111 is to detect a HIGH STATE 4 times longer
than a HIGH in the DATA frame and validate it as a STOP.
START and STOP are used only as header and trailer
0000 + 1111 give you a null DC component in your DATA packets (D).
Example:
START DDDDDDDDDDDDDDDD STOP
Humberto |
|
|
young
Joined: 24 Jun 2004 Posts: 285
|
|
Posted: Thu Feb 24, 2005 9:42 am |
|
|
remodified encoding file
Code: | /*********************************************************/
/* */
/* Send Manchester data bit by bit */
/* */
/*********************************************************/
#if defined(__PCM__)
#include <16F819.h>
#include <stdio.h>
#include <stdlib.h>
#fuses HS,WDT,NOPROTECT
//#device ADC=10
#use delay(clock=10000000)
#use rs232(baud=2400, parity=N, xmit=PIN_A0)
#define M_Tx_Pin PIN_A1
void SEND_DATA(BYTE txbyte)
{
int i,j,b,me;
b = txbyte;
putc(txbyte);
for(i=0;i<8;i++)
{
if(bit_test(me,i))
{ output_high(M_Tx_Pin);
delay_us(417);
output_low(M_Tx_Pin);
delay_us(417);
}
else
{ output_low(M_Tx_Pin);
delay_us(417);
output_high(M_Tx_Pin);
delay_us(417);
}
}
}
//
void remoteprintf(char *c)
{
int8 i,length;
length=strlen(c);
//premable data to init TWS
for(i=0;i<4;i++)
{
output_low(M_Tx_Pin);
delay_us(417);
}
// printf("length: %u\r\n",length);
// send data
for (i=0; i<length;i++)
SEND_DATA(c[i]);
//send stop
for(i=0;i<4;i++)
{
output_high(M_Tx_Pin);
delay_us(417);
}
}
void main()
{
char data[]="bc";
setup_port_a(ADC_OFF);
set_tris_a(0xf3);
setup_CCP1(CCP_OFF);
setup_timer_1(T1_DISABLED);
enable_interrupts(global);
while(1)
{
remoteprintf(data);
}
}
|
|
|
|
young
Joined: 24 Jun 2004 Posts: 285
|
|
Posted: Thu Feb 24, 2005 9:58 am |
|
|
Hi Humberto:
Great appreciation for your come back!
I put a delay after my sending data
while(1)
{
remoteprintf(data);
delay_ms(100);
}
and find out that my idal state of Rx is High.
Here I have three questions
1. This the timing delay after sending each individual bit delay_us(417) right,
2. I am really not sure how to detect start and stop bit even It is clear in concept, I do not not how to program it?
3. during the ideal states there are some noise (it is not alway high, occassionally, there is low signal also, is it normal?
Would you please help |
|
|
young
Joined: 24 Jun 2004 Posts: 285
|
|
Posted: Thu Feb 24, 2005 10:18 am |
|
|
another problem I found is that between each byte (not bit) there is period of low signal for the program, I made, which I think it should not be there, why? |
|
|
young
Joined: 24 Jun 2004 Posts: 285
|
|
Posted: Thu Feb 24, 2005 10:22 am |
|
|
and why I delete the delay_ms(100) after sending the data, the above low level signal will be gone, all the data is just as what you describs
start data stop, why this delay is so trouble making? |
|
|
young
Joined: 24 Jun 2004 Posts: 285
|
|
Posted: Thu Feb 24, 2005 11:41 am |
|
|
saw some posts that use interrupt to decode the received data, here is my proposal, is this right?
1. define the external interrupt Pin as Receive Pin
#define M_Rx_Pin PIN_B0 //(16f819) at edge H_L
2. when a exteral interrupt occured, the external interrupt routine (Ext_int)will setup a timer, for example timer0(Timer_int);
3. Timer0 will count the time, if time reach a certain value; it will invoke (Timer_int);
4. in the routine(Timer_int); will disable external interrupt routine,read input data from the M_Rx_Pin for every certain time period, and at same time setup external interrupt as low to high, at setup timer, if timer reach a certain period, means a stops bit being encounted, end the reading data.
is this doable? |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu Feb 24, 2005 12:28 pm |
|
|
Hola young,
Sorry for this delay but I had been busy.
I preffer that you work, not me and I want to say you that I like the
way you solve the routine SEND_DATA(BYTE txbyte) it's a very
good aproach and the most important: you learn
Quote: |
Here I have three questions
1. This the timing delay after sending each individual bit delay_us(417) right,
2. I am really not sure how to detect start and stop bit even It is clear in concept, I do not not how to program it?
3. during the ideal states there are some noise (it is not alway high, occassionally, there is low signal also, is it normal?
|
1. YES. Baud is the number of signal level changes per second in a
communication line, regardless of the information content of those
signals. Bits per second is the rate of transfer of information bits.
The ratio of BPS to baud depends on the information coding
scheme that you are using. 1 or 2 Stop bit, Parity, etc
For example, each character in asynchronous RS232 coding includes a
start and stop bit that are not counted as information bits, so
the BPS rate is actually less than the baud rate.
2.Fortunately there are a few options:
a) Using CCP
b) Using INT_EXT + any TIMER
c) Polling + TIMER (Higher overhead)
3.The receiver is very noisy when it's in iddle state because it is
sensing another RF sources so itīs normal. The way to "wake up" is
sending a "strong and heavy signal" like 0000111100001111 to
differentiate from the iddle state. With this example we get a square wave
with 1.66ms LOW followed by 1.66ms HIGH. This is critical for proper
operation ot the receiver because it is AC coupled.
Quote: |
another problem I found is that between each byte (not bit) there is period of low signal for the program, I made, which I think it should not be there, why?
|
Don't understand, sorry.
Humberto |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu Feb 24, 2005 12:49 pm |
|
|
young wrote:
Quote: |
saw some posts that use interrupt to decode the received data, here is my proposal, is this right?
1. define the external interrupt Pin as Receive Pin
#define M_Rx_Pin PIN_B0 //(16f819) at edge H_L
2. when a exteral interrupt occured, the external interrupt routine (Ext_int)will setup a timer, for example timer0(Timer_int);
3. Timer0 will count the time, if time reach a certain value; it will invoke (Timer_int);
4. in the routine(Timer_int); will disable external interrupt routine,read input data from the M_Rx_Pin for every certain time period, and at same time setup external interrupt as low to high, at setup timer, if timer reach a certain period, means a stops bit being encounted, end the reading data.
is this doable?
|
YES, thatīs the way
Tell us your result.
Humberto |
|
|
young
Joined: 24 Jun 2004 Posts: 285
|
|
Posted: Thu Feb 24, 2005 12:55 pm |
|
|
thank you Humberto:
When you come back, I am alive again! The way I talk, and the way you explain to me, keep me thinking for new approaches!
I am writing program using external interrupt + timer to decode the data right now, I changed a little bit of my proposal in the last post.
Quote: |
1. define the external interrupt Pin as Receive Pin
#define M_Rx_Pin PIN_B0 //(16f819) at edge H_L
2. when a exteral interrupt occured, the external interrupt routine (Ext_int)will setup a timer, for example timer0(Timer_int);
3. Timer0 will count the time, if time reach a certain value; it will invoke (Timer_int);
4. in the routine(Timer_int); will disable external interrupt routine,read input data from the M_Rx_Pin for every certain time period, and at same time setup external interrupt as low to high, at setup timer, if timer reach a certain period, means a stops bit being encounted, end the reading data.
|
It is a little data check, if I am receiving data, data bit number is a integer num, and num divide by 8 is one byte, when stop bit occured, I will remove any data that is over the exactly 8 times of data:
hard to explain: I will do this,
if I received 20 bit of data, and stop bit occured, 20/8 the left over is 4, so I will just keep the first 16 bit of data and remove the rest 4 bit of data.
please evaluate my approach. |
|
|
languer
Joined: 09 Jan 2004 Posts: 144 Location: USA
|
|
Posted: Thu Feb 24, 2005 2:27 pm |
|
|
This is an excellent thread.
I just want to add the following link with code for manchester comms between PICs. The author uses another 'cool' trick for the coding/decoding. Anyway, hope it helps.
http://www.ottawarobotics.org/articles/rf/rf.html
Also, I have been able to do burst-communications by applying suggestions previously posted by Humberto and Ttelmah, something like this:
Code: | #define junk 0xAA
#define STX 0xF3
#define ETX 0xCF
...
void xmt()
{
output_high(RFEN); // enable rfPIC & stabilize PLL
delay_ms(5);
output_high(DATA); // warmup receiver
delay_ms(15);
for (n=0;n<5;n++)
{
putc( junk ); // unbias data-slicer
}
for ( n = 0; n < (bufferSize - 1) ; n++ )
{
printf( "%c%u%c",STX,n,ETX ); // send byte
}
delay_us(50);
output_low(RFEN); // disable rfPIC
} |
The use of STX and ETX to properly identify your good character works great because (if properly selected), the receiver has some inmunity to receiving bad characters. When it does however, they are lost (i.e. if the character does not follow the STX-CHR-ETX it is thrown out). They do not have to, you could implement error correction but that's more overhead on the link. Choosing STX and ETX is also very important as you have to choose something that provides some inmunity to noise (a series of "1010..." are bad because noise is very correlated to this), better links would have more than one STX and ETX (more like, STX1-STX2-STX3 etc) which provides even better inmunity.
Understand that "plain" manchester encoding/decoding only improves the probabilty of receiving the characters, but does nothing against receiving noise. It is error detection (which Ttelmah's example had, and the link above does too), error correction, and some communication protocol helps you on this.
I am currently working on implementing the code provided on the above link over RS232 comms (having a little trouble on the receive side).
just my two cents... |
|
|
young
Joined: 24 Jun 2004 Posts: 285
|
|
Posted: Mon Feb 28, 2005 12:08 pm |
|
|
Hi Humberto:
Here is the program for encoding and decoding, so far I saw at the receiver that the data I transfer from the TWS is received by RWS correctly, However, I am having a little bit of problem decoding it.
encoding
Code: |
/*********************************************************/
/* */
/* Send Manchester data bit by bit */
/* */
/*********************************************************/
#if defined(__PCM__)
#include <16F819.h>
#include <stdio.h>
#include <stdlib.h>
#fuses HS,NOWDT,NOPROTECT
//#device ADC=10
#use delay(clock=10000000)
#use rs232(baud=9600, parity=N, xmit=PIN_A0)
#define M_Tx_Pin PIN_A1
void SEND_DATA(BYTE txbyte)
{
int i,j,b;
b = txbyte;
// putc(txbyte);
for(i=0;i<8;i++)
{
if(bit_test(b,i))
{ output_high(M_Tx_Pin);
delay_us(417);
output_low(M_Tx_Pin);
delay_us(417);
}
else
{ output_low(M_Tx_Pin);
delay_us(417);
output_high(M_Tx_Pin);
delay_us(417);
}
}
}
//
void remoteprintf(char *c)
{
int8 i,length;
length=strlen(c);
//premable data to init TWS
for(i=0;i<4;i++)
{
output_low(M_Tx_Pin);
delay_us(417);
}
// printf("length: %u\r\n",length);
// send data
for (i=0; i<length;i++)
SEND_DATA(c[i]);
//send stop
for(i=0;i<4;i++)
{
output_high(M_Tx_Pin);
delay_us(417);
}
}
void main()
{
char data[]="bc";
setup_port_a(ADC_OFF);
set_tris_a(0xf3);
setup_CCP1(CCP_OFF);
setup_timer_1(T1_DISABLED);
enable_interrupts(global);
while(1)
{
remoteprintf(data);
delay_ms(1);
}
}
|
decoding
Code: |
/*********************************************************/
/* */
/* Decoding Manchester data bit by bit */
/* */
/*********************************************************/
#if defined(__PCM__)
#include <16F819.h>
#Device *=16
#include <stdio.h>
#include <stdlib.h>
#fuses HS,NOWDT,NOPROTECT,NOBROWNOUT
//#device ADC=10
#use delay(clock=10000000)
#use rs232(baud=9600, parity=N, xmit=PIN_A0, rcv=PIN_A1,ERRORS)
#define M_Rx_Pin PIN_B0
int16 data_ori[40];
char data_decod[40];
char status; //data 1 start 0 stop
int8 bit_num,data_num,i,j,k;
int1 tem;
#int_ext //allow ext interrupt
int_isr() //Interrupt Service Routine
{
if(status==1)
set_timer0(0); //Set Timer 0 to zero equal to 256*6.4=1638.4us
if(status==0);
set_timer1(0);
}
#INT_TIMER0
timer0_isr()
{
EXT_INT_EDGE(L_TO_H);
disABLE_INTERRUPTS(INT_TIMER0);
ENABLE_INTERRUPTS(INT_TIMER1);
enable_interrupts(int_ext); //Allow ext Interrupt on Rb0
enable_interrupts(global); //Allow Global Interrupt
status=0;
}
#INT_TIMER1
timer1_isr()
{
EXT_INT_EDGE(H_TO_L);
disABLE_INTERRUPTS(INT_TIMER1);
ENABLE_INTERRUPTS(INT_TIMER0);
enable_interrupts(int_ext); //Allow ext Interrupt on Rb0
enable_interrupts(global); //Allow Global Interrupt
status=1;
}
void main()
{
char data1[20],datar,ddl,ddh,datadecode;
char firstbit;
status=1; //data pre and post part
SET_TRIS_b(0xff);
set_Tris_a(0x00);
SETUP_CCP1(CCP_OFF);
SETUP_ADC_PORTS(NO_ANALOGS);
SET_TIMER0(RTCC_DIV_16|RTCC_Internal);
setup_timer_1(T1_DIV_BY_8 |T1_INTERNAL ); //Timer 1 Setup
ext_int_edge(H_TO_L); //Wait for falling edge--> then jump to Interrupt Service Routine
enable_interrupts(int_ext); //Allow ext Interrupt on Rb0
ENABLE_INTERRUPTS(INT_TIMER0);
ENABLE_INTERRUPTS(INT_TIMER1);
enable_interrupts(global); //Allow Global Interrupt
status=0; //lsb part
bit_num=0;
firstbit=0;
while(1)
{
//start bit detected after H_TO_L edge and certain time period
if(status==0)
{
//Start reading bit by bit for every certain time period
if(firstbit==1)
{delay_us(179); firstbit=0;} //take the data at the input wave center of the first bit
//179+29=208=417/2 1638us timer0 interrupt, delay start bit =4*417=1667
//1667-1638=29
else
delay_us(417);
tem=input(PIN_B0);
data_num=bit_num/16; //
j=bit_num%16;
if(tem==1)
{ bit_set(data_ori[data_num],j); }
else
{ bit_clear(data_ori[data_num],j);}
bit_num++;
}
//stop bit detected after L_TO_H detected
if(status==1)
{
firstbit=1;//process the data (decoding the data)
for(i=0;i<data_num;i++)
{
for(k=0;k<8;k++)
{
if((bit_test(data_ori[i],2*k)==1) && ((bit_test(data_ori[i],2*k+1)==0)))
bit_set(data_decod[i],k);
else if((bit_test(data_ori[i],2*k)==0) && ((bit_test(data_ori[i],2*k+1)==1)))
bit_clear(data_decod[i],k);
}
}
data_decod[data_num+1]='\0';
// printf("Data_num: %u\r\n",data_num);
puts(data_decod);
}
}
}
|
I am sending data as these format:
starting bit (4)
1 delay_us(417) 1 delay_us(417) 1 delay_us(417) 1 delay_us(417)
data
bit by bit with a 417us delay;
stopping bit
0 delay_us(417) 0 delay_us(417) 0 delay_us(417) 0delay_us(417)
receiving method:
1. setup a external interrupt RB0 (PIN_RB0):
in this routine set timer0 or timer1 for start or stop detection.
2. in timer0 routine:
change external interrrupt int as L_T_H to detecting stop bit, and set status as 0, which means after detecting the external interrupt a certain period (4 start bit delay time), which means the program is facing the data right now
3. in timer1 rountine
change external interrupt as H_T_L to detect start bit,and set status as 1, which means after detecting the external interrupt a certain period (4 stop bit delay time), which means the program is facing the stop bit right now
4. in main rountin:
keep checking start status,if status=0, and it there is no data receive yet, set first bit staus and start a delay which is eaqual to the middle of rhe first bit, else the first bit have been taken then take another 417 us delay for the continuous data.
if status=1 stop bit, then in this routine, decode every bit back to original bit sent from the TWS. |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Mon Feb 28, 2005 3:14 pm |
|
|
Hi young,
Well, I have been reading your code and ufff!! itīs not easy to
understand and I donīt have all the time for this, at least letīs assume
that itīs complex and twisted.
Remember what I said you in the beggining of this thread, that itīs not
the only or the best way to do this, but such method was very easy
and self demostrative just to explain the idea.
Now that you have a better understanding of what and how to do it, we
can go to the site that you mention:
http://www.quickbuilder.co.uk/qb/articles/
where there are a less complex encoding/decoding technique that I
suggest we can follow, to save our sanity.
Let me know if you are agree.
Humberto |
|
|
Guest
|
|
Posted: Mon Feb 28, 2005 3:26 pm |
|
|
Thank you:
My purpose is to make the system work,, no matter what the code could be. |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Mon Feb 28, 2005 4:17 pm |
|
|
I didnīt test it but it seems easy to impliment, you can use the UART and
all the advantages of the rs232 built in functions like kbhit() and getc().
Humberto |
|
|
|
|
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
|