/** ****************************************************************************** * @addtogroup OpenPilotModules OpenPilot Modules * @{ * @addtogroup TemperatureModule Temperature Module * @brief Measures the temperature from external sensor. * Updates the TemperatureState object * @{ * * @file temperature.c * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2019. * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010. * @brief Module to read the temperature periodically from NTC or LM35 sensors. * * @see The GNU Public License (GPL) Version 3 * *****************************************************************************/ /* * 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, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /** * Output object: TemperatureState * * This module will periodically generate information on the temperature state. * * UAVObjects are automatically generated by the UAVObjectGenerator from * the object definition XML file. * * Modules have no API, all communication to other modules is done through UAVObjects. * However modules may use the API exposed by shared libraries. * See the OpenPilot wiki for more details. * http://www.openpilot.org/OpenPilot_Application_Architecture * */ #include "openpilot.h" #include "temperaturestate.h" #include "temperaturesettings.h" #include "hwsettings.h" // // Configuration // #define SAMPLE_PERIOD_MS 500 #ifndef PIOS_ADC_NTCTEMPERATURE_PIN #define PIOS_ADC_NTCTEMPERATURE_PIN -1 #endif #ifndef PIOS_ADC_LM35TEMPERATURE_PIN #define PIOS_ADC_LM35TEMPERATURE_PIN -1 #endif static int8_t ntcTemperatureADCPin = PIOS_ADC_NTCTEMPERATURE_PIN; // ADC pin for temperature (ntc) static int8_t lm35TemperatureADCPin = PIOS_ADC_LM35TEMPERATURE_PIN; // ADC pin for temperature (lm35) // Private functions static void onTimer(UAVObjEvent *ev); /** * Initialise the module, called on startup * \returns 0 on success or -1 if initialisation failed */ int32_t TemperatureInitialize(void) { bool temperatureEnabled; HwSettingsOptionalModulesData optionalModules; HwSettingsOptionalModulesGet(&optionalModules); #ifdef MODULE_TEMPERATURE_BUILTIN temperatureEnabled = true; optionalModules.Temperature = HWSETTINGS_OPTIONALMODULES_ENABLED; HwSettingsOptionalModulesSet(&optionalModules); #else if (optionalModules.Temperature == HWSETTINGS_OPTIONALMODULES_ENABLED) { temperatureEnabled = true; } else { temperatureEnabled = false; } #endif uint8_t adcRouting[HWSETTINGS_ADCROUTING_NUMELEM]; HwSettingsADCRoutingArrayGet(adcRouting); // Determine if the temperature sensors are routed to ADC pins for (int i = 0; i < HWSETTINGS_ADCROUTING_NUMELEM; i++) { if (adcRouting[i] == HWSETTINGS_ADCROUTING_NTCTEMPERATURE) { ntcTemperatureADCPin = i; } if (adcRouting[i] == HWSETTINGS_ADCROUTING_LM35TEMPERATURE) { lm35TemperatureADCPin = i; } } // Don't enable module if no ADC pins are routed to the sensors if (ntcTemperatureADCPin < 0 && lm35TemperatureADCPin < 0) { temperatureEnabled = false; } // Start module if (temperatureEnabled) { TemperatureStateInitialize(); static UAVObjEvent ev; memset(&ev, 0, sizeof(UAVObjEvent)); EventPeriodicCallbackCreate(&ev, onTimer, SAMPLE_PERIOD_MS / portTICK_RATE_MS); } return 0; } MODULE_INITCALL(TemperatureInitialize, 0); static void onTimer(__attribute__((unused)) UAVObjEvent *ev) { static TemperatureSettingsData temperatureSettings; static TemperatureStateData temperatureData; TemperatureSettingsGet(&temperatureSettings); TemperatureStateGet(&temperatureData); #ifdef PIOS_INCLUDE_ADC // calculate the temperature (ntc) if (ntcTemperatureADCPin >= 0) { float ntc_resistance = 0; if (temperatureSettings.NtcVoltageDivider == TEMPERATURESETTINGS_NTCVOLTAGEDIVIDER_NTCTOGROUND) { ntc_resistance = temperatureSettings.NtcSerialResistor / ((temperatureSettings.NtcVoltageReference / PIOS_ADC_PinGetVolt(ntcTemperatureADCPin)) - 1); } else if (temperatureSettings.NtcVoltageDivider == TEMPERATURESETTINGS_NTCVOLTAGEDIVIDER_NTCTOVREF) { ntc_resistance = temperatureSettings.NtcSerialResistor * ((temperatureSettings.NtcVoltageReference / PIOS_ADC_PinGetVolt(ntcTemperatureADCPin)) - 1); } float steinhart = ntc_resistance / temperatureSettings.NtcNominalValue; steinhart = logf(steinhart); steinhart /= temperatureSettings.NtcBetaCoeff; steinhart += 1.0f / (temperatureSettings.NtcNominalTemperature + 273.15f); steinhart = 1.0f / steinhart; temperatureData.Temperature1 = steinhart - 273.15f; } else { temperatureData.Temperature1 = 0; } // calculate the temperature (lm35) if (lm35TemperatureADCPin >= 0) { temperatureData.Temperature2 = (PIOS_ADC_PinGetVolt(lm35TemperatureADCPin) / temperatureSettings.Lm35Sensitivity); } else { temperatureData.Temperature2 = 0; } #else /* ifdef PIOS_INCLUDE_ADC */ temperatureData.Temperature1 = 0; temperatureData.Temperature2 = 0; #endif /* PIOS_INCLUDE_ADC */ TemperatureStateSet(&temperatureData); } /** * @} */