Improvements to photo resistor-based lux estimation

- Code now compiles
- Estimation of the photo resistor resistance works
- Lux estimation from the photo resistor resistance needs more work and calibration
- Lux is now encoded in the BLE advertisement payload
This commit is contained in:
rbaron 2021-09-02 21:29:11 +02:00
parent dcd0fc4ae1
commit e32803d44d
5 changed files with 38 additions and 16 deletions

View file

@ -11,13 +11,14 @@
#define PRST_PHOTO_OUT NRF_GPIO_PIN_MAP(0, 2) #define PRST_PHOTO_OUT NRF_GPIO_PIN_MAP(0, 2)
// Deep sleep. // Deep sleep.
#define PRST_DEEP_SLEEP_IN_SECONDS 300 #define PRST_DEEP_SLEEP_IN_SECONDS 2
// Analog to digital converter (ADC). // Analog to digital converter (ADC).
// Prints out ADC debug info, such as the values read for battery and soil // Prints out ADC debug info, such as the values read for battery and soil
// moisture. // moisture.
#define PRST_ADC_BATT_DEBUG 0 #define PRST_ADC_BATT_DEBUG 0
#define PRST_ADC_SOIL_DEBUG 0 #define PRST_ADC_SOIL_DEBUG 0
#define PRST_ADC_PHOTO_DEBUG 1
// BLE. // BLE.
// Prints out BLE debug info, such as the final encoded advertisement packet. // Prints out BLE debug info, such as the final encoded advertisement packet.
@ -27,7 +28,7 @@
// 1. Two most significant bits are set to 1; // 1. Two most significant bits are set to 1;
// 2. The remaining bits should not _all_ be set to 0; // 2. The remaining bits should not _all_ be set to 0;
// 2. The remaining bits should not _all_ be set to 1; // 2. The remaining bits should not _all_ be set to 1;
#define PRST_BLE_MAC_ADDR "f0:ca:f0:ca:00:01" #define PRST_BLE_MAC_ADDR "f0:ca:f0:ca:01:01"
#define PRST_BLE_ADV_NAME "prst" #define PRST_BLE_ADV_NAME "prst"
// Total time spend advertising. // Total time spend advertising.
#define PRST_BLE_ADV_TIME_IN_MS 1000 #define PRST_BLE_ADV_TIME_IN_MS 1000

View file

