This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Initializing two sensors with the same dev. add. but in different period of time with I2C in nrf51822

Hi, I'm using two sensors with the same device address through I2C. each sensor is supposed in a specific period of time (not working together), each sensor has a different enable pin and different configuration. when I initialize the sensor individually they are working fine and I get the results properly but when I'm going to combine and schedule the time, the first sensor is working and while initializing the second it's stuck.

I understand that because of the same address and alternative enable pin, it's not possible to initialize both at the main loop, that's why they are in the header file. the code is attached and I would appreciate for any tips.

#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include "nordic_common.h"
#include "nrf.h"
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "nrf51_bitfields.h"
#include "softdevice_handler.h"
#include "app_error.h"
#include "ble_bas.h"
#include "ble_control.h"
#include "hw_select.h"
#include "hw_lmp91000.h"
#include "simple_uart.h"
#include "nrfface.h"
#include "debug.h"
#include "twi_master2.h"
#include "twiface.h"
#include "hw_lcd12864.h"

uint32_t sensorRAW, soundLevel, old_soundLevel, sound_level_counter;
uint8_t lmp91000_available_flag;

/**@brief Function for handling the ADC interrupt.
 * @details  This function will fetch the conversion result from the ADC, convert the value into
 *           percentage and send it to peer.
 */
/*
void ADC_IRQHandler(void)
{
    if (NRF_ADC->EVENTS_END != 0)
    {
        NRF_ADC->EVENTS_END = 0;
        sensorRAW = NRF_ADC->RESULT;
        //NRF_ADC->TASKS_STOP = 1;
		lmp91000_available_flag = 1;        
    }
}

*/



static TwiDevice LMP91000, *This = &LMP91000;

uint8_t lmp91000_get_status(void)
{
	bool ok;
	uint8_t data[1];

	ok = Twiface_readReg(This, LMP91000_STATUS_REG, data, 1);
	if (ok) {
		return data[0] & 0x01;
	}
	else {
		return 0xFF;
	}
}

void lmp91000_set_lock(void)
{
	Twiface_writeReg(This, LMP91000_LOCK_REG, 1);
}
void lmp91000_clear_lock(void)
{
	Twiface_writeReg(This, LMP91000_LOCK_REG, 0);
}


//SO2 configuration
void lmp91000_SO2_cfg(void)
{
	uint8_t result;


	nrf_gpio_pin_clear(LMP91000_SO2_MENB_PIN);
	nrf_delay_ms(1);
	nrf_gpio_pin_set(LMP91000_SO2_MENB_PIN);
	nrf_gpio_pin_clear(LMP91000_CO_MENB_PIN);
	do 
	{
		result = lmp91000_get_status();
	} while (result != 1);
	lmp91000_clear_lock();
	//nrf_delay_ms(1);
	Twiface_writeReg(This, LMP91000_TIACN_REG, LMP91000_TIA_GAIN_350KOHM | LMP91000_TIA_RLOAD_10);
	//nrf_delay_ms(1);
	Twiface_writeReg(This, LMP91000_REFCN_REG, LMP91000_REF_SOURCE_EXTERNAL | LMP91000_INT_ZERO_20 | LMP91000_BIAS_POSITIVE | LMP91000_BIAS_4);
	//nrf_delay_ms(1);
	Twiface_writeReg(This, LMP91000_MODECN_REG, LMP91000_SHORTING_FET_DISABLED | LMP91000_OP_MODE_3_LEAD_CELL);
	lmp91000_set_lock();
	nrf_delay_ms(1);

}

