#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <stdio.h>
#include <stdarg.h>
#include <errno.h>
#define I2C_STRUCTS_VERSION 1
#include <applibs/log.h>
#include <applibs/gpio.h>
#include <applibs/i2c.h>
#include <applibs/networking.h>
#include <applibs/storage.h>
#include "epoll_timerfd_utilities.h"
#include "BME680_reg.h"
#include <azureiot/iothub_device_client_ll.h>
#include <azureiot/iothub_client_core_common.h>
#include <azureiot/iothub_client_options.h>
#include <azureiot/iothub.h>
#include <azureiot/iothubtransportmqtt.h>
#include <azureiot/azure_sphere_provisioning.h>
#include "epoll_timerfd_utilities.h"
#define SCOPEID_LENGTH 20
static char scopeId[SCOPEID_LENGTH]; // ScopeId for the Azure IoT Central application, set in
// app_manifest.json, CmdArgs
static volatile sig_atomic_t terminationRequired = false;
static I2C_DeviceAddress bme680_addr = 0x77;
static IOTHUB_DEVICE_CLIENT_LL_HANDLE iothubClientHandle = NULL;
static const int keepalivePeriodSeconds = 20;
static bool iothubAuthenticated = false;
static void SendMessageCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* context);
static void TwinCallback(DEVICE_TWIN_UPDATE_STATE updateState, const unsigned char* payload,
size_t payloadSize, void* userContextCallback);
static void TwinReportBoolState(const char* propertyName, bool propertyValue);
static void ReportStatusCallback(int result, void* context);
static void readWaterDetectHandler(EventData* eventData);
static const char* GetReasonString(IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason);
static const char* getAzureSphereProvisioningResultString(
AZURE_SPHERE_PROV_RETURN_VALUE provisioningResult);
static void SendTelemetry(const unsigned char* key, const unsigned char* key1, const unsigned char* value1,
const unsigned char* key2, const unsigned char* value2,
const unsigned char* key3, const unsigned char* value3,
const unsigned char* key4, const unsigned char* value4,
const unsigned char* key5, const unsigned char* value5);
static void SetupAzureClient(void);
static uint8_t calculate_heat(void);
static double get_temperature(void);
static double get_humidity(void);
static double get_pressure(void);
static double get_gas(void);
static void init_device(void);
static void SendData(void);
static int InitPeripheralsAndHandlers(void);
static void ClosePeripheralsAndHandlers(void);
static int azureTimerFd = -1;
static int epollFd = -1;
static int i2cFd = -1;
static int waterDetectGpioFd = -1;
static int waterDetectTimerFd = -1;
static GPIO_Value_Type waterDetectState = GPIO_Value_Low;
static const int AzureIoTDefaultPollPeriodSeconds = 10;
static const int AzureIoTMinReconnectPeriodSeconds = 60;
static const int AzureIoTMaxReconnectPeriodSeconds = 10 * 60;
static const int waterDetectPollPeriod = 5000000000;
static int azureIoTPollPeriodSeconds = -1;
static void AzureTimerEventHandler(EventData* eventData);
static void TerminationHandler(int signalNumber)
{
// Don't use Log_Debug here, as it is not guaranteed to be async-signal-safe.
terminationRequired = true;
}
int main(int argc, char* argv[])
{
Log_Debug("IoT Hub/Central Application starting.\n");
if (argc == 2) {
Log_Debug("Setting Azure Scope ID %s\n", argv[1]);
strncpy(scopeId, argv[1], SCOPEID_LENGTH);
}
else {
Log_Debug("ScopeId needs to be set in the app_manifest CmdArgs\n");
return -1;
}
if (InitPeripheralsAndHandlers() != 0) {
terminationRequired = true;
}
// Main loop
while (!terminationRequired) {
if (WaitForEventAndCallHandler(epollFd) != 0) {
terminationRequired = true;
}
}
ClosePeripheralsAndHandlers();
Log_Debug("Application exiting.\n");
return 0;
}
/// <summary>
/// Azure timer event: Check connection status and send telemetry
/// </summary>
static void AzureTimerEventHandler(EventData* eventData)
{
if (ConsumeTimerFdEvent(azureTimerFd) != 0) {
terminationRequired = true;
return;
}
bool isNetworkReady = false;
if (Networking_IsNetworkingReady(&isNetworkReady) != -1) {
if (isNetworkReady && !iothubAuthenticated) {
SetupAzureClient();
}
}
else {
Log_Debug("Failed to get Network state\n");
}
if (iothubAuthenticated) {
SendData();
IoTHubDeviceClient_LL_DoWork(iothubClientHandle);
}
}
static EventData azureEventData = { .eventHandler = &AzureTimerEventHandler };
static EventData waterDetectEventData = { .eventHandler = &readWaterDetectHandler };
static int InitPeripheralsAndHandlers(void)
{
struct sigaction action;
memset(&action, 0, sizeof(struct sigaction));
action.sa_handler = TerminationHandler;
sigaction(SIGTERM, &action, NULL);
epollFd = CreateEpollFd();
if (epollFd < 0) {
return -1;
}
Log_Debug("Opening ISU2 I2C\n");
i2cFd = I2CMaster_Open(2);
I2CMaster_SetBusSpeed(i2cFd, I2C_BUS_SPEED_STANDARD);
I2CMaster_SetTimeout(i2cFd, 100);
I2CMaster_SetDefaultTargetAddress(i2cFd, bme680_addr);
init_device();
azureIoTPollPeriodSeconds = AzureIoTDefaultPollPeriodSeconds;
struct timespec azureTelemetryPeriod = { azureIoTPollPeriodSeconds, 0 };
azureTimerFd =
CreateTimerFdAndAddToEpoll(epollFd, &azureTelemetryPeriod, &azureEventData, EPOLLIN);
Log_Debug("Opening GPIO2 as input.\n");
waterDetectGpioFd = GPIO_OpenAsInput(2);
if (waterDetectGpioFd < 0) {
Log_Debug("ERROR: Could not open button GPIO: %s (%d).\n", strerror(errno), errno);
return -1;
}
struct timespec waterDetectCheckPeriod = { 0, waterDetectPollPeriod };
waterDetectTimerFd = CreateTimerFdAndAddToEpoll(epollFd, &waterDetectCheckPeriod, &waterDetectEventData, EPOLLIN);
if (waterDetectTimerFd < 0) return -1;
return 0;
}
static void readWaterDetectHandler(EventData *eventData)
{
GPIO_Value_Type newState;
int result = GPIO_GetValue(waterDetectGpioFd, &newState);
if (result != 0) {
Log_Debug("ERROR: Could not read button GPIO: %s (%d).\n", strerror(errno), errno);
//terminationRequired = true;
return;
}
waterDetectState = newState;
}
static void init_device(void) {
I2CMaster_Write(i2cFd, bme680_addr, ctrl_hum_data, sizeof(ctrl_hum_data));
I2CMaster_Write(i2cFd, bme680_addr, ctrl_meas_data, sizeof(ctrl_meas_data));
I2CMaster_Write(i2cFd, bme680_addr, ctrl_gas_1_data, sizeof(ctrl_gas_1_data));
I2CMaster_Write(i2cFd, bme680_addr, gas_wait_0_data, sizeof(gas_wait_0_data));
res_heat_0_data[1] = calculate_heat();
I2CMaster_Write(i2cFd, bme680_addr, res_heat_0_data, sizeof(res_heat_0_data));
I2CMaster_Write(i2cFd, bme680_addr, config_data, sizeof(config_data));
}
static uint8_t calculate_heat(void)
{
int par_g1, par_g2, par_g2_temp, par_g3, res_heat_range, res_heat_val;
uint8_t current_reg = 0xED;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_g1, 1);
current_reg = 0xEB;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_g2_temp, 1);
current_reg++;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_g2, 1);
current_reg = 0xEE;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_g3, 1);
current_reg = 0x02;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &res_heat_range, 1);
current_reg = 0x00;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &res_heat_val, 1);
par_g2 = (par_g2 << 8) + par_g2_temp;
res_heat_range &= 0b00110000;
double var1 = ((double)par_g1 / 16.0) + 49.0;
double var2 = (((double)par_g2 / 32768.0) * 0.0005) + 0.00235;
double var3 = (double)par_g3 / 1024.0;
double var4 = var1 * (1.0 + (var2 * (double)300.0));
double var5 = var4 + (var3 * (double)23.0);
return (uint8_t)(3.4 * ((var5 * (4.0 / (4.0 + (double)res_heat_range)) *
(1.0 / (1.0 + ((double)res_heat_val * 0.002)))) - 25));
}
static void ClosePeripheralsAndHandlers(void)
{
Log_Debug("Closing file descriptors\n");
CloseFdAndPrintError(i2cFd, "I2C");
CloseFdAndPrintError(azureTimerFd, "AzureTimer");
CloseFdAndPrintError(epollFd, "Epoll");
CloseFdAndPrintError(waterDetectGpioFd, "WaterDetectGpio");
CloseFdAndPrintError(waterDetectTimerFd, "WaterDetectTimer");
}
static void HubConnectionStatusCallback(IOTHUB_CLIENT_CONNECTION_STATUS result,
IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason,
void* userContextCallback)
{
iothubAuthenticated = (result == IOTHUB_CLIENT_CONNECTION_AUTHENTICATED);
Log_Debug("IoT Hub Authenticated: %s\n", GetReasonString(reason));
}
static void SetupAzureClient(void)
{
if (iothubClientHandle != NULL)
IoTHubDeviceClient_LL_Destroy(iothubClientHandle);
AZURE_SPHERE_PROV_RETURN_VALUE provResult =
IoTHubDeviceClient_LL_CreateWithAzureSphereDeviceAuthProvisioning(scopeId, 10000,
&iothubClientHandle);
Log_Debug("IoTHubDeviceClient_LL_CreateWithAzureSphereDeviceAuthProvisioning returned '%s'.\n",
getAzureSphereProvisioningResultString(provResult));
if (provResult.result != AZURE_SPHERE_PROV_RESULT_OK) {
// If we fail to connect, reduce the polling frequency, starting at
// AzureIoTMinReconnectPeriodSeconds and with a backoff up to
// AzureIoTMaxReconnectPeriodSeconds
if (azureIoTPollPeriodSeconds == AzureIoTDefaultPollPeriodSeconds) {
azureIoTPollPeriodSeconds = AzureIoTMinReconnectPeriodSeconds;
}
else {
azureIoTPollPeriodSeconds *= 2;
if (azureIoTPollPeriodSeconds > AzureIoTMaxReconnectPeriodSeconds) {
azureIoTPollPeriodSeconds = AzureIoTMaxReconnectPeriodSeconds;
}
}
struct timespec azureTelemetryPeriod = { azureIoTPollPeriodSeconds, 0 };
SetTimerFdToPeriod(azureTimerFd, &azureTelemetryPeriod);
Log_Debug("ERROR: failure to create IoTHub Handle - will retry in %i seconds.\n",
azureIoTPollPeriodSeconds);
return;
}
// Successfully connected, so make sure the polling frequency is back to the default
azureIoTPollPeriodSeconds = AzureIoTDefaultPollPeriodSeconds;
struct timespec azureTelemetryPeriod = { azureIoTPollPeriodSeconds, 0 };
SetTimerFdToPeriod(azureTimerFd, &azureTelemetryPeriod);
iothubAuthenticated = true;
if (IoTHubDeviceClient_LL_SetOption(iothubClientHandle, OPTION_KEEP_ALIVE,
&keepalivePeriodSeconds) != IOTHUB_CLIENT_OK) {
Log_Debug("ERROR: failure setting option \"%s\"\n", OPTION_KEEP_ALIVE);
return;
}
//IoTHubDeviceClient_LL_SetDeviceTwinCallback(iothubClientHandle, TwinCallback, NULL);
IoTHubDeviceClient_LL_SetConnectionStatusCallback(iothubClientHandle,
HubConnectionStatusCallback, NULL);
}
static const char* GetReasonString(IOTHUB_CLIENT_CONNECTION_STATUS_REASON reason)
{
static char* reasonString = "unknown reason";
switch (reason) {
case IOTHUB_CLIENT_CONNECTION_EXPIRED_SAS_TOKEN:
reasonString = "IOTHUB_CLIENT_CONNECTION_EXPIRED_SAS_TOKEN";
break;
case IOTHUB_CLIENT_CONNECTION_DEVICE_DISABLED:
reasonString = "IOTHUB_CLIENT_CONNECTION_DEVICE_DISABLED";
break;
case IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL:
reasonString = "IOTHUB_CLIENT_CONNECTION_BAD_CREDENTIAL";
break;
case IOTHUB_CLIENT_CONNECTION_RETRY_EXPIRED:
reasonString = "IOTHUB_CLIENT_CONNECTION_RETRY_EXPIRED";
break;
case IOTHUB_CLIENT_CONNECTION_NO_NETWORK:
reasonString = "IOTHUB_CLIENT_CONNECTION_NO_NETWORK";
break;
case IOTHUB_CLIENT_CONNECTION_COMMUNICATION_ERROR:
reasonString = "IOTHUB_CLIENT_CONNECTION_COMMUNICATION_ERROR";
break;
case IOTHUB_CLIENT_CONNECTION_OK:
reasonString = "IOTHUB_CLIENT_CONNECTION_OK";
break;
}
return reasonString;
}
static const char* getAzureSphereProvisioningResultString(
AZURE_SPHERE_PROV_RETURN_VALUE provisioningResult)
{
switch (provisioningResult.result) {
case AZURE_SPHERE_PROV_RESULT_OK:
return "AZURE_SPHERE_PROV_RESULT_OK";
case AZURE_SPHERE_PROV_RESULT_INVALID_PARAM:
return "AZURE_SPHERE_PROV_RESULT_INVALID_PARAM";
case AZURE_SPHERE_PROV_RESULT_NETWORK_NOT_READY:
return "AZURE_SPHERE_PROV_RESULT_NETWORK_NOT_READY";
case AZURE_SPHERE_PROV_RESULT_DEVICEAUTH_NOT_READY:
return "AZURE_SPHERE_PROV_RESULT_DEVICEAUTH_NOT_READY";
case AZURE_SPHERE_PROV_RESULT_PROV_DEVICE_ERROR:
return "AZURE_SPHERE_PROV_RESULT_PROV_DEVICE_ERROR";
case AZURE_SPHERE_PROV_RESULT_GENERIC_ERROR:
return "AZURE_SPHERE_PROV_RESULT_GENERIC_ERROR";
default:
return "UNKNOWN_RETURN_VALUE";
}
}
static void SendTelemetry(const unsigned char* key, const unsigned char* key1, const unsigned char* value1,
const unsigned char* key2, const unsigned char* value2,
const unsigned char* key3, const unsigned char* value3,
const unsigned char* key4, const unsigned char* value4,
const unsigned char* key5, const unsigned char* value5)
{
static char eventBuffer[300] = { 0 };
static const char* EventMsgTemplate = "{ \"%s\": { \
\"%s\" : \"%s\", \
\"%s\" : \"%s\", \
\"%s\" : \"%s\", \
\"%s\" : \"%s\", \
\"%s\" : \"%s\"}}";
int len = snprintf(eventBuffer, sizeof(eventBuffer), EventMsgTemplate, key,
key1, value1, key2, value2, key3, value3, key4, value4, key5, value5);
if (len < 0)
return;
Log_Debug("Sending IoT Hub Message: %s\n", eventBuffer);
IOTHUB_MESSAGE_HANDLE messageHandle = IoTHubMessage_CreateFromString(eventBuffer);
if (messageHandle == 0) {
Log_Debug("WARNING: unable to create a new IoTHubMessage\n");
return;
}
if (IoTHubDeviceClient_LL_SendEventAsync(iothubClientHandle, messageHandle, SendMessageCallback,
/*&callback_param*/ 0) != IOTHUB_CLIENT_OK) {
Log_Debug("WARNING: failed to hand over the message to IoTHubClient\n");
}
else {
Log_Debug("INFO: IoTHubClient accepted the message for delivery\n");
}
IoTHubMessage_Destroy(messageHandle);
}
static void SendMessageCallback(IOTHUB_CLIENT_CONFIRMATION_RESULT result, void* context)
{
Log_Debug("INFO: Message received by IoT Hub. Result is: %d\n", result);
}
void SendData(void)
{
double temperature, humidity, pressure, gas_res;
temperature = get_temperature();
humidity = get_humidity();
pressure = get_pressure();
gas_res = get_gas();
char tempBuffer[20];
int len = snprintf(tempBuffer, 20, "%3.2f", temperature);
char humBuffer[20];
len = snprintf(humBuffer, 20, "%3.1f", humidity);
char pressBuffer[20];
len = snprintf(pressBuffer, 20, "%6.1f", pressure);
char gasBuffer[20];
len = snprintf(gasBuffer, 20, "%3.2f", gas_res);
bool water_present = false;
if (waterDetectState == GPIO_Value_High) water_present = true;
char waterPresentBuffer[20];
len = snprintf(waterPresentBuffer, 20, "%s", water_present ? "true" : "false");
if (len > 0)
SendTelemetry("Env_data", "temperature", tempBuffer, "humidity", humBuffer, "pressure",
pressBuffer, "gas", gasBuffer, "water_present", waterPresentBuffer);
I2CMaster_Write(i2cFd, bme680_addr, reset_data, sizeof(reset_data));
init_device();
}
static double get_gas(void)
{
static const const_array1[] = {1, 1, 1, 1, 1, 0.99, 1, 0.992, 1, 1, 0.998, 0.995, 1, 0.99, 1, 1};
static const const_array2[] = { 8000000, 4000000, 2000000, 1000000, 499500.4995, 248262.1648,
125000, 63004.03226, 31281.28128, 15625, 7812.5, 3906.25, 1953.125, 976.5625, 488.28125, 244.140625};
uint8_t gas_adc_lsb, gas_adc_msb, gas_range, range_switching_error;
uint16_t raw_gas_adc;
double gas_res;
uint8_t current_reg = 0x2B;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &gas_adc_lsb, 1);
current_reg = 0x2A;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &gas_adc_msb, 1);
current_reg = 0x2B;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &gas_range, 1);
current_reg = 0x04;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &range_switching_error, 1);
raw_gas_adc = (gas_adc_msb << 2) + (gas_adc_lsb >> 6);
gas_range = gas_range & 0b1111;
double var1 = (1340.0 + 5.0 * range_switching_error) * const_array1[gas_range];
gas_res = var1 * const_array2[gas_range] / (raw_gas_adc - 512.0 + var1);
return gas_res;
}
static double get_pressure(void)
{
uint32_t raw_press_adc;
uint8_t par_p1_lsb, par_p1_msb, par_p2_lsb, par_p2_msb, par_p3, par_p4_lsb, par_p4_msb,
par_p5_lsb, par_p5_msb, par_p6, par_p7, par_p8_lsb, par_p8_msb, par_p9_lsb, par_p9_msb,
par_p10, press_adc_xlsb, press_adc_lsb, press_adc_msb;
uint16_t par_p1, par_p2, par_p4, par_p5, par_p8, par_p9;
uint32_t press_comp;
uint8_t current_reg = 0x8E;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p1_lsb, 1);
current_reg++;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p1_msb, 1);
current_reg++;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p2_lsb, 1);
current_reg++;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p2_msb, 1);
current_reg++;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p3, 1);
current_reg = 0x94;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p4_lsb, 1);
current_reg++;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p4_msb, 1);
current_reg++;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p5_lsb, 1);
current_reg++;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p5_msb, 1);
current_reg = 0x99;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p6, 1);
current_reg--;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p7, 1);
current_reg = 0x9C;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p8_lsb, 1);
current_reg = 0x9D;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p8_msb, 1);
current_reg = 0x9E;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p9_lsb, 1);
current_reg = 0x9F;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p9_msb, 1);
current_reg = 0xA0;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_p10, 1);
current_reg = 0x21;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &press_adc_xlsb, 1);
current_reg--;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &press_adc_lsb, 1);
current_reg--;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &press_adc_msb, 1);
par_p1 = (par_p1_msb << 8) + par_p1_lsb;
par_p2 = (par_p2_msb << 8) + par_p2_lsb;
par_p4 = (par_p4_msb << 8) + par_p4_lsb;
par_p5 = (par_p5_msb << 8) + par_p5_lsb;
par_p8 = (par_p8_msb << 8) + par_p8_lsb;
par_p9 = (par_p9_msb << 8) + par_p9_lsb;
raw_press_adc = (press_adc_msb << 12) + (press_adc_lsb << 4) + (press_adc_xlsb >> 4);
double t_fine = get_temperature() * 5120.0;
int32_t var1 = ((int32_t)t_fine >> 1) - 64000;
int32_t var2 = ((((var1 >> 2) * (var1 >> 2)) >> 11) * (int32_t)par_p6) >> 2;
var2 = var2 + ((var1 * (int32_t)par_p5) << 1);
var2 = (var2 >> 2) + ((int32_t)par_p4 << 16);
var1 = (((((var1 >> 2) * (var1 >> 2)) >> 13) * ((int32_t)par_p3 << 5)) >> 3) +
(((int32_t)par_p2 * var1) >> 1);
var1 = var1 >> 18;
var1 = ((32768 + var1) * (int32_t)par_p1) >> 15;
press_comp = 1048576 - raw_press_adc;
press_comp = (uint32_t)((press_comp - (var2 >> 12)) * ((uint32_t)3125));
if (press_comp >= (1 << 30)) press_comp = ((press_comp / (uint32_t)var1) << 1);
else press_comp = ((press_comp << 1) / (uint32_t)var1);
var1 = ((int32_t)par_p9 * (int32_t)(((press_comp >> 3) *
(press_comp >> 3)) >> 13)) >> 12;
var2 = ((int32_t)(press_comp >> 2) * (int32_t)par_p8) >> 13;
int32_t var3 = ((int32_t)(press_comp >> 8) * (int32_t)(press_comp >> 8) *
(int32_t)(press_comp >> 8) * (int32_t)par_p10) >> 17;
press_comp = (int32_t)(press_comp)+((var1 + var2 + var3 + ((int32_t)par_p7 << 7)) >> 4);
Log_Debug("Pressure integer val is %i\n", press_comp);
return (double)press_comp;
}
static double get_humidity(void)
{
uint32_t raw_hum_adc;
uint8_t par_h1_lsb, par_h1_msb, par_h2_lsb, par_h2_msb, par_h3, par_h4, par_h5, par_h6, par_h7,
hum_adc_lsb, hum_adc_msb;
uint16_t par_h1, par_h2;
const double temp_comp = get_temperature();
uint8_t current_reg = 0xE2;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_h1_lsb, 1);
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_h2_lsb, 1);
current_reg = 0xE3;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_h1_msb, 1);
current_reg = 0xE1;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_h2_msb, 1);
current_reg = 0xE4;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_h3, 1);
current_reg++;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_h4, 1);
current_reg++;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_h5, 1);
current_reg++;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_h6, 1);
current_reg++; //0xE8
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_h7, 1);
current_reg = 0x26;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &hum_adc_lsb, 1);
current_reg = 0x25;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &hum_adc_msb, 1);
raw_hum_adc = (hum_adc_msb << 8) + hum_adc_lsb;
par_h1 = (par_h1_msb << 4) + (par_h1_lsb >> 4);
par_h2 = (par_h2_msb << 4) + (par_h2_lsb >> 4);
double var1 = raw_hum_adc - (((double)par_h1 * 16.0) + (((double)par_h3 / 2.0) * temp_comp));
double var2 = var1 * (((double)par_h2 / 262144.0) * (1.0 + (((double)par_h4 / 16384.0) *
temp_comp) + (((double)par_h5 / 1048576.0) * temp_comp * temp_comp)));
double var3 = (double)par_h6 / 16384.0;
double var4 = (double)par_h7 / 2097152.0;
return var2 + ((var3 + (var4 * temp_comp)) * var2 * var2);
}
static double get_temperature(void)
{
uint32_t raw_temp_adc;
uint8_t par_t1_lsb, par_t1_msb, par_t2_lsb, par_t2_msb, par_t3, temp_adc_xlsb,
temp_adc_lsb, temp_adc_msb;
uint16_t par_t1, par_t2;
uint8_t current_reg = 0xE9;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_t1_lsb, 1);
current_reg = 0xEA;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_t1_msb, 1);
current_reg = 0x8A;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_t2_lsb, 1);
current_reg = 0x8B;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_t2_msb, 1);
current_reg = 0x8C;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &par_t3, 1);
current_reg = 0x24;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &temp_adc_xlsb, 1);
current_reg = 0x23;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &temp_adc_lsb, 1);
current_reg = 0x22;
I2CMaster_WriteThenRead(i2cFd, bme680_addr, ¤t_reg, 1, &temp_adc_msb, 1);
temp_adc_xlsb >>= 4;
raw_temp_adc = (temp_adc_msb << 12) + (temp_adc_lsb << 4) + temp_adc_xlsb;
par_t1 = (par_t1_msb << 8) + par_t1_lsb;
par_t2 = (par_t2_msb << 8) + par_t2_lsb;
double var1 = (((double)raw_temp_adc / 16384.0) - ((double)par_t1 / 1024.0)) * (double)par_t2;
double var2 = ((((double)raw_temp_adc / 131072.0) - ((double)par_t1 / 8192.0)) *
(((double)raw_temp_adc / 131072.0) - ((double)par_t1 / 8192.0))) *
((double)par_t3 * 16.0);
double t_fine = var1 + var2;
double temp_comp = t_fine / 5120.0;
return temp_comp;
}
Comments