Showing posts with label Inordinately Proud. Show all posts
Showing posts with label Inordinately Proud. Show all posts

Monday, April 17, 2023

Shipometer progess

 We are on Shipometer 23.04 now. Shipometer 23.03 is a failure, for perhaps multiple reasons.

First, the shipometer is a HAT for a Raspberry Pi that can carry a ZED-F9R GPS+IMU, a BME280 pressure/temperature/humidity sensor, and an ICM20948 9DoF sensor. Even though the GPS+IMU has an IMU built into it, I want the ICM20948 because I can control it at a lower level, and because it has a magnetometer in it as well. 

Finally, it carries an LPC210x as a precision timer. The ZED-F9R generates a pulse-per-second (PPS) which is accurately timed to have its rising edge right at the top of each second, with sub-microsecond accuracy. This PPS is routed to and captured by the Pi, but is also routed to the timer capture input of the LPC210x. This microprocessor is an old ARM7TDMI, but has a hardware 32-bit timer capable at running at 60MHz, with multiple usable capture inputs. The LPC210x is programmed to count at 60MHz, reset after 3.6 billion cycles, capture several inputs, and output the exact timer count of each pulse to its serial port, which is wired to the Pi UART1. This way, the time of each PPS and sensor data-ready signal can be recorded with no latency due to things like interrupts and real-time software.

Tuesday, June 23, 2015

Hey mom! I'm on the Internet!

I just noticed this picture on the Sparkfun AVC2015 site:

That's from AVC 2014, and that is Yukari II, breadboard and everything. Those are my toes on the right.

Friday, June 12, 2015

(Simulated) Success!

If my robot does this at the competition, it will represent full mission success: scoring at least one point.
The left is a spreadsheet plot of the simulated position, and the right is the simulated GPS data dropped into Google Earth.

I had gone into this thinking that the software was good and the hardware flaked out last year. I made a bunch of changes to the software, and it got worse before it got better, but I suspect there were enough bugs in the old code that it wouldn't have worked even if the hardware had worked. Last year, it did try to turn, though.

This proves the value of a good simulation. I have simulated the race more than 100 times, including times when the robot just drove around in circles. The above run was the first which actually successfully sought a waypoint. More about the simulation below the fold.

Thursday, June 11, 2015

Telemetry Database

On one of my previous for-work projects, I was involved in flight software for an instrument bound for low-earth orbit. I am Inordinately Proud of that, because the instrument is still working, in year eight of its two-year mission. The instrument has never crashed. However, that's not what I am talking about today.

One of the things that project used was a command/telemetry database. In the spirit of One Authoritative Source, that database was used to generate PDF documentation for humans (which was then printed out and put into a big three-ring binder for us to take notes on) but also for the ground system to create command packets and interpret telemetry packets. Further, the database was used to generate some of the flight software code involved in interpreting commands and generating telemetry. Mostly in the flight software it was used to make structs, which the flight software used to parse commands and form telemetry. The code had to use the right struct names, but the actual definition of the struct came from the cmd/tlm db.

I have wanted to implement this in Yukari for a long time now, and I have finally done it. The TelemetryDatabase.ods file is the authoritative source for all packet creation and interpretation. This table contains one row for each packet field, grouped into contiguous blocks describing each packet, and eleven columns:

  1. Apid - Application Process ID, the CCSDS term for "packet ID". Each different kind of packet has a different apid, and all packets with the same apid have the same structure.
  2. shortName - Name of the packet, must be a valid C++ identifier
  3. wrapRobot - set to 'y' if we want to automatically generate code to start and end the packet. This is typically set to 'n' when the header is generated in one routine, most commonly in main.cpp, and the body is generated somewhere else, like a sensor routine.
  4. extract - set to 'y' if you want to extract this kind of packet with extractPacket
  5. hasTC - C++ expression, which when evaluated in the embedded code in the right context, produces the timestamp to use on this packet. If the packet doesn't require a timestamp, this field is blank
  6. extractor - One of "csv", "source", "dump". Used to control how the extractPacket ground support program creates extracted packet tables.
  7. source - C++ expression, which when evaluated in the embedded code in the right context, produces the value for this field
  8. field - field name to the outside world
  9. type - C++ field type. If the field is an array (char[] is most typical) include the array size right after the 
  10. unit - Unit of this field, typically some SI unit for floating-point values, or DN or TC ticks for integer values
  11. description in English
Columns 1 through 6 only need to be set for the first field in a packet.  A blank apid is treated as having the same apid (and therefore being in the same packet) as the previous field. Fields in a packet must be contiguous, apids must be unique for packets, and order of fields counts, but order of apids doesn't.

This table is converted from ODS format to CSV using ssconvert, a program which comes with Gnumeric. It is then run through a perl script tlmDb.pl, which generates the following things:
  • A bunch of include files of the form write_packet_$shortName.inc which contain C++ code to write the packets in the embedded code.
  • extract_head.inc  - This file contains all the packets as C++ structs. This file is used in the head of extractPacket.cpp, which is why it is called extract_head.inc
  • extract_body.inc - This file contains a series of blocks of code. Each one starts an appropriate dump file if necessary, reverses each field from (CCSDS-mandated) big-endian to little-endian as necessary, then dumps the packet in the dump file. This is where the extractor field above comes into play. CSV dumps the packet into a CSV file, with all fields printed as ASCII decimal. "Dump" is used for packets with a variable-length payload, like source images and NMEA sentences. These packets have their last field just concatenated to the dump file.
The table itself is useful as a human-readable reference for the packets. Since it is the One Authoritative Source, any change here is immediately reflected in the code. 

This is worked into the makefiles, particularly into the makefile for the packet library. Since the output of tlmDb.pl depends on the table, we treat extract_head.inc as the primary output (it will always be present). We make it depend on TelemetryDatabase.csv , which in turn depends on TelemetryDatabase.ods (we keep the telemetry database in spreadsheet form to take advantage of formulas). All C++ files which create packets then use #include "write_packet_$shortName.inc" in the proper context, and depend on extract_head.inc even if that file isn't used directly.

I spend some time scouring the Internet for a make-friendly program which could convert an ODS spreadsheet to CSV. I finally found ssconvert after trying to get soffice --convert-to to work without success. I also tried the program unoconv, but this appears to be a wrapper around soffice.

Monday, October 21, 2013

IT WORKED!!!

I turned the Rocketometer over to the rocket guys back in July, and had no contact with it until after the flight today. It had been exposed to every environment it was going to see except for vacuum, but I still had no confidence that it would work.

Well, it did.

The first time I stuck the SD card into my computer after the flight, it said "what card?"

 That was disappointing.

 It took a few minutes for the computer to recognize the card, but when it did, I saw that it had recorded 419 MiB in 66 files. One of the last was also the longest, so I ran it through my quick extraction program, then through IDL, and saw the characteristic acceleration pulse during first and second stage.

The first thing I did after that was press the Victory button on my phone:

 No one else in the lab either heard that or got it, so I had to shout, "It Worked!!!".

Now I have to analyze the data...