PDA

View Full Version : Questions/problems with coding a serial connection



Joms
03-18-2009, 10:14 AM
Two questions on the attached .spin file...

1.· I am trying to make the variables dst & src output four hex characters which is working fine.· Example, if the variable = 111 then it outputs '30,30,36,45'.· The problem is I am trying to calculate the checksum and it requires that I add all of the transmitted digits including the '30,30,36,45'.· I arrived at the 301 by adding all of the fixed tx bytes together manually.· If I manually add the 4 hex bytes together and replace the variables with them the checksum calculates properly.

2.· I was having a problem with it not sending the entire string of data.· I discovered that because I am using the .tx pub that it would stop the cog before the buffer was actually empty.· To make this work temporarily I just added a one second delay.· My question, is there anyway to tell when the buffer is empty so that I don't waste extra time just waiting?

Thanks in advance for all the help...

After about a month of working with it, I am really starting to like the propeller...

StefanL38
03-19-2009, 12:54 AM
Hello Joms,

I don't understand your question 1

so I'm asking back:
which variable has value 111
how is the value 111 translated into the hexbytes 30,30,36,45 ?

If 30,30,36,45 should be ASCII-Code this means "0","0","6","E". What does this have to with value 111 ????

Is Your EncoreRouterControl.spin-file the TOP-object-file ?

If this is the case it will only run ONCE the method SendSource and that's all

You shouldn't start and stop the FullDuplexSerialPlus-object (FDS+)all the time inside method Sendsource and GetSource

The FDS+-object is menat to use it in the following way
right at the beginning you call ONLY ONE Time SendData.Start(31, 30, 0, 9600)

and as long as you do not run out of cogs you NEVER stop it

The FDS+-object works as some kind of a driver in the backround
you start it and then it runs in the backround
waiting for bytes to be send AND waiting for bytes to be received (send and receive at the SAME time as this is what the FULLDUPLEX means)

You can imagine this
starting the FDS+object is like employing a butler
once you have engaged him
you can shout commands at him
"send the following bytes" "ABCDEFG01234567890"
the butler will write all bytes onto a sheet of paper and send them
while you can do already other things
and you even can shout another command at him while he is still sending bytes
"receive a string" or whatever
and he is abe to do both things at the same time
after finishing your commands he stands there in idle-mode waiting for new commands

you don't have to fire him (call senddata.stop)
and hire him again (call senddata.start(..) all the time
you would like to do him a little send or receive-job

If you need something to male sure that send and receive does NOT run crossed over
you could add a method to the FDS+-object that is just
LOOKING for rx_head == rx_tail

WITHOUT taking bytes out of the receivebuffer
(like rxcheck does it)

same thing for the sendbuffer
LOOKING for tx_head == tx_tail
WITHOUT sending a byte

about your checksum-problem
please post in DETAIL what you are adding manually and what you are doing else
and how you get a hexcode sequence 30,30,36,45 out of a value 111

best regards

Stefan

Joms
03-19-2009, 04:00 AM
GREAT EXPLINATION STEFAN!!!

On the first question of how I arrived at the 6E part.· I actually messed up and should have put the number 110, the first thing I do in this object is subtract 1.· Anyways, here is how I got there…

DEC 110 = HEX 006E,· Character 6 = HEX 36,· Character E = HEX 45,· Character 0 = HEX 30

The device I am trying to send the data to wants to see 4 hex characters for each variable…

This EncoreRouterControl.Spin is not the top object file.· My top file actually calls on the senddata PUB or the getsource PUB.· Part of the reason I was trying to not leave the FullDuplexSerialPlus running all the time is because I will actually be using it to output data to about 4 different devices, meaning I will want to change the tx and rx pins that are declared when I start it.· I would like to only use 1 cog to send the data to each device as I will never be sending data to multiple devices at the same time.· If there is a better way to send multiple devices information using the same FDS cog that I am not aware of, please let me know…

I actually do not need to send and receive data at the same time but when I tried the Simple_Serial out of the Propeller Library there was no way to do SendData.hex(dst,4) that I found anyway…

·As for the Checksum Calculation Algorithm, the checksum is calculated on the items following the SOH (Hex 01) and before the inserted checksum value.· The calculation is a negative sum mod 256 of those values.· The way I arrived at the 301 is by manually adding up all of the hex bytes that I am sending out using the SendData.tx command.

Thanks for the long explaination and all the help so far… I am fairly new to the serial communications and been trying all sorts of different things for the checksum calculation and can’t seem to make anything I try work.

MagIO2
03-19-2009, 04:36 AM
I did not have a closer look to the sources of other objects by myself yet, but if there would be a need, I'd try to enhance the features of FullDuplexSerial. Why not having a command to switch the pins?

Starting point is the start function where you set the pins and speed initially. See what happens there with the parameters and try to figure out where the cog stores those pin information. As I understood Stefan, there is a command interface to the COG. You have to expand this by a new command which switches the pins while the COG is running.

Maybe I have some time later to check that out as well.

Joms
03-19-2009, 04:47 AM
You know, to be honest I never thought about trying it that way... I am going to see how hard it would be to modify the FullDuplexSerial...

If worst comes to worst I will just end up putting a delay in there of a few milliseconds or something that allows enough time for it to complete...

Any ideas on the checksum format problem I am having?, that is where I am really stumped...


---EDIT---

Another thought I just had as a work around would be to stop the FullDuplexSerial right before I start it whenever I need to switch pins.· Might not be the best way, but it would work for testing without the delay anyways...

Post Edited (Joms) : 3/18/2009 8:52:28 PM GMT

StefanL38
03-19-2009, 10:11 AM
Hello Joms,

it's always the same:
as soon as there is more information available new suggestions can be made to solve a problem

In the obex there is an object Multiple serial port driver (http://obex.parallax.com/objects/340/)
that supports up to 4 serial ports per cog. With this driver there is no need to change pins.

I'm not familiar with checksum calculation. But I'm quite good in mathemathics in general. To make life easier for me
can you post the general formula and an example with some bytes

a.) what the result of the checksum-calculation should be
b.) what the result is that you get from the calculation in your SPIN-program

