Need Advice in Assembly strategy

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My project is to average several angle measurement taken in a moving vehicle and periodically combine that average with a GPS bearing in order to end up with a ASCII string that will contain the average of the readings referenced to North (0 degrees).  The measurements are in 11.25 degree increments and I have scaled them in Hex in a look up table and then added them and divided to find the average in Hex.  That seems to work on the Studio 7 simulator.

 

I'm not sure how to proceed.  I made a 7 byte table in a sort of CORDIC fashion (Decimal for 180,  90, 45, 22.5, ...  ) and used one memory byte to keep track of which bytes to add together in decimal to build the Hex bearing.  The 7 bytes used for the decimal representation were to be found by adding the CORDIC decimal values used to build the bearing.  However, the length of the code grew with each decimal place and it got so that it was hard for me to read the code I had written!

 

Should I first convert the bearing part of the GPS string (ASCII) into hex and combine that with the average vehicle bearing or should change the vehicle bearing to ASCI and combine.  There must be a simpler way, but I have yet to see it.

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The usual strategy is to only use assembler when really necessary.

 

So: is it really necessary to use assembler to do this?

 

Where is this ASCII string going?

 

Does the maths really need to be done on the humble AVR (what model?) - or is there a bigger computer that could better handle it ... ?

 

If the maths does really need to be done on the embedded device, could you not chose a microcontroller better suited to such processing ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would convert the ASCII string from the GPS into a format that matches the output of the gyrometer.  This will make it easier to average the results from the gyrometer (I'm assuming something like an HMC5883 module) with the GPS data. 

 

 I'll assume that this is an automobile application and that the electronic compass IC is being read every 1 second.   Assuming an average of 16 readings of the electronic compass IC gives a bearing that is averaged with the reading from the GPS.  I'll assume that there are 35 directional bearing values since 360 degrees/11.25 degree_increments.   I'd scale the 360 degree bearing value by 0.7 (256/360) so that you have the bearing occupy a single byte.  Let's call this a table of hex-degrees with there being 256 hex-degrees to a full circle.  This gives about 8 units for each of the degree_increments (11.25*0.7 = 7.875; or ~8).

 

In assembler, to get an average of 16 byte values, have an 8-bit variable that is an offset into an SRAM table of 16 values. With each reading, put the new value into the table at the table's beginning plus the offset.   Then add all the 16 values together to get a 16-bit word result.  Get the average by right-shifting the sum by 4 bits using LSR high-byte, ROR low-byte so that the carry moves correctly through the divide by 16 process.  Finally, increase the offset value, then AND the offset with 0x0f so that the offset rolls over from 1111 to 0000.

 

Average the electronic compass value with the GPS value.  Then convert that bearing back to 360 degrees by multiplying by 1.4.  This could be done by multiplying by 3 and then dividing by 2 to get the *1.5 result and subtracting a value to the get approx *1.4.

 

Finally convert the new 360-bearing value back to an ASCII string of the bearing.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:
 I'll assume that this is an automobile application and that the electronic compass IC is being read every 1 second.

 

Actually, the input is once every 800uS in the range 0x00 to 0x1F.  128 scaled readings are averaged with the objectof eliminating the effect of voice modulation on the FM signal which can cause bearing error.  Actually, each individual reading is used to address a two byte look up table as it is read (plenty of time to do that after each individual reading).  That table is in flash.  The same address is used to increment a value in a one byte table in SRAM to be used to see if the bearing Mode matches the average. It won't matter much if the measurements are postponed (CEI commanded) while the data is formatted.  The ASCII will be sent out by WIFI to a lap top PC or maybe a cell phone.  Google maps will be used and a line on the map will go from the reception point toward the hidden transmitter.

 

My effort is only to get the position and bearing info in the proper form to the PC/cell phone.  I'm just trying to modify a 1970's "Doppler Scan" ham radio FM direction finder without spending much money.  I'm using a Tiny1634 because it has two UARTs (one for the GPS in and one to send data out).  The Tiny1634 seems to have everything I need.

 

I have the 128 measurement average working to my satisfaction, I just need to combine that with the GPS bearing and output the data in ASCII.  If I can make it work on the simulator, the hardware should be pretty easy (famous last words).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It is simpler (in time/code/speed) to do maths in binary instead of in a non-binary representation.
I would convert the GPS true heading into a 2-byte binary value, average that, and convert the average into ASCII when required.
Depending on the resolution required you could use simple right-shifts to do the division in the averaging.


You mentioned 'GPS String (ASCII)' which to me implies something like an NMEA $GPRMC sentence transmitted from the GPS every 1 second.
The heading value in that sentence would already be averaged and filtered.
Some GPS units can be configured for different 'modes', eg. 'aviation' where only mild averaging/filtering is performed, 'marine' where a lot of averaging is done, ...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hex is just a representation. I gather you convert the ascii value to a numeric value - the number is the same whether you represent it in decimal, binary,hex or base 5. Rather than think of the implementation, think in terms of the problem you want to solve then solve how you want to represent the angles - in degrees, fractions of degrees etc. Scale your inputs to suit the representation, do the averaging,calcs etc, then convert back to your display representation. Then you can write the code in whatever language you want. For the speed you're talking, floating point might be an easier representation.

 

If you use a PC or smartphone, you have much more computation power available than the humble AVR, so have the AVR handle the real time acquisition and hand the computation up the line.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Memories... averaging wind direction caused beginners problems because 360º = 0º and so ((360º-a littleº) + a littleº))/2 = 180º... oh dear wrong average direction.

