/* * i2c_sensors.c * * Created on: Jan 23, 2023 * Author: Sword */ #include "driver/i2c.h" #include #include #include "esp_log.h" #include "driver/gpio.h" #include "i2c_sensors.h" #include "data_processing.h" #include "ulp_main.h" #include "port.h" static const char *TAG = "I2C"; #define LOG_LOCAL_LEVEL ESP_LOG_INFO #define I2C_MASTER_SCL_IO GPIO_NUM_2 /*!< GPIO number used for I2C master clock */ #define I2C_MASTER_SDA_IO GPIO_NUM_3 /*!< GPIO number used for I2C master data */ #define I2C_MASTER_NUM 0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */ #define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */ #define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ #define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */ #define I2C_MASTER_TIMEOUT_MS (1000/ portTICK_PERIOD_MS) /*buffers to store incoming data/values from different sensors*/ //union byteAccessibleUint16 rawHumidity; //union byteAccessibleUint16 rawTemperature; //union byteAccessibleInt16 rawThermocoupleTemperature; typedef struct { union { uint8_t state:2; uint8_t res_mod:1; uint8_t reserv:1; uint8_t i2c_wdt:1; uint8_t reser2:2; uint8_t otp_busy:1; uint8_t data; }; }status_t; //Sensor Data /*RTC_DATA_ATTR static float temperature; RTC_DATA_ATTR static float humidity; RTC_DATA_ATTR static float thermocoupleTemp;*/ static float temperature; static float humidity; static float thermocoupleTemp; RTC_DATA_ATTR uint32_t light_data; RTC_DATA_ATTR uint32_t prev_light_data; float light_full_scale; //Sensor previous Data /*RTC_DATA_ATTR static float prev_temperature; RTC_DATA_ATTR static float prev_humidity; RTC_DATA_ATTR static float prev_thermocoupleTemp;*/ static uint16_t ens210_devid; static uint8_t mc3419_chipId; static uint8_t mcp9600_idRevision; static uint16_t accel_x; static uint16_t accel_y; static uint16_t accel_z; static uint8_t i2cBuffer[6]; esp_err_t i2c_get_accel_reg_byte(uint8_t *reg, uint8_t *byte); void i2c_master_init(void) { /*Set the port number of i2c-peripheral on chip*/ i2c_port_t i2c_master_port = I2C_MASTER_NUM; /*setting the i2c peripheral to act as an i2c-master*/ i2c_config_t conf = { .mode = I2C_MODE_MASTER, .sda_io_num = I2C_MASTER_SDA_IO, .scl_io_num = I2C_MASTER_SCL_IO, .sda_pullup_en = GPIO_PULLUP_DISABLE, .scl_pullup_en = GPIO_PULLUP_DISABLE, .master.clk_speed = I2C_MASTER_FREQ_HZ, }; /*Configuring the i2c with the previous settings*/ ESP_ERROR_CHECK(i2c_param_config(i2c_master_port, &conf)); /*Install the configured i2c driver*/ ESP_ERROR_CHECK(i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0)); } /*Sensors initialization functions*/ /**********************************/ bool i2c_initialize_temp_humidity_sensor(void) { bool flag = false; if(ESP_OK == i2c_ens210_set_active_mode()) { flag = true; ESP_LOGI(TAG, "ENS210 Setting Active Mode"); } if(ESP_OK == i2c_ens210_fetch_dev_id()) { ESP_LOGI(TAG, "ENS210 part ID: %02X", get_ens210_devId()); } if(ESP_OK != i2c_start_temp_humid()) { flag = false; } return flag; } bool i2c_initialize_accel_sensor(void) { bool flag = flag; if(ESP_OK == i2c_get_mc3419_state()) { flag = true; /* These settings should be set in standby mode (before switch to wakeup mode)*/ /* ACCELEROMETER threshold should be set at each accelerometer initialization */ /* 1- switch to STANDBY mode*/ if(ESP_OK == i2c_set_mc3419_mode(MC3419_STANDBY_MODE)) { /* 2- Set Initial motion threshold*/ if(ESP_OK == i2c_set_mc3419_motionThreshold(data_get_motion_threshold())) { /* 3- Enable interrupt flag INT1 for accelerometer*/ i2c_enable_mc3419_motion_int(true); /* 4- Clear all pending INT flags*/ i2c_clear_mc3419_int_flag(); /*LOG*/ ESP_LOGI(TAG,"The new motion_detection threshold %d has been set",data_get_motion_threshold()); } } if(ESP_OK == i2c_set_mc3419_mode(MC3419_WAKE_MODE)) { if(ESP_OK == i2c_fetch_mc3419_chipId()) { ESP_LOGI(TAG, "MC3419 Chip Id: %02X", get_mc3419_chipId()); i2c_get_mc3419_state(); } else { ESP_LOGI(TAG, "Failed to get MC3419 chipid"); flag = false; } } else { ESP_LOGI(TAG, "Failed to set MC3419 to wake mode"); flag = false; } } else { ESP_LOGI(TAG, "Failed to get MC3419 state"); } return flag; } /*ENS210-Sensor functions*/ /**********************************/ esp_err_t i2c_start_temp_humid(void) { esp_err_t ret = ESP_FAIL; i2cBuffer[0] = ENS210_SENS_RUN; i2cBuffer[1] = 3; ret = i2c_master_write_to_device(I2C_MASTER_NUM, ENS210_ADDR, i2cBuffer, 2, 1000 / portTICK_PERIOD_MS); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send sensor run request to ENS210."); return ret; } i2cBuffer[0] = ENS210_SENS_START; i2cBuffer[1] = 3; ret = i2c_master_write_to_device(I2C_MASTER_NUM, ENS210_ADDR, i2cBuffer, 2, 131 / portTICK_PERIOD_MS); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send sensor start request to ENS210."); } return ret; } esp_err_t i2c_stop_temp_humid(void) { esp_err_t ret = ESP_FAIL; i2cBuffer[0] = ENS210_SENS_STOP; i2cBuffer[1] = 3; ret = i2c_master_write_to_device(I2C_MASTER_NUM, ENS210_ADDR, i2cBuffer, 2, 1000 / portTICK_PERIOD_MS); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send sensor stop request to ENS210."); return ret; } return ret; } esp_err_t i2c_fetch_temp(void) { uint16_t temp = 0; uint16_t hum = 0; float tempC = 0; // Read temperature and humidity i2cBuffer[0] = ENS210_T_VAL; esp_err_t ret = ESP_FAIL; ret = i2c_master_write_to_device(I2C_MASTER_NUM, ENS210_ADDR, &i2cBuffer[0], 1, (I2C_MASTER_TIMEOUT_MS)); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to send T_VAL command to ENS210 sensor."); return ret; } ret = i2c_master_read_from_device(I2C_MASTER_NUM, ENS210_ADDR, i2cBuffer, 6, (I2C_MASTER_TIMEOUT_MS)); if(ret == ESP_OK) { //ESP_LOGI(TAG, "Reading temperature and humidity from ENS210 sensor"); } else { ESP_LOGI(TAG, "Failed to read from ENS210 sensor"); return ret; } if(i2cBuffer[2] & 0x01) { temp = i2cBuffer[0] | (i2cBuffer[1] << 8); tempC = temp/64.0; tempC -= 273.15; ulp_ulp_prev_temperature = ulp_ulp_temperature; ulp_ulp_temperature = tempC; ulp_ens_temp_raw = temp; temperature = tempC; } else { ESP_LOGI(TAG, "Invalid temperature data"); } if(i2cBuffer[5] & 0x01) { hum = i2cBuffer[3] | (i2cBuffer[4] << 8); ulp_ulp_prev_humidity = ulp_ulp_humidity; ulp_ulp_humidity = hum/512.0; humidity = hum/512.0; ulp_humidity_raw = hum; } else { ESP_LOGI(TAG, "Invalid humidity data"); } return ret; } float get_temperature_data(void) { return temperature; } float get_prev_temperature_data(void) { return ulp_ulp_prev_temperature; } float get_humidity_data(void) { return humidity; } float get_prev_humidity_data(void) { return ulp_ulp_prev_humidity; } esp_err_t i2c_ens210_fetch_dev_id(void) { i2cBuffer[0] = ENS210_PART_ID; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, ENS210_ADDR, i2cBuffer, 1, 1000 / portTICK_PERIOD_MS); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send part ID request to ENS210."); return ret; } vTaskDelay(100 / portTICK_PERIOD_MS); ret = i2c_master_read_from_device(I2C_MASTER_NUM, ENS210_ADDR, i2cBuffer, 2, (I2C_MASTER_TIMEOUT_MS)); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to receive any part ID response from ENS210."); } ens210_devid = i2cBuffer[1] | (i2cBuffer[0] << 8); return ret; } uint16_t get_ens210_devId(void) { return ens210_devid; } esp_err_t i2c_ens210_set_active_mode(void) { i2cBuffer[0] = ENS210_SYS_CTRL; i2cBuffer[1] = 0; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, ENS210_ADDR, i2cBuffer, 2, I2C_MASTER_TIMEOUT_MS); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send active mode write request to ENS210."); return ret; } vTaskDelay(1000 / portTICK_PERIOD_MS); i2cBuffer[0] = ENS210_SYS_STAT; ret = i2c_master_write_to_device(I2C_MASTER_NUM, ENS210_ADDR, i2cBuffer, 1, I2C_MASTER_TIMEOUT_MS); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send sys stat read request to ENS210."); return ret; } ret = i2c_master_read_from_device(I2C_MASTER_NUM, ENS210_ADDR, i2cBuffer, 1, I2C_MASTER_TIMEOUT_MS); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to receive sys stat response from ENS210."); } else { ESP_LOGI(TAG, "ENS210 sys stat: %d", i2cBuffer[0]); } return ret; } /*MC3419-Sensor functions*/ /**********************************/ esp_err_t i2c_fetch_mc3419_chipId(void) { i2cBuffer[0] = CHIP_IDENTIFICATION_REGISTER; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, i2cBuffer, 1, I2C_MASTER_TIMEOUT_MS); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send chip id request to MC3419."); return ret; } ret = i2c_master_read_from_device(I2C_MASTER_NUM, MC3419_ADDR, i2cBuffer, 1, I2C_MASTER_TIMEOUT_MS); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to get chip id response from MC3419."); } else { mc3419_chipId = i2cBuffer[0]; } return ret; } uint16_t get_mc3419_chipId(void) { return mc3419_chipId; } esp_err_t i2c_get_accel_reg_byte(uint8_t *reg, uint8_t *byte) { esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, reg, 1, I2C_MASTER_TIMEOUT_MS); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send read reg request to MC3419."); return ret; } ret = i2c_master_read_from_device(I2C_MASTER_NUM, MC3419_ADDR, byte, 1, I2C_MASTER_TIMEOUT_MS); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to get read reg response from MC3419."); } return ret; } esp_err_t i2c_set_mc3419_mode(uint8_t mode) { status_t s; i2cBuffer[0] = MODE_REGISTER; i2c_get_accel_reg_byte(i2cBuffer, (uint8_t *)&s); s.state = 1; s.res_mod = mode; i2cBuffer[1] = s.data; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, i2cBuffer, 2, I2C_MASTER_TIMEOUT_MS); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send mode request to MC3419."); } return ret; } esp_err_t i2c_get_mc3419_state(void) { i2cBuffer[0] = DEVICE_STATUS_REGISTER; status_t status; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, i2cBuffer, 1, I2C_MASTER_TIMEOUT_MS); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send status reg request to MC3419."); return ret; } ret = i2c_master_read_from_device(I2C_MASTER_NUM, MC3419_ADDR, (uint8_t *)&status, 1, I2C_MASTER_TIMEOUT_MS); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to get status reg response from MC3419."); } else { ESP_LOGI(TAG, "Device Status: STATE: %d RES_MODE: %d I2C_WDT: %d OTP_BUSY: %d", status.state, status.res_mod, status.i2c_wdt, status.otp_busy); } return ret; } esp_err_t i2c_fetch_accel_pos(void) { i2cBuffer[0] = XOUT_ACCELEROMETER_DATA_LSB_REGISTER; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, i2cBuffer, 1, I2C_MASTER_TIMEOUT_MS); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send XYZ request to MC3419."); return ret; } ret = i2c_master_read_from_device(I2C_MASTER_NUM, MC3419_ADDR, i2cBuffer, 6, I2C_MASTER_TIMEOUT_MS); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to get XYZ response from MC3419."); } else { accel_x = i2cBuffer[0] | (i2cBuffer[1] << 8); accel_y = i2cBuffer[2] | (i2cBuffer[3] << 8); accel_z = i2cBuffer[4] | (i2cBuffer[5] << 8); } return ret; } esp_err_t i2c_clear_mc3419_int_flag(void) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; /* 3- Setting up the register address and its value */ i2cBuffer[0] = INTERRUPT_STATUS_REGISTER; i2cBuffer[1] = 0x00; // Clear all pending interrupt flags. esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to clear all pending interrupt flags of MC3419."); return ret; } //Log the following message for indication ESP_LOGI(TAG,"all pending interrupt flags of MC3419 have been cleared successfully"); vTaskDelay(1000 / portTICK_PERIOD_MS); return ret; } esp_err_t i2c_get_mc3419_int_flags(uint8_t *flags) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; /* 2- Set the register address and the receiving buffer*/ i2cBuffer[0] = INTERRUPT_STATUS_REGISTER; /* 3- read one byte from the INTERRUPT_STATUS_REGISTER*/ esp_err_t ret = i2c_get_accel_reg_byte(&i2cBuffer[0],&i2cBuffer[1]); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to read one from the INTERRUPT_STATUS_REGISTER of MC3419."); return ret; } //Log the following message for indication ESP_LOGI(TAG,"Reading one byte from the INTERRUPT_STATUS_REGISTER of MC3419 successfully"); /* 4- Storing the received byte in the corresponding pointer*/ *flags = i2cBuffer[1]; vTaskDelay(1000 / portTICK_PERIOD_MS); return ret; } esp_err_t i2c_enable_mc3419_motion_int(bool enableFlag) { // Return true if ok, return false if invalid data or error. uint8_t tempByte; uint8_t tempMode; /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; /* 2- Set the register address (MODE_REGISTER)*/ i2cBuffer[0] = MODE_REGISTER; /* 3- Read current mode, so we can return to it after configuring the device*/ esp_err_t ret = i2c_get_accel_reg_byte(&i2cBuffer[0],&tempMode); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to read the current mode of MC3419."); return ret; } // Keep only the mode bits. tempMode &= 0x03; /* 4- Switch to STANDBY mode if necessary*/ if(MC3419_STANDBY_MODE != tempMode) { ret = i2c_set_mc3419_mode(MC3419_STANDBY_MODE); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to switch to STANDBY-MODE for MC3419."); return ret; // I2C error. } } /* 5- Set the register address (INTERRUPT_ENABLE_REGISTER)*/ i2cBuffer[0] = INTERRUPT_ENABLE_REGISTER; /* 6- Read and update AnyMotion interrupt enable bit.*/ ret = i2c_get_accel_reg_byte(&i2cBuffer[0],&tempByte); ESP_LOGI(TAG, "MC3419 interrupt register: 0x%X", tempByte); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to read interrupt enable bit of MC3419."); return ret; } if(enableFlag) tempByte |= 0x04; // Enable AnyMotion interrupt. else tempByte &= ~0x04; // Disable AnyMotion interrupt. /* 7- Setting up the register address and its value */ i2cBuffer[0] = INTERRUPT_ENABLE_REGISTER; i2cBuffer[1] = tempByte; ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to update the AnyMotion interrupt enable bit of MC3419."); return ret; } vTaskDelay(100 / portTICK_PERIOD_MS); i2cBuffer[0] = INTERRUPT_ENABLE_REGISTER; /* Read INTERRUPT_ENABLE_REGISTER to confirm if the interrupt flags are set.*/ ret = i2c_get_accel_reg_byte(&i2cBuffer[0],&tempByte); ESP_LOGI(TAG, "MC3419 INTERRUPT_ENABLE_REGISTER: 0x%X", tempByte); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to read INTERRUPT_ENABLE_REGISTER of MC3419."); return ret; } /* 4- Restore original mode.*/ if(MC3419_STANDBY_MODE != tempMode) { ret = i2c_set_mc3419_mode(tempMode); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to restore the original mode of MC3419."); return ret; // I2C error. } } // From MC3419 data sheet if(MC3419_WAKE_MODE == tempMode) vTaskDelay(1000 / portTICK_PERIOD_MS); // No error. Data valid. return ret; } esp_err_t i2c_set_mc3419_motionThreshold(uint16_t threshold) { // Return true if ok, return false if invalid data or error. uint8_t tempByte; uint8_t tempMode; /* Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; // Read current mode, so we can return to it after configuring the device. i2cBuffer[0] = MODE_REGISTER; /* Read and update AnyMotion interrupt enable bit.*/ esp_err_t ret = i2c_get_accel_reg_byte(&i2cBuffer[0],&tempMode); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to read the mode of MC3419."); return ret; } // Keep only the mode bits. tempMode &= 0x03; /* Switch to STANDBY mode if necessary*/ if(MC3419_STANDBY_MODE != tempMode) { ret = i2c_set_mc3419_mode(MC3419_STANDBY_MODE); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to switch to STANDBY-MODE for MC3419."); return ret; // I2C error. } } // Set sample rate. i2cBuffer[0] = SAMPLE_RATE_REGISTER; i2cBuffer[1] = 0x08; // Sample rates are different for the MC3419 and MC3419-P chips. ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to set the new sample rate of MC3419."); return ret; } // Disable decimation. i2cBuffer[0] = FIFO_CONTROL_2_AND_SAMPLE_RATE_2_REGISTER; i2cBuffer[1] = 0x00; ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to disable decimation of MC3419."); return ret; } // Configure AnyMotion feature. i2cBuffer[0] = ANY_MOTION_THRESHOLD_MSB_REGISTER; i2cBuffer[1] = (uint8_t)((threshold >> 8) & 0x007F); // Bit 7 is reserved. ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to configure AnyMotion feature of MC3419."); return ret; } i2cBuffer[0] = ANY_MOTION_THRESHOLD_LSB_REGISTER; i2cBuffer[1] = (uint8_t)(threshold & 0x00FF); ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to set the value LSB threshold of MC3419."); return ret; } i2cBuffer[0] = ANY_MOTION_DEBOUNCE_REGISTER; i2cBuffer[1] = 0x00; ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to set the value of DEBOUNCE_REGISTER of MC3419."); return ret; } // Enable AnyMotion feature. i2cBuffer[0] = MOTION_CONTROL_REGISTER; ret = i2c_get_accel_reg_byte(&i2cBuffer[0],&tempByte); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to enable AnyMotion feature of MC3419."); return ret; } // Motion block in reset? if(0x80 == (tempByte & 0x80)) { ESP_LOGI(TAG, "Warning: resetting accelerometer motion control block."); // Reset Motion block. i2cBuffer[0] = MOTION_CONTROL_REGISTER; i2cBuffer[1] = 0x80; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to Reset Motion block of MC3419."); return ret; } } // Enable AnyMotion feature. i2cBuffer[0] = MOTION_CONTROL_REGISTER; i2cBuffer[1] = 0x04; ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to Enable AnyMotion feature again of MC3419."); return ret; } // Configure interrupt hardware pins. i2cBuffer[0] = GPIO_CONTROL_REGISTER; i2cBuffer[1] = 0xCC; // Configure both interrupt pins as push-pull, active high. ret = i2c_master_write_to_device(I2C_MASTER_NUM, MC3419_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to configure interrupt hardware pins of MC3419."); return ret; } /* Restore original mode.*/ if(MC3419_STANDBY_MODE != tempMode) { ret = i2c_set_mc3419_mode(tempMode); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to restore the original mode of MC3419."); return ret; // I2C error. } } // From MC3419 data sheet if(MC3419_WAKE_MODE == tempMode) vTaskDelay(1000 / portTICK_PERIOD_MS); // No error. Data valid. return ret; } uint16_t get_accel_x(void) { return accel_x; } uint16_t get_accel_y(void) { return accel_y; } uint16_t get_accel_z(void) { return accel_z; } /*MCP9600-Sensor functions*/ /**********************************/ bool i2c_initialize_thermocouple_sensor(void) { bool flag = false; if(ESP_OK == i2c_mcp9600_set_type(THERMOCOUPLE_TYPE_K)) { flag = true; } if(ESP_OK == i2c_mcp9600_fetch_dev_id()) { ESP_LOGI(TAG, "MCP9600 part ID & Revision: %02X", get_mcp9600_devId()); } if(ESP_OK != i2c_start_thermocoupleConversion()) { flag = false; } return flag; } esp_err_t i2c_mcp9600_set_burst_mode(void) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; /*A Burst Mode of one sample will execute, then device will go into Shutdown mode*/ /* we have to clear the flags that are related to the previous conversion * The configuration register is as following * * Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 * ------------------------------------------------------------------------------ * Cold-Junc| ADC Measurement | Burst Mode Temperature | Shutdown * resol. | Resolution | Samples | Modes * *cold-Junction/Ambient Sensor Resolution: * 0 = 0.0625°C * 1 = 0.25°C *bit 6-5 ADC Measurement Resolution: ADC Resolution bits (see Table 5-3): * 00 =18-bit Resolution * 01 =16-bit Resolution * 10 =14-bit Resolution * 11 =12-bit Resolution *bit 4-2 Burst Mode Temperature Samples: Number of Temperature Samples bits * 000 = 1 sample * 001 = 2 samples * 010 = 4 samples * 011 = 8 samples * 100 = 16 samples * 101 = 32 samples * 110 = 64 samples * 111 = 128 samples *bit 1-0 Shutdown Modes: Shutdown Mode bits * 00 = Normal operation * 01 = Shutdown mode * 10 = Burst mode * 11 = Unimplemented: this setting has no effect * * */ /* 3- Setting up the required sensor configurations */ i2cBuffer[0] = MCP9600_DEVICE_CONFIG_REG; i2cBuffer[1] = 0xA2; // 0.25C cold junction resolution, 16-bit ADC resolution, 1 sample when in Burst mode, Burst mode. esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to Burst-mode and its configuration to MCP9600."); return ret; } //Log the following message for indication //ESP_LOGI(TAG,"Burst-mode and its configuration have been set to MCP9600\r\n"); vTaskDelay(1000 / portTICK_PERIOD_MS); return ret; } esp_err_t i2c_mcp9600_fetch_dev_id(void) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; /* 2- LOOK FOR A MCP9600 SENSOR (THERMOCOOUPLE) */ i2cBuffer[0] = MCP9600_DEVICE_ID_REVISION; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0], 1, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send part ID request to MCP9600."); return ret; } /* Delay for some time Required by MCP9600 data sheet */ vTaskDelay(100/portTICK_PERIOD_MS); /* Note that the MCP9600 chip reads out big endian. * Chip ID must be 0x40 and revision must be greater than 0x13. * Older chips have a bad bug in them. * */ ret = i2c_master_read_from_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0], 2,(I2C_MASTER_TIMEOUT_MS)); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to receive any part ID response from MCP9600."); } /*Store the device ID in its corresponding buffer*/ mcp9600_idRevision = i2cBuffer[1] | (i2cBuffer[0] << 8); return ret; } uint16_t get_mcp9600_devId(void) { return mcp9600_idRevision; } esp_err_t i2c_start_thermocoupleConversion(void) { esp_err_t ret = ESP_FAIL; /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; /* we have to clear the flags that are related to the previous conversion * (Clear Burst Complete and Th Update bits) * The status register is as following * * Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 * ------------------------------------------------------------------------------ * Burst |TH Update| Short | Input | Alert 4 | Alert 3 | Alert 2 | Alert 1 * Complete | | Circuit | Range | Status | Status | Status | Status * * Burst Complete: Burst Mode Conversions Status Flag bit * 1 = TΔ register Burst mode conversions complete * 0 = Writing ‘0’ has no effect * Once Burst mode is enabled, this bit is normally set after the first burst is complete. User can clear it and * poll the bit periodically until the next burst of temperature conversions is complete * TH Update: Temperature Update Flag bit * 1 = Temperature conversion complete * 0 = Writing ‘0’ has no effect * This bit is normally set. User can clear it and poll the bit until the next temperature conversion is complete * * */ /* 2- Clear both the Burst Complete flag and ThUpdate flag to start a new conversion */ i2cBuffer[0] = MCP9600_STATUS_REG; i2cBuffer[1] = 0xC0; ret = i2c_master_write_to_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to reset flags of MCP9600 that are related to previous conversion"); return ret; } ret = i2c_mcp9600_set_burst_mode(); if(ESP_OK != ret) { return ret; } //Log the following message for indication //ESP_LOGI(TAG,"Setting up for new conversion process\r\n"); return ret; } esp_err_t i2c_fetch_thermocoupleTemp(void) { esp_err_t ret = ESP_FAIL; uint16_t temp; uint8_t counter = 0; /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; /*Clear flags*/ i2c_start_thermocoupleConversion(); /* 2- Wait until the previously-started conversions get completed */ do { /*Send the request to read from the MCP9600 status register*/ i2cBuffer[0] = MCP9600_STATUS_REG; ret = i2c_master_write_to_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0], 1, (I2C_MASTER_TIMEOUT_MS)); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to send status request to MCP9600 sensor."); return ret; } /*Read the response from the MCP9600*/ ret = i2c_master_read_from_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0], 1, (I2C_MASTER_TIMEOUT_MS)); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to receive any status response from MCP9600 sensor."); return ret; } /*Check the time-out*/ counter++; if (3 < counter){ // Wait for at least one complete temperature conversion to occur since waking up. This can take up to 332 milliseconds, including the temperature calculation time. ESP_LOGI(TAG, "Timeout for getting data from MCP9600 sensor."); return(ESP_FAIL); // Timeout. } /* Delay for some time Required by MCP9600 data sheet */ vTaskDelay(111/portTICK_PERIOD_MS); } while (!(i2cBuffer[0] & MCP9600_TH_UPDATE_BIT)); /* If Input Range Bit (temperature valid flag) is set then * there is a sensor error, such as an open or shorted thermocouple, etc*/ /* 3- Check to ensure that input-range-bit didn't set*/ if(!(i2cBuffer[0] & MCP9600_INPUT_RANGE_BIT)) { /* 4- Read the conversion result */ /*Send the request to MCP9600 to read the temperature*/ i2cBuffer[0] = MCP9600_HOT_JUNCTION_REG; ret = i2c_master_write_to_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0],1, (I2C_MASTER_TIMEOUT_MS)); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to send temperature request to MCP9600 sensor."); return ret; } /*Read the response from MCP9600*/ ret = i2c_master_read_from_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to receive any temperature response from MCP9600 sensor."); return ret; } /*Check if the temperature is equal or greater than zero*/ /*temp = i2cBuffer[1] | (i2cBuffer[0] << 8); if(temp >= 0) thermocoupleTemp = (i2cBuffer[1]*16) + (i2cBuffer[0] /16); else thermocoupleTemp = (i2cBuffer[1]*16) + (i2cBuffer[0] /16) - 4096;*/ temp = i2cBuffer[1] | (i2cBuffer[0] << 8); ulp_ulp_prev_thermocoupleTemp = ulp_ulp_thermocoupleTemp; ulp_ulp_thermocoupleTemp = temp; ulp_ulp_thermocoupleTemp /= 16; thermocoupleTemp = temp/16.0; if(temp & 0x8000) // Adjust for sign bit { ulp_ulp_thermocoupleTemp -= 4096; thermocoupleTemp -= 4096; } ulp_thermo_temp_raw = ulp_ulp_thermocoupleTemp; } /* Delay for some time Required by MCP9600 data sheet */ vTaskDelay(100/portTICK_PERIOD_MS); return ret; } float get_thermocouple_data(void) { return thermocoupleTemp; } float get_prev_thermocouple_data(void) { return ulp_ulp_prev_thermocoupleTemp; } esp_err_t i2c_mcp9600_set_alert_config(alertNum_t alertNum) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; /* Bit7 | Bit6 | Bit5 | Bit4 | Bit3 | Bit2 | Bit1 | Bit0 * ----------------------------------------------------------------------------------- * Interrupt| --------------- | Monitor | Rise or | ActiveHigh | Comp/Int | Alert * clear | | TH/TC | Fall | ActiveLow | | Enable *bit 7 Interrupt Clear: Interrupt Clear bit * 1 = Clears Interrupt flag (forced ‘0’ by device) * 0 = Normal state or cleared state *bit 6-5 Unimplemented: Read as ‘0’ *bit 4 Monitor TH or TC: Temperature Maintain/Detect bit * 1 = Alert monitor for TC cold-junction sensor * 0 = Alert monitor for TH thermocouple temperature *bit 3 Rise/Fall: Alert Temperature Direction bit * 1 = Alert limit for falling or cooling temperatures * 0 = Alert limit for rising or heating temperatures *bit 2 Active-High/Low: Alert State bit * 1 = Active-high * 0 = Active-low *bit 1 Comp./Int.: Alert Mode bit * 1 = Interrupt mode: Interrupt clears bit (bit 7) – must be set to deassert the alert output * 0 = Comparator mode *bit 0 Alert Enable: Alert Output Enable bit * 1 = Alert output is enabled * 0 = Alert output is disabled */ /* 3- Determine which Alert to set */ switch(alertNum) { case 1: i2cBuffer[0] = MCP9600_ALERT1_CONFIG_REG; break; case 2: i2cBuffer[0] = MCP9600_ALERT2_CONFIG_REG; break; case 3: i2cBuffer[0] = MCP9600_ALERT3_CONFIG_REG; break; case 4: i2cBuffer[0] = MCP9600_ALERT4_CONFIG_REG; break; default: i2cBuffer[0] = 0; break; } i2cBuffer[1] = 0b10000111; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to set Alert%d configurations MCP9600.",alertNum); return ret; } //Log the following message for indication ESP_LOGI(TAG,"Set Alert%d confiurations",alertNum); vTaskDelay(1000 / portTICK_PERIOD_MS); return ret; } esp_err_t i2c_mcp9600_set_alert_limit(alertNum_t alertNum, float alertLimit) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[3]; uint16_t limitValue = 0; uint16_t temp; /* 2- Determine which Alert to set */ switch(alertNum) { case 1: i2cBuffer[0] = MCP9600_ALERT1_LIMIT_REG; break; case 2: i2cBuffer[0] = MCP9600_ALERT2_LIMIT_REG; break; case 3: i2cBuffer[0] = MCP9600_ALERT3_LIMIT_REG; break; case 4: i2cBuffer[0] = MCP9600_ALERT4_LIMIT_REG; break; default: i2cBuffer[0] = 0; break; } /*Check if the alert limit is positive or negative*/ if(alertLimit < 0) { limitValue |= 0b0000100000000000; alertLimit *= -1; } /*init the value for the buffer*/ if(alertLimit > 2047) limitValue = 2047; else { temp = (uint16_t)(alertLimit); temp &= 0b0000011111111111; limitValue = temp << 4; } /*Estimate the fraction*/ temp = (((uint16_t)(alertLimit*100)) % 100); if(temp>=25 && temp<50) limitValue &= 4; else if(temp>=50 && temp<75) limitValue &= 8; else limitValue &= 12; /* 3- Put the limit in the i2c buffer*/ i2cBuffer[1] = limitValue>>8; //high byte firstly i2cBuffer[2] = limitValue; //low byte secondly /*Send the limit*/ esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0], 3, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to set Alert%d limit MCP9600.",alertNum); return ret; } //Log the following message for indication ESP_LOGI(TAG,"Set Alert%d limit",alertNum); vTaskDelay(1000 / portTICK_PERIOD_MS); return ret; } esp_err_t i2c_mcp9600_set_alert_hyst(alertNum_t alertNum, float alertHyst) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; /* 2- Determine which Alert to set */ switch(alertNum) { case 1: i2cBuffer[0] = MCP9600_ALERT1_HYST_REG; break; case 2: i2cBuffer[0] = MCP9600_ALERT2_HYST_REG; break; case 3: i2cBuffer[0] = MCP9600_ALERT3_HYST_REG; break; case 4: i2cBuffer[0] = MCP9600_ALERT4_HYST_REG; break; default: i2cBuffer[0] = 0; break; } /* 3- constrain alertHyst*/ if(alertHyst > 255) alertHyst = 255; else if(alertHyst < 0) alertHyst = 0; /*Put the Hyst in i2c buffer*/ i2cBuffer[1] = (uint16_t)(alertHyst); /*Send the limit*/ esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to set Alert%d Hysteresis MCP9600.",alertNum); return ret; } //Log the following message for indication ESP_LOGI(TAG,"Set Alert%d Hysteresis",alertNum); vTaskDelay(1000 / portTICK_PERIOD_MS); return ret; } esp_err_t i2c_mcp9600_set_sleep(void) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; /* 2- Start new conversion */ i2cBuffer[0] = MCP9600_DEVICE_CONFIG_REG; i2cBuffer[1] = 0xA1; // 0.25C cold junction resolution, 16-bit ADC resolution, 1 sample when in Burst mode, Shutdown mode. esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to set Shutdown-mode and its configuration to MCP9600."); return ret; } //Log the following message for indication ESP_LOGI(TAG,"Shutdown-mode and its configuration have been set to MCP9600\r\n"); vTaskDelay(1000 / portTICK_PERIOD_MS); return ret; } esp_err_t i2c_mcp9600_set_type(uint8_t thermocoupleType) { uint8_t tempThermocoupleType; /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; tempThermocoupleType = thermocoupleType; tempThermocoupleType &= 0x70; // Keep thermocouple type. Set filter coefficient to "Filter off". /* 2- Start new conversion */ i2cBuffer[0] = MCP9600_THERMOCOUPLE_CONFIG; i2cBuffer[1] = tempThermocoupleType; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, MCP9600_ADDR, &i2cBuffer[0], 2, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to set thermocouple type of MCP9600."); return ret; } //Log the following message for indication ESP_LOGI(TAG,"Thermocouple type has been set successfully\r\n"); vTaskDelay(1000 / portTICK_PERIOD_MS); return ret; } bool i2c_initialize_light_sensor(void) { /* Fetch manufacturer ID */ esp_err_t ret = i2c_opt3001_fetch_manufact_id(); if(ret != ESP_OK) { return false; } /* Fetch Device ID */ ret = i2c_opt3001_fetch_dev_id(); if(ret != ESP_OK) { return false; } /* Set the Conversion-Time */ ret = i2c_opt3001_set_conversion_time(CONVERSION_TIME_800Ms); if(ret != ESP_OK) { return false; } /* Set the Converion-mode */ ret = i2c_opt3001_set_conversion_mode(SINGLE_SHOT_CONVERSION_MODE); if(ret != ESP_OK) { return false; } /* Set the FULL_SCALE_LUX range */ ret = i2c_opt3001_set_full_lux_scale(FULL_SCALE_RANGE_LUX_655); if(ret != ESP_OK) { return false; } return true; } esp_err_t i2c_opt3001_fetch_manufact_id(void) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; /* 2- LOOK FOR A OPT3001 SENSOR (Light sensor) */ i2cBuffer[0] = MANUFACTURER_ID_REGISTER; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, OPT3001_ADDR, &i2cBuffer[0], 1, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send manufacturer ID request to OPT3001."); return ret; } /* Delay for some time Required */ vTaskDelay(100/portTICK_PERIOD_MS); ret = i2c_master_read_from_device(I2C_MASTER_NUM, OPT3001_ADDR, &i2cBuffer[0], 2,(I2C_MASTER_TIMEOUT_MS)); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to receive any manufacturer ID response from OPT3001."); } else { ESP_LOGI(TAG, "The manufacturer ID response from OPT3001 is 0x%X%X",i2cBuffer[0],i2cBuffer[1]); } return ret; } esp_err_t i2c_opt3001_fetch_dev_id(void) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; /* 2- LOOK FOR A OPT3001 SENSOR (Light sensor) */ i2cBuffer[0] = DEVICE_ID_REGISTER; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, OPT3001_ADDR, &i2cBuffer[0], 1, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send Device ID request to OPT3001."); return ret; } /* Delay for some time Required */ vTaskDelay(100/portTICK_PERIOD_MS); ret = i2c_master_read_from_device(I2C_MASTER_NUM, OPT3001_ADDR, &i2cBuffer[0], 2,(I2C_MASTER_TIMEOUT_MS)); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to receive any Device ID response from OPT3001."); } else { ESP_LOGI(TAG, "The Device ID response from OPT3001 is 0x%X%X",i2cBuffer[0],i2cBuffer[1]); } return ret; } uint16_t i2c_opt3001_fetch_configuration(void) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[2]; uint16_t config_reg; /* 2- LOOK FOR A OPT3001 SENSOR (Light sensor) */ i2cBuffer[0] = CONFIGURATION_REGISTER; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, OPT3001_ADDR, &i2cBuffer[0], 1, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send configuration request to OPT3001."); return 0xFFFF; } /* Delay for some time Required */ vTaskDelay(100/portTICK_PERIOD_MS); ret = i2c_master_read_from_device(I2C_MASTER_NUM, OPT3001_ADDR, &i2cBuffer[0], 2,(I2C_MASTER_TIMEOUT_MS)); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to receive any configuration response from OPT3001."); return 0xFFFF; } config_reg = ((i2cBuffer[0]<<8)|i2cBuffer[1]); return config_reg; } conversionFlagState_t i2c_opt3001_get_conv_ready_flag(void) { /* Read the configuration register*/ uint16_t config_reg = i2c_opt3001_fetch_configuration(); /* Check if MCU failed to read the configuration register */ if(0xFFFF == config_reg) { return FAILED_TO_READ_CONVERSION_READY_FLAG; } /* Extract and check the Conversion_ready_flag bit from the configuration register */ if((config_reg & 7)) return CONVERSION_READY_FLAG_IS_SET; else return CONVERSION_READY_FLAG_IS_NOT_SET_YET; } esp_err_t i2c_opt3001_fetch_light_data(void) { conversionFlagState_t conv_flag; uint16_t result; uint8_t exponent; uint8_t counter = 0; /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[3]; /* Set the Conversion-Time */ esp_err_t ret = i2c_opt3001_set_conversion_time(CONVERSION_TIME_800Ms); if(ret != ESP_OK) { return ret; } /* Set the Converion-mode */ ret = i2c_opt3001_set_conversion_mode(SINGLE_SHOT_CONVERSION_MODE); if(ret != ESP_OK) { return ret; } /* delay for 0.6 second for conversion process */ vTaskDelay(850/portTICK_PERIOD_MS); /* Read the conversion ready flag */ conv_flag = i2c_opt3001_get_conv_ready_flag(); /* Wait to complete the conversion process */ //while(CONVERSION_READY_FLAG_IS_SET != conv_flag) //{ // if((conv_flag == FAILED_TO_READ_CONVERSION_READY_FLAG) || (counter == 20)) // { // if(conv_flag == FAILED_TO_READ_CONVERSION_READY_FLAG) // { // ESP_LOGI(TAG,"Failed to read light data from the OPT3001 sensor (issue with analog conversion process)"); // } // else if(counter == 20) // { // ESP_LOGI(TAG,"Failed to read light data from the OPT3001 sensor (timeout)"); // } // return ESP_FAIL; // } // // /* Wait for another 100ms*/ // vTaskDelay(100/portTICK_PERIOD_MS); // counter++; // // /* Read the conversion ready flag */ // conv_flag = i2c_opt3001_get_conv_ready_flag(); //} /* Send the address of the result register */ i2cBuffer[0] = RESULT_REGISTER; ret = i2c_master_write_to_device(I2C_MASTER_NUM, OPT3001_ADDR, &i2cBuffer[0], 1, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send result request to OPT3001."); return ESP_FAIL; } /* Delay for some time Required */ vTaskDelay(100/portTICK_PERIOD_MS); /* Read the result register of the OPT3001 sensor */ ret = i2c_master_read_from_device(I2C_MASTER_NUM, OPT3001_ADDR, &i2cBuffer[0], 2,(I2C_MASTER_TIMEOUT_MS)); if(ESP_OK != ret) { ESP_LOGI(TAG, "Failed to receive any configuration response from OPT3001."); return ESP_FAIL; } //ESP_LOGI(TAG,"-----> Result register is equal to = 0x%X%X",i2cBuffer[0],i2cBuffer[1]); result = ((i2cBuffer[0]<<8) | i2cBuffer[1]); result = result & 0x0FFF; //exponent = (i2cBuffer[0] & 0xF0)>>4; //light_data = 0.01 * pow(2,exponent) * result; prev_light_data = light_data; light_data = light_full_scale * result; ulp_light_data_opt = light_data; return ESP_OK; } uint32_t get_light_data(void) { return light_data; } uint32_t get_prev_light_data(void) { return prev_light_data; } esp_err_t i2c_opt3001_set_full_lux_scale(fullScaleRangeLux_t scale) { /*Note that the exponent field can be disabled (set to zero) by enabling the exponent mask (configuration register, ME field = 1) and manually programming the full-scale range (configuration register, RN[3:0] < 1100b (0Ch)), allowing for simpler operation in a manually-programmed, full-scale mode */ /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[3]; uint8_t bit = 0; /* Read the configuration register*/ uint16_t config_reg = i2c_opt3001_fetch_configuration(); /* Check if MCU failed to read the configuration register */ if(0xFFFF == config_reg) { return ESP_FAIL; } /* Set the Mask-exponent-field bit to 1 */ config_reg = config_reg | (1<<2); /* Check the requested Full-scale */ for(uint8_t i = 0; i<4; i++) { bit = scale & (1<>8; i2cBuffer[2] = config_reg&0xFF; /* Send the new value of the configuration register */ esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, OPT3001_ADDR, &i2cBuffer[0], 3, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send/write the new FullScale-configuration to OPT3001."); return ret; } else { switch(scale) { case FULL_SCALE_RANGE_LUX_40: ESP_LOGI(TAG, "The new FullScale-configurations (40) have been written to OPT3001 successfully"); break; case FULL_SCALE_RANGE_LUX_82: ESP_LOGI(TAG, "The new FullScale-configurations (82) have been written to OPT3001 successfully"); break; case FULL_SCALE_RANGE_LUX_164: ESP_LOGI(TAG, "The new FullScale-configurations (164) have been written to OPT3001 successfully"); break; case FULL_SCALE_RANGE_LUX_327: ESP_LOGI(TAG, "The new FullScale-configurations (327) have been written to OPT3001 successfully"); break; case FULL_SCALE_RANGE_LUX_655: ESP_LOGI(TAG, "The new FullScale-configurations (655) have been written to OPT3001 successfully"); break; case FULL_SCALE_RANGE_LUX_1314: ESP_LOGI(TAG, "The new FullScale-configurations (1314) have been written to OPT3001 successfully"); break; case FULL_SCALE_RANGE_LUX_2621: ESP_LOGI(TAG, "The new FullScale-configurations (2621) have been written to OPT3001 successfully"); break; case FULL_SCALE_RANGE_LUX_5241: ESP_LOGI(TAG, "The new FullScale-configurations (5241) have been written to OPT3001 successfully"); break; case FULL_SCALE_RANGE_LUX_10483: ESP_LOGI(TAG, "The new FullScale-configurations (10483) have been written to OPT3001 successfully"); break; case FULL_SCALE_RANGE_LUX_20966: ESP_LOGI(TAG, "The new FullScale-configurations (20966) have been written to OPT3001 successfully"); break; case FULL_SCALE_RANGE_LUX_41933: ESP_LOGI(TAG, "The new FullScale-configurations (41933) have been written to OPT3001 successfully"); break; case FULL_SCALE_RANGE_LUX_83865: ESP_LOGI(TAG, "The new FullScale-configurations (83865) have been written to OPT3001 successfully"); break; } } /* Set the light_full_scale that will be used in the result calculation */ light_full_scale = 0.01*pow(2,scale); ulp_light_exponent = scale; return ret; } esp_err_t i2c_opt3001_set_conversion_time(lightConversionTime_t CTime) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[3]; /* Read the configuration register*/ uint16_t config_reg = i2c_opt3001_fetch_configuration(); /* Check if MCU failed to read the configuration register */ if(0xFFFF == config_reg) { return ESP_FAIL; } /* Set the corresponding bits for the conversion-time in the configuration register */ switch(CTime) { case CONVERSION_TIME_100Ms: config_reg = config_reg & (~(1<<11)); break; case CONVERSION_TIME_800Ms: config_reg = config_reg | (1<<11); break; } /* Send the new values for the configuration register */ i2cBuffer[0] = CONFIGURATION_REGISTER; i2cBuffer[1] = config_reg>>8; i2cBuffer[2] = config_reg&0xFF; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, OPT3001_ADDR, &i2cBuffer[0], 3, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send/write the new Time-configuration to OPT3001."); return ret; } else { //ESP_LOGI(TAG, "The new Time-configurations have been written to OPT3001 successfully"); } return ret; } esp_err_t i2c_opt3001_set_conversion_mode(lightConversionMode_t CMode) { /* 1- Creating i2c buffer for sending and receiving */ uint8_t i2cBuffer[3]; /* Read the configuration register*/ uint16_t config_reg = i2c_opt3001_fetch_configuration(); /* Check if MCU failed to read the configuration register */ if(0xFFFF == config_reg) { return ESP_FAIL; } /* Set the corresponding bits for the conversion-mode in the configuration register */ switch(CMode) { case SHUT_DOWN_CONVERSION_MODE: config_reg = config_reg & (~(1<<9)); config_reg = config_reg & (~(1<<10)); break; case SINGLE_SHOT_CONVERSION_MODE: config_reg = config_reg | (1<<9); config_reg = config_reg & (~(1<<10)); break; case CONTINUOUS_CONVERSION_MODE: config_reg = config_reg | (1<<9); config_reg = config_reg | (1<<10); break; } /* Send the new values for the configuration register */ i2cBuffer[0] = CONFIGURATION_REGISTER; i2cBuffer[1] = config_reg>>8; i2cBuffer[2] = config_reg&0xFF; esp_err_t ret = i2c_master_write_to_device(I2C_MASTER_NUM, OPT3001_ADDR, &i2cBuffer[0], 3, (I2C_MASTER_TIMEOUT_MS)); if(ret != ESP_OK) { ESP_LOGI(TAG, "Failed to send/write the new mode-configuration to OPT3001."); return ret; } else { //ESP_LOGI(TAG, "The new mode-configurations have been written to OPT3001 successfully"); } return ret; }