mixer.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, James Jackson and Daniel Koch, BYU MAGICC Lab
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 
33 #include <stdint.h>
34 
35 #include "mixer.h"
36 #include "rosflight.h"
37 
38 namespace rosflight_firmware
39 {
40 
42  RF_(_rf)
43 {
44  mixer_to_use_ = nullptr;
45 }
46 
48 {
49  init_mixing();
50  RF_.params_.add_callback([this](uint8_t param_id)
51  {
52  this->param_change_callback(param_id);
54  RF_.params_.add_callback([this](uint8_t param_id)
55  {
56  this->param_change_callback(param_id);
57  }, PARAM_RC_TYPE);
58  RF_.params_.add_callback([this](uint8_t param_id)
59  {
60  this->param_change_callback(param_id);
61  }, PARAM_MIXER);
62 }
63 
64 void Mixer::param_change_callback(uint16_t param_id)
65 {
66  switch (param_id)
67  {
68  case PARAM_MIXER:
69  init_mixing();
70  break;
71  default:
72  init_PWM();
73  break;
74  }
75 }
76 
77 
79 {
80  // clear the invalid mixer error
82 
83  uint8_t mixer_choice = RF_.params_.get_param_int(PARAM_MIXER);
84 
85  if (mixer_choice >= NUM_MIXERS)
86  {
87  RF_.comm_manager_.log(CommLink::LogSeverity::LOG_ERROR, "Invalid Mixer Choice");
88 
89  // set the invalid mixer flag
91  mixer_to_use_ = nullptr;
92  }
93  else
94  {
95  mixer_to_use_ = array_of_mixers_[mixer_choice];
96  }
97 
98 
99  init_PWM();
100 
101  for (int8_t i=0; i<8; i++)
102  {
103  raw_outputs_[i] = 0.0f;
104  unsaturated_outputs_[i] = 0.0f;
105  }
106 }
107 
109 {
110  uint32_t refresh_rate = RF_.params_.get_param_int(PARAM_MOTOR_PWM_SEND_RATE);
111  if (refresh_rate == 0 && mixer_to_use_ != nullptr)
112  {
113  refresh_rate = mixer_to_use_->default_pwm_rate;
114  }
115  int16_t off_pwm = 1000;
116 
117  if (mixer_to_use_ == nullptr || refresh_rate == 0)
118  RF_.board_.pwm_init(50, 0);
119  else
120  RF_.board_.pwm_init(refresh_rate, off_pwm);
121 }
122 
123 
124 void Mixer::write_motor(uint8_t index, float value)
125 {
127  {
128  if (value > 1.0)
129  {
130  value = 1.0;
131  }
134  {
136  }
137  else if (value < 0.0)
138  {
139  value = 0.0;
140  }
141  }
142  else
143  {
144  value = 0.0;
145  }
146  raw_outputs_[index] = value;
147  RF_.board_.pwm_write(index, raw_outputs_[index]);
148 }
149 
150 
151 void Mixer::write_servo(uint8_t index, float value)
152 {
153  if (value > 1.0)
154  {
155  value = 1.0;
156  }
157  else if (value < -1.0)
158  {
159  value = -1.0;
160  }
161  raw_outputs_[index] = value;
162  RF_.board_.pwm_write(index, raw_outputs_[index] * 0.5 + 0.5);
163 }
164 
165 
167 {
169  float max_output = 1.0f;
170 
171  // Reverse Fixedwing channels just before mixing if we need to
173  {
174  commands.x *= RF_.params_.get_param_int(PARAM_AILERON_REVERSE) ? -1 : 1;
175  commands.y *= RF_.params_.get_param_int(PARAM_ELEVATOR_REVERSE) ? -1 : 1;
176  commands.z *= RF_.params_.get_param_int(PARAM_RUDDER_REVERSE) ? -1 : 1;
177  }
179  {
180  // For multirotors, disregard yaw commands if throttle is low to prevent motor spin-up while arming/disarming
181  commands.z = 0.0;
182  }
183 
184  if (mixer_to_use_ == nullptr)
185  return;
186 
187  for (int8_t i=0; i<8; i++)
188  {
189  if (mixer_to_use_->output_type[i] != NONE)
190  {
191  // Matrix multiply to mix outputs
192  unsaturated_outputs_[i] = (commands.F*mixer_to_use_->F[i] + commands.x*mixer_to_use_->x[i] +
193  commands.y*mixer_to_use_->y[i] + commands.z*mixer_to_use_->z[i]);
194 
195  // Save off the largest control output if it is greater than 1.0 for future scaling
196  if (unsaturated_outputs_[i] > max_output)
197  {
198  max_output = unsaturated_outputs_[i];
199  }
200  }
201  }
202 
203  // saturate outputs to maintain controllability even during aggressive maneuvers
204  float scale_factor = 1.0;
205  if (max_output > 1.0)
206  {
207  scale_factor = 1.0/max_output;
208  }
209 
210 
211 
212  for (int8_t i=0; i<8; i++)
213  {
214  // Write output to motors
215  if (mixer_to_use_->output_type[i] == S)
216  {
218  }
219  else if (mixer_to_use_->output_type[i] == M)
220  {
221  // scale all motor outputs by scale factor (this is usually 1.0, unless we saturated)
222  unsaturated_outputs_[i] *= scale_factor;
224  }
225  }
226 }
227 
228 }
virtual void pwm_init(uint32_t refresh_rate, uint16_t idle_pwm)=0
Mixer(ROSflight &_rf)
Definition: mixer.cpp:41
ROSflight & RF_
Definition: mixer.h:85
float get_param_float(uint16_t id) const
Get the value of a floating point parameter by id.
Definition: param.h:326
void write_servo(uint8_t index, float value)
Definition: mixer.cpp:151
float raw_outputs_[8]
Definition: mixer.h:87
virtual void pwm_write(uint8_t channel, float value)=0
void add_callback(std::function< void(int)> callback, uint16_t param_id)
Definition: param.cpp:308
const State & state() const
Definition: state_manager.h:82
void set_error(uint16_t error)
void clear_error(uint16_t error)
void log(CommLink::LogSeverity severity, const char *fmt,...)
void param_change_callback(uint16_t param_id)
Definition: mixer.cpp:64
const Output & output() const
Definition: controller.h:61
output_type_t output_type[8]
Definition: mixer.h:76
int get_param_int(uint16_t id) const
Get the value of an integer parameter by id.
Definition: param.h:316
const mixer_t * array_of_mixers_[NUM_MIXERS]
Definition: mixer.h:215
const mixer_t * mixer_to_use_
Definition: mixer.h:213
float unsaturated_outputs_[8]
Definition: mixer.h:88
void write_motor(uint8_t index, float value)
Definition: mixer.cpp:124


rosflight_firmware
Author(s): Daniel Koch , James Jackson
autogenerated on Wed Jul 3 2019 19:59:25