Относительно использования I2C с Arduino для кремниевой микроструктуры 5852 D 1.5 psi
Я пытаюсь получить выход от датчика (микроструктура 5852D), но я получаю только два выхода: 11 и 255 для равномерного приложения давления.
Ниже приведен мой код, пожалуйста, покажите мне, как преодолеть эту проблему.
#include "Wire.h"
#define addrs 0x5F // I2C bus address
void setup()
{
Wire.begin();
Serial.begin(9600);
}
void loop()
{
byte lobyte;
byte hibyte;
int Press;
Wire.beginTransmission(addrs);
Wire.write(1);
int x = Wire.endTransmission();
Serial.print("endTransmission: ");
Serial.println(x, DEC);
Wire.requestFrom(addrs, 2); // содержимое ваших первых двух регистров
while(Wire.available() < 2 ); // Check for data from slave
{
delay(1000);
lobyte = Wire.read(); // Read press high byte
Serial.println(lobyte, DEC);
hibyte = Wire.read(); // Read press low byte
Serial.println(hibyte, DEC);
Press = toPressure(hibyte, lobyte);
Serial.print("Pressure: ");
Serial.println(Press);
delay(1000);
}
}
float toPressure(byte hi, byte lo)
{
int a = (hi * 256 + lo) & 0x3FFF; // see pdf, mask 14 bit
float rv = (a - 116)* 0.8606; // faster //(t - 1638.0) / 30.84 + 600.0
return rv;
}
2 ответа
Проблемы в вашем коде:
При взаимодействии с датчиком датчик ожидает адрес регистра после адреса устройства. Вместо того, чтобы указать ему адрес регистрации, вы отправили количество байтов, которое хотели бы получить. Хорошая догадка, но, к сожалению, устройство было спроектировано не таким образом.
Вы неправильно объединили наименее значимые и наиболее значимые биты выходного сигнала датчика. LSB содержит 6 (не 8) наименее значимых битов, в то время как MSB содержит 6 наиболее значимых битов. Сначала вы объединили их, как
00MMMMMM00LLLLLLL
(где биты с пометкой L поступают из LSB, а биты с пометкой M поступают из MSB), а затем замаскировали два верхних бита, как вMMMMMM00LLLLLL
. Правильный способ состоял бы в том, чтобы сдвинуть только 6 бит MSB влево, создав0000MMMMMMLLLLLLL
, а затем замаскировав верхние 4 бита, оставивMMMMMMLLLLLLL
.Вы должны любой ценой избегать 32-разрядной математики с плавающей запятой на 8-разрядных микроконтроллерах, если у вас нет огромного количества процессорных циклов.
Для считывания данных с датчика необходимо сначала выбрать регистр, который вы хотите прочитать. Чтобы выбрать регистр, вы должны сначала отправить адрес устройства (95 в десятичном формате, 5F в шестнадцатеричном) с установленным битом запроса на запись, а затем адрес регистра байта, который вы хотите прочитать.
Затем вы можете прочитать содержимое выбранного регистра, сначала отправив адрес устройства, на этот раз с четким битом запроса на запись, а затем получив один байт данных, за которым немедленно следует "не подтверждать" (NACK) для завершения передачи.
Внутренние регистры организованы так, как показано в следующей таблице:
Вот мое мнение о коде. Он хорошо компилируется, но, очевидно, я не могу проверить, действительно ли он работает, так как у меня нет датчика. Я удалил процедуру масштабирования, поскольку было бы разумно сначала довести ее до некоторого уровня, прежде чем внедрять менее существенные функции.
#include "Wire.h"
#include <stdint.h>
#define SENSOR_I2C_ADDR 95
#define SENSOR_REG_PRESSURE_LSB 128
#define SENSOR_REG_PRESSURE_MSB 129
void setup()
{
Wire.begin();
Serial.begin(9600);
}
void loop()
{
Wire.beginTransmission(SENSOR_I2C_ADDR); //Send the address of the register where the least
Wire.write(SENSOR_REG_PRESSURE_LSB); //..significant bits of the pressure measurement are found
Wire.endTransmission(false); //Send a repeated start
Wire.requestFrom(SENSOR_I2C_ADDR, 1, false); //Request 1 byte of data, followed by a repeated start
Wire.beginTransmission(SENSOR_I2C_ADDR); //Send the address of the register where the most
Wire.write(SENSOR_REG_PRESSURE_MSB); //..significant bits of the pressure measurement are found
Wire.endTransmission(false); //Send a repeated start
Wire.requestFrom(SENSOR_I2C_ADDR, 1, true); //Request 1 byte of data, followed by a stop, ending the transaction.
uint16_t pressureRaw;
//There should now be two bytes of data in the receive buffer.
if(Wire.available() == 2)
{
uint8_t lsb = Wire.read(); //The first byte contains the 6 least significant bits
uint16_t msb = Wire.read(); //The second byte contains the 6 most significant bits
pressureRaw = (msb << 6 | lsb) & 0x0FFF; //The most significant bits are aligned and combined with the
//..least significant bits. As the resulting value only has
//..12 bits of precision the upper 4 bits are masked to zero.
Serial.print("Raw pressure value: ");
Serial.println(pressureRaw);
}
else //If more or less than 2 bytes have been received something isn't right.
{
while(Wire.available()) //Clear the buffer
Wire.read();
Serial.println("I2C transaction error");
}
delay(1000);
}
По какой-то непостижимой причине микроструктуры кремния решили не включать спецификацию интерфейса I2C в саму таблицу данных. Вместо этого информация содержится в отдельном примечании к приложению.
ИЗМЕНИТЬ:
Очевидно, Wire.flush() абсолютно ничего не делает. Осуществление с Wire.cpp:
void TwoWire::flush(void)
{
// XX: будет реализовано.
}
И нет, реализация также не входит в базовый класс: virtual void flush() = 0;
. Чтобы обойти это, я заменил вызов flush циклом read ().
Извини, если опоздал на вечеринку. Я решил это много лет назад. Вот мой YT video demo со ссылкой на Google Drive на код в описании видео. Он работает со всей серией датчиков SM58XX. Просто введите параметры для вашей конкретной модели в верхних строках кода, и вы отправитесь на гонки. https://www.youtube.com/watch?v=Xb2J1puSOwk
- Отправка и получение различных типов данных через I2C в Arduino
- Как работают функции вне цикла void?
- Как отображать переменные на 0,96-дюймовом OLED-дисплее с библиотекой u8glib?
- Как отправить строку на мастер с помощью i2c
- Как выбрать альтернативные контакты I2C на ESP32?
- Что означает в I2C «NACK получен»?
- NodeMCU с RFID RC522 и LCD-модулем интерфейса I2C вместе
- Несколько датчиков I2C с одинаковым адресом
Спасибо , я действительно попробую это, и повторю вам, какая доза выйдет!!!!!, @Shripad Puntambekar
Привет, Джеймс, мы работали в соответствии с вашим решением, но получили результат, поскольку lsb все больше формируется от 3 до 61 при давлении 0 мбар, а msb остается постоянным 65535 продолжение.поэтому я запутался, как получить точный вывод.Пожалуйста, помогите другим способом. Спасибо заранее., @Shripad Puntambekar
@ShripadPuntambekar Я не могу помочь никаким другим способом, так как у меня нет датчика. Мой код выводит только комбинированное значение, поэтому вы, должно быть, изменили код, чтобы получить отдельный байт со старшими битами и другой с младшими битами. Не могли бы вы, пожалуйста, проверить, работает ли мой код, **без его изменения**? Я нашел возможный источник ошибок в библиотеке проводов arduino, над которой я работал в обновлении вышеупомянутого кода, поэтому, пожалуйста, скопируйте приведенный выше код еще раз., @jms