altos/telefire*: Do voltage tests in decivolts instead of ADC units
authorKeith Packard <keithp@keithp.com>
Fri, 1 Jun 2018 05:39:45 +0000 (22:39 -0700)
committerKeith Packard <keithp@keithp.com>
Fri, 1 Jun 2018 05:39:45 +0000 (22:39 -0700)
This requires that each pad device specify the ADC reference voltage
and all relevant voltage divider resistor values explicitly so that
the ADC values can be converted to decivolts and compared with one
another. This should be easier to understand in the future when
reading the code.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/drivers/ao_pad.c
src/telefire-v0.1/ao_pins.h
src/telefire-v0.2/ao_pins.h
src/telefireeight-v1.0/ao_pins.h
src/telefiretwo-v0.1/ao_pins.h

index b0ec21617d177005da40eba90d9e6192ee1d590c..ed749d1cf756e4be62a961abab7e8bf69fc4d866 100644 (file)
@@ -153,13 +153,36 @@ ao_pad_run(void)
 
 #define AO_PAD_ARM_SIREN_INTERVAL      200
 
-#ifndef AO_PYRO_R_PYRO_SENSE
-#define AO_PYRO_R_PYRO_SENSE   100
-#define AO_PYRO_R_SENSE_GND    27
-#define AO_FIRE_R_POWER_FET    100
-#define AO_FIRE_R_FET_SENSE    100
-#define AO_FIRE_R_SENSE_GND    27
-#endif
+/* Resistor values needed for various voltage test ratios:
+ *
+ *     Net names involved:
+ *
+ *     V_BATT          Battery power, after the initial power switch
+ *     V_PYRO          Pyro power, after the pyro power switch (and initial power switch)
+ *     PYRO_SENSE      ADC input to sense V_PYRO voltage
+ *     BATT_SENSE      ADC input to sense V_BATT voltage
+ *     IGNITER         FET output to pad (the other pad lead hooks to V_PYRO)
+ *     IGNITER_SENSE   ADC input to sense igniter voltage
+ *
+ *     AO_PAD_R_V_BATT_BATT_SENSE      Resistor from battery rail to battery sense input
+ *     AO_PAD_R_BATT_SENSE_GND         Resistor from battery sense input to ground
+ *
+ *     AO_PAD_R_V_BATT_V_PYRO          Resistor from battery rail to pyro rail
+ *     AO_PAD_R_V_PYRO_PYRO_SENSE      Resistor from pyro rail to pyro sense input
+ *     AO_PAD_R_PYRO_SENSE_GND         Resistor from pyro sense input to ground
+ *
+ *     AO_PAD_R_V_PYRO_IGNITER         Optional resistors from pyro rail to FET igniter output
+ *     AO_PAD_R_IGNITER_IGNITER_SENSE  Resistors from FET igniter output to igniter sense ADC inputs
+ *     AO_PAD_R_IGNITER_SENSE_GND      Resistors from igniter sense ADC inputs to ground
+ */
+
+int16_t
+ao_pad_decivolt(int16_t adc, int16_t r_plus, int16_t r_minus)
+{
+       int32_t mul = (int32_t) AO_ADC_REFERENCE_DV * (r_plus + r_minus);
+       int32_t div = (int32_t) AO_ADC_MAX * r_minus;
+       return ((int32_t) adc * mul + mul/2) / div;
+}
 
 static void
 ao_pad_monitor(void)
@@ -174,6 +197,7 @@ ao_pad_monitor(void)
        sample = ao_data_head;
        for (;;) {
                __pdata int16_t                 pyro;
+
                ao_arch_critical(
                        while (sample == ao_data_head)
                                ao_sleep((void *) DATA_TO_XDATA(&ao_data_head));
@@ -183,28 +207,18 @@ ao_pad_monitor(void)
                packet = &ao_data_ring[sample];
                sample = ao_data_ring_next(sample);
 
-               pyro = packet->adc.pyro;
+               /* Reply battery voltage */
+               query.battery = ao_pad_decivolt(packet->adc.batt, AO_PAD_R_V_BATT_BATT_SENSE, AO_PAD_R_BATT_SENSE_GND);
 
-#define VOLTS_TO_PYRO(x) ((int16_t) ((x) * ((1.0 * AO_PYRO_R_SENSE_GND) / \
-                                           (1.0 * (AO_PYRO_R_SENSE_GND + AO_PYRO_R_PYRO_SENSE)) / 3.3 * AO_ADC_MAX)))
+               /* Current pyro voltage */
+               pyro = ao_pad_decivolt(packet->adc.pyro,
+                                      AO_PAD_R_V_PYRO_PYRO_SENSE,
+                                      AO_PAD_R_PYRO_SENSE_GND);
 
