Two sensors on the 5V pin

Hi,

I have two sensors connected to my board, one accelerometer (BNO055 with i2c) and a incremental rotary encoder. Both share the same ground and 5V
As long as only one of them is connected, they work fine, when I connect both, only the rotary encoder gives me values, the bno055 doesn‘t answer anymore.

I think, this is because the BNO055 has way more resistance and thereby doesn‘t get current anymore. Does this make sence :D?

In case my guess is right, what do I do to resolve this problem?

Edit: Here two images of my breadboard, I‘m using a Nucleo32G431KB microcontroller board from stm



Short explanation: the red wire is the GND of the BNO055,
Grey wire is gnd of rotary encoder
Black wire is 5V of BNO055,
Purple wire is 5V of rotary encoder

I don‘t think you need a code, because the bno055 has a own project, when i run this without the grey and purple wire connected, it works fine, as soon as i connect them both, i get transmision errors

1 Like

No.

What to do?

Please follow the advice given in the link below when posting code, in particular the section entitled 'Posting code and common code problems'

Use code tags (the </> icon above the compose window) to make it easier to read and copy for examination

Post a schematic.
Post an image of your project.

Did you jumper the power rails on the breadboard?

Bread board power rail split


Using one of these?

Generic 9V battery image

What did the I2C scanner report when both devices are connected?

First of all, thanks for your answer, sorry for not providing enough information. I thought this may have been a general problem with a simple solution.

As expected, with the rotary encoder connected, it found nothing. When I removed it, the scanner found the bno055 with address 0x28. See images below, first one with the rotary encoder, second one without.


The wiring of the breadboard does not make sense. Post a schematic.

Here you go

1 Like

Did you flip the wiring around in the diagram? The normal arduino layout is for SCL/SDA to be on analog pins A5/A4, but I'm not familiar with the board you are using.

No, this is correct. It works fine when the rotary encoder is not connected.
I looked it up in the datasheet.

Can you provide a link to the rotary encoder you are using?

Can you post the code you are using for testing?

What does the STM support group say about the matter? The only thing I can see is to try the other I2C pins.


Good luck.

The code would be nice as it allows others to see the addresses used. The BNO055 uses I2C address 0x28 (default) or 0x29. What does the rotary encoder use? Next less knowing the data for the rotary encoder we don't know the current draw? When both devices are connected what happens to your 5.0 volt voltage? So best guess is address conflict or not enough power available and likely the first.

Ron

Rotary encoder appears to be the common KY-040 type, so not an I2C device.

To the OP, will you confirm that the BNO055 is wired to D4 & D5 when it is showing up in the I2C scanner code?

A general suggestion, in electronic wiring, BLACK is generally used for GND, and RED for Vcc, using that convention can help avoid wiring errors.

Do you have a voltmeter to measure the +5V and GND pins to verify they are correct? I'm wondering if the pinout is for the board with the pins facing upward, instead of plugged into a breadboard. The A4/A5 pins are directly opposite the D4/D5 pins, so the board being flipped upside down might explain the I2C working, and you might be getting phantom powering through the I2C pullup resistors.
< edit > Looking at the pinout in reply #10 the I2C is on the D4/D5 pins for this board.

It's this one:

Honestly I don't see, why there should be a address conflict? The rotary encoder doesn't use i2c or similar. Or is there something I don't know yet?
Unfortunately I don't have anything here to check the power available, but I will try with a external power source.

It is all the time wired to D4/D5. The only thing I changed when its address showed up, was to disconnect 5V and GND from the rotary encoder

Here's the code, but I don't think the problem has anything to do with it, since it works fine as long as the encoder isn't connected.

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2022 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <movingQueue.h>
#include <string.h>
#include <stdio.h>
#include <sys/time.h>
#include <math.h>

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

UART_HandleTypeDef huart2;

/* USER CODE BEGIN PV */
static const uint8_t BNO055_ADDR = 0x28 << 1;	// leftshift by 1 bit, since this is a 7 bit address

static const uint8_t OPR_MODE_NDOF = 0x0C;

