Dennis Frie created the DIY_OSD to run on Arduino for RC plane FPV. It also runs on a Flytron Simple-OSD board; the older board with a couple of hardware mods. The main discussion thread is on RC Groups http://www.rcgroups.com/forums/showthread.php?t=1473207.
The Flytron board is available here http://www.flytron.com/.
I’ve been using V17 on a older Flytron board for some months when one day recently the GPS data became unreliable. To help solve the problem I wanted to display satellite numbers during flight. As I’ve not done any serious Arduino programming, it was time to learn at least enough to get it done. So I got the latest code and started reading. I’m using the latest Arduino 1.something, running on Kubuntu 10.04 Linux and a USB-ttl interface that came with the Flytron board.
It only took a few hours of reading and experimenting to get the information I wanted on the screen. So I’m still working on the GPS problem.
The trick with loading the sketch to the Flyron board is to click to start the load, count to 3 then power up the Flytron board. This gets the bootloader and the Arduino programmer in sync. It seems to take ages to load a 30K sketch as I’m used to a few seconds for the PIC programmer.
Video in unused image lines
While looking at the code I decided to see if I could send GPS data back to the ground station embedded in some unused lines of the video signal. It didn’t look too difficult so I set to work.
There’s not much CPU time or memory left available for adding features. I tried making a pattern to shift out effectively reducing the bit rate but this didn’t work; I think it was running out of RAM. The next attempt was to clock the GPS data directly into the video line. The clock rate was too fast and would make decoding more difficult, if it wasn’t distorted on the way through. It is possible to reduce the SPI clock rate during the data output which effectively slows the data. I also added a header to assist with decoding and a simple check character on the end.
I wanted the data asyncronous, having a fixed bit rate to simplify decoding. The problem was that although the SPI clocked the data bytes out steadily, it was too difficult to make all the gaps between bytes the same. The SPI transmit is not double buffered and I didn’t want to use the ready flag so the answer was to make the gaps larger and make every byte begin with a rising edge, in this case a 1. The header includes a pattern that will let the receiver asses the bit rate before the data arrives for each line. I did find that if I loaded the SPI data register before the last byte was sent the data output stopped.
The dimming was applied during data transmission to provide better contrast for the bits and hopefully easier detection. The camera I’m using for testing, a HobbyKing $20 CCD, outputs reasonably quiet black lines for the first 19 or 20 lines. So dimming isn’t really needed and detection shouldn’t be too difficult as long as the shortest bits are not distorted. I don’t know yet how noise on the video link will affect this but suspect it will introduce extra bits.
The data sent includes latitude, longitude, altitude and a couple of alarm bytes. The data bytes are all 7-bit ascii with a 1 for bit 8, sent MSB first (I think). It’s sent in 3 video lines; 14, 15 and 16. With header, check and gaps it’s about 20 bytes in 80% of a line.
For testing I set the lines to 75, 76 and 77 so that they appear in the image. Also the LED is turned on for the header of the first line providing a sync for the oscilloscope for easy viewing of the data. During testing a lens cap on the camera provides a black background; well low level noise actually.
This is the more tricky bit. I have a circuit board that I designed 6+ months ago to use as a OSD. It has a LM1881 sync detector interrupting a PIC18F2525. I have made a new board based on this one but including a high speed comparator for data recovery and a 5V servo supply. It’s also got a GPS receiver on-board so for antenna tracking the ground station could sort out it’s own fix.
I Thought about writing the PIC code in assembler. I’ve had another look at Pinguino (a PIC version of Arduino) but it only supports a couple of PIC chips with internal USB. A major shortcoming from the Pinguino developers.
Some Technical Details
Putting the data into the video stream is the easy part with the DIY-OSD. Detecting the data reliably at the decoder is more tricky.
This is still a work in progress but it’s looking good so far. As long as SPI can stay in sync for one byte, it should be OK. In theory, I can see the data in the received video signal. Unfortunately my V-Mate recorder doesn’t record lines 14,15 and 16. There is lots of redundancy as every frame contains the data. It would only need a good frame every few seconds to keep up with a distant model. With the data split into 3 lines, a bad line only looses 1/3 of the data, which could be corrected on the next frame.
With the HK ckeap CCD camera that I am testing with, the first 18 lines contain no video ie. a quiet black level. This means that data has good definition against the background. A data 1 is the same as a white text pixel.
NOTE: I may move the data to higher line numbers (maybe 21-22-23) so that I can record it with the V-Mate. This would provide a real flight recording that could be played back to the decoder for development and testing.
It waits for video line 14 then places 3 lines of bytes (1=white, 0-black) by writing bytes to SPDR. Delays are needed between bytes so they don’t overwrite and the SPI clock is reduced back to 1/2 speed (4MHz) for the data lines. Data includes lat, log, sat-cont, batt-alarm and mah-alarm.
A header pattern of “11111111 10101010” starts each line of data and a check character of the XOR of all data bytes with the msb =1 (OR 10000000).
The gap between bytes is variable depensing on the code and timing delays between bytes. Longer gaps make the bytes easier to see by less data per line. So that the decoder can find the start of each byte the msb (1xxxxxxxx) is set high. This leaves 7 bits for each character which is OK for acsii; just do “AND 01111111” on received data.
Using the receiving SPI to follow the bit rate it doesn’t really need the header pattern; but it doesn’t hurt either. I may have to adjust the byte spacing timing as I work on the decoder.
This uses a LM1881 to detect frame and line syn and interrupt the CPU. The CPU counts to line 14 and waits for a rising edge. It starts the SPI transmitting 1 byte which clocks in 8 bits of data on MISO. If it’s fast enough to start the SPI it will read all 8 bits but if not a 1-bit delay will allow it to read 7 bits + 1 from the gap. This would need a simple rotate-right to correct.
Every byte starts with a rising edge of the first bit (1); so after receiving 8 bits the SPI is stopped and the CPU looks for the next rising edge to repeat the process for the number of bytes expected for each line.
When 3 lines have been received and checked the actual position data is updated. Bad lines are counted and could be alarmed or other action taken. The CPU is very busy during receive of each line, looking for rising edges and delaying. I will disable interrupts during each of the 3 lines and just run, probably with a timer based exit for when something goes wrong.
After the 3 lines are received there is plenty of time to work with the data or do other things. The OSD sends XX frames per second but only updates the data occasionally, so there are repeats sent of the data. The decoder could decode all frames or just occasionally. I thought about adding a counter or update flag to the 1st line header to signal the decoder that new data is available, but I haven’t done this yet.
The decoder pcb has a LM1881 for sync detection and a high speed comparator to clean up the data and drive the SPI MISO from the composite video. The board also has eeprom, gps and a 5V servo power supply. It does have to be a high speed comparator to square up the data. The board uses a TLV3501. The preset pot adjusts the detection level for the comparator. This probably means that the video signal supplied has to be reasonably good, steady amplitude, which it should be anyway to provide a usable picture.
more to come…