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)  | 
