2019-11-01 23:32:12 -03:00
|
|
|
/*
|
|
|
|
This program 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 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
/*
|
|
|
|
control IMU heater
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <AP_HAL/AP_HAL.h>
|
|
|
|
#include <AP_Math/AP_Math.h>
|
|
|
|
#include <AP_IOMCU/AP_IOMCU.h>
|
|
|
|
#include <AP_Logger/AP_Logger.h>
|
|
|
|
#include <GCS_MAVLink/GCS.h>
|
|
|
|
#include "AP_BoardConfig.h"
|
|
|
|
|
|
|
|
#if HAL_HAVE_IMU_HEATER
|
|
|
|
|
|
|
|
extern const AP_HAL::HAL& hal;
|
|
|
|
|
2021-10-28 19:21:31 -03:00
|
|
|
#ifndef HAL_HEATER_GPIO_ON
|
|
|
|
#define HAL_HEATER_GPIO_ON 1
|
|
|
|
#endif
|
|
|
|
|
2019-11-01 23:32:12 -03:00
|
|
|
void AP_BoardConfig::set_imu_temp(float current)
|
|
|
|
{
|
|
|
|
int8_t target = heater.imu_target_temperature.get();
|
|
|
|
// pass to HAL for Linux
|
|
|
|
hal.util->set_imu_target_temp((int8_t *)&heater.imu_target_temperature);
|
|
|
|
hal.util->set_imu_temp(current);
|
|
|
|
|
|
|
|
if (target == -1) {
|
2021-08-15 20:34:23 -03:00
|
|
|
// nothing to do, make sure heater is left off
|
|
|
|
#if defined(HAL_HEATER_GPIO_PIN)
|
2021-10-28 19:21:31 -03:00
|
|
|
hal.gpio->write(HAL_HEATER_GPIO_PIN, !HAL_HEATER_GPIO_ON);
|
2021-08-15 20:34:23 -03:00
|
|
|
#endif
|
2019-11-01 23:32:12 -03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// limit to 65 degrees to prevent damage
|
|
|
|
target = constrain_int16(target, -1, 65);
|
|
|
|
|
|
|
|
// average over temperatures to remove noise
|
|
|
|
heater.count++;
|
|
|
|
heater.sum += current;
|
|
|
|
|
|
|
|
// update at 10Hz
|
|
|
|
uint32_t now = AP_HAL::millis();
|
|
|
|
if (now - heater.last_update_ms < 100) {
|
|
|
|
#if defined(HAL_HEATER_GPIO_PIN)
|
|
|
|
// output as duty cycle to local pin. Use a random sequence to
|
|
|
|
// prevent a periodic change to magnetic field
|
|
|
|
bool heater_on = (get_random16() < uint32_t(heater.output) * 0xFFFFU / 100U);
|
2021-10-28 19:21:31 -03:00
|
|
|
hal.gpio->write(HAL_HEATER_GPIO_PIN, heater_on?HAL_HEATER_GPIO_ON : !HAL_HEATER_GPIO_ON);
|
2019-11-01 23:32:12 -03:00
|
|
|
#endif
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
float dt = (now - heater.last_update_ms) * 0.001;
|
|
|
|
dt = constrain_float(dt, 0, 0.5);
|
|
|
|
|
|
|
|
heater.last_update_ms = now;
|
|
|
|
|
2021-10-15 18:22:01 -03:00
|
|
|
heater.temperature = heater.sum / heater.count;
|
2019-11-01 23:32:12 -03:00
|
|
|
heater.sum = 0;
|
|
|
|
heater.count = 0;
|
|
|
|
|
|
|
|
if (target < 0) {
|
|
|
|
heater.output = 0;
|
|
|
|
} else {
|
2021-10-15 18:22:01 -03:00
|
|
|
heater.output = heater.pi_controller.update(heater.temperature, target, dt);
|
2019-11-01 23:32:12 -03:00
|
|
|
heater.output = constrain_float(heater.output, 0, 100);
|
|
|
|
}
|
|
|
|
|
2022-06-05 08:28:40 -03:00
|
|
|
#if HAL_LOGGING_ENABLED
|
2019-11-01 23:32:12 -03:00
|
|
|
if (now - heater.last_log_ms >= 1000) {
|
2020-04-06 23:54:19 -03:00
|
|
|
// @LoggerMessage: HEAT
|
|
|
|
// @Description: IMU Heater data
|
|
|
|
// @Field: TimeUS: Time since system startup
|
|
|
|
// @Field: Temp: Current IMU temperature
|
|
|
|
// @Field: Targ: Target IMU temperature
|
|
|
|
// @Field: P: Proportional portion of response
|
|
|
|
// @Field: I: Integral portion of response
|
|
|
|
// @Field: Out: Controller output to heating element
|
2021-08-17 06:57:41 -03:00
|
|
|
AP::logger().WriteStreaming("HEAT", "TimeUS,Temp,Targ,P,I,Out", "Qfbfff",
|
2019-11-01 23:32:12 -03:00
|
|
|
AP_HAL::micros64(),
|
2021-10-15 18:22:01 -03:00
|
|
|
heater.temperature, target,
|
2019-11-01 23:32:12 -03:00
|
|
|
heater.pi_controller.get_P(),
|
|
|
|
heater.pi_controller.get_I(),
|
|
|
|
heater.output);
|
|
|
|
heater.last_log_ms = now;
|
|
|
|
}
|
2022-06-05 08:28:40 -03:00
|
|
|
#endif // HAL_LOGGING_ENABLED
|
|
|
|
|
2019-11-01 23:32:12 -03:00
|
|
|
#if 0
|
2019-11-20 06:20:24 -04:00
|
|
|
gcs().send_text(MAV_SEVERITY_INFO, "Heater: Out=%.1f Temp=%.1f",
|
|
|
|
double(heater.output),
|
|
|
|
double(avg));
|
2019-11-01 23:32:12 -03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#if HAL_WITH_IO_MCU
|
|
|
|
if (io_enabled()) {
|
|
|
|
AP_IOMCU *iomcu = AP::iomcu();
|
|
|
|
if (iomcu) {
|
|
|
|
// tell IOMCU to setup heater
|
|
|
|
iomcu->set_heater_duty_cycle(heater.output);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2021-10-15 18:22:01 -03:00
|
|
|
// getter for current temperature, return false if heater disabled
|
|
|
|
bool AP_BoardConfig::get_board_heater_temperature(float &temperature) const
|
|
|
|
{
|
|
|
|
if (heater.imu_target_temperature == -1) {
|
|
|
|
return false; // heater disabled
|
|
|
|
}
|
|
|
|
temperature = heater.temperature;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// getter for min arming temperature, return false if heater disabled or min check disabled
|
|
|
|
bool AP_BoardConfig::get_board_heater_arming_temperature(int8_t &temperature) const
|
|
|
|
{
|
|
|
|
if ((heater.imu_target_temperature == -1) || (heater.imu_arming_temperature_margin_low == 0)) {
|
|
|
|
return false; // heater or temperature check disabled
|
|
|
|
}
|
|
|
|
temperature = heater.imu_target_temperature - heater.imu_arming_temperature_margin_low;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-11-01 23:32:12 -03:00
|
|
|
#endif // HAL_HAVE_IMU_HEATER
|