This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

ADS1115: ADS1115 3 out of 4 channels steady readings but the 4th has too much noise

Part Number: ADS1115

Tool/software:

Hi

 

I have an ADS1115 setup and working as intended (mostly), using the attached circuit.

I need to detect the UV light levels from a photo diode, (that side all works great)

 

My problem is Channel 0 fluctuates around 300 - 600 "points" while the other readings are steady and unchanged.

This makes controlling the light levels accurately near impossible, I have tested this on a few different boards so it is not just a one off.

 

I have read online that changing the Mux could result in problems, but this only happens for one of the 4 channels.

When I read from only one channel (any one) the levels are pretty stable, maybe fluctuating 1 or 2 points.

Strangely when I use a break point in my code to detect when the value has been changed by more than 100 there is not a problem even with the I2C line getting new values all the time, but when I ask for it from the host PC side then the break point triggers. ( Comms from Host PC to MCU are on uart 1.5M baud)

So sending a command seems to be a problem (from Host to MCU, not the ADS1115, that is running all the time) but only for Channel 0, I have tried doing this on the other channels and I have not seen the problem at all even when it would normally trigger the problem.

But if I change it to only read from one channel and the use the same commands it will not give the problem.

My code that I am using is the follows:

 

void UV_Process()
{

	// need a switch case to keep this to none blocking code.

	unsigned char UV_ADSwrite[6];
	unsigned char UV_ADSread[6];

	UV_ADSwrite[0] = 0x01; // channel info setting.

	UV_ADSwrite[2] = 0x83; //10000011 LSB


	// Run to adjust / set the PWM UV level CHECK that the hood is closed first, set to ZERO unless the hood is closed.

	if(UV_Control.setpoint > 0 && HAL_GPIO_ReadPin(Hood_Close1_GPIO_Port, Hood_Close1_Pin) && HAL_GPIO_ReadPin(Hood_Close2_GPIO_Port, Hood_Close2_Pin))
	{
		if(UV_CHN == 0)
		{
		//uv_dc = UV_PID_Set(&UV_Control, &UV_status);
		__HAL_TIM_SET_COMPARE(UV_PWM_TIM, UV_PWM_CH, UV_Control.setpoint);
		}
	}
	else
	{
		__HAL_TIM_SET_COMPARE(UV_PWM_TIM, UV_PWM_CH, 0);
	}

	switch(UV_reader_steps)
	{

	case(UV_send):

		if(UV_CHN == 0)
				{
					UV_ADSwrite[1] = 0x42; // select channel and start conversion // Try 0xC1
				}
		else if(UV_CHN == 1)
				{
					UV_ADSwrite[1] = 0x52; // select channel and start conversion // Try 0xD1
				}
		else if(UV_CHN == 2)
				{
					UV_ADSwrite[1] = 0x62; // select channel and start conversion // Try 0xE1
				}
		else if(UV_CHN == 3)
				{
					UV_ADSwrite[1] = 0x72; // select channel and start conversion // Try 0xF1
				}

		// Send the info and then move on to the next part
		HAL_I2C_Master_Transmit(&hi2c1, UV_ADDRESS << 1, UV_ADSwrite, 3, 100);

		// specify format and send data command
		UV_ADSwrite[0] = 0x00;
		HAL_I2C_Master_Transmit(&hi2c1, UV_ADDRESS << 1 , UV_ADSwrite, 1 ,100);

		UV_reader_steps = UV_wait; // go to next step

		UV_Wait = HAL_GetTick();

		break;

	case(UV_wait):
			// this needs to wait until 20mS has passed for conversion to work after change of MUX Reg in ADC
					if((HAL_GetTick() - UV_Wait) > 20)
					{
						UV_reader_steps = UV_read;
					}

		break;

	case(UV_read):
			// get the reading
			HAL_I2C_Master_Receive(&hi2c1, UV_ADDRESS <<1, UV_ADSread, 2, 100);


			UV_Data_Send.UV_Levels[UV_CHN] = (UV_ADSread[0] << 8 | UV_ADSread[1] );

			UV_reader_steps = UV_send;

			UV_CHN++; // go to the next channel.

			if(UV_CHN > 3) // loop back to the first channel.
			{
				UV_CHN = 0;

				if(UV_Send_Data)
				{
					// Function call to send UV data to Controller
				}
			}

		break;

	}


}

 

 

Any input would be great, I have measuring between 0 and 3.3V with 4 single ended voltages.

I have tried reducing the SPS and did not have much improvement.

I would like to know if the timing and the Reg commands are setup that they do not interfere with each other, the whole code is in a super loop with other functions and processes running.