-
-#define VOLTS_TO_FIRE(x) ((int16_t) ((x) * ((1.0 * AO_FIRE_R_SENSE_GND) / \
-                                           (1.0 * (AO_FIRE_R_SENSE_GND + AO_FIRE_R_FET_SENSE)) / 3.3 * AO_ADC_MAX)))
-
-               /* convert ADC value to voltage in tenths, then add .2 for the diode drop */
-               query.battery = (packet->adc.batt + 96) / 192 + 2;
                cur = 0;
-               if (pyro > VOLTS_TO_PYRO(10)) {
+               if (pyro > query.battery * 7 / 8) {
                        query.arm_status = AO_PAD_ARM_STATUS_ARMED;
                        cur |= AO_LED_ARMED;
-#if AO_FIRE_R_POWER_FET
-               } else if (pyro > VOLTS_TO_PYRO(5)) {
-                       if ((ao_time() % 100) < 50)
-                               cur |= AO_LED_ARMED;
-                       query.arm_status = AO_PAD_ARM_STATUS_UNKNOWN;
-                       arm_beep_time = 0;
-#endif
                } else {
                        query.arm_status = AO_PAD_ARM_STATUS_DISARMED;
                        arm_beep_time = 0;
@@ -217,54 +231,50 @@ ao_pad_monitor(void)
                        cur |= AO_LED_GREEN;
 
                for (c = 0; c < AO_PAD_NUM; c++) {
-                       int16_t         sense = packet->adc.sense[c];
+                       int16_t         sense = ao_pad_decivolt(packet->adc.sense[c],
+                                                               AO_PAD_R_IGNITER_IGNITER_SENSE,
+                                                               AO_PAD_R_IGNITER_SENSE_GND);
                        uint8_t status = AO_PAD_IGNITER_STATUS_UNKNOWN;
 
                        /*
-                        *      pyro is run through a divider, so pyro = v_pyro * 27 / 127 ~= v_pyro / 20
-                        *      v_pyro = pyro * 127 / 27
-                        *
-                        *              v_pyro \
-                        *      100k            igniter
-                        *              output /
-                        *      100k           \
-                        *              sense   relay
-                        *      27k            /
-                        *              gnd ---
+                        *      Here's the resistor stack on each
+                        *      igniter channel. Note that
+                        *      AO_PAD_R_V_PYRO_IGNITER is optional
                         *
-                        *              v_pyro \
-                        *      200k            igniter
-                        *              output /
-                        *      200k           \
-                        *              sense   relay
-                        *      22k            /
-                        *              gnd ---
+                        *                                      v_pyro \
+                        *      AO_PAD_R_V_PYRO_IGNITER                 igniter
+                        *                                      output /
+                        *      AO_PAD_R_IGNITER_IGNITER_SENSE         \
+                        *                                      sense   relay
+                        *      AO_PAD_R_IGNITER_SENSE_GND             /
+                        *                                      gnd ---
                         *
-                        *      If the relay is closed, then sense will be 0
-                        *      If no igniter is present, then sense will be v_pyro * 27k/227k = pyro * 127 / 227 ~= pyro/2
-                        *      If igniter is present, then sense will be v_pyro * 27k/127k ~= v_pyro / 20 = pyro
                         */
 
-#if AO_FIRE_R_POWER_FET
+#ifdef AO_PAD_R_V_PYRO_IGNITER
                        if (sense <= pyro / 8) {
+                               /* close to zero → relay is closed */
                                status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_CLOSED;
                                if ((ao_time() % 100) < 50)
                                        cur |= AO_LED_CONTINUITY(c);
-                       } else
-                       if (pyro / 8 * 3 <= sense && sense <= pyro / 8 * 5)
-                               status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
-                       else if (pyro / 8 * 7 <= sense) {
-                               status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
-                               cur |= AO_LED_CONTINUITY(c);
-                       }
-#else
-                       if (sense >= pyro / 8 * 5) {
-                               status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
-                               cur |= AO_LED_CONTINUITY(c);
-                       } else {
-                               status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
                        }
+                       else
 #endif
+                       {
+                               if (sense >= (pyro * 7) / 8) {
+
+                                       /* sense close to pyro voltage; igniter is good
+                                        */
+                                       status = AO_PAD_IGNITER_STATUS_GOOD_IGNITER_RELAY_OPEN;
+                                       cur |= AO_LED_CONTINUITY(c);
+                               } else {
+
+                                       /* relay not shorted (if we can tell),
+                                        * and igniter not obviously present
+                                        */
+                                       status = AO_PAD_IGNITER_STATUS_NO_IGNITER_RELAY_OPEN;
+                               }
+                       }
                        query.igniter_status[c] = status;
                }
                if (cur != prev) {
index ee0ca7166c3639d45d22c54cc97c212bd7e839d9..8266589e254845f6ee2ad20fd7a77aa3ec119dd2 100644 (file)
 #define AO_STROBE_PIN          1
 #define AO_STROBE              P1_1
 
-/* test these values with real igniters */
-#define AO_PAD_RELAY_CLOSED    3524
-#define AO_PAD_NO_IGNITER      16904
-#define AO_PAD_GOOD_IGNITER    22514
+#define AO_ADC_REFERENCE_DV    33
+#define AO_PAD_R_V_BATT_BATT_SENSE     100
+#define AO_PAD_R_BATT_SENSE_GND                27
+
+#define AO_PAD_R_V_BATT_V_PYRO         100
+#define AO_PAD_R_V_PYRO_PYRO_SENSE     100
+#define AO_PAD_R_PYRO_SENSE_GND                27
+
+#define AO_PAD_R_V_PYRO_IGNITER                100
+#define AO_PAD_R_IGNITER_IGNITER_SENSE 100
+#define AO_PAD_R_IGNITER_SENSE_GND     27
 
 #define AO_PAD_ADC_PYRO                4
 #define AO_PAD_ADC_BATT                5
index 4faeb65f83ea0ce34fd37dbd4cf4a1bed6be5a70..65f5bdcc17f1f4e3aa1da412e911e78b3ebf704f 100644 (file)
 #define AO_STROBE              P2_4
 
 /* test these values with real igniters */
-#define AO_PAD_RELAY_CLOSED    3524
-#define AO_PAD_NO_IGNITER      16904
-#define AO_PAD_GOOD_IGNITER    22514
-
 #define AO_PAD_ADC_PYRO                4
 #define AO_PAD_ADC_BATT                5
 
 #define AO_ADC_FIRST_PIN       0
 
+#define AO_ADC_REFERENCE_DV    33
+#define AO_PAD_R_V_BATT_BATT_SENSE     100
+#define AO_PAD_R_BATT_SENSE_GND                27
+
+#define AO_PAD_R_V_BATT_V_PYRO         100
+#define AO_PAD_R_V_PYRO_PYRO_SENSE     100
+#define AO_PAD_R_PYRO_SENSE_GND                27
+
+#define AO_PAD_R_V_PYRO_IGNITER                100
+#define AO_PAD_R_IGNITER_IGNITER_SENSE 100
+#define AO_PAD_R_IGNITER_SENSE_GND     27
+
+
 struct ao_adc {
        int16_t         sense[AO_PAD_NUM];
        int16_t         pyro;
index 271d2cbe88e75412016e1a48fe45147a5f85edc6..15e1fa111c96f0623b0f75d3c9ba62bfe666a5a4 100644 (file)
 #define AO_ADC_SQ9             AO_ADC_PYRO
 #define AO_ADC_SQ10            AO_ADC_BATT
 
+#define AO_ADC_REFERENCE_DV    33
+
 #define AO_ADC_RCC_AHBENR      ((1 << STM_RCC_AHBENR_GPIOAEN) | \
                                 (1 << STM_RCC_AHBENR_GPIOBEN) | \
                                 (1 << STM_RCC_AHBENR_GPIOCEN))
 
-#define AO_PYRO_R_PYRO_SENSE   200
-#define AO_PYRO_R_SENSE_GND    22
 
-#define AO_FIRE_R_POWER_FET    0
-#define AO_FIRE_R_FET_SENSE    200
-#define AO_FIRE_R_SENSE_GND    22
+#define AO_PAD_R_V_BATT_BATT_SENSE     200
+#define AO_PAD_R_BATT_SENSE_GND                22
+
+#define AO_PAD_R_V_BATT_V_PYRO         200
+#define AO_PAD_R_V_PYRO_PYRO_SENSE     200
+#define AO_PAD_R_PYRO_SENSE_GND                22
+
+#undef AO_PAD_R_V_PYRO_IGNITER
+#define AO_PAD_R_IGNITER_IGNITER_SENSE 200
+#define AO_PAD_R_IGNITER_SENSE_GND     22
 
 #define HAS_ADC_TEMP           0
 
index 1e5c0d09bac5c943979c0341b37431e32532faa2..dedd0fad3ece4345d47e0c35f665518a6965e739 100644 (file)
 
 #define HAS_ADC_TEMP           0
 
+#define AO_ADC_REFERENCE_DV    33
+
+#define AO_PAD_R_V_BATT_BATT_SENSE     200
+#define AO_PAD_R_BATT_SENSE_GND                22
+
+#define AO_PAD_R_V_BATT_V_PYRO         200
+#define AO_PAD_R_V_PYRO_PYRO_SENSE     200
+#define AO_PAD_R_PYRO_SENSE_GND                22
+
+#undef AO_PAD_R_V_PYRO_IGNITER
+#define AO_PAD_R_IGNITER_IGNITER_SENSE 200
+#define AO_PAD_R_IGNITER_SENSE_GND     22
+
 struct ao_adc {
        int16_t         sense[AO_PAD_NUM];
        int16_t         pyro;