Paparazzi UAS  v5.8.2_stable-0-g6260b7c
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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 
28 #include "subsystems/electrical.h"
29 
30 #include "mcu_periph/adc.h"
31 #include "subsystems/commands.h"
32 
33 #include "autopilot.h"
34 
35 #include "generated/airframe.h"
36 #include BOARD_CONFIG
37 
38 #ifdef MILLIAMP_PER_PERCENT
39 #warning "deprecated MILLIAMP_PER_PERCENT --> Please use MILLIAMP_AT_FULL_THROTTLE"
40 #endif
41 #if defined BATTERY_SENS || defined BATTERY_OFFSET
42 #warning "BATTERY_SENS and BATTERY_OFFSET are deprecated, please remove them --> if you want to change the default use VoltageOfAdc"
43 #endif
44 
45 #if defined COMMAND_THROTTLE
46 #define COMMAND_CURRENT_ESTIMATION COMMAND_THROTTLE
47 #elif defined COMMAND_THRUST
48 #define COMMAND_CURRENT_ESTIMATION COMMAND_THRUST
49 #endif
50 
51 #ifndef BAT_CHECKER_DELAY
52 #define BAT_CHECKER_DELAY 5
53 #endif
54 
55 #define ELECTRICAL_PERIODIC_FREQ 10
56 
57 #ifndef MIN_BAT_LEVEL
58 #define MIN_BAT_LEVEL 3
59 #endif
60 
61 PRINT_CONFIG_VAR(LOW_BAT_LEVEL)
62 PRINT_CONFIG_VAR(CRITIC_BAT_LEVEL)
63 PRINT_CONFIG_VAR(MIN_BAT_LEVEL)
64 
66 
67 #if defined ADC_CHANNEL_VSUPPLY || (defined ADC_CHANNEL_CURRENT && !defined SITL) || defined MILLIAMP_AT_FULL_THROTTLE
68 static struct {
69 #ifdef ADC_CHANNEL_VSUPPLY
70  struct adc_buf vsupply_adc_buf;
71 #endif
72 #if defined ADC_CHANNEL_CURRENT && !defined SITL
73  struct adc_buf current_adc_buf;
74 #endif
75 #ifdef MILLIAMP_AT_FULL_THROTTLE
76  float nonlin_factor;
77 #endif
78 } electrical_priv;
79 #endif
80 
81 #ifndef VoltageOfAdc
82 #define VoltageOfAdc(adc) DefaultVoltageOfAdc(adc)
83 #endif
84 #ifndef MilliAmpereOfAdc
85 #define MilliAmpereOfAdc(adc) DefaultMilliAmpereOfAdc(adc)
86 #endif
87 
88 #ifndef CURRENT_ESTIMATION_NONLINEARITY
89 #define CURRENT_ESTIMATION_NONLINEARITY 1.2
90 #endif
91 
92 #if defined MILLIAMP_AT_FULL_THROTTLE && !defined MILLIAMP_AT_IDLE_THROTTLE
93  PRINT_CONFIG_MSG("Assuming 0 mA at idle throttle")
94  #define MILLIAMP_AT_IDLE_THROTTLE 0
95 #endif
96 
97 PRINT_CONFIG_VAR(MILLIAMP_AT_IDLE_THROTTLE)
98 
99 void electrical_init(void)
100 {
101  electrical.vsupply = 0;
102  electrical.current = 0;
103  electrical.energy = 0;
104 
105  electrical.bat_low = FALSE;
106  electrical.bat_critical = FALSE;
107 
108 #if defined ADC_CHANNEL_VSUPPLY
109  adc_buf_channel(ADC_CHANNEL_VSUPPLY, &electrical_priv.vsupply_adc_buf, DEFAULT_AV_NB_SAMPLE);
110 #endif
111 
112  /* measure current if available, otherwise estimate it */
113 #if defined ADC_CHANNEL_CURRENT && !defined SITL
114  adc_buf_channel(ADC_CHANNEL_CURRENT, &electrical_priv.current_adc_buf, DEFAULT_AV_NB_SAMPLE);
115 #elif defined MILLIAMP_AT_FULL_THROTTLE
116  PRINT_CONFIG_VAR(CURRENT_ESTIMATION_NONLINEARITY)
117  electrical_priv.nonlin_factor = CURRENT_ESTIMATION_NONLINEARITY;
118 #endif
119 }
120 
122 {
123  static uint32_t bat_low_counter = 0;
124  static uint32_t bat_critical_counter = 0;
125  static bool_t vsupply_check_started = FALSE;
126 
127 #if defined(ADC_CHANNEL_VSUPPLY) && !defined(SITL)
128  electrical.vsupply = 10 * VoltageOfAdc((electrical_priv.vsupply_adc_buf.sum /
129  electrical_priv.vsupply_adc_buf.av_nb_sample));
130 #endif
131 
132 #ifdef ADC_CHANNEL_CURRENT
133 #ifndef SITL
134  int32_t current_adc = electrical_priv.current_adc_buf.sum / electrical_priv.current_adc_buf.av_nb_sample;
135  electrical.current = MilliAmpereOfAdc(current_adc);
136  /* Prevent an overflow on high current spikes when using the motor brake */
137  BoundAbs(electrical.current, 65000);
138 #endif
139 #elif defined MILLIAMP_AT_FULL_THROTTLE && defined COMMAND_CURRENT_ESTIMATION
140  /*
141  * Superellipse: abs(x/a)^n + abs(y/b)^n = 1
142  * with a = 1
143  * b = mA at full throttle
144  * n = 1.2 This defines nonlinearity (1 = linear)
145  * x = throttle
146  * y = current
147  *
148  * define CURRENT_ESTIMATION_NONLINEARITY in your airframe file to change the default nonlinearity factor of 1.2
149  */
150  float full_current = (float)MILLIAMP_AT_FULL_THROTTLE;
151  float idle_current = (float)MILLIAMP_AT_IDLE_THROTTLE;
152 
153  float x = ((float)commands[COMMAND_CURRENT_ESTIMATION]) / ((float)MAX_PPRZ);
154 
155  /* Boundary check for x to prevent math errors due to negative numbers in
156  * pow() */
157  if(x > 1.0f) {
158  x = 1.0f;
159  } else if(x < 0.0f) {
160  x = 0.0f;
161  }
162 
163  /* electrical.current y = ( b^n - (b* x/a)^n )^1/n
164  * a=1, n = electrical_priv.nonlin_factor
165  */
166 #ifndef FBW
167  if(kill_throttle) {
168  // Assume no current when throttle killed (motors off)
169  electrical.current = 0;
170  } else {
171 #endif
172  electrical.current = full_current -
173  pow((pow(full_current - idle_current, electrical_priv.nonlin_factor) -
174  pow(((full_current - idle_current) * x), electrical_priv.nonlin_factor)),
175  (1. / electrical_priv.nonlin_factor));
176 #ifndef FBW
177  }
178 #endif
179 #endif /* ADC_CHANNEL_CURRENT */
180 
181  // mAh = mA * dt (10Hz -> hours)
182  electrical.energy += ((float)electrical.current) / 3600.0f / ELECTRICAL_PERIODIC_FREQ;
183 
184  /*if valid voltage is seen then start checking. Set min level to 0 to always start*/
185  if (electrical.vsupply >= MIN_BAT_LEVEL * 10) {
186  vsupply_check_started = TRUE;
187  }
188 
189  if (vsupply_check_started) {
190  if (electrical.vsupply < LOW_BAT_LEVEL * 10) {
191  if (bat_low_counter > 0) {
192  bat_low_counter--;
193  }
194  if (bat_low_counter == 0) {
195  electrical.bat_low = TRUE;
196  }
197  } else {
198  // reset battery low status and counter
199  bat_low_counter = BAT_CHECKER_DELAY * ELECTRICAL_PERIODIC_FREQ;
200  electrical.bat_low = FALSE;
201  }
202 
203  if (electrical.vsupply < CRITIC_BAT_LEVEL * 10) {
204  if (bat_critical_counter > 0) {
205  bat_critical_counter--;
206  }
207  if (bat_critical_counter == 0) {
208  electrical.bat_critical = TRUE;
209  }
210  } else {
211  // reset battery critical status and counter
212  bat_critical_counter = BAT_CHECKER_DELAY * ELECTRICAL_PERIODIC_FREQ;
213  electrical.bat_critical = FALSE;
214  }
215  }
216 
217 }
int32_t current
current in milliamps
Definition: electrical.h:49
#define LOW_BAT_LEVEL
low battery level in Volts (for 3S LiPo)
Definition: electrical.h:36
bool_t bat_low
battery low status
Definition: electrical.h:52
#define VoltageOfAdc(adc)
Definition: electrical.c:82
#define MIN_BAT_LEVEL
Definition: electrical.c:58
bool_t bat_critical
battery critical status
Definition: electrical.h:53
arch independent ADC (Analog to Digital Converter) API
#define FALSE
Definition: std.h:5
Generic interface for all ADC hardware drivers, independent from microcontroller architecture.
Definition: adc.h:53
#define MilliAmpereOfAdc(adc)
Definition: electrical.c:85
#define TRUE
Definition: std.h:4
void electrical_init(void)
Definition: electrical.c:99
Interface for electrical status: supply voltage, current, battery status, etc.
#define BAT_CHECKER_DELAY
Definition: electrical.c:52
#define ELECTRICAL_PERIODIC_FREQ
Definition: electrical.c:55
unsigned long uint32_t
Definition: types.h:18
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
#define ADC_CHANNEL_VSUPPLY
Definition: apogee_1.0.h:205
bool_t kill_throttle
Definition: autopilot.c:42
Hardware independent code for commands handling.
void adc_buf_channel(uint8_t adc_channel, struct adc_buf *s, uint8_t av_nb_sample)
Registers a buffer to be used to store the specified converted channel Usage:
Definition: adc_arch.c:91
signed long int32_t
Definition: types.h:19
void electrical_periodic(void)
Definition: electrical.c:121
pprz_t commands[COMMANDS_NB]
Storage of intermediate command values.
Definition: commands.c:30
#define CURRENT_ESTIMATION_NONLINEARITY
Definition: electrical.c:89
uint16_t vsupply
supply voltage in decivolts
Definition: electrical.h:48
#define DEFAULT_AV_NB_SAMPLE
Definition: adc.h:41
float energy
consumed energy in mAh
Definition: electrical.h:51
struct Electrical electrical
Definition: electrical.c:65
#define MAX_PPRZ
Definition: paparazzi.h:8
#define CRITIC_BAT_LEVEL
critical battery level in Volts (for 3S LiPo)
Definition: electrical.h:42