static const uint8_t REG_UNIT_SEL = 0x3B;
static const uint8_t REG_CONFIG_OPERATION_MODE = 0x3D;
static const uint8_t REG_CALIB_STAT = 0x35;
static const uint8_t REG_LINEAR_ACCEL_X = 0x28;	// 0x28 for LSB, 0x29 for MSB
static const uint8_t REG_LINEAR_ACCEL_Y = 0x2A;	// 0x2A for LSB, 0x2B for MSB
static const uint8_t REG_LINEAR_ACCEL_Z = 0x2C;	// 0x2C for LSB, 0x2D for MSB
static const uint8_t REG_MAG_X = 0x0E;			// 0x0E for LSB, 0x0F for MSB
static const uint8_t REG_MAG_Y = 0x10;			// 0x10 for LSB, 0x11 for MSB
static const uint8_t REG_MAG_Z = 0x12;			// 0x12 for LSB, 0x13 for MSB
static const uint8_t REG_GRV_X = 0x2E;
static const uint8_t REG_QUAT_X = 0x22;
static const uint8_t REG_QUAT_Y = 0x24;
static const uint8_t REG_QUAT_Z = 0x26;
static const uint8_t REG_QUAT_W = 0x20;
static const uint8_t REG_TEMP = 0x34;

static const uint8_t MAG_DIV_UT = 16.0;			// get microT
static const uint8_t GRV_DIV_MSQ = 100.0;		// get m/s^2
static const uint8_t L_ACCEL_DIV_MSQ = 100.0;	// get m/s^2
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_I2C1_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
double read_linear_accel();

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */
	HAL_StatusTypeDef ret;	// saves the return values of the i2c transmitting functions
	uint8_t  buf[16];	// buffer, where return data from i2c is temporarily saved in
	uint8_t reg[16];	// here are the registers, that I want to read from/write to saved in temporarily

	uint32_t ticks;
	ticks = HAL_GetTick();

	int drift_is_calibrated = 0;
	double l_accel_x_sum = 0;	// sum of acceleration values during calibration
	double drift_calib_value_count = 0;	// counter of stored values during calibration

	double l_speed_x = 0;
	double l_pos_x = 0;

	double accel_calib_value = 0;
	double accel_calib_sum = 0;
	double accel_calib_count = 0;

	double x_pos_five_sec = 0;
	double x_pos_start = 0;
	int progress_count = 3;


  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART2_UART_Init();
  MX_I2C1_Init();
  /* USER CODE BEGIN 2 */
  //----------------- configure the BNO055 --------------------
  reg[0] = REG_CONFIG_OPERATION_MODE;	// tell the bno055, that we want to change the operation mode
  reg[1] = OPR_MODE_NDOF;				// set mode to NDOF
  ret = HAL_I2C_Master_Transmit(&hi2c1, BNO055_ADDR, reg, 2, HAL_MAX_DELAY);
  // check, if transmission was fine
  if (ret != HAL_OK) {
	  strcpy((char*)buf, "Error Rx\r\n");
	  HAL_UART_Transmit(&huart2, (const uint8_t*) buf, strlen((char*)buf), HAL_MAX_DELAY);
  } else {
	  strcpy((char*)buf, "Config OK\r\n");
	  HAL_UART_Transmit(&huart2, (const uint8_t*) buf, strlen((char*)buf), HAL_MAX_DELAY);
  }

  HAL_Delay(7);	// it takes 7ms to change the operation mode from config to ndof


  reg[0] = REG_UNIT_SEL;	// tell the bno055, that we want to change the units
  reg[1] = 0x00;			// set all units to metric
  ret = HAL_I2C_Master_Transmit(&hi2c1, BNO055_ADDR, reg, 2, HAL_MAX_DELAY);
  // check, if transmission was fine
  if (ret != HAL_OK) {
	  strcpy((char*)buf, "Error Rx\r\n");
	  HAL_UART_Transmit(&huart2, (const uint8_t*) buf, strlen((char*)buf), HAL_MAX_DELAY);
  } else {
	  strcpy((char*)buf, "Config OK\r\n");
	  HAL_UART_Transmit(&huart2, (const uint8_t*) buf, strlen((char*)buf), HAL_MAX_DELAY);
  }

	HAL_Delay(7);	// it takes 7ms to change the operation mode from config to ndof

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {

	  //----------------- check calibration status -------------------
	  int isCalibrated = 1;
	    reg[0] = REG_CALIB_STAT;
	    ret = HAL_I2C_Master_Transmit(&hi2c1, BNO055_ADDR, reg, 1, HAL_MAX_DELAY);
	  	// check, if transmission was fine
	  	if (ret != HAL_OK) {
	  	  strcpy((char*)buf, "Error Tx\r\n");
	  	  HAL_UART_Transmit(&huart2, (const uint8_t*) buf, strlen((char*)buf), HAL_MAX_DELAY);
	  	} else {
	  		// read calibration status
	  		ret = HAL_I2C_Master_Receive(&hi2c1, BNO055_ADDR, (uint8_t*)buf, 1, HAL_MAX_DELAY);
	  		if (ret != HAL_OK) {
	  			strcpy((char*)buf, "Error Rx\r\n");
	  		  	HAL_UART_Transmit(&huart2, (const uint8_t*)buf, strlen((char*)buf), HAL_MAX_DELAY);
	  		} else {
	  			// when calib_stat is 0, sensor is not calibrated, when it's 3, it is fully calibrated
	  			// calibration status for fusion sensors is saved in the bits 6 and 7
	  			if ((char)buf[0] >> 6 != 3) {
					strcpy((char*)buf, "Sensor not calibrated \r\n");
					//HAL_UART_Transmit(&huart2, (const uint8_t*)buf, strlen((char*) buf), HAL_MAX_DELAY);
					isCalibrated = 0;
				}
	  		}

	  	}

	  	//----------------------- read sensor data ------------------------
	  	if (isCalibrated == 1 || isCalibrated == 0) {	// || isCalibrated == 0 -> give results, even if sensor is not properly calibrated

	  		// read linear accel data
			double l_accel_x = read_linear_accel();

			uint32_t msecs = msecs + HAL_GetTick() - ticks;	// milliseconds after last call
			ticks = HAL_GetTick();

			if(progress_count == 10) {
				sprintf((char*)buf, "linear speed x:%0.4f\r\n", l_pos_x);
				HAL_UART_Transmit(&huart2, (const uint8_t*)buf, strlen((char*) buf), HAL_MAX_DELAY);

			}

			if(ticks >= 5000 && progress_count == 0) {
				x_pos_five_sec = l_pos_x;
				progress_count = 1;

				sprintf((char*)buf, "linear speed x:%0.4f\r\n", l_pos_x);
				HAL_UART_Transmit(&huart2, (const uint8_t*)buf, strlen((char*) buf), HAL_MAX_DELAY);

			}
			if(ticks >= 10000 && progress_count == 1) {
				double x_diff = 0 - l_pos_x;
				double k = x_diff / pow(ticks, 2);

				x_pos_five_sec = x_pos_five_sec + k * pow(5000,2);

				sprintf((char*)buf, "linear speed x:%0.4f\r\n", l_pos_x);
				HAL_UART_Transmit(&huart2, (const uint8_t*)buf, strlen((char*) buf), HAL_MAX_DELAY);

				sprintf((char*)buf, "linear speed x:%0.4f\r\n", x_pos_five_sec);
				HAL_UART_Transmit(&huart2, (const uint8_t*)buf, strlen((char*) buf), HAL_MAX_DELAY);

				progress_count = 2;
			}

			if(progress_count == 3 && ticks <= 60000) {
				accel_calib_sum += l_accel_x;
				accel_calib_count += 1;
			}

			if(progress_count == 3 && ticks > 60000) {
				accel_calib_value = accel_calib_sum / accel_calib_count;
				progress_count = 4;
			}

			if(progress_count == 4) {
				// todo: save last x values in queue and calculate moving average with corrected values
				enqueue(l_accel_x - accel_calib_value);

				sprintf((char*)buf, "linear speed x:%0.4f\r\n", l_speed_x);
				HAL_UART_Transmit(&huart2, (const uint8_t*)buf, strlen((char*) buf), HAL_MAX_DELAY);
			}

	  	HAL_Delay(10);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

Well that eliminates an address conflict. I did notice the rotary encoder uses two pull-up resistors and assume you have those in place. Also the rotary encoder does not look like much of a load. I am not familiar with the board you are using. :frowning:
Ron

The pullup resistors are normally mounted on the ky-040 rotary encoder pc board. The schematics I've see show 10K ohm, so not a significant load.

If the Nucleo is a 3.3V MCU, connect the + pin on the encoder to 3.3V pin on the Nucleo instead of 5V pin.