diff options
-rw-r--r-- | altoslib/AltosConfigData.java | 10 | ||||
-rw-r--r-- | altoslib/AltosLink.java | 8 | ||||
-rw-r--r-- | altoslib/AltosState.java | 3 | ||||
-rw-r--r-- | doc/altusmetrum.xsl | 17 | ||||
-rw-r--r-- | doc/micropeak.xsl | 127 | ||||
-rw-r--r-- | src/core/ao_convert_pa.c | 8 | ||||
-rw-r--r-- | src/micropeak/Makefile | 4 | ||||
-rw-r--r-- | src/micropeak/ao_micropeak.c | 35 | ||||
-rw-r--r-- | src/micropeak/ao_pins.h | 3 | ||||
-rw-r--r-- | src/micropeak/ao_report_tiny.c | 8 |
10 files changed, 196 insertions, 27 deletions
diff --git a/altoslib/AltosConfigData.java b/altoslib/AltosConfigData.java index f940b150..99b8e39d 100644 --- a/altoslib/AltosConfigData.java +++ b/altoslib/AltosConfigData.java @@ -485,13 +485,15 @@ public class AltosConfigData implements Iterable<String> { reset(); link.printf("c s\nf\nv\n"); read_link(link, "software-version"); + System.out.printf("Log format %d\n", log_format); switch (log_format) { - case AltosLib.AO_LOG_FORMAT_TELEMETRY: - case AltosLib.AO_LOG_FORMAT_TELESCIENCE: - break; - default: + case AltosLib.AO_LOG_FORMAT_FULL: + case AltosLib.AO_LOG_FORMAT_TINY: + case AltosLib.AO_LOG_FORMAT_MEGAMETRUM: link.printf("l\n"); read_link(link, "done"); + default: + break; } } diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index 6d510563..1b722026 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -284,8 +284,8 @@ public abstract class AltosLink implements Runnable { frequency = in_frequency; config_data(); set_radio_frequency(frequency, - config_data.radio_frequency != 0, - config_data.radio_setting != 0, + config_data.radio_frequency > 0, + config_data.radio_setting > 0, config_data.radio_calibration); } @@ -339,10 +339,10 @@ public abstract class AltosLink implements Runnable { public String name; public void start_remote() throws TimeoutException, InterruptedException { - if (debug) - System.out.printf("start remote %7.3f\n", frequency); if (frequency == 0.0) frequency = AltosPreferences.frequency(serial); + if (debug) + System.out.printf("start remote %7.3f\n", frequency); set_radio_frequency(frequency); set_callsign(AltosPreferences.callsign()); printf("p\nE 0\n"); diff --git a/altoslib/AltosState.java b/altoslib/AltosState.java index f28dd1c6..218c598a 100644 --- a/altoslib/AltosState.java +++ b/altoslib/AltosState.java @@ -92,6 +92,9 @@ public class AltosState { public void init (AltosRecord cur, AltosState prev_state) { data = cur; + /* Discard previous state if it was for a different board */ + if (prev_state != null && prev_state.data.serial != data.serial) + prev_state = null; ground_altitude = data.ground_altitude(); altitude = data.altitude(); diff --git a/doc/altusmetrum.xsl b/doc/altusmetrum.xsl index b2677a02..e7ab353b 100644 --- a/doc/altusmetrum.xsl +++ b/doc/altusmetrum.xsl @@ -278,6 +278,19 @@ NAR #88757, TRA #12200 designed for use with single-cell batteries with 3.7 volts nominal. </para> <para> + The battery connectors are a standard 2-pin JST connector and + match batteries sold by Spark Fun. These batteries are + single-cell Lithium Polymer batteries that nominally provide 3.7 + volts. Other vendors sell similar batteries for RC aircraft + using mating connectors, however the polarity for those is + generally reversed from the batteries used by Altus Metrum + products. In particular, the Tenergy batteries supplied for use + in Featherweight flight computers are not compatible with Altus + Metrum flight computers or battery chargers. <emphasis>Check + polarity and voltage before connecting any battery not purchased + from Altus Metrum or Spark Fun.</emphasis> + </para> + <para> By default, we use the unregulated output of the Li-Po battery directly to fire ejection charges. This works marvelously with standard low-current e-matches like the J-Tek from MJG Technologies, and with @@ -481,7 +494,7 @@ NAR #88757, TRA #12200 <para> You can monitor the operation of the radio link by watching the lights on the devices. The red LED will flash each time a packet - is tramsitted, while the green LED will light up on TeleDongle when + is transmitted, while the green LED will light up on TeleDongle when it is waiting to receive a packet from the altimeter. </para> </section> @@ -2199,7 +2212,7 @@ NAR #88757, TRA #12200 </listitem> <listitem> <para> - RF interface for battery charging, configuration, and data recovery. + RF interface for configuration, and data recovery. </para> </listitem> <listitem> diff --git a/doc/micropeak.xsl b/doc/micropeak.xsl index 284d0fb0..aa1adaef 100644 --- a/doc/micropeak.xsl +++ b/doc/micropeak.xsl @@ -37,6 +37,13 @@ Updates for version 1.0 release. </revremark> </revision> + <revision> + <revnumber>1.1</revnumber> + <date>12 December 2012</date> + <revremark> + Add comments about EEPROM storage format and programming jig. + </revremark> + </revision> </revhistory> </bookinfo> <acknowledgements> @@ -223,10 +230,10 @@ NAR #88757, TRA #12200 with the negative battery terminal. </para> <para> - Shipping restrictions prevent us from including a CR1025 - battery with MicroPeak. Many stores carry CR1025 batteries as - they are commonly used in small electronic devices such as - flash lights. + Shipping restrictions may prevent us from including a CR1025 + battery with MicroPeak. If so, many stores carry CR1025 + batteries as they are commonly used in small electronic + devices such as flash lights. </para> </section> <section> @@ -272,6 +279,118 @@ NAR #88757, TRA #12200 serve to further protect the switch from launch forces. </para> </section> + <section> + <title>On-board data storage</title> + <para> + The ATtiny85 has 512 bytes of non-volatile storage, separate + from the code storage memory. The MicroPeak firmware uses this + to store information about the last completed + flight. Barometric measurements from the ground before launch + and at apogee are stored, and used at power-on to compute the + height of the last flight. + </para> + <para> + In addition to the data used to present the height of the last + flight, MicroPeak also stores barometric information sampled + at regular intervals during the flight. This information can + be extracted from MicroPeak through any AVR programming + tool. + </para> + <table frame='all'> + <title>MicroPeak EEPROM Data Storage</title> + <tgroup cols='3' align='center' colsep='1' rowsep='1'> + <colspec align='center' colwidth='2*' colname='Address'/> + <colspec align='center' colwidth='*' colname='Size (bytes)'/> + <colspec align='left' colwidth='7*' colname='Description'/> + <thead> + <row> + <entry align='center'>Address</entry> + <entry align='center'>Size (bytes)</entry> + <entry align='center'>Description</entry> + </row> + </thead> + <tbody> + <row> + <entry>0x000</entry> + <entry>4</entry> + <entry>Average ground pressure (Pa)</entry> + </row> + <row> + <entry>0x004</entry> + <entry>4</entry> + <entry>Minimum flight pressure (Pa)</entry> + </row> + <row> + <entry>0x008</entry> + <entry>2</entry> + <entry>Number of in-flight samples</entry> + </row> + <row> + <entry>0x00a … 0x1fe</entry> + <entry>2</entry> + <entry>Instantaneous flight pressure (Pa) low 16 bits</entry> + </row> + </tbody> + </tgroup> + </table> + <para> + All EEPROM data are stored least-significant byte first. The + instantaneous flight pressure data are stored without the + upper 16 bits of data. The upper bits can be reconstructed + from the previous sample, assuming that pressure doesn't + change by more more than 32kPa in a single sample + interval. Note that this pressure data is <emphasis>not</emphasis> + filtered in any way, while both the recorded ground and apogee + pressure values are, so you shouldn't expect the minimum + instantaneous pressure value to match the recorded minimum + pressure value exactly. + </para> + <para> + MicroPeak samples pressure every 96ms, but stores only every + other sample in the EEPROM. This provides for 251 pressure + samples at 192ms intervals, or 48.192s of storage. The clock + used for these samples is a factory calibrated RC circuit + built into the ATtiny85 and is accurate only to within ±10% at + 25°C. So, you can count on the pressure data being accurate, + but speed or acceleration data computed from this will be + limited by the accuracy of this clock. + </para> + </section> + <section> + <title>MicroPeak Programming Interface</title> + <para> + MicroPeak exposes a standard 6-pin AVR programming interface, + but not using the usual 2x3 array of pins on 0.1" + centers. Instead, there is a single row of tiny 0.60mm × + 0.85mm pads on 1.20mm centers exposed near the edge of the + circuit board. We couldn't find any connector that was + small enough to include on the circuit board. + </para> + <para> + In lieu of an actual connector, the easiest way to connect to + the bare pads is through a set of Pogo pins. These + spring-loaded contacts are designed to connect in precisely + this way. We've designed a programming jig, the MicroPeak + Pogo Pin board which provides a standard AVR interface on one + end and a recessed slot for MicroPeak to align the board with + the Pogo Pins. + </para> + <para> + The MicroPeak Pogo Pin board is not a complete AVR programmer, + it is an interface board that provides a 3.3V regulated power + supply to run the MicroPeak via USB and a standard 6-pin AVR + programming interface with the usual 2x3 grid of pins on 0.1" + centers. This can be connected to any AVR programming + dongle. + </para> + <para> + The AVR programming interface cannot run faster than ¼ of the + AVR CPU clock frequency. Because MicroPeak runs at 250kHz to + save power, you must configure your AVR programming system to + clock the AVR programming interface at no faster than + 62.5kHz, or a clock period of 32µS. + </para> + </section> </chapter> </book> <!-- LocalWords: Altusmetrum MicroPeak diff --git a/src/core/ao_convert_pa.c b/src/core/ao_convert_pa.c index 55fe6e7d..fe6e0ef6 100644 --- a/src/core/ao_convert_pa.c +++ b/src/core/ao_convert_pa.c @@ -43,13 +43,13 @@ ao_pa_to_altitude(int32_t pa) if (pa < 0) pa = 0; - if (pa > 120000) - pa = 120000; + if (pa > 120000L) + pa = 120000L; o = pa >> ALT_SHIFT; part = pa & ALT_MASK; - low = (alt_t) FETCH_ALT(o) * (ALT_SCALE - part); - high = (alt_t) FETCH_ALT(o+1) * part + (ALT_SCALE >> 1); + low = (int32_t) FETCH_ALT(o) * (ALT_SCALE - part); + high = (int32_t) FETCH_ALT(o+1) * part + (ALT_SCALE >> 1); return (low + high) >> ALT_SHIFT; } diff --git a/src/micropeak/Makefile b/src/micropeak/Makefile index 8cf608bb..0c48ed66 100644 --- a/src/micropeak/Makefile +++ b/src/micropeak/Makefile @@ -11,6 +11,7 @@ DUDECPUTYPE=t85 #PROGRAMMER=stk500v2 -P usb PROGRAMMER=usbtiny LOADCMD=avrdude +LOADSLOW=-i 32 -B 32 LOADARG=-p $(DUDECPUTYPE) -c $(PROGRAMMER) -e -U flash:w: CC=avr-gcc OBJCOPY=avr-objcopy @@ -86,6 +87,9 @@ $(PROG).hex: $(PROG) load: $(PROG).hex $(LOADCMD) $(LOADARG)$(PROG).hex +load-slow: $(PROG).hex + $(LOADCMD) $(LOADSLOW) $(LOADARG)$(PROG).hex + ao_product.h: ao-make-product.5c ../Version $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@ diff --git a/src/micropeak/ao_micropeak.c b/src/micropeak/ao_micropeak.c index 10e1d0f9..525cfa42 100644 --- a/src/micropeak/ao_micropeak.c +++ b/src/micropeak/ao_micropeak.c @@ -65,18 +65,40 @@ ao_compute_height(void) } #if !HAS_EEPROM + +#define PA_GROUND_OFFSET 0 +#define PA_MIN_OFFSET 4 +#define N_SAMPLES_OFFSET 8 +#define STARTING_LOG_OFFSET 10 +#define MAX_LOG_OFFSET 512 + +static uint16_t ao_log_offset = STARTING_LOG_OFFSET; + void ao_save_flight(void) { - ao_eeprom_write(0, &pa_ground, sizeof (pa_ground)); - ao_eeprom_write(sizeof (pa_ground), &pa_min, sizeof (pa_min)); + uint16_t n_samples = (ao_log_offset - STARTING_LOG_OFFSET) / sizeof (uint16_t); + ao_eeprom_write(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); + ao_eeprom_write(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); + ao_eeprom_write(N_SAMPLES_OFFSET, &n_samples, sizeof (n_samples)); } void ao_restore_flight(void) { - ao_eeprom_read(0, &pa_ground, sizeof (pa_ground)); - ao_eeprom_read(sizeof (pa_ground), &pa_min, sizeof (pa_min)); + ao_eeprom_read(PA_GROUND_OFFSET, &pa_ground, sizeof (pa_ground)); + ao_eeprom_read(PA_MIN_OFFSET, &pa_min, sizeof (pa_min)); +} + +void +ao_log_micro(void) +{ + uint16_t low_bits = pa; + + if (ao_log_offset < MAX_LOG_OFFSET) { + ao_eeprom_write(ao_log_offset, &low_bits, sizeof (low_bits)); + ao_log_offset += sizeof (low_bits); + } } #endif @@ -110,6 +132,8 @@ main(void) #endif ao_restore_flight(); ao_compute_height(); + /* Give the person a second to get their finger out of the way */ + ao_delay(AO_MS_TO_TICKS(1000)); ao_report_altitude(); ao_spi_init(); @@ -178,6 +202,9 @@ main(void) ao_led_off(AO_LED_REPORT); #if HAS_EEPROM ao_log_micro_data(AO_LOG_MICRO_DATA | pa); +#else + if (sample_count & 1) + ao_log_micro(); #endif pa_avg = pa_avg - (pa_avg >> FILTER_SHIFT) + pa; if (pa_avg < pa_min) diff --git a/src/micropeak/ao_pins.h b/src/micropeak/ao_pins.h index 257b8694..63e9cb1b 100644 --- a/src/micropeak/ao_pins.h +++ b/src/micropeak/ao_pins.h @@ -57,8 +57,9 @@ #define I2C_PIN_SDA PINB0 #define AO_CONST_ATTRIB PROGMEM +typedef int32_t alt_t; #define FETCH_ALT(o) ((alt_t) pgm_read_dword(&altitude_table[o])) -#define AO_ALT_VALUE(x) ((x) * 10) +#define AO_ALT_VALUE(x) ((x) * (alt_t) 10) #endif /* _AO_PINS_H_ */ diff --git a/src/micropeak/ao_report_tiny.c b/src/micropeak/ao_report_tiny.c index 109af1ed..0e8e287f 100644 --- a/src/micropeak/ao_report_tiny.c +++ b/src/micropeak/ao_report_tiny.c @@ -24,7 +24,7 @@ static void ao_report_digit(uint8_t digit) __reentrant { if (!digit) { - mid(AO_MS_TO_TICKS(600)); + mid(AO_MS_TO_TICKS(1000)); pause(AO_MS_TO_TICKS(300)); } else { while (digit--) { @@ -32,14 +32,14 @@ ao_report_digit(uint8_t digit) __reentrant pause(AO_MS_TO_TICKS(300)); } } - pause(AO_MS_TO_TICKS(600)); + pause(AO_MS_TO_TICKS(1000)); } void ao_report_altitude(void) { - __pdata int16_t agl = ao_max_height; - __xdata uint8_t digits[10]; + __pdata alt_t agl = ao_max_height; + static __xdata uint8_t digits[11]; __pdata uint8_t ndigits, i; if (agl < 0) |