From 71b975386081f65f680eb1af25ad2f0aec055dbf Mon Sep 17 00:00:00 2001 From: Theodor Teslia Date: Mon, 27 Feb 2023 16:42:33 +0100 Subject: [PATCH] Finish writing the driver; Still needs testing and debugging --- README.md | 10 +++- include/sta/MS5607.hpp | 25 ++++++++- include/sta/config.hpp | 6 +++ src/MS5607.cpp | 118 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 include/sta/config.hpp diff --git a/README.md b/README.md index 54fa59e..6bd39ff 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # Driver for the MS5607 pressure sensor +# Usage +1. The driver has two main methods: ```int32_t getPressure()``` and ```int32_t getTemperature()``` +2. The constructor takes an SpiDevice pointer and an instance from the OsrLevel enum +3. The OsrLevel enum stores the possible values for the OSR (how fine the sensor measures or sth.) +4. When calling ```getPressure()```, the temperature gets requested from the sensor as well -> May be too slow + ## TODO -1. Understand the Datasheet (RIP) -2. Write the fucking driver \ No newline at end of file +1. Debug +2. Check whether more accurate temp measurements are necessary \ No newline at end of file diff --git a/include/sta/MS5607.hpp b/include/sta/MS5607.hpp index 0dbb189..bc0f33c 100644 --- a/include/sta/MS5607.hpp +++ b/include/sta/MS5607.hpp @@ -2,6 +2,8 @@ #define STA_SENSORS_MS5607_HPP #include +#include +#include namespace sta { class MS5607 { @@ -14,19 +16,40 @@ namespace sta { _4096 = 4 }; + MS5607(SpiDevice* device, OsrLevel osr); + + int32_t getPressure(); + int32_t getTemperature(); + + void changeOsrLevel(OsrLevel newOsr) { this->osr_ = newOsr; } + private: SpiDevice* device_; + OsrLevel osr_; uint16_t sens, off, tcs, tco, t_ref, tempsens; enum Operations { RESET = 0x1E, - READ_PROM = 0xA0, + READ_PROM = 0xA2, D1_CONVERSION = 0x40, D2_CONVERSION = 0x50, ADC_RESULT = 0x00 }; + uint32_t readPressure(); + uint32_t readTemp(); + int32_t calculatePressure(uint32_t d1, int32_t dT); + int32_t calculateTemperature(uint32_t d2); + + void reset(); + void readPROM(); + + // Take first bytes from buffer, swap them and store those in uint16_t + static uint16_t uint_8BufferTouint16_t(uint8_t* buffer); + + const char RESET_DELAY = 2800; // in uS + const char ADC_DELAY = 8220; // in uS; not sure if thats correct since the datasheet doesn't say anything explicitly }; } diff --git a/include/sta/config.hpp b/include/sta/config.hpp new file mode 100644 index 0000000..0e15371 --- /dev/null +++ b/include/sta/config.hpp @@ -0,0 +1,6 @@ +// Needed for sta/endian.hpp +#define STA_MCU_LITTLE_ENDIAN + +// Needed for sta/stm32/delay.hpp +#define STA_PLATFORM_STM32 +#define STA_STM32_DELAY_US_TIM \ No newline at end of file diff --git a/src/MS5607.cpp b/src/MS5607.cpp index e69de29..a477f29 100644 --- a/src/MS5607.cpp +++ b/src/MS5607.cpp @@ -0,0 +1,118 @@ +#include "sta/MS5607.hpp" + +namespace sta { + MS5607::MS5607(SpiDevice* device, OsrLevel level) { + this->device_ = device; + this->osr_ = level; + + this->reset(); + this->readPROM(); + } + + int32_t MS5607::getPressure() { + uint32_t d1 = readPressure(); + + // Since pressure is temp-dependant, temperature needs to be polled + // Could be too costly timewise, since 8ms is needed for the ADC + // May need future optimisation + uint32_t d2 = readTemp(); + int32_t dT = d2 - (this->t_ref << 8); + + return calculatePressure(d1, dT); + } + + uint32_t MS5607::readPressure() { + this->device_->beginTransmission(); + this->device_->transfer(MS5607::Operations::D1_CONVERSION + 2*this->osr_); + delayUs(MS5607::ADC_DELAY); + uint8_t d1Arr[3]; + this->device_->receive(d1Arr, 3); + this->device_->endTransmission(); + + uint32_t res = 0; + res |= d1Arr[0] | d1Arr[1] << 8 | d1Arr[2] << 16; + return res; + } + + int32_t MS5607::calculatePressure(uint32_t d1, int32_t dT) { + int64_t offset = (this->off << 17) + ((this->tco * dT) >> 6); + int64_t sensitivity = (this->sens << 16) + ((this->tcs * dT) >> 7); + int32_t pres = (((d1 * sensitivity) >> 21) - offset) >> 15; + return pres; + } + + int32_t MS5607::getTemperature() { + uint32_t d2 = readTemp(); + + calculateTemperature(d2); + } + + uint32_t MS5607::readTemp() { + this->device_->beginTransmission(); + this->device_->transfer(MS5607::Operations::D2_CONVERSION + 2*this->osr_); + delayUs(MS5607::ADC_DELAY); + uint8_t d2Arr[3]; + this->device_->receive(d2Arr, 3); + this->device_->endTransmission(); + + uint32_t res = 0; + res |= d2Arr[0] | d2Arr[1] << 8 | d2Arr[2] << 16; + } + + int32_t MS5607::calculateTemperature(uint32_t d2) { + int32_t dT = d2 - (this->t_ref << 8); + int32_t temp = 2000 + ((dT * this->tempsens) >> 23); + + // Further calculations for low (<20) and very low (<(-15)) could be possible + // But I don't know whether they are necessary + + return temp; + } + + void MS5607::reset() { + this->device_->beginTransmission(); + this->device_->transfer(MS5607::Operations::RESET); + delayUs(MS5607::RESET_DELAY); + this->device_->endTransmission(); + } + + void MS5607::readPROM() { + this->device_->beginTransmission(); + + this->device_->transfer(Operations::READ_PROM); + uint8_t sensArr[2]; + this->device_->receive(sensArr, 2); + this->sens = uint_8BufferTouint16_t(sensArr); + + this->device_->transfer(Operations::READ_PROM+2); + uint8_t offArr[2]; + this->device_->receive(offArr, 2); + this->off = uint_8BufferTouint16_t(offArr); + + this->device_->transfer(Operations::READ_PROM+4); + uint8_t tcsArr[2]; + this->device_->receive(tcsArr, 2); + this->sens = uint_8BufferTouint16_t(sensArr); + + this->device_->transfer(Operations::READ_PROM+6); + uint8_t tcoArr[2]; + this->device_->receive(tcoArr, 2); + this->tco = uint_8BufferTouint16_t(tcoArr); + + this->device_->transfer(Operations::READ_PROM+8); + uint8_t t_refArr[2]; + this->device_->receive(t_refArr, 2); + this->t_ref = uint_8BufferTouint16_t(t_refArr); + + this->device_->transfer(Operations::READ_PROM+0xA); + uint8_t tempsensArr[2]; + this->device_->receive(tempsensArr, 2); + this->tempsens = uint_8BufferTouint16_t(tempsensArr); + + this->device_->endTransmission(); + } + + uint16_t MS5607::uint_8BufferTouint16_t(uint8_t* buffer) { + return buffer[0] | (buffer[1] << 8); + } +} \ No newline at end of file