String buffer problem
Ole Man Earl
Posts: 262
I have some code here that is driving me nuts !
I have a 6DOF board that outputs acceleration xyz and gyro xyz serially at 115200 baud. The board works fine. I have another program that writes to the TV.text the correct data.
The problem here is the data RunningCount,ax,ay,az,gx,gy,gz do not produce the result I expect. They are always 0 and not the actual values.
I call 'Get6DOF' from a part of my autopilot program expecting the data to be printed via tv.text. Only prints '0'.
Any clues ??
I have some code here that is driving me nuts !
I have a 6DOF board that outputs acceleration xyz and gyro xyz serially at 115200 baud. The board works fine. I have another program that writes to the TV.text the correct data.
The problem here is the data RunningCount,ax,ay,az,gx,gy,gz do not produce the result I expect. They are always 0 and not the actual values.
I call 'Get6DOF' from a part of my autopilot program expecting the data to be printed via tv.text. Only prints '0'.
Any clues ??
Post Edited (Ole Man Earl) : 4/29/2009 9:46:46 PM GMT
I have a 6DOF board that outputs acceleration xyz and gyro xyz serially at 115200 baud. The board works fine. I have another program that writes to the TV.text the correct data.
The problem here is the data RunningCount,ax,ay,az,gx,gy,gz do not produce the result I expect. They are always 0 and not the actual values.
I call 'Get6DOF' from a part of my autopilot program expecting the data to be printed via tv.text. Only prints '0'.
Any clues ??
I have some code here that is driving me nuts !
I have a 6DOF board that outputs acceleration xyz and gyro xyz serially at 115200 baud. The board works fine. I have another program that writes to the TV.text the correct data.
The problem here is the data RunningCount,ax,ay,az,gx,gy,gz do not produce the result I expect. They are always 0 and not the actual values.
I call 'Get6DOF' from a part of my autopilot program expecting the data to be printed via tv.text. Only prints '0'.
Any clues ??
PUB readDOF repeat while Rx <> "A" ' wait for the "A" to insure we are starting with Rx := uart.rxcheck ' a complete 6dof sentence cptr := 0 ' zero the buffer pointer to start repeat while Rx <> "Z" and cptr < 16 ' continue to collect data until the end of sentence ("Z") Rx := uart.rxtime(3) ' get character from uart Rx buffer[noparse][[/noparse] cptr++] := Rx ' save the character in the buff buffer[noparse][[/noparse] cptr] :=0 ' make sure the buffer ends with a 0 tv.str(string($A,1,$B,12)) 'set tv position to col 1 line 12 tv.str(string(" ")) x := buffer[noparse][[/noparse] 0] y := buffer[noparse][[/noparse] 1] z := (x * 255) + y tv.str(string($A,1,$B,11,8)) 'set tv position to col 1 line 12 tv.dec(z) tv.str(string(" Count# #of buffer bytes ")) tv.dec(cptr) tv.out(32) tv.str(string($A,1,$B,12,8)) 'set tv position to col 1 line 12 ' tv.str(buffer) return ' return to calling routine '------------------------------------------------------------------------------------------------------------------------------- PUB Get6DOF ' primary entry point read6DOF ' Put the data in a buffer from 6DOF and print on tv x := buffer[noparse][[/noparse] 1] 'Now put buffer data into variables 'buffer[noparse][[/noparse]0] contains the letter 'A' we don't need y := buffer[noparse][[/noparse] 2] z := (x * 255) + y RunningCount := z x := buffer[noparse][[/noparse] 3] y := buffer[noparse][[/noparse] 4] z := (x * 255) + y ax := z x := buffer[noparse][[/noparse] 5] y := buffer[noparse][[/noparse] 6] z := (x * 255) + y ay := z x := buffer[noparse][[/noparse] 7] y := buffer[noparse][[/noparse] 8] z := (x * 255) + y az := z x := buffer[noparse][[/noparse] 9] y := buffer [noparse][[/noparse]10] z := (x * 255) + y gx := z x := buffer[noparse][[/noparse] 11] y := buffer[noparse][[/noparse] 12] z := (x * 255) + y gy := z x := buffer[noparse][[/noparse] 13] y := buffer[noparse][[/noparse] 14] z := (x * 255) + y gz := z 'buffer[noparse][[/noparse]15] contains the letter 'Z' that we don't need return 'return to caller '------------------------------------------------------------------------------------------------------------------------ PUB read6DOF uartDOF.start (22,23,0,115200) ' start uart on pins 22,23 at 115200 baud for 6DOF Atomic board repeat while Rx <> "A" ' wait for the "A" to insure we are starting with Rx := uartdof.rxcheck ' a complete 6dof sentence cptr := 0 ' zero the buffer pointer to start repeat while Rx <> "Z" and cptr < 16 ' continue to collect data until the end of sentence ("Z") Rx := uartdof.rxtime(1) ' get character from uart Rx buffer[noparse][[/noparse] cptr ++] := Rx ' save the character in the buff buffer[noparse][[/noparse] cptr] :=0 ' make sure the buffer ends with a 0 return ' return to calling routine '------------------------------------------------------------------------------------------------------------------------
Post Edited (Ole Man Earl) : 4/29/2009 9:46:46 PM GMT
Comments
- Insert a space after every "[noparse][[/noparse]" that's followed by a number.
- Add "[noparse][[/noparse] c o d e ]" at the top of your code (but remove the spaces)
- Add "[noparse][[/noparse] / c o d e ]" at the bottom of your code (remove spaces)
These changes will fix the font issue and preserve indentation.It's always a good idea to use the "Preview before posting" feature too.
as long as you don't correct your post you will at best get guesses but no help. And you should post the whole code - if it's to long attach it. And you should describe a bit more in detail what you want to do! And what does the data you receive look like. What about the definition of the variables and the buffer?
The part with x*255+y very much looks like making a word out of two bytes with a bug and potential for improovement. The bug is that you have to multiply with 256 instead of 255 and the improvement would be to use a shift instead. That's much faster than the mulitplication.
dx:=x<<8 + y
x := buffer[noparse][[/noparse]7]
y := buffer[noparse][[/noparse]8]
z := (x * 255) + y
az := z
x := buffer[noparse][[/noparse]7] - "0"
y := buffer[noparse][[/noparse]8] - "0"
z := x * 10 + y
az := z
John Abshier
The x and y variable are byte and z variable is a word. ahh.....I think I see it...x needs to be a word variable also because it gets multiplied by 256 because it is the hi byte part of the data !
No, the data is not ASCII readable, except for a leading 65 "A" and a trailing 5B "Z". I have corrected most and now I get data BUT some of it is not right.
the buffer is like this:
A ll hh ll hh ll hh ll hh ll hh ll hh ll hh ll hh Z
The 'll' are 8 bit low byte data and the 'hh' are 8 bit high byte data.
The A and Z characters are to delineate the data coming in at 115K baud from the 6DOF module.
So the first 2 bytes of data are the Accelerometer x axis data which is ~ 500. this means the high byte should be 5 and the low byte 0 OR..the hi byte low byte combo should be 500 when combined ?
Thanks for your help on this.
BTW How do I edit my post to correct my lack of [noparse][[/noparse] c o d e ] no code in the post ?
Are you sure that your buffer starts with an 'A'? I don't see the A written to the buffer somewhere. So, conversion should start with buffer[noparse][[/noparse] 0 ].
When you use rxcheck, you should make sure that you really got a value and not the value that shows you that the buffer is currently empty. (Just want to mention that because it makes no difference in your code as you wait for an 'A' ;o)
I suppose your buffer is byte? Is the 6DOF sending positive and negative data?
The sign extend is very likely wrong as well. If Y is bigger than 127 and you convert it to a word, then all the bits 8-15 are set to 1. So you have to convert that without sign extension:
z:=x<<8 + ($00ff & y )
Post Edited (MagIO2) : 4/29/2009 9:36:11 PM GMT
z := high * 256 + low or 1 * 256 + 244
of course a shift could be used in place of multiplying by 256
All of this is for positive numbers only. Looking at the data sheet, it says that the data is positive and that it is MSB then LSB. So the data is
A countHi CountLow AXHigh AXLow etc. I think an AX=500 string would be $41 $nn $nn $01 $F4 where $nn is the count variable
John Abshier
Sorry. problem of code on post fixed.
buffer[noparse][[/noparse] 0] is the 65 or letter A and buffer[noparse][[/noparse] 15] is the letter Z or 5B
you are right. It is sent MSB then LSB
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
OS-X: because making Unix user-friendly was easier than debugging Windows
links:
My band's website
Our album on the iTunes Music Store
Here is my whole project.
Post Edited (Ole Man Earl) : 4/29/2009 11:40:46 PM GMT
as you already did not listen to me in my previous post ;o)
Well, ole man, I'm afraid that I have to say: I don't believe you
Your progam only looks like it works, but you have serveral bugs in it (And currently I only concentrate on the topic of this thread and not the whole AutoPilot).
Let me explain something:
You defined the buffer as bytes and you do some calculations with the result being a word. It's very important to know that numbers in SPIN are signed numbers. For a byte the value range is from -128 to 127.
As I read in another post your 6DOF will send you the numbers as unsigned. This means that you currently treat unsigned numbers as being signed which will give you wrong results. Example:
byte $08 - used as unsigned means 8, used as signed means 8
byte $FE - used as unsigned means 254, used as signed means -2
If you extend these bytes to a word in SPIN you get:
byte $08 = word $0008
byte $FE = word $FFFE
For the high byte it's no difference, because you shift it by 8 bits. So, in the end you have $FE00. But for your low byte it makes a difference!!! Instead of adding 254 you are adding -2.
OK ... guess I was a little·bit wrong.·In·SPIN you can use values from·-128 to 127 or from 0 to 255 and it does not do a signed extension if you assign a byte to a word.·Hmm ... I think I·now remember that there's a different assignment operator for that. So, conversion itself is fine.
That's why I said, you have to "and" the low byte with $00FF. This removes the sign again and you really have the value 254 in your add.
But still there might be an issue with the conversion. Because you have the interpretation problem with the high byte as well. According to the specs of the 6DOF $FFFE would mean 65534, but SPIN treats it as -2. I don't know what numbers you can expect, but if something bigger than $7fff is valid, you should switch to use LONG instead of WORD for ax, ay .... Then the conversion looks like:
ax:= ($0000_ff00 & byte[noparse][[/noparse] high ]<<8) + ($0000_00ff & byte[noparse][[/noparse]low])
Another thing:
I raised an question about the 'A'. You expect it being in the buffer and I doubted it. Let's have a look at your read6DOF (which I took from the last ZIP posted):
Now let's correct this function:
And here is one more bug:
You expected "A ll hh ll hh ll hh ll hh ll hh ll hh ll hh ll hh Z", but according to John Abshier's post the spec says the 6DOF sends data in hh ll order.
One tip in general:
You should develop those kind of functions·in a test program·first·and not inside of your main program. Using the real data for a function like that is a very bad idea as variation is not to big. You simply don't find this kind of number conversion bug if you only feed your function with nearly the same data all the time.
In an test environment you can manually set up different content for the buffer and run the function to see if it produces the right output for the whole range of numbers.
(Hope this post saves your aircraft ;o)
Post Edited (MagIO2) : 4/30/2009 9:04:47 PM GMT
This program is working as far as the buffer full of data. I think its working because the numbers I print out on tv appear correct and when I move the 6DOF it responds like I think it should..... Ahh... I did use the code @SSteve provided ! I think I will try your read6DOF part tho.....
I tried your read6dof and it now ALWAYS gets the "A" first. My program would sometimes miss it. Thanks a bunch also...
That's what I really like about this forum...help is only a few keystrokes away !
When your 63...must go back to school !! Got the time now !