For debugging I would add debugoutput showing step by step what is calculated
and run through the variable src from zero to max and analyse what sould be calculated and what you really get
from the SPIN-code

If I summarize your fixed bytes
01
78
48
84
73
09
09

I get 302. You add 301 do you have to substract 1 for this part too ?
As you are sending these values as single bytes could it be that EACH byte has to be substracted by one ?

I'm really unsure about how the calculation SHOULD be made and therefore I need an example
shown mathematically and not as SPIN-code

best regards

Stefan

Joms
03-19-2009, 10:39 AM
Sorry if there was some confusion...· Perhaps the attached document will help...


I am going to look for that 4 port serial driver as that would be a HUGE help!· I was just putting together the code for the serial port and running into problems and I think a 4 port will be a big help...

Thanks a million for all the help on this one...

StefanL38
03-19-2009, 05:30 PM
Hello Joms,

OK catched the bug

your codeline




cksm := (-1*((301 + dst + src)//256))+256





is wrong

Let's say variable src contents value 111 (111-1=110 decimal = hexadecimal $6E
and variable dst contains value 103 decimal (103-1=102 decimal = hexadecimal $66
as your PDF-example shows

you have to translate the value of src - 1 and dst -1 into FOUR SINGLE ASCII-coded hexadecimal digits
decimal 110 has to be translated into "0", "0", "6", "E"

ASCII-Code of "0" is decimal 48 and hexadecimal 30 (3*16 + 0 = 48)
ASCII-Code of "0" is decimal 48 and hexadecimal 30 (3*16 + 0 = 48)
ASCII-Code of "6" is decimal 54 and hexadecimal 36 (3*16 + 6 = 54)
ASCII-Code of "E" is decimal 69 and hexadecimal 45 (4*16 + 5 = 69)

so for calculating the checksum of src-value 110 you have to add decimal 48 + 48 + 54 + 69 = 219
but your codeline simply adds 110 and the add of 2x 09 is missing and I think this is the bug

same thing for variable dst - 1

for this converting you can use the codelines of the method hex in FDS+ as a BASE
define four bytes scr_byte1...scr_byte4 for the four digits and store the ASCII-code
of the digits inside these bytes

then your checksum has to be calculated like this

to make the code more readable I would divide the whole calculation in several parts




cksm := _protocol_ID + _SeqNo + _T + _I

cksm := cksm + _TAB
cksm := cksm + dst_byte1 + dst_byte2 + dst_byte3 + dst_byte4

cksm := cksk + _TAB
cksm := cksm + src_byte1 + src_byte2 + src_byte3 + src_byte4

cksm := cksm // 256
cksm := 256 - cksm 'now the right checksum should be calculated





use EXACTLY the values of the PDF-example to TEST your code

here it is useful if you define constants and variables




CON
_SOH = 1
_protocol_ID = 78
_SeqNo = 48
_T = 84
_I = 73
_zero = 48
_TAB = 9
_EOT = 4

VAR
dst_byte1
dst_byte2
dst_byte3
dst_byte4

src_byte1
src_byte2
src_byte3
src_byte4





then your method PUB SendSource(dst, src) | cksm

looks like this




SendData.tx(_SOH)
SendData.tx(_protocol_ID)
SendData.tx(_SeqNo)

SendData.tx(_T)
SendData.tx(_I)

SendData.tx(_TAB)
SendData.hex(dst,4)

SendData.tx(_TAB)
SendData.hex(src,4)

SendData.hex(cksm,2)

SendData.tx(_EOT)





I did not test this code and the codelines show NOT everything

best regards

Stefan

P.S.: without the PDF-description I would have NEVER found the bug !

Post Edited (StefanL38) : 3/19/2009 9:40:01 AM GMT

Joms
03-20-2009, 05:23 AM
Thanks for the explination... I now understand what is going on, but I am having problems with the formatting part...

After I declare the dst_byte1, dst_byte2, dst_byte3, dst_byte4, and the respective sources, How do I do the calculation to put the 110 into them?· Basically what I mean, is how do I determine their values before it gets to the calculation point?

Sorry if you already explained this and I just don't understand it as I am currently learning spin.· You have been a huge help so far, and Thank You for that...

(EDIT)·- I·re-read what I wrote and it might·be a little hard to understand, so what I mean is how·do I translate the single·byte (dst) into the four·bytes·(byte1, byte2, byte3, byte4) ?

As a side note that might relate with this problem, durring part of this same project I need to access the bits within another byte that I am storing.· Basically what I am doing is I have a spin file that is scanning a parrallel to serial IC and inputing a byte depending on which input is active.· How do I actually turn that byte into 8 seperate bits, as it is my understanding that bits are not supported in spin.

This is of course a different question that I am having with this same program I am makeing, but I have a feeling that when I figure out how to fix the original question I was asking, that it will be self-explanitory on how to fix this issue...

Thanks again for all the help!

Post Edited (Joms) : 3/19/2009 9:56:54 PM GMT

StefanL38
03-20-2009, 02:25 PM
hello Joms,

as a quick answer

your parameters "src" and "dst" are longs. which means the are four bytes = 4x8bits = 32bits big

take a close look into the method hex of the FDS+-object

this is the original version




PUB hex(value, digits)

'' Print a hexadecimal number

value <<= (8 - digits) << 2
repeat digits
tx(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))





it is very compact coded
you gave in a value to this method and the method sends out as many digits as you said by the value if variable digits

this line converts the value into ONE hexadecimal digit




lookupz((value <-= 4) & $F : "0".."9", "A".."F"))




of course you need the lines around to do it for all digits

as a hint

the lines




repeat digits
tx(lookupz((value <-= 4) & $F : "0".."9", "A".."F"))





send out the hexadecimal digits
and for your program you have to modify it that the digits get stored into your variables
dst_byte1, dst_byte2 ...

I'm not a friend of serving completed code because you won't learn much from this way

write some own code to analyse what is happending here

if you have CONCRETE questions about whatever feel free to post them here


to get single bits you simply do a AND-command with the interesting bit set to one

example your value is




bitno 87654321
value %10101000

bitno 87654321
Mask %00001000

value and Mask

value %10101000
Mask %00001000
result %00001000


value %10101000
Mask %00000001
result %00000000





result contains zero if the interesting bit is zero
or a value <> zero if the interesting bit was 1

best regards

Stefan

Joms
03-21-2009, 11:54 AM
Great... After pulling my hair out all after noon I did get the orginal problem to work. It ended up being a type-o on my part, and I felt like an idiot after I figured it out...

I do have a question on the mask thing, but I think I am going to start a new post on that. Thanks for your help with that problem. I understand not giving the code as I would not have learned anything...