Sunday, April 24, 2016

Satellite tracking

The beginnings of a new project.  Software is coming together, but now it's time to pull together the hardware.  This will be an antenna azimuth/elevation  satellite tracker.  In previous posts I have explored the calculations necessary and the details of using hobby servos to create a simple proof of concept.


For now I am experimenting with the ATMega2560 board (on the left) as it has plenty of flash and RAM space for the task at hand.  I plan to control the device via a web page that it serves up, so for now I have an ethernet shield attached, though in the end the plan is to use WiFi.

Calculating satellite passes requires an accurate position for the observer in terms of latitude and longitude, but also elevation and time-of-day.  I am using a GPS module to provide this information (lower right).

While the mighty ATMega2560 is certainly capable of generating the necessary PWM signals to position servos, I have decided to offload that to separate controller based on the PCA9685 which provides I2C interfacing of 16 channels of 12 bit PWM data.  This particular board was originally intended to be used as an RGB LED controller, but my plan is to re-purpose it for this task.  It has its own internal 25 MHz oscillator that offloads the ATMega2560 from having to generate these signals.  That, plus the fact that I happened to have one on hand drove the decision to use this component to drive my servos.

After spending some time in the Avionics industry and working on electronic aviation attitude indicators, the math involved in Euler angle solutions to the orientation of a rigid body, plus the mapping of raw gyro, accelerometer and magnetometer sensor data into 3D space is a bit tedious.  Fortunately for me, Bosch has done an amazing job of taking MEMS data from on-die sensors and adding an ARM Cortex M0 processor to produce a single chip solution that abstracts away all the raw sensor fusion and spits out data directly in quaternions, Euler angles or vectors.

The plan is to use this sensor mounted on the antenna fixture to measure azimuth and elevation relative to the calculated position on earth with no careful alignment of antenna orientation required.  The Arduino will accept keplerian elements for the desired satellite and then automagically track the spacecraft as it passes overhead.

More updates as this comes together into a demonstrable solution.

Saturday, April 16, 2016

Interesting problem

Today, I was writing some code that had some bitmap files embedded in them.  Not wanting  to waste space, I decided to use gzip to compress the bitmap.  After converting the compressed file to something that looks like a byte array in C, I get something like this:

unsigned char bitmap[] =
{
    0x1f, 0x8b, 0x08, 0x08, 0x2d, 0x87, 0xf9, 0x56,
    0x02, 0x0b, 0x69, 0x63, 0x6e, 0x5f, 0x73, 0x79,
    0x6e, 0x74, 0x68, 0x2e, 0x62, 0x6d, 0x70, 0x00,
    0xed, 0x99, 0x31, 0x0e, 0x82, 0x30, 0x14, 0x86,
    0x45, 0xa4, 0x5f, 0xf6, 0x0f, 0x21, 0x93, 0x3c,
    0x23, 0x70, 0xbf, 0xab, 0x06, 0xff, 0x9e, 0x00,

    .
    .
    .

    0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xe1, 0x05,
    0x5e, 0xd7, 0xb8, 0x1c, 0x36, 0x40, 0x00, 0x00
};


So, nothing terribly interesting in that, but after compiling this into an executable, I get trapped by my virus scanner saying that my shiny new executable has a virus.  If I comment out the bitmap part of the code, no virus.

Apparently whatever byte pattern is created by compressing this particular bitmap gets flagged by my virus scanner, so in order to debug this code, I need to create an exception for the executable I am producing in the virus scanner.  Never had this happen before, but is certainly an artifact of the world we now live in.

I ran into another interesting trap while unit testing this code.  The basic problem at hand was to embed a series of bitmap files in executable code that could be reconstituted at will.  So, to unit test this code, I created the list of bitmap files and used gzip to compress them into a series of filename.bmp.gz compressed files.  Each of the bitmaps is 16k bytes and they compressed down to about 1k on average, so the savings is significant.

I created a utility that would take a list of file names and generate a C source code file similar to what is shown above which was then included in a unit test program.  The test program recreated the decompressed file using my decompression algorithm and wrote the resultant file back to the disk in a different folder.  What I expected was to see a directory full of identical files to the original set.  What I got instead was about 1/3 of the files had 2 or 4 bytes extra.  The rest were identical to the original.

This as you might guess had me more than a little concerned that my decompression algorithm, while not detecting any errors, including a CRC check of the decompressed memory image of the file, was still different on disk than the original by length and therefore content.

Loading the bitmaps up into an image viewer showed very minor corruption of the image.  Rats...

To check this out, I did a binary difference of all the affected files and I saw an interesting pattern emerge.  Every file that contained a 0x0A byte value in the original file, had a two byte sequence (0x0D, 0x0A) replacing it in the corrupt file.

For those that spend some time programming computers, this may be recognized as an automatic Unix/Linux end-of-line convention being replaced by a Windows end-of-line convention.  Unix/Linux uses (typically) line-feed characters only at the end of a line of text in a file whilst Windows (typically) uses a carriage-return/line-feed pair of characters.  (Thanks Microsoft...)

The cause of this result was failing to remember to open the new file in binary mode rather than non-binary mode which caused the file write operation to replace every line-feed character in the file with a carriage-return/line-feed pair.  A simple change to the file open to use binary mode and the resulting files were now identical to the originals.  Don't forget to unit test your code.