bool lmp91000_init(void)
{
nrf_gpio_pin_clear(LMP91000_SO2_MENB_PIN);
	nrf_delay_ms(100);
	nrf_gpio_cfg_input(LMP91000_VOUT_PIN, NRF_GPIO_PIN_NOPULL);
	
		nrf_gpio_cfg_output(LMP91000_CO_MENB_PIN);
	nrf_gpio_pin_set(LMP91000_CO_MENB_PIN);
	Twiface_initDevice(
		This, LMP91000_NAME, LMP91000_TWIUNIT, LMP91000_TWIFREQ,
		LMP91000_DEVADDR, LMP91000_SDA, LMP91000_SCL);
	return true;
}
bool lmp91000_SO2_init(void)
{
nrf_gpio_pin_clear(LMP91000_CO_MENB_PIN);
	nrf_delay_ms(100);
	nrf_gpio_cfg_input(LMP91000_VOUT_PIN, NRF_GPIO_PIN_NOPULL);
	nrf_gpio_cfg_output(LMP91000_SO2_MENB_PIN);
	nrf_gpio_pin_set(LMP91000_SO2_MENB_PIN);	
	Twiface_initDevice(
		This, LMP91000_NAME, LMP91000_TWIUNIT, LMP91000_TWIFREQ,
		LMP91000_DEVADDR, LMP91000_SDA, LMP91000_SCL);
	return true;
	
	/*

	*/
}
void lmp91000_cfg(void)
{
	uint8_t result;


	nrf_gpio_pin_clear(LMP91000_CO_MENB_PIN);
	nrf_delay_ms(1);
nrf_gpio_pin_set(LMP91000_CO_MENB_PIN);
	nrf_gpio_pin_clear(LMP91000_SO2_MENB_PIN);
	do 
	{
		result = lmp91000_get_status();
	} while (result != 1);
	lmp91000_clear_lock();
	//nrf_delay_ms(1);
	Twiface_writeReg(This, LMP91000_TIACN_REG, LMP91000_TIA_GAIN_14KOHM | LMP91000_TIA_RLOAD_10);
	//nrf_delay_ms(1);
	Twiface_writeReg(This, LMP91000_REFCN_REG, LMP91000_REF_SOURCE_EXTERNAL | LMP91000_INT_ZERO_20 | LMP91000_BIAS_POSITIVE | LMP91000_BIAS_0);
	//nrf_delay_ms(1);
	Twiface_writeReg(This, LMP91000_MODECN_REG, LMP91000_SHORTING_FET_DISABLED | LMP91000_OP_MODE_3_LEAD_CELL);
	lmp91000_set_lock();
	nrf_delay_ms(1);
	
}

/*bool lmp91000_init(void)
{

	nrf_delay_ms(100);
	nrf_gpio_cfg_input(LMP91000_VOUT_PIN, NRF_GPIO_PIN_NOPULL);
	nrf_gpio_cfg_output(LMP91000_CO_MENB_PIN);
	Twiface_initDevice(
		This, LMP91000_NAME, LMP91000_TWIUNIT, LMP91000_TWIFREQ,
		LMP91000_DEVADDR, LMP91000_SDA, LMP91000_SCL);
	return true;
}*/
void lmp91000_adc_start(void)
{
	char lcd_str[50];
	uint32_t temp, i,j,k, sensor_value, temp_value, base_value, temp1;



//SO2 configuration


	//uint32_t temp, i, sensor_value, temp_value, base_value, temp1;
	

for(j=0;j<10;j++)
{
lmp91000_init();
	lmp91000_cfg();
	NRF_ADC->INTENSET   = ADC_INTENSET_END_Disabled;
	NRF_ADC->CONFIG     = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos)  |
		(ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) | 
		(ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos)  |
		(LMP91000_VOUT_ADC << ADC_CONFIG_PSEL_Pos)    |		
		(ADC_CONFIG_EXTREFSEL_None  << ADC_CONFIG_EXTREFSEL_Pos);
	NRF_ADC->EVENTS_END = 0;
	NRF_ADC->ENABLE     = ADC_ENABLE_ENABLE_Enabled;
	nrf_delay_us(200);

	temp = 0;
	for(i=0; i<10; i++)
	{
		temp += get_lmp_vout();
	}

	/*sensor_value = temp / 10;

	temp_value = temperature_value / 27;
	base_value = 159 + temp_value * temp_value * temp_value / 1000 * 175 / 10000000 + temp_value * temp_value / 1000 * 6 / 100000 + 25 * temp_value / 10000;

	if(sensor_value > base_value - 1)
	{
		temp = (sensor_value - base_value) * 120;
		if (temp_value < 100)
		{
			temp1 = 10000 - ((100 - temp_value) * 9 + 300);
			sensorRAW = temp * 10000 / temp1;
		}else if (temp_value < 230)
		{
			temp1 = 10000 - ((230 - temp_value) * 3);
			sensorRAW = temp * 10000 / temp1;
		}else
		{
			temp1 = 10000 - ((temp_value - 230) * 3);
			sensorRAW = temp * temp1 / 10000;
		}
	}else*/
	{
		sensorRAW=temp ;
	}
	sprintf(lcd_str, "GAS CO(PPM)  \t");
		ssd1306_put_char(0, 0, lcd_str);
}
nrf_delay_ms(1);


	for(k=0;k<10;k++)
	
