Hi,
Iβm trying to read a pressure sensor on a pixhawk 4 mini I2c bus on GPS port.
It works nicely on UART&I2CB (i2c bus 2) starting the driver with βms5611 start -T 5837β, but I cannot make it work on the GPS I2C bus (i2c bus 1).
In both cases, the sensor is properly detected when I run i2cdetect, here is the output:
- on i2c bus 1
Scanning I2C bus: 1
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: β β β β β β β β β β β β β β β β
10: β β β β β β β β β β β β β β β β
20: β β β β β β β β β β β β β β β β
30: β β β β β β β β β β β β β β β β
40: β β β β β β β β β β β β β β β β
50: β β β β β β β β β β β β β β β β
60: β β β β β β β β β β β β β β β β
70: β β β β β β 76 β β β β β β β β β
- on i2c bus 2
Scanning I2C bus: 2
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: β β β β β β β β β β β β β β β β
10: β β β β β β β β β β β β β β β β
20: β β β β β β β β β β β β β β β β
30: β β β β β β β β β β β β β β β β
40: β β β β β β β β β β β β β β β β
50: β β β β β β β β β β β β β β β β
60: β β β β β β β β β β β β β β β β
70: β β β β β β 76 β β β β β β β β β
Digging into the code with a debugger, I added a couple of printfs in the driver to check what happens:
- file: ms5611.cpp
int
MS5611::measure()
{
int ret;
perf_begin(_measure_perf);
/*
* In phase zero, request temperature; in other phases, request pressure.
*/
unsigned addr = (_measure_phase == 0) ? ADDR_CMD_CONVERT_D2 : ADDR_CMD_CONVERT_D1;
/*
* Send the command to begin measuring.
*/
ret = _interface->ioctl(IOCTL_MEASURE, addr);
printf("ret: %d \n", ret);
if (OK != ret) {
perf_count(_comms_errors);
}
perf_end(_measure_perf);
return ret;
}
this function returns -125, instead of the OK code,
It comes from this function
- file: ms5611_i2c.cpp
MS5611_I2C::ioctl(unsigned operation, unsigned &arg)
{
int ret;
switch (operation) {
case IOCTL_RESET:
ret = _reset();
printf("reset\n");
break;
case IOCTL_MEASURE:
ret = _measure(arg);;//<ββHERE
printf("ret ioctl: %d \n", ret);
break;
default:
ret = EINVAL;
}
return ret;
}
- then from this function (same file):
int
MS5611_I2C::_measure(unsigned addr)
{
/*
* Disable retries on this command; we canβt know whether failure
* means the device did or did not see the command.
*/
_retries = 0;
uint8_t cmd = addr;
return transfer(&cmd, 1, nullptr, 0);
}
- then from transfer:
int I2C::transfer(const uint8_t *send, const unsigned send_len, uint8_t *recv, const unsigned recv_len)
{
px4_i2c_msg_t msgv[2];
unsigned msgs;
int ret = PX4_ERROR;
unsigned retry_count = 0;
if (_dev == nullptr) {
PX4_ERR("I2C device not opened");
return 1;
}
do {
if (get_device_address() != 14)
{
/* code */
printf("transfer out %p/%u in %p/%u\n", send, send_len, recv, recv_len);
}
msgs = 0;
//printf("transfer command %p \n",send);
if (send_len > 0) {
//printf("device clock %f \n",_bus_clocks[get_device_bus() - 1]);
msgv[msgs].frequency = _bus_clocks[get_device_bus() - 1];
msgv[msgs].addr = get_device_address();
msgv[msgs].flags = 0;
msgv[msgs].buffer = const_cast<uint8_t *>(send);
msgv[msgs].length = send_len;
msgs++;
}
if (recv_len > 0) {
msgv[msgs].frequency = _bus_clocks[get_device_bus() - 1];
msgv[msgs].addr = get_device_address();
msgv[msgs].flags = I2C_M_READ;
msgv[msgs].buffer = recv;
msgv[msgs].length = recv_len;
msgs++;
}
//printf("transfer command %d \n",get_device_address());
if (msgs == 0) {
return -EINVAL;
printf("transfer error-------\n");
}
ret = I2C_TRANSFER(_dev, &msgv[0], msgs);
/* success */
if (ret == PX4_OK) {
break;
}
/* if we have already retried once, or we are going to give up, then reset the bus */
if ((retry_count >= 1) || (retry_count >= _retries)) {
I2C_RESET(_dev);
}
} while (retry_count++ < _retries);
return ret;
}
In both cases (bus i2c 1 and bus i2c 2), we send the same message:
transfer out 0x20030377/1 in 0/0
but in one case we get the error code, and in one case it works.
It seems that it comes from the ret = I2C_TRANSFER(_dev, &msgv[0], msgs);
Any idea on what could happen?
Thanks for the help!