Ross McKenzie ValuSoft Melbourne Australia

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

John3 wrote:
The ASCII will be sent out by WIFI to a lap top PC

So why not just send the raw data to the PC, and let it do the maths?

 

The PC is far better at maths than a tinyAVR !!

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you are really proposing to implement a floating point library in AVR code do you really think you can do a better job than the authors of a C library who've been honing/fixing this stuff for years?

 

In Codevision you can easily interwork with Atmel Asm 2 code.

 

In GCC you can use a combination of avr-gcc and avr-as but this does use a different Asm syntax.

 

Certainly in the avr-as case you don't even need to go anywhere near C. You can simply link your Asm code against libm.a. As long as you setup the registers to make the calls to the float library in the ABI format of the C compiler the access will simply work. It can help, though, to sketch out what you want to achieve in C first then see what it does to call the FP library functions involved.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well, maybe one should decide which maths should be done before deciding if it can be done on an avr -

 

For averaging wind /angular direction, I know of 3, not fully satisfying methods:

 

a) keep track of the first value, coerce each other value to be between -180 and 180 ° (if value >180 value = value -360; else if value <-180 value = value + 360)

b)average the cos(value) and the sin(value)  -sin, cos can be stored into  arrays ...(if the sum of squares of these average differs too much from 1, one know the direction varies too much , and the average does not make sense); they can be, if felt useful, weighted by the speed .... if there is any.

c) count values (with 1° accuracy, it is a 360 uint8 array); find the max (but what happens if there are two maxima? -no trigo, a short array is enough-)

 

BTW : sending raw values into a PC/a RPi (or nanoPi, PCduino) and choosing between these 3 (maybe there are others, more satisfying) "methods" would be an interesting 1rst step...

Last Edited: Tue. Apr 25, 2017 - 05:24 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Here is a possible program to use on a laptop PC:

http://www.silcom.com/~pelican2/PicoDopp/PICODOPP.htm#GH

 

What I need to do is send the Doppler bearing and GPS data to a com port on a laptop with the above or similar program running on it.

 

Apparently, the AVR code can be simplified

If a different combination of DF and GPS units is employed, GoogleHunt operation is still possible, if the port is manually switched back and forth between the DF and GPS units

Perhaps I should just send the average bearing I have found  over about 0.1 second alternated by the last GPS bearing.  That looks much easier (for me) to code than trying to only send the pre-combined (true) bearing to the PC.  

Certainly in the avr-as case you don't even need to go anywhere near C. You can simply link your Asm code against libm.a. 

I will definitely check that out!

 

Thanks everyone for the info.

 

John 3   smiley