@ -63,12 +63,13 @@ static void rtc_callback() {
prst_pwm_stop(); prst_pwm_stop();
nrf_gpio_pin_clear(PRST_FAST_DISCH_PIN); nrf_gpio_pin_clear(PRST_FAST_DISCH_PIN);
nrf_gpio_pin_set(PRST_PHOTO_V); // set GPIO for photoresistor HIGH nrf_gpio_pin_set(PRST_PHOTO_V);
prst_adc_photo_sensor_t photo_read = prst_adc_photo_read(batt_read.voltage); // read PHOTO SENSOR value prst_adc_photo_sensor_t photo_read = prst_adc_photo_read(batt_read.voltage);
nrf_gpio_pin_clear(PRST_PHOTO_V); // clear GPIO for photoresistor nrf_gpio_pin_clear(PRST_PHOTO_V);
prst_ble_update_adv_data(batt_read.millivolts, temp_humi.temp_millicelcius, prst_ble_update_adv_data(batt_read.millivolts, temp_humi.temp_millicelcius,
temp_humi.humidity, soil_read.relative, photo_read.lux, run_counter); temp_humi.humidity, soil_read.relative,
photo_read.lux, run_counter);
prst_adv_start(); prst_adv_start();
nrf_delay_ms(PRST_BLE_ADV_TIME_IN_MS); nrf_delay_ms(PRST_BLE_ADV_TIME_IN_MS);
prst_adv_stop(); prst_adv_stop();

View file

@ -71,8 +71,8 @@ void prst_adc_init() {
nrf_saadc_channel_config_t photo_channel_config = nrf_saadc_channel_config_t photo_channel_config =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PRST_ADC_PHOTO_INPUT); NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(PRST_ADC_PHOTO_INPUT);
APP_ERROR_CHECK( APP_ERROR_CHECK(nrf_drv_saadc_channel_init(PRST_ADC_PHOTO_CHANNEL,
nrf_drv_saadc_channel_init(PRST_ADC_PHOTO_CHANNEL, &photo_channel_config)); &photo_channel_config));
} }
prst_adc_batt_read_t prst_adc_batt_read() { prst_adc_batt_read_t prst_adc_batt_read() {
@ -131,14 +131,28 @@ prst_adc_soil_moisture_t prst_adc_soil_read(double battery_voltage) {
} }
prst_adc_photo_sensor_t prst_adc_photo_read(double battery_voltage) { prst_adc_photo_sensor_t prst_adc_photo_read(double battery_voltage) {
nrf_saadc_value_t raw_photo_output = sample_adc_channel(PRST_ADC_PHOTO_CHANNEL); nrf_saadc_value_t raw_photo_output =
sample_adc_channel(PRST_ADC_PHOTO_CHANNEL);
prst_adc_photo_sensor_t ret; prst_adc_photo_sensor_t ret;
ret.raw = raw_photo_output; ret.raw = raw_photo_output;
ret.voltage = (3.6 * raw_photo_output) / (1 << PRST_ADC_RESOLUTION); ret.voltage = (3.6 * raw_photo_output) / (1 << PRST_ADC_RESOLUTION);
ret.lux = (uint16_t)ret.voltage*100000/(battery_voltage-ret.voltage); // This value needs to be calibrated.
#if PRST_ADC_SOIL_DEBUG // The photo resistor forms a voltage divider with a 10 kOhm resistor.
NRF_LOG_INFO("[adc] Read lux level: %d (raw); %d (lux)", // The voltage here is measured in the middle of the voltage divider.
ret.raw, ret.lux); // Vcc ---- (R_photo) ---|--- (10k) ---- GND
// Vout
// So we can estimate R_photo = R * (Vcc - Vout) / Vout
const double photo_resistance =
1e4 * (battery_voltage - ret.voltage) / ret.voltage;
// TODO: Now that we have the resistor value of the photo resistor, we need to
// estimate the value in lux. This needs to be calibrated with a real board in
// complete dark and in a super bright environment.
// This current value is just a placeholder.
ret.lux = (uint16_t)UINT16_MAX * (photo_resistance / 1e4);
#if PRST_ADC_PHOTO_DEBUG
NRF_LOG_INFO("[adc] Read lux level: %d (raw); %d (lux)", ret.raw, ret.lux);
#endif #endif
return ret; return ret;
} }

View file

@ -33,8 +33,9 @@
| 6-7 | Relative air humidity, scaled from 0 (0%) to 0xffff (100%) | | 6-7 | Relative air humidity, scaled from 0 (0%) to 0xffff (100%) |
| 8-9 | Soil moisture, scaled from from 0 (0%) to 0xffff (100%) | | 8-9 | Soil moisture, scaled from from 0 (0%) to 0xffff (100%) |
| 10-15 | b-parasite's own MAC address | | 10-15 | b-parasite's own MAC address |
| 16-17 | Lux level from the photoresistor |
*/ */
#define SERVICE_DATA_LEN 16 #define SERVICE_DATA_LEN 18
static uint8_t service_data[SERVICE_DATA_LEN]; static uint8_t service_data[SERVICE_DATA_LEN];
// Stores the encoded advertisement data. As per BLE spec, 31 bytes max. // Stores the encoded advertisement data. As per BLE spec, 31 bytes max.
@ -135,7 +136,8 @@ void prst_ble_init() {
void prst_ble_update_adv_data(uint16_t batt_millivolts, void prst_ble_update_adv_data(uint16_t batt_millivolts,
uint16_t temp_millicelcius, uint16_t humidity, uint16_t temp_millicelcius, uint16_t humidity,
uint16_t soil_moisture, uint8_t run_counter) { uint16_t soil_moisture, uint16_t lux,
uint8_t run_counter) {
// 4 bits for a small wrap-around counter for deduplicating messages on the // 4 bits for a small wrap-around counter for deduplicating messages on the
// receiver. // receiver.
service_data[1] = run_counter & 0x0f; service_data[1] = run_counter & 0x0f;
@ -152,6 +154,9 @@ void prst_ble_update_adv_data(uint16_t batt_millivolts,
service_data[8] = soil_moisture >> 8; service_data[8] = soil_moisture >> 8;
service_data[9] = soil_moisture & 0xff; service_data[9] = soil_moisture & 0xff;
service_data[16] = lux >> 8;
service_data[17] = lux & 0xff;
// Encodes adv_data_ into .gap_adv_data_. // Encodes adv_data_ into .gap_adv_data_.
uint32_t err_code = ble_advdata_encode( uint32_t err_code = ble_advdata_encode(
&adv_data_, gap_adv_data_.adv_data.p_data, &gap_adv_data_.adv_data.len); &adv_data_, gap_adv_data_.adv_data.p_data, &gap_adv_data_.adv_data.len);

View file

@ -13,6 +13,7 @@ void prst_adv_stop();
void prst_ble_update_adv_data(uint16_t batt_millivolts, void prst_ble_update_adv_data(uint16_t batt_millivolts,
uint16_t temp_millicelcius, uint16_t humidity, uint16_t temp_millicelcius, uint16_t humidity,
uint16_t soil_moisture, uint8_t run_counter); uint16_t soil_moisture, uint16_t lux,
uint8_t run_counter);
#endif // _PRST_BLE_H_ #endif // _PRST_BLE_H_