diff --git a/conf/messages.xml b/conf/messages.xml
index 0e884d14aa..696a5f69f0 100644
--- a/conf/messages.xml
+++ b/conf/messages.xml
@@ -593,9 +593,9 @@
-
-
-
+
+
+
diff --git a/conf/modules/AOA_pwm.xml b/conf/modules/AOA_pwm.xml
new file mode 100644
index 0000000000..4c548f28ed
--- /dev/null
+++ b/conf/modules/AOA_pwm.xml
@@ -0,0 +1,39 @@
+
+
+
+
+ Angle of Attack sensor using PWM input
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ pwm_meas
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/conf/telemetry/fixedwing_flight_recorder.xml b/conf/telemetry/fixedwing_flight_recorder.xml
index cd89f5dc68..c833ac2bef 100644
--- a/conf/telemetry/fixedwing_flight_recorder.xml
+++ b/conf/telemetry/fixedwing_flight_recorder.xml
@@ -125,7 +125,8 @@
-
+
+
diff --git a/sw/airborne/modules/sensors/aoa_adc.c b/sw/airborne/modules/sensors/aoa_adc.c
index 098cb5390f..f5760ecacb 100644
--- a/sw/airborne/modules/sensors/aoa_adc.c
+++ b/sw/airborne/modules/sensors/aoa_adc.c
@@ -87,6 +87,6 @@ void aoa_adc_update(void)
stateSetAngleOfAttack_f(aoa_adc.angle);
#endif
- RunOnceEvery(30, DOWNLINK_SEND_AOA_ADC(DefaultChannel, DefaultDevice, &aoa_adc.raw, &aoa_adc.angle));
+ RunOnceEvery(30, DOWNLINK_SEND_AOA(DefaultChannel, DefaultDevice, &aoa_adc.raw, &aoa_adc.angle));
}
diff --git a/sw/airborne/modules/sensors/aoa_adc.h b/sw/airborne/modules/sensors/aoa_adc.h
index 02c429c52d..a1186c0c1e 100644
--- a/sw/airborne/modules/sensors/aoa_adc.h
+++ b/sw/airborne/modules/sensors/aoa_adc.h
@@ -38,7 +38,7 @@
*/
struct Aoa_Adc {
struct adc_buf buf;
- uint16_t raw; ///< raw ADC value
+ uint32_t raw; ///< raw ADC value
float angle; ///< Angle of attack in radians
float offset; ///< Angle of attack offset in radians
float sens; ///< sensitiviy, i.e. scale to conver raw to angle
diff --git a/sw/airborne/modules/sensors/aoa_pwm.c b/sw/airborne/modules/sensors/aoa_pwm.c
new file mode 100644
index 0000000000..bde6e0f065
--- /dev/null
+++ b/sw/airborne/modules/sensors/aoa_pwm.c
@@ -0,0 +1,147 @@
+/*
+* Copyright (C) 2015 Jean-François Erdelyi, Gautier Hattenberger
+*
+* This file is part of paparazzi
+*
+* paparazzi is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2, or (at your option)
+* any later version.
+*
+* paparazzi is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with paparazzi; see the file COPYING. If not, see
+* .
+*/
+
+/**
+* @file "modules/sensors/aoa_pwm.c"
+* @author Jean-François Erdelyi
+* @brief Angle of Attack sensor on PWM
+*
+* SENSOR, exemple : US DIGITAL MA3-P12-125-B
+* @see http://www.usdigital.com/products/encoders/absolute/rotary/shaft/ma3
+*/
+
+#include "modules/sensors/aoa_pwm.h"
+#include "mcu_periph/pwm_input.h"
+#include "messages.h"
+#include "subsystems/datalink/downlink.h"
+#include "generated/airframe.h"
+
+#if LOG_AOA
+#include "sdLog.h"
+#include "subsystems/chibios-libopencm3/chibios_sdlog.h"
+bool_t log_started;
+#endif
+
+#ifndef AOA_PWM_CHANNEL
+#error "AOA_PWM_CHANNEL needs to be defined to use AOA_pwm module"
+#endif
+
+/// Default to a 12 bit PWM sensor
+#ifndef AOA_PWM_PERIOD
+#define AOA_PWM_PERIOD 4096
+#endif
+/// Some sensor may need an initial PWM offset (1 usec in the case of an MA3 sensor)
+#ifndef AOA_PWM_OFFSET
+#define AOA_PWM_OFFSET 1
+#endif
+/// Default offset value (assuming 0 AOA is in the middle of the range)
+#ifndef AOA_ANGLE_OFFSET
+#define AOA_ANGLE_OFFSET M_PI
+#endif
+/// Default extra offset that can be ajusted from settings
+#ifndef AOA_OFFSET
+#define AOA_OFFSET 0.0f
+#endif
+/// Default filter value
+#ifndef AOA_FILTER
+#define AOA_FILTER 0.0f
+#endif
+/// Default sensitivity (2*pi on a PWM of period AOA_PWM_PERIOD)
+#ifndef AOA_SENS
+#define AOA_SENS ((2.0f*M_PI)/AOA_PWM_PERIOD)
+#endif
+// Set AOA_REVERSE to TRUE to change rotation direction
+#if AOA_REVERSE
+#define AOA_SIGN -1
+#else
+#define AOA_SIGN 1
+#endif
+// Enable telemetry report
+#ifndef SEND_SYNC_AOA
+#define SEND_SYNC_AOA TRUE
+#endif
+// Enable SD card logging
+#ifndef LOG_AOA
+#define LOG_AOA FALSE
+#endif
+
+struct Aoa_Pwm aoa_pwm;
+
+#if PERIODIC_TELEMETRY
+#include "subsystems/datalink/telemetry.h"
+
+static void send_aoa(struct transport_tx *trans, struct link_device *dev)
+{
+ pprz_msg_send_AOA(trans, dev, AC_ID, &aoa_pwm.raw, &aoa_pwm.angle);
+}
+
+#endif
+
+void aoa_pwm_init(void)
+{
+ aoa_pwm.offset = AOA_OFFSET;
+ aoa_pwm.filter = AOA_FILTER;
+ aoa_pwm.sens = AOA_SENS;
+ aoa_pwm.angle = 0.0f;
+ aoa_pwm.raw = 0.0f;
+#if LOG_AOA
+ log_started = FALSE;
+#endif
+#if PERIODIC_TELEMETRY
+ register_periodic_telemetry(DefaultPeriodic, "AOA", send_aoa);
+#endif
+}
+
+void aoa_pwm_update(void) {
+ static float prev_aoa = 0.0f;
+
+ // raw duty cycle in usec
+ uint32_t duty_raw = pwm_input_duty_tics[AOA_PWM_CHANNEL] / PWM_INPUT_TICKS_PER_USEC;
+
+ // remove some offset if needed
+ aoa_pwm.raw = duty_raw - AOA_PWM_OFFSET;
+ // FIXME for some reason, the last value of the MA3 encoder is not 4096 but 4097
+ // this case is not handled since we don't care about angles close to +- 180 deg
+ aoa_pwm.angle = AOA_SIGN * (((float)aoa_pwm.raw * aoa_pwm.sens) - aoa_pwm.offset - AOA_ANGLE_OFFSET);
+ // filter angle
+ aoa_pwm.angle = aoa_pwm.filter * prev_aoa + (1.0f - aoa_pwm.filter) * aoa_pwm.angle;
+ prev_aoa = aoa_pwm.angle;
+
+#if USE_AOA
+ stateSetAngleOfAttack_f(aoa_adc.angle);
+#endif
+
+#if SEND_SYNC_AOA
+ RunOnceEvery(10, DOWNLINK_SEND_AOA(DefaultChannel, DefaultDevice, &aoa_pwm.raw, &aoa_pwm.angle));
+#endif
+
+#if LOG_AOA
+ if(pprzLogFile != -1) {
+ if (!log_started) {
+ sdLogWriteLog(pprzLogFile, "AOA_PWM: ANGLE(deg) RAW(int16)\n");
+ log_started = TRUE;
+ } else {
+ float angle = DegOfRad(aoa_pwm.angle);
+ sdLogWriteLog(pprzLogFile, "AOA_PWM: %.3f %d\n", angle, aoa_pwm.raw);
+ }
+ }
+#endif
+}
+
diff --git a/sw/airborne/modules/sensors/aoa_pwm.h b/sw/airborne/modules/sensors/aoa_pwm.h
new file mode 100644
index 0000000000..252ce946c5
--- /dev/null
+++ b/sw/airborne/modules/sensors/aoa_pwm.h
@@ -0,0 +1,53 @@
+/*
+* Copyright (C) 2015 Jean-François Erdelyi, Gautier Hattenberger
+*
+* This file is part of paparazzi
+*
+* paparazzi is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2, or (at your option)
+* any later version.
+*
+* paparazzi is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with paparazzi; see the file COPYING. If not, see
+* .
+*/
+
+/**
+* @file "modules/sensors/aoa_ppm.h"
+* @author Jean-François Erdelyi
+* @brief Angle of Attack sensor on PWM
+*
+* SENSOR, example : US DIGITAL MA3-P12-125-B
+*/
+
+#ifndef AOA_PWM_H
+#define AOA_PWM_H
+
+#include "std.h"
+
+struct Aoa_Pwm {
+ uint32_t raw; ///< raw PWM value
+ float angle; ///< Angle of attack in radians
+ float offset; ///< Angle of attack offset in radians
+ float sens; ///< sensitiviy, i.e. scale to conver raw to angle
+
+ /** Filtering value [0-1]
+ * 0: no filtering
+ * 1: output is a constant value
+ */
+ float filter;
+};
+
+extern struct Aoa_Pwm aoa_pwm;
+
+extern void aoa_pwm_init(void);
+extern void aoa_pwm_update(void);
+
+#endif /* AOA_PWM_H */
+