View previous topic :: View next topic |
Author |
Message |
zonemikel
Joined: 13 Oct 2007 Posts: 53 Location: Texas
|
Sending "packets" using RS-232, is this a good ide |
Posted: Wed Aug 18, 2010 6:18 pm |
|
|
Hello thanks for all your previous help !
I'm trying to send out tons of data from the pic over a wireless transceiver to another wireless transceiver. Since the data is always pretty much the same I have developed a packet format. I take the data in on the non pic side using C# software that I have created.
Anyway I don't want to convolute the question with too many details.
When I do something like
Code: |
unsigned byte test = 0xFF;
printf("%c",test);
|
Q1:
Does it convert the byte into a char and then send it out? Or does it see that its not in the "char" range and do something else ?
I know I can use "%x" but then I end up sending out two bytes where I only need to send out one. Because 0b11111111 is one byte and 255 decimal or 0xFF hex but if i use the %x then I'm sending out 2 chars which is 16 bits, I don't want to send out twice as much data as i need to !
Q2:
Mainly I'm trying to send 8 bit ADC conversion data, what would be the best way to send this over the UART ? That is what is the best way to send values 0-255 decimal by transmitting only 8 bits of data (plus parity or whatever small overhead rs-232 has).
Thanks, I've been wrestling with this for a while. Just trying to regroup my thoughts and make sure I haven't over/under thought it before I continue. _________________ Smart people know how stupid they are. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Aug 18, 2010 7:33 pm |
|
|
Make a test program and look at the .LST file. What does the following
code do ? It moves 'test' into the W register. Then it waits in a polling
loop, while testing for the TXIF flag to go high. Then it puts the data into
the TXREG, which lets the UART send it out. So, it doesn't change the
value in 'test' before it sends it.
Code: |
.................... unsigned byte test = 0xFF;
....................
.................... printf("%c",test);
0026: MOVF test,W
0028: BTFSS PIR1.TXIF
002A: BRA 0028
002C: MOVWF TXREG
|
I compiled this for an 18F452. |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
Re: Sending "packets" using RS-232, is this a good |
Posted: Wed Aug 18, 2010 8:56 pm |
|
|
zonemikel wrote: | Hello thanks for all your previous help !
I'm trying to send out tons of data from the pic over a wireless transceiver to another wireless transceiver.... |
You can send binary unstructured data or you can send structured data. It really depends on the type of data you are sending and what you want to do in the event of packet loss/corruption, what you mean by "tons of data", the data rate of your wireless link, the reliability of the wireless link and the spare capacity of the link actual bytes per second in versus the baud rate of the link.
If you have a fixed length packet format then you could use a message start delimiter, a fixed length payload, a CRC or other form of payload validation and an end of message delimiter. With this approach you can have the start and end delimiters also embedded in the payload providing your parsing logic was able to resync on false start/end of the message detection.
Two variants on this would be to support a variable length payload by incorporation a length field and another is to use escape processing when if you detect a start or end delimited in the message you immediately prepend it with a escape delimiter which could be the start or end delimited or another character which must also be delimited. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
zonemikel
Joined: 13 Oct 2007 Posts: 53 Location: Texas
|
|
Posted: Wed Aug 18, 2010 10:08 pm |
|
|
I made up a packet structure in which it was like
receiver|sender|flags|number|data|CRC
except for the data all those are one byte (at least thats the plan so far) the data will contain bytes also but it will be a few of them holding some ADC values. They are fixed length packets.
On the receiving end i check for the first two bytes before I even start to read the rest of the "packet", in this way you could have multiple devices and senders/receivers (in theroy!).
I'm able to transmit at 19200 baud, and I cant change that.
Its working pretty well so far, I just wanted to be sure I was not setting myself up for failure later. I thought maybe by sending it through printf or putc I was appending something to the data, kind of like the actual byte 1 is 0b00000001 but you can append a 11 to the right side to make it a char 0b11000001.
But as pcmProg pointed out thats not the case (I think thats what you said) but just to be clear when i send 0b00000001 for example
printf("%c", '0x01');
can i expect to receive '0x01' on the other end or '0x31' which is the char '1' thats where my confusion lies.
I know, I know just make a test program. I'll do it tomorrow.
Thanks guys ! If I get something good I'll post it in here for others to use, got a ways to go before that. _________________ Smart people know how stupid they are. |
|
|
MikeW
Joined: 15 Sep 2003 Posts: 184 Location: Warrington UK
|
|
Posted: Thu Aug 19, 2010 12:21 am |
|
|
I did a similar thing years ago, but I also added a messagenumber, which was simply an incrementing number from the previous message, so it started at 0-255 and rolled over.
That way when you do the error checking and resending etc, you don't mistake the resend for a new message.
Your flags byte is just a part of the data bytes, so you don't need to highlight it in the basic format, better to define that in the data byte format.
startof packet|receiver|sender|messagenumber|numberofdatabytes|data|CRC|end of packet
Start of packet is typically STX, end of packet is ETX characters.
Also, you will need to check every character going out for STX and ETX in the stream, and if found send it twice, and of course remove it at the other end, to enable those characters to not be interpreted as real STX or ETX (its called byte stuffing).
Hope thats clear.
The main thing is to try to think of all possible errors, and cater for them.
Mike
Last edited by MikeW on Thu Aug 19, 2010 1:06 am; edited 1 time in total |
|
|
asmallri
Joined: 12 Aug 2004 Posts: 1634 Location: Perth, Australia
|
|
Posted: Thu Aug 19, 2010 12:58 am |
|
|
MikeW wrote: | (its called bit stuffing). |
It is called byte stuffing. Bit stuffing is a lower level mechanism used by some link layer protocols. _________________ Regards, Andrew
http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!! |
|
|
zonemikel
Joined: 13 Oct 2007 Posts: 53 Location: Texas
|
|
Posted: Thu Aug 19, 2010 7:33 am |
|
|
Quote: | The main thing is to try to think of all possible errors, and cater for them. |
oh is that all !
The flags are not part of the header so I see why you say they could be part of the "data", its just that the "data" is just a few chars/bytes anyway and each one is explicitly defined. My "data" consists of about 6 different bytes from different ADC conversions. The flag on the incoming packet tells the pic which adc conversions to send in the outgoing packet.
I'll see how far I can get today. _________________ Smart people know how stupid they are. |
|
|
zonemikel
Joined: 13 Oct 2007 Posts: 53 Location: Texas
|
Finally found out whats wrong !!! |
Posted: Thu Aug 19, 2010 2:04 pm |
|
|
well after ripping my hair out all morning i finally found out what is going wrong.
I made the pic parrot back the packet from the computer, everything works Great except . . . as soon as we get to any values higher than 0x3F the pic stays stuck at 0x3F or even seems to flood over into the next var.
so if i send the packet (in hex separated by '.'s)
31.31.80.73.00.00.00.
i get back from the pic
31.31.3F.3F.00.00.00.
3F just happens to be 0b00111111 so that must have some thing to do with it. I've tried unsigned char, char and unsigned int8 they all seem to do the same thing.
Code: |
// the variables
#define incPKT_sz 8 // incoming packet size
#define outPKT_sz 8 // outgoing packet size
char incPKT[incPKT_sz]; // x byte incoming packet
char outPKT[outPKT_sz]; // x byte outgoing packet
int8 pktIndex = 0; // packet index (see interrupt RDA)
// the part that stores the packet
#int_rda
void serial_isr() {
incPKT[pktIndex] = fgetc(wireless);
// if it is for us then start filling buffer, else we stay at 0
if(pktIndex == 0 && incPKT[pktIndex] == ID){
pktIndex++;}
// if it is from the server we want to lisetn too then continue
else if(pktIndex == 1 && incPKT[pktIndex] == serverID){
pktIndex++; }
// if its for us from the guy we want to listen too get it !
else if(pktIndex < incPKT_sz && pktIndex > 1){
pktIndex++; }
// if we are on 63 we have received 64 bytes our packet is done
else if(pktIndex >= incPKT_sz){
state = NEWPACKET; // set new packet to 1 so we process the packet
if(pktCount < 255){pktCount++;}else{pktCount = 0;} // int8 max = 255
pktIndex = 0; // reset our index
}else{
pktIndex = 0; // first two bytes were incorrect, start over
}// end if
}
// the part that sends the packet back (note its the same as the rx'ed packet)
void sendPacket(int1 increment){ // send the packet out
if(increment && pktCount < 255){ // if they want to increment the pkt cnt
pktCount++; // increment it
outPKT[3] = pktCount; // update packet
} else if(increment){
pktCount = 0; // 0 it
outPKT[3] = pktCount; // update packet
}
for(i=0; i <= outPKT_sz; i++){
putc(incPKT[i], wireless);
}
}
|
Anyone know whats going on ? i guess for testing i'll try and limit my values to less than 64, but thats why my ADC values are coming back weird .. i was wondering why the hell they were all 3F i thought the error was elsewhere.
thanks ! _________________ Smart people know how stupid they are. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 19, 2010 2:52 pm |
|
|
I would test it with a much more simple echo program.
Try something like this:
Code: |
#include <16F877.H>
#fuses XT, NOWDT, BROWNOUT, PUT, NOLVP
#use delay(clock=4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
//====================================
void main()
{
char c;
while(1)
{
c = getc();
putc(c);
}
} |
|
|
|
zonemikel
Joined: 13 Oct 2007 Posts: 53 Location: Texas
|
|
Posted: Thu Aug 19, 2010 5:18 pm |
|
|
Well this is weird !!! Sometimes it does and sometimes it does not.
This is my code (all of it), I'm on a 16F887.
Code: |
#include <16F887.h> // basic header for this pic
#device adc=8 // adc of 8 bits so 0=0v 256=vref(5v?)
// fuses, if brownout at 4v when we turn on motors we get brownout
#fuses INTRC_IO, NOWDT, NOPROTECT, NOBROWNOUT, PUT, NOLVP, BORV21
#use delay(clock=4000000) // 4MHz clock
#use rs232(baud=19200,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,STOP=1)
unsigned char test = 0;
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_OFF);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);// This device COMP currently not supported by the PICWizard
//Setup_Oscillator parameter not selected from Intr Oscillotar Config tab
// TODO: USER CODE!!
while(1){
delay_ms(500);
printf("11");
putc('\x3F');
putc('\x4F');
putc(test);
putc(test);
putc(test);
putc(test);
test++;
}
}
|
It seems to count past 0x3F then kind of get stuck on it later on
31.31.3F.4F.3F.3F.3F.
In fact it counts to 7F then stays on 3F for a while longer then if you wait long enough it will start counting from 0 again ?
I'm lost as to why it would do that, maybe I partially burnt up my pic and its causing this erratic behavior. _________________ Smart people know how stupid they are. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Aug 19, 2010 5:40 pm |
|
|
Quote: | 31.31.3F.4F.3F.3F.3F. |
What device and/or program are you using to receive and display this data ?
Also your data above has dots (periods) in it. I don't see anything in
your test program that sends those characters. |
|
|
Humberto
Joined: 08 Sep 2003 Posts: 1215 Location: Buenos Aires, La Reina del Plata
|
|
Posted: Thu Aug 19, 2010 6:14 pm |
|
|
Also check the Data Bits and the Stop Bit configuration -must be 8 and 1 respectively- of the "device and/or
program are you using to receive and display the data". |
|
|
zonemikel
Joined: 13 Oct 2007 Posts: 53 Location: Texas
|
|
Posted: Thu Aug 19, 2010 7:43 pm |
|
|
Quote: | What device and/or program are you using to receive and display this data ?
Also your data above has dots (periods) in it. I don't see anything in
your test program that sends those characters. |
I'm using my own c# program. It counts all the way to 7F and then all of them go to 3F for a period (im sure the rest of the increments to FF) and then it starts again at 0x00. I add the dots in with my c# program to make things more clear. My program displays 80 and FF in hex just fine i know that for sure because of other variables it is displaying using the same functions.
I'll modify the test program to send chars 0xFF and before that to see if its my c# program mangling up the data.
Besides that I made sure all my flags/vars etc were below 3F and everything is working great. _________________ Smart people know how stupid they are. |
|
|
zonemikel
Joined: 13 Oct 2007 Posts: 53 Location: Texas
|
|
Posted: Tue Aug 24, 2010 4:06 pm |
|
|
Finally found out what was wrong.
In my receiving c# program I was using ascii encoding which only supports 127 chars.
I tried switching to UTF8 and unicode but they still seem to have problems understanding whats coming out of the pic.
I also tried using LONG_DATA, but I'm not sure if thats what I'm supposed to do. It does not seem to help.
I think i should be using UTF8. I would hate to have to doctor the chars coming out of the pic and have 50% overhead just so that c# gets a 16bit char.
Anyone else run into these types of problems ?
EDIT ------------- UPDATE
I'll just edit so I dont bump, but i do want closure to this thread. I ended up using encoding.UTF8 and it works. Not really sure where I was going wrong, I think it was in using strings so I could do .indexOf stuff. Anyway Use bytes for your buffers and such.
Anyone who does this later, use UTF8 encoding not ASCII. Unless you only want 127 values. If your returning a readADC thats 8 bit and its value is anywhere above 127 C# would return 127 if you have ascii encoding (which is default).
Yet again it was a C# problem not a Pic or C problem. I find that with all the "wonderful" intellisence and dot operators its really hard to find out whats really going on sometimes. _________________ Smart people know how stupid they are. |
|
|
|