{
	

lmp91000_SO2_init();
	lmp91000_SO2_cfg();
	NRF_ADC->INTENSET   = ADC_INTENSET_END_Disabled;
	NRF_ADC->CONFIG     = (ADC_CONFIG_RES_10bit << ADC_CONFIG_RES_Pos)  |
		(ADC_CONFIG_INPSEL_AnalogInputOneThirdPrescaling << ADC_CONFIG_INPSEL_Pos) | 
		(ADC_CONFIG_REFSEL_VBG << ADC_CONFIG_REFSEL_Pos)  |
		(LMP91000_VOUT_ADC << ADC_CONFIG_PSEL_Pos)    |		
		(ADC_CONFIG_EXTREFSEL_None  << ADC_CONFIG_EXTREFSEL_Pos);
	NRF_ADC->EVENTS_END = 0;
	NRF_ADC->ENABLE     = ADC_ENABLE_ENABLE_Enabled;
	nrf_delay_us(200);

	temp = 0;
	for(i=0; i<10; i++)
	{
		temp += get_lmp_vout();
	}

	sensor_value = temp ;

	/*temp_value = temperature_value / 27;
	base_value = 159 + temp_value * temp_value * temp_value / 1000 * 175 / 10000000 + temp_value * temp_value / 1000 * 6 / 100000 + 25 * temp_value / 10000;

	if(sensor_value > base_value - 1)
	{
		temp = (sensor_value - base_value) * 120;
		if (temp_value < 100)
		{
			temp1 = 10000 - ((100 - temp_value) * 9 + 300);
			sensorRAW = temp * 10000 / temp1;
		}else if (temp_value < 230)
		{
			temp1 = 10000 - ((230 - temp_value) * 3);
			sensorRAW = temp * 10000 / temp1;
		}else
		{
			temp1 = 10000 - ((temp_value - 230) * 3);
			sensorRAW = temp * temp1 / 10000;
		}
	}else*/
	{
		sensorRAW = 0;
	}
	
	sensorRAW=temp;
	sprintf(lcd_str, "GAS SO2(PPM)  \t");
		ssd1306_put_char(0, 0, lcd_str);
}
}
Parents Reply Children
  • You seem to have a lot of redundant code, and half of it seems to be irrelevant and/or commented out making it hard to read. But I did it anyway and have some questions:

    1. Is it really necessary to initiate the sensors 10 times each in a for loop? Could the initializing function be placed outside the loop?
    2. Why do you configure LMP91000_VOUT_PIN, LMP91000_CO_MENB_PIN, and LMP91000_SO2_MENB_PIN as inputs and outputs over and over? Are they ever configured as something else?
    3. Why do you clear LMP91000_SO2_MENB_PIN and LMP91000_CO_MENB_PIN in both the init and cfg functions without ever setting them?
    4. In e.g. lmp91000_SO2_cfg() you clear LMP91000_CO_MENB_PIN and not the LMP91000_SO2_MENB_PIN. I'm unfamiliar with your implementation, but that doesn't make sense to me. The MENB pin is active low, but are you not trying to read from the LMP91000_SO2 sensor here?
Related