EG, does this need to be in sigle shot mode or will continuous mode work ?

MCU is STM32F103 and written in C

  • Hi Travis,

    Let me take a look and I will get back to you by the end of the week.

    Best Regards,

    Angel

  • Hi Travis,

    You mention that when reading from only one channel the output is stable, but when cycling through the mux (to read 4 single ended inputs) you encounter this problem.

    Are you operating the device in single-shot or continuous conversion mode? 

    When the configuration register is changed during an ongoing conversion (or when operating in continuous conversion mode) the new configuration will not take effect until the ongoing conversion completes. Unlike many other Delta-Sigma devices, the new configuration does not reset the digital filter and restart the conversion. This may make it unclear when the previous conversion has completed, and the new one has started. 

    It is suggested that when continuously cycling the mux, single-shot mode be used.

    Also, we recommend adding current limiting resistors/input filtering to the inputs of the ADC to protect against overvoltage and for noise/anti-aliasing purposes since these aren't present in your schematic capture.  

    Have you tested the outputs (OUT_A/OUT_B) in case there is noise here which is then reflected in your output codes? 

    I would like to know if the timing and the Reg commands are setup that they do not interfere with each other, the whole code is in a super loop with other functions and processes running.

    The best way to verify that that the timing and register commands are setup properly is to use a logic analyzer or a scope and probe the digital communication lines when issuing a read or write to a register. This will allow you to verify that the digital communication complies with the specs and diagrams shown in the data sheet. 

    There isn't much we can comment on if the problem is coming from the way you are setting up your microcontroller and code. 

    Best Regards,

    Angel

  • Hi.

    Part of what I was wondering was if the register settings I am using is correct and in the right sequence.

    I have changed the register settings from 0x42 / 0x52 / 0x62 0x72 ( With the 0x83 standard half of the register as well ) to / 0xC3 / 0xD3 / 0xE3 / 0xF3 this should tell it to use single shot mode and stay in power down mode but I get way more noise with these Reg values than the first option in continues mode, and again when I only read from one channel then it reads perfectly stable.

    The noise with these settings is across all channels, not only one.

  • Hi Travis,

    I will get back to you by tomorrow.

    Best Regards,

    Angel

  • Hi Travis

    I have changed the register settings from 0x42 / 0x52 / 0x62 0x72 ( With the 0x83 standard half of the register as well ) to / 0xC3 / 0xD3 / 0xE3 / 0xF3 this should tell it to use single shot mode

    These register settings seem to be correct. 

    In your loop, are you setting a configuration, waiting for the conversion to complete, reading the conversion result, then setting next configuration and repeating, or what is the flow being used in your program?

    I get way more noise with these Reg values than the first option in continues mode,

    Can you elaborate on what you are seeing? At the same data rate there shouldn't be much of a different in noise levels using single-shot vs continuous conversion mode, so this is odd. 

    when I only read from one channel then it reads perfectly stable.

    The noise with these settings is across all channels, not only one.

    This seems rather unclear as to what you are seeing. You see good results when reading only one channel, but bad results in all channels when cycling through the mux or what do you mean here?

    I would like to know if the timing and the Reg commands are setup that they do not interfere with each other, the whole code is in a super loop with other functions and processes running.

    I would suggest using a logic analyzer to probe the communication lines and verify that your code is working as intended.

    Best Regards,

    Angel

  • Hi Angel

    My loop sequence is :

    Send 0x83C3 // specifies the setting and starts a read

    Send 0x00  // This I am told specifies the data format ( I have tried without this and it seems to make no difference )

    Wait 20ms // for ADC to convert a reading.

    Read from ADS1115 and save to channle 0 data

    This repeats using 0x83C3 / 0x83D3  / 0x83E3  /0x83F3  for channle 0, 1, 2 and 3

    This then loops back and starts again.

    The noise across all channels was a code problem that I think has been solved as it is not coming up anymore.

    But when I read from channel 0 ( or any single channel ) continuesly and do not change the Mux, the readings are stable, only when I start changing signals around does it come up with the first repeat of the loop.

    I ended up reading from channel 0 twice and throwing away the first value, this give me a much cleaner reading, I still do not know why though.

  • Hi Travis,

    The loop sequence seems fine. 

    The noise across all channels was a code problem that I think has been solved as it is not coming up anymore.

    It seems likely that the issues may come from the code/firmware. Again, it is always a good idea to probe the communication lines to make sure everything looks ok.

    Using a delay to wait for conversions to complete should be okay if you make sure to wait enough time, but you could also use the conversion ready pin to see when a conversion has completed. This can help to remove ambiguity if a conversion result being read is new or not.

    Best Regards,

    Angel