Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# MuMo SW V3

## known bugs
when unplugging the USB, sometimes the display is not updated immediately, but only at the next RTCtick ???

## ToDo's

2. make SNR work both in devStatusReq and on display
Expand Down
2 changes: 1 addition & 1 deletion lib/application/maincontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ void mainController::goTo(mainState newState) {
}

void mainController::runSleep() {
if (!power::hasUsbPower() && !debugPort::isDebugProbePresent()) {
if (power::noUsbPowerDelayed() && !debugPort::isDebugProbePresent()) {
prepareSleep();
goSleep();
wakeUp();
Expand Down
13 changes: 10 additions & 3 deletions lib/power/power.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,19 @@ bool power::mockUsbPower{false};
#endif

bool power::usbPower{false};
uint32_t power::usbPowerOffCount{usbPowerOffCountMax};

bool power::hasUsbPower() {
#ifndef generic
bool pinState = (GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOB, usbPowerPresent_Pin));
return pinState;
bool result = (GPIO_PIN_SET == HAL_GPIO_ReadPin(GPIOB, usbPowerPresent_Pin));
if (result) {
usbPowerOffCount = usbPowerOffCountMax;
} else {
if (usbPowerOffCount > 0) {
usbPowerOffCount--;
}
}
return result;
#else
return mockUsbPower;
#endif
Expand All @@ -42,4 +50,3 @@ bool power::isUsbRemoved() {
return false;
}
}

3 changes: 3 additions & 0 deletions lib/power/power.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,15 @@ class power {
static bool isUsbConnected();
static bool isUsbRemoved();
static bool hasUsbPower();
static bool noUsbPowerDelayed() { return (usbPowerOffCount == 0); };

#ifndef unitTesting

private:
#endif
static bool usbPower;
static uint32_t usbPowerOffCount;
static constexpr uint32_t usbPowerOffCountMax{16U};
#ifdef generic
static bool mockUsbPower;
#endif
Expand Down
2 changes: 0 additions & 2 deletions lib/sensors/bme680.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,6 @@ void bme680::run() {
}

void bme680::startSampling() {
state = sensorDeviceState::sampling;
// run a ADC conversion cycle for Temp Hum and Presure, and when ready, read and store all raw ADC results
writeRegister(bme680::registers::ctrl_hum, 0b00000001);
writeRegister(bme680::registers::ctrl_meas, 0b00100101);
state = sensorDeviceState::sampling;
Expand Down
88 changes: 2 additions & 86 deletions lib/sensors/bme680.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,7 @@ class bme680 {
static uint32_t rawDataBarometricPressure;
static uint32_t rawDataRelativeHumidity;

static bool awake;


// Calibration data
static float calibrationCoefficientTemperature1;
static float calibrationCoefficientTemperature2;
Expand All @@ -113,87 +112,4 @@ class bme680 {
static float calibrationCoefficientHumidity7;

friend class sensorDeviceCollection;
};

/*
Initialization
Write I2C : register = [E0], data[1] = [B6 ]
Read I2C : register = [D0], data[1] = [61 ]
Read I2C : register = [F0], data[1] = [00 ]
Read I2C : register = [8A], data[23] = [62 67 03 10 8F 90 68 D7 58 00 38 22 62 FF 2C 1E 00 00 71 F4 5B F6 1E ]
Read I2C : register = [E1], data[14] = [3D BD 37 00 2D 14 78 9C B6 65 AB DC FB 12 ]
Read I2C : register = [00], data[5] = [28 AA 16 4C 03 ]

Configuration
Read I2C : register = [74], data[1] = [00 ]
Read I2C : register = [74], data[1] = [00 ]
Read I2C : register = [71], data[5] = [00 00 00 00 00 ]
Write I2C : register = [71], data[9] = [80 72 05 73 00 74 44 75 00 ]
Set Heater Config
Read I2C : register = [74], data[1] = [44 ]
Write I2C : register = [5A], data[1] = [78 ]
Write I2C : register = [64], data[1] = [59 ]
Read I2C : register = [70], data[2] = [00 80 ]
Write I2C : register = [70], data[3] = [08 71 80 ]

Set Operation Mode
Read I2C : register = [74], data[1] = [44 ]
Write I2C : register = [74], data[1] = [45 ]

Read Data
Read I2C : register = [1D], data[17] = [80 FF 48 92 00 75 F8 00 62 20 80 00 00 00 04 00 04 ]
Read I2C : register = [5A], data[1] = [78 ]
Read I2C : register = [50], data[1] = [00 ]
Read I2C : register = [64], data[1] = [59 ]


par_h1 uint16_t 893
par_h2 uint16_t 987
par_h3 int8_t 0 '\0'
par_h4 int8_t 45 '-'
par_h5 int8_t 20 '\024'
par_h6 uint8_t 120 'x'
par_h7 int8_t -100 '\234'
par_gh1 int8_t -5 'û'
par_gh2 int16_t -9045
par_gh3 int8_t 18 '\022'

par_t1 uint16_t 26038
par_t2 int16_t 26466
par_t3 int8_t 3

par_p1 uint16_t 37007
par_p2 int16_t -10392
par_p3 int8_t 88 'X'
par_p4 int16_t 8760
par_p5 int16_t -158
par_p6 int8_t 30 '\036'
par_p7 int8_t 44 ','
par_p8 int16_t -2959
par_p9 int16_t -2469
par_p10 uint8_t 30 '\036'
t_fine float 107711.469
res_heat_range uint8_t 1 '\001'
res_heat_val int8_t 40 '('
range_sw_err int8_t 0 '\0'

adc_temp uint32_t 484376

mine :
rawData1 uint8_t 16 '\020'
rawData2 uint8_t 143 '\217'
rawData3 uint8_t 144 '\220'
rawData uint32_t 67833
theirs
buff[5] uint8_t 119 'w'
buff[6] uint8_t 16 '\020'
buff[7] uint8_t 128 '\200'

My READ
Read I2C : register = [8A], data[23] = [62 67 03 10 8F 90 68 D7 58 00 38 22 62 FF 2C 1E 00 00 71 F4 5B F6 1E ]
Read I2C : register = [E1], data[14] = [3D BD 37 00 2D 14 78 9C B6 65 AB DC FB 12 ]
Read I2C : register = [00], data[5] = [28 AA 16 4C 03 ]



*/
};
148 changes: 148 additions & 0 deletions lib/sensors/scd40.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
// ######################################################################################
// ### Author : Pascal Roobrouck - https://github.com/Strooom ###
// ### License : CC 4.0 BY-NC-SA - https://creativecommons.org/licenses/by-nc-sa/4.0/ ###
// ######################################################################################

#include <scd40.hpp>
#include <settingscollection.hpp>
#include <sensirion.hpp>

#ifndef generic
#include "main.h"
extern I2C_HandleTypeDef hi2c2;
#else
uint8_t mockSCD40Registers[256];
bool mockSCD40Present{false};
#include <cstring>
#endif

sensorDeviceState scd40::state{sensorDeviceState::unknown};
sensorChannel scd40::channels[nmbrChannels] = {
{1, "temperature", "~C"},
{0, "relativeHumidity", "%RH"},
{0, "CO2", "ppm"},
};

uint32_t scd40::rawDataTemperature;
uint32_t scd40::rawDataRelativeHumidity;
uint32_t scd40::rawCo2;

bool scd40::isPresent() {
return (testI2cAddress(i2cAddress));
}

void scd40::initialize() {
for (uint32_t channelIndex = 0; channelIndex < nmbrChannels; channelIndex++) {
channels[channelIndex].set(0, 0);
}
writeCommand(scd40::commands::stopPeriodicMeasurement); // stop any previous measurement
#ifndef generic
HAL_Delay(500); // stopping requires 500ms processing
#endif
writeCommand(scd40::commands::startLowPowerPeriodicMeasurement); // now start the low power periodic measurement = 1 sample / 30 seconds
state = sensorDeviceState::sleeping;
}

void scd40::run() {
if ((state == sensorDeviceState::sampling) && samplingIsReady()) {
readSample();

if (channels[temperature].needsSampling()) {
float scd40Temperature = calculateTemperature(rawDataTemperature);
channels[temperature].addSample(scd40Temperature);
}
if (channels[relativeHumidity].needsSampling()) {
float scd40RelativeHumidity = calculateRelativeHumidity(rawDataRelativeHumidity);
channels[relativeHumidity].addSample(scd40RelativeHumidity);
}
if (channels[co2].needsSampling()) {
float scd40CO2 = calculateCO2(rawCo2);
channels[co2].addSample(scd40CO2);
}
state = sensorDeviceState::sleeping;
}
}

void scd40::startSampling() {
state = sensorDeviceState::sampling;
}

bool scd40::samplingIsReady() {
uint16_t tmpResult;
writeCommand(scd40::commands::getDataReadyStatus);
#ifndef generic
HAL_Delay(2);
#endif
readData(&tmpResult, 1U);
return (!((tmpResult & 0x07FF) == 0)); // datasheet 3.8.2 : 11 least significant bits are zero -> data not ready
}

void scd40::readSample() {
uint16_t tmpResult[3];
writeCommand(scd40::commands::readMeasurement);
#ifndef generic
HAL_Delay(2);
#endif
readData(tmpResult, 3U);
rawCo2 = tmpResult[0];
rawDataTemperature = tmpResult[1];
rawDataRelativeHumidity = tmpResult[2];
}

float scd40::calculateTemperature(uint32_t rawData) {
float result{0.0F};
result = -45.0F + ((175.0F * static_cast<float>(rawData)) / 65535.0F);
return result;
}

float scd40::calculateRelativeHumidity(uint32_t rawData) {
float result{0.0F};
result = (100.0F * static_cast<float>(rawData)) / 65535.0F;
return result;
}

float scd40::calculateCO2(uint32_t rawData) {
return static_cast<float>(rawData);
}

bool scd40::testI2cAddress(const uint8_t addressToTest) {
#ifndef generic
return (HAL_OK == HAL_I2C_IsDeviceReady(&hi2c2, static_cast<uint16_t>(addressToTest << 1), halTrials, halTimeout));
#else
return mockSCD40Present;
#endif
}

void scd40::writeCommand(const scd40::commands aCommand) {
uint16_t command = static_cast<uint16_t>(aCommand);
uint8_t commandAsBytes[2];
commandAsBytes[0] = static_cast<uint8_t>(command >> 8);
commandAsBytes[1] = static_cast<uint8_t>(command & 0x00FF);
#ifndef generic
for (uint32_t trials = 0; trials < halTrials; trials++) {
HAL_StatusTypeDef result;
result = HAL_I2C_Master_Transmit(&hi2c2, static_cast<uint16_t>(i2cAddress << 1), commandAsBytes, 2U, halTimeout);
if (result == HAL_OK) {
return;
}
HAL_Delay(halTimeout);
}
#endif
}

void scd40::readData(uint16_t* data, const uint32_t dataLength) {
uint8_t tmpData[dataLength * 3]{};
#ifndef generic
for (uint32_t trials = 0; trials < halTrials; trials++) {
HAL_StatusTypeDef result;
result = HAL_I2C_Master_Receive(&hi2c2, static_cast<uint16_t>(i2cAddress << 1), tmpData, static_cast<uint16_t>(dataLength * 3), halTimeout);
if (result == HAL_OK) {
break;
}
HAL_Delay(halTimeout);
}
#endif
for (uint32_t index = 0; index < dataLength; index++) {
data[index] = sensirion::asUint16(&tmpData[index * 3]);
}
}
Loading
Loading