diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 38852e8975cdd4496e36f965293a27bcdfb38140..dc630721eef6582109b785e60a3cefa307d246cf 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -8,7 +8,7 @@ "defines": [ "DEBUG", "_ARCH_CORTEXM4_STM32F4", - "_BOARD_STM32F407VG_STM32F4DISCOVERY", + "_BOARD_STM32F4DISCOVERY", "_MIOSIX_BOARDNAME=stm32f407vg_stm32f4discovery", "HSE_VALUE=8000000", "SYSCLK_FREQ_168MHz=168000000", diff --git a/.vscode/settings.json b/.vscode/settings.json index 499e63fbe0bc2fbf8adf05ba283e4de56d1fb77a..caa4ff15bf38b4658d34a4bf0af6745b62d54e44 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,246 +1,264 @@ { - "cmake.configureSettings": { - "CMAKE_C_COMPILER_LAUNCHER": "ccache", - "CMAKE_CXX_COMPILER_LAUNCHER": "ccache" - }, - "cmake.parallelJobs": 1, - "files.associations": { - "sstream": "cpp", - "format": "cpp", - "any": "cpp", - "array": "cpp", - "atomic": "cpp", - "bit": "cpp", - "*.tcc": "cpp", - "bitset": "cpp", - "cctype": "cpp", - "chrono": "cpp", - "clocale": "cpp", - "cmath": "cpp", - "codecvt": "cpp", - "complex": "cpp", - "condition_variable": "cpp", - "cstdarg": "cpp", - "cstddef": "cpp", - "cstdint": "cpp", - "cstdio": "cpp", - "cstdlib": "cpp", - "cstring": "cpp", - "ctime": "cpp", - "cwchar": "cpp", - "cwctype": "cpp", - "deque": "cpp", - "list": "cpp", - "map": "cpp", - "set": "cpp", - "unordered_map": "cpp", - "vector": "cpp", - "exception": "cpp", - "algorithm": "cpp", - "functional": "cpp", - "iterator": "cpp", - "memory": "cpp", - "memory_resource": "cpp", - "numeric": "cpp", - "optional": "cpp", - "random": "cpp", - "ratio": "cpp", - "regex": "cpp", - "string": "cpp", - "string_view": "cpp", - "system_error": "cpp", - "tuple": "cpp", - "type_traits": "cpp", - "utility": "cpp", - "fstream": "cpp", - "future": "cpp", - "initializer_list": "cpp", - "iomanip": "cpp", - "iosfwd": "cpp", - "iostream": "cpp", - "istream": "cpp", - "limits": "cpp", - "mutex": "cpp", - "new": "cpp", - "ostream": "cpp", - "shared_mutex": "cpp", - "stdexcept": "cpp", - "streambuf": "cpp", - "thread": "cpp", - "cinttypes": "cpp", - "typeindex": "cpp", - "typeinfo": "cpp", - "variant": "cpp", - "__config": "cpp", - "__threading_support": "cpp", - "__mutex_base": "cpp", - "__tree": "cpp", - "locale": "cpp", - "__bit_reference": "cpp", - "__bits": "cpp", - "__debug": "cpp", - "__errc": "cpp", - "__functional_base": "cpp", - "__hash_table": "cpp", - "__locale": "cpp", - "__node_handle": "cpp", - "__nullptr": "cpp", - "__split_buffer": "cpp", - "__string": "cpp", - "__tuple": "cpp", - "ios": "cpp", - "queue": "cpp", - "stack": "cpp", - "__functional_03": "cpp", - "filesystem": "cpp", - "unordered_set": "cpp", - "hash_map": "cpp", - "valarray": "cpp", - "ranges": "cpp", - "compare": "cpp", - "concepts": "cpp", - "core": "cpp", - "iterativelinearsolvers": "cpp", - "pastixsupport": "cpp", - "superlusupport": "cpp", - "adolcforward": "cpp", - "alignedvector3": "cpp", - "bvh": "cpp", - "fft": "cpp", - "iterativesolvers": "cpp", - "mprealsupport": "cpp", - "matrixfunctions": "cpp", - "nonlinearoptimization": "cpp", - "openglsupport": "cpp", - "polynomials": "cpp", - "autodiff": "cpp", - "sparseextra": "cpp", - "specialfunctions": "cpp" - }, - "cSpell.words": [ - "aelf", - "airbrakes", - "Airbrakes", - "Alessandro", - "AMSL", - "atthr", - "AVDD", - "Baro", - "boardcore", - "Boardcorev", - "boudrate", - "Corigliano", - "CORTEXM", - "cpitch", - "cppcheck", - "croll", - "cwise", - "cyaw", - "DATABUS", - "deleteme", - "DMEIE", - "Doxyfile", - "doxygen", - "DRDY", - "Duca", - "Ecompass", - "Eigen", - "elfs", - "Erbetta", - "Fatt", - "Fatttr", - "fedetft's", - "fiprintf", - "Gatttr", - "getdetahstate", - "GNSS", - "Gpio", - "GPIOA", - "GPIOB", - "GPIOC", - "GPIOD", - "GPIOE", - "GPIOF", - "GPIOG", - "GPIOS", - "gpstr", - "Hatt", - "HSCMAND", - "HSCMRNN", - "HWMAPPING", - "IDLEIE", - "irqn", - "irqv", - "Kalman", - "Katt", - "kbps", - "ldrex", - "leds", - "LIFCR", - "logdecoder", - "Luca", - "MEKF", - "MINC", - "miosix", - "mkdir", - "mosfet", - "mosi", - "MPXHZ", - "Musso", - "NATT", - "NBAR", - "NDTR", - "NGPS", - "NMAG", - "NMEA", - "NMEKF", - "nord", - "NVIC", - "peripehral", - "PINC", - "Pitot", - "Plin", - "Qgbw", - "Qget", - "Qhandle", - "Qput", - "Qwait", - "Qwakeup", - "Riccardo", - "RXNE", - "RXNEIE", - "sats", - "Satt", - "sdio", - "SDRAM", - "spitch", - "sqdip", - "sqtrp", - "sroll", - "SSCDANN", - "SSCDRRN", - "stof", - "syaw", - "TCIE", - "TEIE", - "Terraneo", - "testsuite", - "TSCPP", - "Ublox", - "UBXACK", - "UBXGPS", - "UBXNAV", - "Unsync", - "upcounter", - "USART", - "vbat", - "velnord", - "vout", - "vsense", - "Xbee", - "xnord", - "yned" - ], - "cSpell.language": "en", - "cSpell.enabled": true + "cmake.configureSettings": { + "CMAKE_C_COMPILER_LAUNCHER": "ccache", + "CMAKE_CXX_COMPILER_LAUNCHER": "ccache" + }, + "cmake.parallelJobs": 1, + "files.associations": { + "sstream": "cpp", + "format": "cpp", + "any": "cpp", + "array": "cpp", + "atomic": "cpp", + "bit": "cpp", + "*.tcc": "cpp", + "bitset": "cpp", + "cctype": "cpp", + "chrono": "cpp", + "clocale": "cpp", + "cmath": "cpp", + "codecvt": "cpp", + "complex": "cpp", + "condition_variable": "cpp", + "cstdarg": "cpp", + "cstddef": "cpp", + "cstdint": "cpp", + "cstdio": "cpp", + "cstdlib": "cpp", + "cstring": "cpp", + "ctime": "cpp", + "cwchar": "cpp", + "cwctype": "cpp", + "deque": "cpp", + "list": "cpp", + "map": "cpp", + "set": "cpp", + "unordered_map": "cpp", + "vector": "cpp", + "exception": "cpp", + "algorithm": "cpp", + "functional": "cpp", + "iterator": "cpp", + "memory": "cpp", + "memory_resource": "cpp", + "numeric": "cpp", + "optional": "cpp", + "random": "cpp", + "ratio": "cpp", + "regex": "cpp", + "string": "cpp", + "string_view": "cpp", + "system_error": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "fstream": "cpp", + "future": "cpp", + "initializer_list": "cpp", + "iomanip": "cpp", + "iosfwd": "cpp", + "iostream": "cpp", + "istream": "cpp", + "limits": "cpp", + "mutex": "cpp", + "new": "cpp", + "ostream": "cpp", + "shared_mutex": "cpp", + "stdexcept": "cpp", + "streambuf": "cpp", + "thread": "cpp", + "cinttypes": "cpp", + "typeindex": "cpp", + "typeinfo": "cpp", + "variant": "cpp", + "__config": "cpp", + "__threading_support": "cpp", + "__mutex_base": "cpp", + "__tree": "cpp", + "locale": "cpp", + "__bit_reference": "cpp", + "__bits": "cpp", + "__debug": "cpp", + "__errc": "cpp", + "__functional_base": "cpp", + "__hash_table": "cpp", + "__locale": "cpp", + "__node_handle": "cpp", + "__nullptr": "cpp", + "__split_buffer": "cpp", + "__string": "cpp", + "__tuple": "cpp", + "ios": "cpp", + "queue": "cpp", + "stack": "cpp", + "__functional_03": "cpp", + "filesystem": "cpp", + "unordered_set": "cpp", + "hash_map": "cpp", + "valarray": "cpp", + "ranges": "cpp", + "compare": "cpp", + "concepts": "cpp", + "core": "cpp", + "iterativelinearsolvers": "cpp", + "pastixsupport": "cpp", + "superlusupport": "cpp", + "adolcforward": "cpp", + "alignedvector3": "cpp", + "bvh": "cpp", + "fft": "cpp", + "iterativesolvers": "cpp", + "mprealsupport": "cpp", + "matrixfunctions": "cpp", + "nonlinearoptimization": "cpp", + "openglsupport": "cpp", + "polynomials": "cpp", + "autodiff": "cpp", + "sparseextra": "cpp", + "specialfunctions": "cpp" + }, + "cSpell.words": [ + "ADCPRE", + "ADON", + "aelf", + "airbrakes", + "Airbrakes", + "Alessandro", + "AMSL", + "atthr", + "AVDD", + "Baro", + "boardcore", + "Boardcorev", + "boudrate", + "Corigliano", + "CORTEXM", + "cpitch", + "cppcheck", + "croll", + "cwise", + "cyaw", + "DATABUS", + "deleteme", + "DMEIE", + "Doxyfile", + "doxygen", + "DRDY", + "Duca", + "Ecompass", + "Eigen", + "elfs", + "Erbetta", + "Fatt", + "Fatttr", + "fedetft's", + "fiprintf", + "Gatttr", + "getdetahstate", + "GNSS", + "Gpio", + "GPIOA", + "GPIOB", + "GPIOC", + "GPIOD", + "GPIOE", + "GPIOF", + "GPIOG", + "GPIOS", + "gpstr", + "Hatt", + "HIFCR", + "HISR", + "HSCMAND", + "HSCMRNN", + "HWMAPPING", + "IDLEIE", + "irqn", + "irqv", + "JEOC", + "JOFR", + "JSQR", + "JSWSTART", + "Kalman", + "Katt", + "kbps", + "ldrex", + "leds", + "LIFCR", + "LISR", + "logdecoder", + "Luca", + "Matteo", + "MEKF", + "microcontrollers", + "MINC", + "miosix", + "mkdir", + "mosfet", + "mosi", + "MPXHZ", + "Musso", + "NATT", + "NBAR", + "NDTR", + "NGPS", + "Nidasio", + "NMAG", + "NMEA", + "NMEKF", + "nord", + "NVIC", + "peripehral", + "Piazzolla", + "PINC", + "Pitot", + "Plin", + "Qgbw", + "Qget", + "Qhandle", + "Qput", + "Qwait", + "Qwakeup", + "Riccardo", + "RXNE", + "RXNEIE", + "sats", + "Satt", + "sdio", + "SDRAM", + "smpr", + "SMPR", + "spitch", + "sqdip", + "sqtrp", + "sroll", + "SSCDANN", + "SSCDRRN", + "stof", + "SWSTART", + "syaw", + "TCIE", + "TCIF", + "TEIE", + "Terraneo", + "testsuite", + "TSCPP", + "TSVREFE", + "Ublox", + "UBXACK", + "UBXGPS", + "UBXNAV", + "Unsync", + "upcounter", + "USART", + "vbat", + "velnord", + "vout", + "vsense", + "Xbee", + "xnord", + "yned" + ], + "cSpell.language": "en", + "cSpell.enabled": true } \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index f7a55228cdd5d6724a274cd40f0c6d7947d04f0e..cdbc08614f50f7d21b57c0a4f332df58e4477b91 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,7 +178,7 @@ add_executable(test-general-purpose-timer src/tests/drivers/timer/test-general-p sbs_target(test-general-purpose-timer stm32f429zi_stm32f4discovery) add_executable(test-internal-adc src/tests/drivers/test-internal-adc.cpp) -sbs_target(test-internal-adc stm32f429zi_skyward_death_stack_x) +sbs_target(test-internal-adc stm32f407vg_stm32f4discovery) add_executable(test-internal-adc-dma src/tests/drivers/test-internal-adc-dma.cpp) sbs_target(test-internal-adc-dma stm32f429zi_stm32f4discovery) @@ -231,6 +231,9 @@ sbs_target(test-xbee-snd stm32f429zi_stm32f4discovery) add_executable(test-usart src/tests/drivers/usart/test-usart.cpp) sbs_target(test-usart stm32f407vg_stm32f4discovery) +add_executable(test-internal-temp src/tests/drivers/test-internal-temp.cpp) +sbs_target(test-internal-temp stm32f407vg_stm32f4discovery) + #-----------------------------------------------------------------------------# # Tests - Events # #-----------------------------------------------------------------------------# diff --git a/cmake/boardcore.cmake b/cmake/boardcore.cmake index 3c6806988b9fcf80a1a9bce82c4536b4ae40033f..120f7bc5e0143d8e5cb78cd3c578603ca66f844e 100644 --- a/cmake/boardcore.cmake +++ b/cmake/boardcore.cmake @@ -43,6 +43,7 @@ foreach(OPT_BOARD ${BOARDS}) ${SBS_BASE}/src/shared/diagnostic/PrintLogger.cpp # Drivers + ${SBS_BASE}/src/shared/drivers/adc/InternalTemp.cpp ${SBS_BASE}/src/shared/drivers/adc/InternalADC.cpp ${SBS_BASE}/src/shared/drivers/canbus/Canbus.cpp ${SBS_BASE}/src/shared/drivers/canbus/CanInterrupt.cpp diff --git a/src/shared/drivers/adc/InternalADC.cpp b/src/shared/drivers/adc/InternalADC.cpp index 5599223012b51872d29bec8cfdee357fa9fb0f33..737b2b6bc040925b2f7268ebc6154edcb17f25b3 100644 --- a/src/shared/drivers/adc/InternalADC.cpp +++ b/src/shared/drivers/adc/InternalADC.cpp @@ -72,9 +72,7 @@ InternalADC::InternalADC(ADC_TypeDef* adc, const float supplyVoltage, // Init indexMap for (auto i = 0; i < CH_NUM; i++) - { indexMap[i] = -1; - } } InternalADC::~InternalADC() @@ -90,13 +88,13 @@ bool InternalADC::init() adc->CR2 |= ADC_CR2_ADON; // Set single conversion mode - adc->CR2 &= ~ADC_CR2_CONT; + // adc->CR2 &= ~ADC_CR2_CONT; // Set scan mode - adc->CR1 |= ADC_CR1_SCAN; + // adc->CR1 |= ADC_CR1_SCAN; // Data alignment - adc->CR2 &= ~ADC_CR2_ALIGN; // right + // adc->CR2 &= ~ADC_CR2_ALIGN; // right if (isUsingDMA) { @@ -130,33 +128,22 @@ bool InternalADC::init() return true; } -bool InternalADC::enableChannel(Channel channel) -{ - return enableChannel(channel, CYCLES_3); -} - bool InternalADC::enableChannel(Channel channel, SampleTime sampleTime) { // Check channel number if (channel < CH0 || channel >= CH_NUM) - { return false; - } // Add channel to the sequence if (!isUsingDMA) { if (!addInjectedChannel(channel)) - { return false; - } } else { if (!addRegularChannel(channel)) - { return false; - } // Update the DMA number of data dmaStream->NDTR = activeChannels; @@ -168,6 +155,52 @@ bool InternalADC::enableChannel(Channel channel, SampleTime sampleTime) return true; } +bool InternalADC::addRegularChannel(Channel channel) +{ + // Check active channels number + if (activeChannels >= 16) + return false; + + // Add the channel to the sequence + volatile uint32_t* sqrPtr; + switch (activeChannels / 6) + { + case 1: + sqrPtr = &(adc->SQR2); + break; + case 2: + sqrPtr = &(adc->SQR1); + break; + default: + sqrPtr = &(adc->SQR3); + } + *sqrPtr = channel << ((activeChannels % 6) * 5); + + // Update the channels number in the register + adc->SQR1 &= ~ADC_SQR1_L; + adc->SQR1 |= activeChannels << 20; + + // Save the index of the channel in the ADC's regular sequence + indexMap[channel] = activeChannels; + + // Update the counter + activeChannels++; + + return true; +} + +ADCData InternalADC::readChannel(Channel channel, SampleTime sampleTime) +{ + setChannelSampleTime(channel, sampleTime); + startRegularConversion(); + + while (!(adc->SR & ADC_SR_EOC)) + ; + + return {TimestampTimer::getTimestamp(), channel, + static_cast<uint16_t>(adc->DR) * supplyVoltage / RESOLUTION}; +} + InternalADCData InternalADC::getVoltage(Channel channel) { float voltage = 0; @@ -219,14 +252,14 @@ InternalADCData InternalADC::sampleImpl() // This should trigger the DMA stream for each channel's conversion - // Wait for tranfer end + // Wait for transfer end while (!(*statusReg & (transferCompleteMask | transferErrorMask))) ; // Clear the transfer complete flag *clearFlagReg |= transferCompleteMask; - // If and error has occurred (probaly due to a higher priority stream) + // If and error has occurred (probably due to a higher priority stream) // don't update the timestamp, the values should not have been updated if (*statusReg & transferErrorMask) { @@ -244,6 +277,8 @@ InternalADCData InternalADC::sampleImpl() return lastSample; } +float InternalADC::getSupplyVoltage() { return supplyVoltage; } + inline void InternalADC::resetRegisters() { // Reset the ADC configuration @@ -277,9 +312,7 @@ inline bool InternalADC::addInjectedChannel(Channel channel) { // Check active channels number if (activeChannels >= 4) - { return false; - } // Add the channel to the sequence, starting from position 4 adc->JSQR |= channel << (15 - activeChannels * 5); @@ -292,9 +325,7 @@ inline bool InternalADC::addInjectedChannel(Channel channel) for (auto i = 0; i < CH_NUM; i++) { if (indexMap[i] >= 0) - { indexMap[i]++; - } } // Set this channel index to 0 @@ -306,53 +337,15 @@ inline bool InternalADC::addInjectedChannel(Channel channel) return true; } -inline bool InternalADC::addRegularChannel(Channel channel) -{ - // Check active channels number - if (activeChannels >= 16) - { - return false; - } - - // Add the channel to the sequence - volatile uint32_t* sqrPtr; - switch (activeChannels % 6) - { - case 1: - sqrPtr = &(adc->SQR3); - break; - case 2: - sqrPtr = &(adc->SQR2); - break; - default: - sqrPtr = &(adc->SQR1); - } - *sqrPtr = channel << ((activeChannels % 6) * 5); - - // Update the channels number in the register - adc->SQR1 |= activeChannels << 20; - - // Save the index of the channel in the ADC's regular sequence - indexMap[channel] = activeChannels; - - // Update the counter - activeChannels++; - - return true; -} - inline void InternalADC::setChannelSampleTime(Channel channel, SampleTime sampleTime) { volatile uint32_t* smprPtr; if (channel <= 9) - { smprPtr = &(adc->SMPR2); - } else - { smprPtr = &(adc->SMPR1); - } + *smprPtr = sampleTime << (channel * 3); } diff --git a/src/shared/drivers/adc/InternalADC.h b/src/shared/drivers/adc/InternalADC.h index 662419e817ef60eb8622b6326af3ad5f11bf3f72..ab0498619a7447080ab2efa4c6c6b7c53438e73b 100644 --- a/src/shared/drivers/adc/InternalADC.h +++ b/src/shared/drivers/adc/InternalADC.h @@ -90,6 +90,9 @@ public: CH13, CH14, CH15, + CH16, + CH17, + CH18, CH_NUM }; @@ -127,9 +130,14 @@ public: */ bool init() override; - bool enableChannel(Channel channel); + /** + * @brief Make a regular conversion for the specified channel. + */ + ADCData readChannel(Channel channel, SampleTime sampleTime = CYCLES_3); + + bool enableChannel(Channel channel, SampleTime sampleTime = CYCLES_3); - bool enableChannel(Channel channel, SampleTime sampleTime); + bool addRegularChannel(Channel channel); InternalADCData getVoltage(Channel channel); @@ -137,6 +145,8 @@ public: InternalADCData sampleImpl() override; + float getSupplyVoltage(); + private: inline void resetRegisters(); @@ -146,8 +156,6 @@ private: inline bool addInjectedChannel(Channel channel); - inline bool addRegularChannel(Channel channel); - inline void setChannelSampleTime(Channel channel, SampleTime sampleTime); ADC_TypeDef* adc; @@ -168,7 +176,7 @@ private: * We'll use up to 4 injected channel by default and up to 16 channels when * using DMA. * - * The differentiation is necessary because whitout DMA it is much simplier + * The differentiation is necessary because whiteout DMA it is much simpler * to use injected channel for multichannel readings. Otherwise we would * need to handle each channel's end of conversion interrupt or go through */ @@ -182,7 +190,7 @@ private: volatile uint32_t* clearFlagReg; static constexpr int INJECTED_CHANNEL_N = 4; - static constexpr int RESOLUTION = 4096; ///< 12 bits + static constexpr int RESOLUTION = 4095; ///< 12 bits }; } // namespace Boardcore diff --git a/src/shared/drivers/adc/InternalTemp.cpp b/src/shared/drivers/adc/InternalTemp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e6c15b2fc9629145d82ac9a6cb4f7fe6c63dcfec --- /dev/null +++ b/src/shared/drivers/adc/InternalTemp.cpp @@ -0,0 +1,84 @@ +/* Copyright (c) 2022 Skyward Experimental Rocketry + * Authors: Giulia Ghirardini + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "InternalTemp.h" + +#ifdef _ARCH_CORTEXM4_STM32F4 +#define TEMP30_CAL_VALUE ((uint16_t*)((uint32_t)0x1FFF7A2C)) +#define TEMP110_CAL_VALUE ((uint16_t*)((uint32_t)0x1FFF7A2E)) +#define TEMP30 30 +#define TEMP110 110 +#endif + +namespace Boardcore +{ + +InternalTemp::InternalTemp(InternalADC::SampleTime sampleTime, + const float supplyVoltage) + : adc(ADC1, supplyVoltage), sampleTime(sampleTime) +{ +} + +bool InternalTemp::init() +{ + bool result = adc.init(); + +#if defined(_BOARD_STM32F4DISCOVERY) || defined(_ARCH_CORTEXM3_STM32F2) + adc.addRegularChannel(InternalADC::CH16); +#else + adc.addRegularChannel(InternalADC::CH18); +#endif + + ADC->CCR &= ~ADC_CCR_VBATE; + ADC->CCR |= ADC_CCR_TSVREFE; + + return result; +} + +bool InternalTemp::selfTest() { return adc.selfTest(); } + +InternalTempData InternalTemp::sampleImpl() +{ +#if defined(_BOARD_STM32F4DISCOVERY) || defined(_ARCH_CORTEXM3_STM32F2) + auto adcData = adc.readChannel(InternalADC::CH16, sampleTime); +#else + auto adcData = adc.readChannel(InternalADC::CH18, sampleTime); +#endif + + InternalTempData data; + data.temperatureTimestamp = adcData.voltageTimestamp; + +#ifdef _ARCH_CORTEXM3_STM32F2 + // Default conversion + data.temperature = ((adcData.voltage - 0.76) / 0.0025) + 25; +#else + // Factory calibration + float voltage30 = static_cast<float>(*TEMP30_CAL_VALUE) * 3.3 / 4095; + float voltage110 = static_cast<float>(*TEMP110_CAL_VALUE) * 3.3 / 4095; + float slope = (voltage110 - voltage30) / (TEMP110 - TEMP30); + data.temperature = ((adcData.voltage - voltage30) / slope) + TEMP30; +#endif + + return data; +} + +} // namespace Boardcore diff --git a/src/shared/drivers/adc/InternalTemp.h b/src/shared/drivers/adc/InternalTemp.h new file mode 100644 index 0000000000000000000000000000000000000000..a66e32cafa0283ee463a82c0d8c7be4b3efa99a3 --- /dev/null +++ b/src/shared/drivers/adc/InternalTemp.h @@ -0,0 +1,51 @@ +/* Copyright (c) 2022 Skyward Experimental Rocketry + * Authors: Giulia Ghirardini + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once +#include <drivers/adc/InternalADC.h> + +#include "InternalTempData.h" + +namespace Boardcore +{ + +class InternalTemp : public Sensor<InternalTempData> +{ +public: + explicit InternalTemp( + InternalADC::SampleTime sampleTime = InternalADC::CYCLES_480, + const float supplyVoltage = 5.0); + + bool init() override; + + bool selfTest() override; + + InternalTempData sampleImpl() override; + + // InternalTempData addRegularChannel(InternalADC::Channel channel); + +private: + InternalADC adc; + InternalADC::SampleTime sampleTime; +}; + +} // namespace Boardcore diff --git a/src/shared/drivers/adc/InternalTempData.h b/src/shared/drivers/adc/InternalTempData.h new file mode 100644 index 0000000000000000000000000000000000000000..96f709033d5cdcadb60b4d3e53f19d2da7901b90 --- /dev/null +++ b/src/shared/drivers/adc/InternalTempData.h @@ -0,0 +1,42 @@ +/* Copyright (c) 2021 Skyward Experimental Rocketry + * Author: Alberto Nidasio + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#pragma once + +#include <sensors/SensorData.h> + +namespace Boardcore +{ + +struct InternalTempData : public TemperatureData +{ + InternalTempData() : TemperatureData{0, 0} {} + + static std::string header() { return "timestamp,temperature\n"; } + + void print(std::ostream& os) const + { + os << temperatureTimestamp << "," << temperature << "\n"; + } +}; + +} // namespace Boardcore diff --git a/src/tests/drivers/test-internal-temp.cpp b/src/tests/drivers/test-internal-temp.cpp new file mode 100644 index 0000000000000000000000000000000000000000..23fd7844a83f5ae4978d26f092253f76067814e3 --- /dev/null +++ b/src/tests/drivers/test-internal-temp.cpp @@ -0,0 +1,44 @@ +/* Copyright (c) 2022 Skyward Experimental Rocketry + * Authors: Giulia Ghirardini + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include <drivers/adc/InternalTemp.h> +#include <drivers/timer/TimestampTimer.h> +#include <miosix.h> +#include <utils/ClockUtils.h> + +using namespace Boardcore; + +int main() +{ + ADC->CCR |= ADC_CCR_ADCPRE_0 | ADC_CCR_ADCPRE_1; + + InternalTemp temp(InternalADC::CYCLES_480, 3.0); + temp.init(); + + for (;;) + { + temp.sample(); + printf("Temperature: %2.3f\n", temp.getLastSample().temperature); + + miosix::delayMs(1000); + } +}