Paparazzi UAS  v6.3_unstable
Paparazzi is a free software Unmanned Aircraft System.
electrical.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2010-2013 The Paparazzi Team
3  *
4  * This file is part of paparazzi.
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
29 
30 #include "mcu_periph/adc.h"
31 #include "modules/core/commands.h"
32 
33 #include "autopilot.h"
34 
35 #include "generated/airframe.h"
36 #include "generated/modules.h"
37 #include BOARD_CONFIG
38 
39 #ifdef MILLIAMP_PER_PERCENT
40 #warning "deprecated MILLIAMP_PER_PERCENT --> Please use MILLIAMP_AT_FULL_THROTTLE"
41 #endif
42 #if defined BATTERY_SENS || defined BATTERY_OFFSET
43 #warning "BATTERY_SENS and BATTERY_OFFSET are deprecated, please remove them --> if you want to change the default use VoltageOfAdc"
44 #endif
45 
46 #if defined COMMAND_THROTTLE
47 #define COMMAND_CURRENT_ESTIMATION COMMAND_THROTTLE
48 #elif defined COMMAND_THRUST
49 #define COMMAND_CURRENT_ESTIMATION COMMAND_THRUST
50 #endif
51 
52 #ifndef BAT_CHECKER_DELAY
53 #define BAT_CHECKER_DELAY 5
54 #endif
55 
56 #ifndef MIN_BAT_LEVEL
57 #define MIN_BAT_LEVEL 3
58 #endif
59 
60 #ifndef TAKEOFF_BAT_LEVEL
61 #define TAKEOFF_BAT_LEVEL LOW_BAT_LEVEL
62 #endif
63 PRINT_CONFIG_VAR(TAKEOFF_BAT_LEVEL)
64 
65 PRINT_CONFIG_VAR(LOW_BAT_LEVEL)
66 PRINT_CONFIG_VAR(CRITIC_BAT_LEVEL)
67 PRINT_CONFIG_VAR(MIN_BAT_LEVEL)
68 
69 #ifndef VoltageOfAdc
70 #define VoltageOfAdc(adc) DefaultVoltageOfAdc(adc)
71 #endif
72 #ifndef MilliAmpereOfAdc
73 #define MilliAmpereOfAdc(adc) DefaultMilliAmpereOfAdc(adc)
74 #endif
75 
76 #ifndef CURRENT_ESTIMATION_NONLINEARITY
77 #define CURRENT_ESTIMATION_NONLINEARITY 1.2
78 #endif
79 PRINT_CONFIG_VAR(CURRENT_ESTIMATION_NONLINEARITY)
80 
81 #if defined MILLIAMP_AT_FULL_THROTTLE && !defined MILLIAMP_AT_IDLE_THROTTLE
82  PRINT_CONFIG_MSG("Assuming 0 mA at idle throttle")
83  #define MILLIAMP_AT_IDLE_THROTTLE 0
84 #endif
85 
86 PRINT_CONFIG_VAR(MILLIAMP_AT_IDLE_THROTTLE)
87 
88 /* Main external structure */
89 struct Electrical electrical;
90 
91 #if defined ADC_CHANNEL_VSUPPLY || (defined ADC_CHANNEL_CURRENT && !defined SITL) || defined MILLIAMP_AT_FULL_THROTTLE
92 static struct {
93 #ifdef ADC_CHANNEL_VSUPPLY
94  struct adc_buf vsupply_adc_buf;
95 #endif
96 #if defined ADC_CHANNEL_CURRENT && !defined SITL
97  struct adc_buf current_adc_buf;
98 #endif
99 #if defined ADC_CHANNEL_CURRENT2 && !defined SITL
100  struct adc_buf current2_adc_buf;
101 #endif
102 #ifdef MILLIAMP_AT_FULL_THROTTLE
103  float nonlin_factor;
104 #endif
105 } electrical_priv;
106 #endif
107 
108 #ifdef PREFLIGHT_CHECKS
109 /* Preflight checks */
111 static struct preflight_check_t electrical_pfc;
112 
113 static void electrical_preflight(struct preflight_result_t *result) {
115  preflight_error(result, "Battery level %.2fV below minimum takeoff level %.2fV", electrical.vsupply, TAKEOFF_BAT_LEVEL);
116  } else {
117  preflight_success(result, "Battery level %.2fV above takeoff level %.2fV", electrical.vsupply, TAKEOFF_BAT_LEVEL);
118  }
119 }
120 #endif // PREFLIGHT_CHECKS
121 
122 void electrical_init(void)
123 {
124  electrical.vsupply = 0.f;
125  electrical.current = 0.f;
126  electrical.charge = 0.f;
127  electrical.energy = 0.f;
128  electrical.avg_power = 0;
129  electrical.avg_cnt = 0;
130 
131  electrical.bat_low = false;
132  electrical.bat_critical = false;
133 
134 #if defined ADC_CHANNEL_VSUPPLY
135  adc_buf_channel(ADC_CHANNEL_VSUPPLY, &electrical_priv.vsupply_adc_buf, DEFAULT_AV_NB_SAMPLE);
136 #endif
137 
138  /* measure current if available, otherwise estimate it */
139 #if defined ADC_CHANNEL_CURRENT && !defined SITL
140  adc_buf_channel(ADC_CHANNEL_CURRENT, &electrical_priv.current_adc_buf, DEFAULT_AV_NB_SAMPLE);
141 
142 #if defined ADC_CHANNEL_CURRENT2 && !defined SITL
143  adc_buf_channel(ADC_CHANNEL_CURRENT2, &electrical_priv.current2_adc_buf, DEFAULT_AV_NB_SAMPLE);
144 #endif
145 #elif defined MILLIAMP_AT_FULL_THROTTLE
146  electrical_priv.nonlin_factor = CURRENT_ESTIMATION_NONLINEARITY;
147 #endif
148 
149  /* Register preflight checks */
150 #if PREFLIGHT_CHECKS
151  preflight_check_register(&electrical_pfc, electrical_preflight);
152 #endif
153 }
154 
156 {
157  static uint32_t bat_low_counter = 0;
158  static uint32_t bat_critical_counter = 0;
159  static bool vsupply_check_started = false;
160 
161 #if defined(ADC_CHANNEL_VSUPPLY) && !defined(SITL) && !USE_BATTERY_MONITOR
162  electrical.vsupply = VoltageOfAdc((electrical_priv.vsupply_adc_buf.sum /
163  electrical_priv.vsupply_adc_buf.av_nb_sample));
164 #endif
165 
166 #ifdef ADC_CHANNEL_CURRENT
167 #ifndef SITL
168  int32_t current_adc = electrical_priv.current_adc_buf.sum / electrical_priv.current_adc_buf.av_nb_sample;
169  electrical.current = MilliAmpereOfAdc(current_adc) / 1000.f;
170 
171 #ifdef ADC_CHANNEL_CURRENT2
172  current_adc = electrical_priv.current2_adc_buf.sum / electrical_priv.current2_adc_buf.av_nb_sample;
173  electrical.current += MilliAmpereOfAdc2(current_adc) / 1000.f;
174 #endif
175 #endif
176 #elif defined MILLIAMP_AT_FULL_THROTTLE && defined COMMAND_CURRENT_ESTIMATION
177  /*
178  * Superellipse: abs(x/a)^n + abs(y/b)^n = 1
179  * with a = 1
180  * b = mA at full throttle
181  * n = 1.2 This defines nonlinearity (1 = linear)
182  * x = throttle
183  * y = current
184  *
185  * define CURRENT_ESTIMATION_NONLINEARITY in your airframe file to change the default nonlinearity factor of 1.2
186  */
187  static float full_current = (float)MILLIAMP_AT_FULL_THROTTLE / 1000.f;
188  static float idle_current = (float)MILLIAMP_AT_IDLE_THROTTLE / 1000.f;
189 
190  float x = ((float)commands[COMMAND_CURRENT_ESTIMATION]) / ((float)MAX_PPRZ);
191 
192  /* Boundary check for x to prevent math errors due to negative numbers in
193  * pow() */
194  Bound(x, 0.f, 1.f);
195 
196  /* electrical.current y = ( b^n - (b* x/a)^n )^1/n
197  * a=1, n = electrical_priv.nonlin_factor
198  */
199 #ifndef FBW
201  // Assume no current when throttle killed (motors off)
202  electrical.current = 0;
203  } else {
204 #endif
205  electrical.current = full_current -
206  powf((powf(full_current - idle_current, electrical_priv.nonlin_factor) -
207  powf(((full_current - idle_current) * x), electrical_priv.nonlin_factor)),
208  (1.f / electrical_priv.nonlin_factor));
209 #ifndef FBW
210  }
211 #endif
212 #endif /* ADC_CHANNEL_CURRENT */
213 
214  static const float period_to_hour = 1 / 3600.f / ELECTRICAL_PERIODIC_FREQ;
215  float consumed_since_last = electrical.current * period_to_hour;
216 
217  electrical.charge += consumed_since_last;
218  electrical.energy += consumed_since_last * electrical.vsupply;
219 
220  /*if valid voltage is seen then start checking. Set min level to 0 to always start*/
222  vsupply_check_started = true;
223  }
224 
225  if (vsupply_check_started) {
227  if (bat_low_counter > 0) {
228  bat_low_counter--;
229  }
230  if (bat_low_counter == 0) {
231  electrical.bat_low = true;
232  }
233  } else {
234  // reset battery low status and counter
235  bat_low_counter = BAT_CHECKER_DELAY * ELECTRICAL_PERIODIC_FREQ;
236  electrical.bat_low = false;
237  }
238 
240  if (bat_critical_counter > 0) {
241  bat_critical_counter--;
242  }
243  if (bat_critical_counter == 0) {
244  electrical.bat_critical = true;
245  }
246  } else {
247  // reset battery critical status and counter
248  bat_critical_counter = BAT_CHECKER_DELAY * ELECTRICAL_PERIODIC_FREQ;
249  electrical.bat_critical = false;
250  }
251  }
252 
253  float power = electrical.vsupply * electrical.current;
254  electrical.avg_power += power;
256 }
257 
258 void electrical_avg_reset(float var __attribute__((unused)))
259 {
260  electrical.avg_power = 0;
261  electrical.avg_cnt = 0;
262 }
arch independent ADC (Analog to Digital Converter) API
#define DEFAULT_AV_NB_SAMPLE
Definition: adc.h:41
Generic interface for all ADC hardware drivers, independent from microcontroller architecture.
Definition: adc.h:53
#define ADC_CHANNEL_VSUPPLY
Definition: board.h:197
bool autopilot_throttle_killed(void)
get kill status
Definition: autopilot.c:308
Core autopilot interface common to all firmwares.
void adc_buf_channel(uint8_t adc_channel, struct adc_buf *s, uint8_t av_nb_sample)
Link between ChibiOS ADC drivers and Paparazzi adc_buffers.
Definition: adc_arch.c:312
pprz_t commands[COMMANDS_NB]
Definition: commands.c:30
Hardware independent code for commands handling.
#define ADC_CHANNEL_CURRENT
void electrical_avg_reset(float var)
Definition: electrical.c:258
#define BAT_CHECKER_DELAY
Definition: electrical.c:53
#define VoltageOfAdc(adc)
Definition: electrical.c:70
#define MilliAmpereOfAdc(adc)
Definition: electrical.c:73
struct Electrical electrical
Definition: electrical.c:89
#define TAKEOFF_BAT_LEVEL
Definition: electrical.c:61
#define CURRENT_ESTIMATION_NONLINEARITY
Definition: electrical.c:77
void electrical_init(void)
Definition: electrical.c:122
#define MIN_BAT_LEVEL
Definition: electrical.c:57
void electrical_periodic(void)
Definition: electrical.c:155
Interface for electrical status: supply voltage, current, battery status, etc.
uint32_t avg_power
average power sum
Definition: electrical.h:52
#define LOW_BAT_LEVEL
low battery level in Volts (for 3S LiPo)
Definition: electrical.h:36
float energy
consumed energy in Wh
Definition: electrical.h:48
float current
current in A
Definition: electrical.h:46
uint32_t avg_cnt
average power counter
Definition: electrical.h:53
#define CRITIC_BAT_LEVEL
critical battery level in Volts (for 3S LiPo)
Definition: electrical.h:41
bool bat_low
battery low status
Definition: electrical.h:49
float charge
consumed electric charge in Ah
Definition: electrical.h:47
float vsupply
supply voltage in V
Definition: electrical.h:45
bool bat_critical
battery critical status
Definition: electrical.h:50
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
#define MAX_PPRZ
Definition: paparazzi.h:8
void preflight_error(struct preflight_result_t *result, const char *fmt,...)
Register a preflight error used inside the preflight checking functions.
void preflight_success(struct preflight_result_t *result, const char *fmt,...)
Register a preflight success used inside the preflight checking functions.
void preflight_check_register(struct preflight_check_t *check, preflight_check_f func)
Register a preflight check and add it to the linked list.
int int32_t
Typedef defining 32 bit int type.
Definition: vl53l1_types.h:83
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
Definition: vl53l1_types.h:78