Paparazzi UAS  v5.15_devel-230-gc96ce27
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 static float period_to_hour = 1 / 3600.f / ELECTRICAL_PERIODIC_FREQ;
57 
58 #ifndef MIN_BAT_LEVEL
59 #define MIN_BAT_LEVEL 3
60 #endif
61 
62 PRINT_CONFIG_VAR(LOW_BAT_LEVEL)
63 PRINT_CONFIG_VAR(CRITIC_BAT_LEVEL)
64 PRINT_CONFIG_VAR(MIN_BAT_LEVEL)
65 
67 
68 #if defined ADC_CHANNEL_VSUPPLY || (defined ADC_CHANNEL_CURRENT && !defined SITL) || defined MILLIAMP_AT_FULL_THROTTLE
69 static struct {
70 #ifdef ADC_CHANNEL_VSUPPLY
71  struct adc_buf vsupply_adc_buf;
72 #endif
73 #if defined ADC_CHANNEL_CURRENT && !defined SITL
74  struct adc_buf current_adc_buf;
75 #endif
76 #ifdef MILLIAMP_AT_FULL_THROTTLE
77  float nonlin_factor;
78 #endif
79 } electrical_priv;
80 #endif
81 
82 #ifndef VoltageOfAdc
83 #define VoltageOfAdc(adc) DefaultVoltageOfAdc(adc)
84 #endif
85 #ifndef MilliAmpereOfAdc
86 #define MilliAmpereOfAdc(adc) DefaultMilliAmpereOfAdc(adc)
87 #endif
88 
89 #ifndef CURRENT_ESTIMATION_NONLINEARITY
90 #define CURRENT_ESTIMATION_NONLINEARITY 1.2
91 #endif
92 
93 #if defined MILLIAMP_AT_FULL_THROTTLE && !defined MILLIAMP_AT_IDLE_THROTTLE
94  PRINT_CONFIG_MSG("Assuming 0 mA at idle throttle")
95  #define MILLIAMP_AT_IDLE_THROTTLE 0
96 #endif
97 
98 PRINT_CONFIG_VAR(MILLIAMP_AT_IDLE_THROTTLE)
99 
100 void electrical_init(void)
101 {
102  electrical.vsupply = 0.f;
103  electrical.current = 0.f;
104  electrical.charge = 0.f;
105  electrical.energy = 0.f;
106 
107  electrical.bat_low = false;
108  electrical.bat_critical = false;
109 
110 #if defined ADC_CHANNEL_VSUPPLY
111  adc_buf_channel(ADC_CHANNEL_VSUPPLY, &electrical_priv.vsupply_adc_buf, DEFAULT_AV_NB_SAMPLE);
112 #endif
113 
114  /* measure current if available, otherwise estimate it */
115 #if defined ADC_CHANNEL_CURRENT && !defined SITL
116  adc_buf_channel(ADC_CHANNEL_CURRENT, &electrical_priv.current_adc_buf, DEFAULT_AV_NB_SAMPLE);
117 #elif defined MILLIAMP_AT_FULL_THROTTLE
118  PRINT_CONFIG_VAR(CURRENT_ESTIMATION_NONLINEARITY)
119  electrical_priv.nonlin_factor = CURRENT_ESTIMATION_NONLINEARITY;
120 #endif
121 }
122 
124 {
125  static uint32_t bat_low_counter = 0;
126  static uint32_t bat_critical_counter = 0;
127  static bool vsupply_check_started = false;
128 
129 #if defined(ADC_CHANNEL_VSUPPLY) && !defined(SITL) && !USE_BATTERY_MONITOR
130  electrical.vsupply = VoltageOfAdc((electrical_priv.vsupply_adc_buf.sum /
131  electrical_priv.vsupply_adc_buf.av_nb_sample));
132 #endif
133 
134 #ifdef ADC_CHANNEL_CURRENT
135 #ifndef SITL
136  int32_t current_adc = electrical_priv.current_adc_buf.sum / electrical_priv.current_adc_buf.av_nb_sample;
137  electrical.current = MilliAmpereOfAdc(current_adc) / 1000.f;
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  static float full_current = (float)MILLIAMP_AT_FULL_THROTTLE / 1000.f;
151  static float idle_current = (float)MILLIAMP_AT_IDLE_THROTTLE / 1000.f;
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  Bound(x, 0.f, 1.f);
158 
159  /* electrical.current y = ( b^n - (b* x/a)^n )^1/n
160  * a=1, n = electrical_priv.nonlin_factor
161  */
162 #ifndef FBW
164  // Assume no current when throttle killed (motors off)
165  electrical.current = 0;
166  } else {
167 #endif
168  electrical.current = full_current -
169  powf((powf(full_current - idle_current, electrical_priv.nonlin_factor) -
170  powf(((full_current - idle_current) * x), electrical_priv.nonlin_factor)),
171  (1.f / electrical_priv.nonlin_factor));
172 #ifndef FBW
173  }
174 #endif
175 #endif /* ADC_CHANNEL_CURRENT */
176 
177  float consumed_since_last = electrical.current * period_to_hour;
178 
179  electrical.charge += consumed_since_last;
180  electrical.energy += consumed_since_last * electrical.vsupply;
181 
182  /*if valid voltage is seen then start checking. Set min level to 0 to always start*/
183  if (electrical.vsupply >= MIN_BAT_LEVEL) {
184  vsupply_check_started = true;
185  }
186 
187  if (vsupply_check_started) {
188  if (electrical.vsupply < LOW_BAT_LEVEL) {
189  if (bat_low_counter > 0) {
190  bat_low_counter--;
191  }
192  if (bat_low_counter == 0) {
193  electrical.bat_low = true;
194  }
195  } else {
196  // reset battery low status and counter
197  bat_low_counter = BAT_CHECKER_DELAY * ELECTRICAL_PERIODIC_FREQ;
198  electrical.bat_low = false;
199  }
200 
201  if (electrical.vsupply < CRITIC_BAT_LEVEL) {
202  if (bat_critical_counter > 0) {
203  bat_critical_counter--;
204  }
205  if (bat_critical_counter == 0) {
206  electrical.bat_critical = true;
207  }
208  } else {
209  // reset battery critical status and counter
210  bat_critical_counter = BAT_CHECKER_DELAY * ELECTRICAL_PERIODIC_FREQ;
211  electrical.bat_critical = false;
212  }
213  }
214 
215 }
bool autopilot_throttle_killed(void)
get kill status
Definition: autopilot.c:230
#define LOW_BAT_LEVEL
low battery level in Volts (for 3S LiPo)
Definition: electrical.h:36
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:281
float vsupply
supply voltage in V
Definition: electrical.h:45
#define VoltageOfAdc(adc)
Definition: electrical.c:83
#define MIN_BAT_LEVEL
Definition: electrical.c:59
arch independent ADC (Analog to Digital Converter) API
Generic interface for all ADC hardware drivers, independent from microcontroller architecture.
Definition: adc.h:53
#define MilliAmpereOfAdc(adc)
Definition: electrical.c:86
void electrical_init(void)
Definition: electrical.c:100
bool bat_critical
battery critical status
Definition: electrical.h:50
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
float charge
consumed electric charge in Ah
Definition: electrical.h:47
static float period_to_hour
Definition: electrical.c:56
unsigned long uint32_t
Definition: types.h:18
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
Hardware independent code for commands handling.
bool bat_low
battery low status
Definition: electrical.h:49
signed long int32_t
Definition: types.h:19
void electrical_periodic(void)
Definition: electrical.c:123
Core autopilot interface common to all firmwares.
pprz_t commands[COMMANDS_NB]
Storage of intermediate command values.
Definition: commands.c:30
#define CURRENT_ESTIMATION_NONLINEARITY
Definition: electrical.c:90
#define DEFAULT_AV_NB_SAMPLE
Definition: adc.h:41
float energy
consumed energy in Wh
Definition: electrical.h:48
struct Electrical electrical
Definition: electrical.c:66
#define MAX_PPRZ
Definition: paparazzi.h:8
#define CRITIC_BAT_LEVEL
critical battery level in Volts (for 3S LiPo)
Definition: electrical.h:41
float current
current in A
Definition: electrical.h:46
#define ADC_CHANNEL_VSUPPLY
Definition: board.h:200