morcra
November 6, 2020, 6:38pm
1
Hi
i try to use platform.io with vs code since a few days now.
I try to get data from an i2c device.
After a lot of trouble with mbed i used a code for arduino framework.
First time I programmed it i got my output as i wanted. For the next run I changed the address of the device, no working output anymore, so I switched back to the old address ( the code worked 2minutes ago, just changed one variable) and now I dont get any correct output anymore.
How is this possible? Do I need more steps to setup the environment?
ty
Such problems require a more detail to solve.
can you show a schematic diagram of what components and chips you connect together?
can you show the full platformio.ini
and the code?
Though a suddenly changing / non-working I2C device sounds more like an electrical issue to me.
morcra
November 7, 2020, 11:07am
3
I am using a Nucleo F401RE and a gy-521. I connected 5V, GND, SDA, SCL between both boards. On the breadboard where the GY-521 is placed on I connected the GND with the AD0 pin.
That setup worked once. I disconnected the AD0 and Ground to test a different address and it stopped to work, even after putting it back in the old working configuration. I changed the port in the software as well.
I will post the arduino code here, because it worked after the first time of programming and the second time it failed. I have more problems with the mbed platform but could be the same reason.
This is the platformio.ini code
[env:nucleo_f401re]
platform = ststm32
board = nucleo_f401re
framework = arduino
This is the code (found it on the web, working with the mkr1000 and arduino ide) I use to test the board after failing hard with platform.io , vs code and mbed.
#include <Arduino.h>
#include<Wire.h>
const int MPU1=0x68;
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
void setup(){
Wire.begin();
Wire.beginTransmission(MPU1);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
Serial.begin(9600);
}
void loop(){
Wire.beginTransmission(MPU1);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU1,12,true);
AcX=Wire.read()<<8|Wire.read();
AcY=Wire.read()<<8|Wire.read();
AcZ=Wire.read()<<8|Wire.read();
GyX=Wire.read()<<8|Wire.read();
GyY=Wire.read()<<8|Wire.read();
GyZ=Wire.read()<<8|Wire.read();
Serial.print("Accelerometer: ");
Serial.print("X = "); Serial.print(AcX);
Serial.print(" | Y = "); Serial.print(AcY);
Serial.print(" | Z = "); Serial.println(AcZ);
Serial.print("Gyroscope: ");
Serial.print("X = "); Serial.print(GyX);
Serial.print(" | Y = "); Serial.print(GyY);
Serial.print(" | Z = "); Serial.println(GyZ);
Serial.println(" ");
delay(1000);
}
AD0 is pulled down to GND by 4.7k resistor R6 anyways schematics . If AD0 would be high, the address would change from 0x68 to 0x69.
I don’t see a problem with your wiring. For VCC, either 3.3V or 5V can be used, so that’s ok. Can you try 3.3V regardless?
You can insert a check there wether the device has actually returned 12 bytes.
if (Wire.available() != 12)
{
Serial.println("I2C device failed to respond with 12 bytes");
return; //early exit
}
what is the output of the firmware now?
morcra
November 7, 2020, 5:44pm
5
thanks a lot.
I wanted to try it out. My Laptop was shut down and the Nucleo was not conntected.
I just started everything up, compiled the code and programed the nucleo again. Now the code works, output is correct.
I can try to compile it again and program the mcu again without changing anything now
Double check for bad wiring or replace cables if in doubt, too.
morcra
November 13, 2020, 3:10pm
7
I am not able to find the problem, I might test a different IDE
#include "mbed.h"
#include<iostream>
#define WHO_AM_I_MPU6050 0x75 // Should return 0x68
#define ACCEL_XOUT_H 0x3B
#define ADO 0
#if ADO
#define MPU6050_ADDRESS 0x69<<1 // Device address when ADO = 1
#else
#define MPU6050_ADDRESS 0x68<<1 // Device address when ADO = 0
#endif
I2C i2c(I2C_SDA, I2C_SCL);
float sum = 0;
uint32_t sumCount = 0;
DigitalOut onboardled(LED1);
int16_t accelCount[3]; // Stores the 16-bit signed accelerometer sensor output
float ax, ay, az; // Stores the real accel value in g's
char readByte(uint8_t address, uint8_t subAddress)
{
char data[1]; // `data` will store the register data
char data_write[1];
data_write[0] = subAddress;
i2c.write(address, data_write, 1, 1); // no stop
i2c.read(address, data, 1, 0);
std:cout<<data[0]<<"\n\r";
return data[0];
}
void readAccelData(int16_t * destination);
void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest);
int main()
{
//Set up I2C
i2c.frequency(400000); // use fast (400 kHz) I2C
// Read the WHO_AM_I register, this is a good test of communication
uint8_t whoami = readByte(MPU6050_ADDRESS, WHO_AM_I_MPU6050); // Read WHO_AM_I register for MPU-6050
std::cout<<"I am 0x"<<+whoami<<"\n\r"; // Not working !!!!!!!!!
std::cout<<"I am 0x"<<whoami<<"\n\r";
printf("I AM 0x%x\n\r", whoami); printf("I SHOULD BE 0x68\n\r");
// init
// mpu6050.initMPU6050(); std::cout<<("MPU6050 initialized for active data mode....\n\r"); // Initialize device for active mode read of acclerometer, gyroscope, and temperature
while(1) {
readAccelData(accelCount); // Read the x/y/z adc values
wait_us(100000);
// std::cout<<"ACCEL_XOUT_H: "<<ax;
// printf("ax = %f", 1000*ax);
}
}
void readBytes(uint8_t address, uint8_t subAddress, uint8_t count, uint8_t * dest)
{
char data[14];
char data_write[1];
data_write[0] = subAddress;
i2c.write(address, data_write, 1, 1); // no sto
i2c.read(address, data, count, 0);
for(int ii = 0; ii < count; ii++) {
dest[ii] = data[ii];
}
}
void readAccelData(int16_t * destination)
{
uint8_t rawData[6]; // x/y/z accel register data stored here
readBytes(MPU6050_ADDRESS, ACCEL_XOUT_H, 6, &rawData[0]); // Read the six raw data registers into data array
destination[0] = (int16_t)(((int16_t)rawData[0] << 8) | rawData[1]) ; // Turn the MSB and LSB into a signed 16-bit value
destination[1] = (int16_t)(((int16_t)rawData[2] << 8) | rawData[3]) ;
destination[2] = (int16_t)(((int16_t)rawData[4] << 8) | rawData[5]) ;
std::cout<<"destination inside of lib: "<<+destination[0]<<"\n\r";
std::cout<<"destination inside of lib: "<<+destination[1]<<"\n\r";
std::cout<<"destination inside of lib: "<<+destination[2]<<"\n\r";
std::cout<<" -------------------------------------------"<<"\n\r";
wait_us(1000000);
}
It seems like that code is working. The only thing I changed was adding this line
printf("I AM 0x%x\n\r", whoami); printf("I SHOULD BE 0x68\n\r");
without that line my output was always zero. How is that possible?
Are there any problems with platformio and nucleo? I am super confused right now
morcra
November 13, 2020, 3:15pm
8
now it works without that line. why shouldnt it …
I didnt change anything else here. It feels like a 50:50 chance