Относительно использования I2C с Arduino для кремниевой микроструктуры 5852 D 1.5 psi

i2c

Я пытаюсь получить выход от датчика (микроструктура 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;

} 

, 👍1


2 ответа


3

Проблемы в вашем коде:

  • При взаимодействии с датчиком датчик ожидает адрес регистра после адреса устройства. Вместо того, чтобы указать ему адрес регистрации, вы отправили количество байтов, которое хотели бы получить. Хорошая догадка, но, к сожалению, устройство было спроектировано не таким образом.

  • Вы неправильно объединили наименее значимые и наиболее значимые биты выходного сигнала датчика. LSB содержит 6 (не 8) наименее значимых битов, в то время как MSB содержит 6 наиболее значимых битов. Сначала вы объединили их, как 00MMMMMM00LLLLLLL (где биты с пометкой L поступают из LSB, а биты с пометкой M поступают из MSB), а затем замаскировали два верхних бита, как в MMMMMM00LLLLLL. Правильный способ состоял бы в том, чтобы сдвинуть только 6 бит MSB влево, создав 0000MMMMMMLLLLLLL, а затем замаскировав верхние 4 бита, оставив MMMMMMLLLLLLL.

  • Вы должны любой ценой избегать 32-разрядной математики с плавающей запятой на 8-разрядных микроконтроллерах, если у вас нет огромного количества процессорных циклов.

Для считывания данных с датчика необходимо сначала выбрать регистр, который вы хотите прочитать. Чтобы выбрать регистр, вы должны сначала отправить адрес устройства (95 в десятичном формате, 5F в шестнадцатеричном) с установленным битом запроса на запись, а затем адрес регистра байта, который вы хотите прочитать.
Затем вы можете прочитать содержимое выбранного регистра, сначала отправив адрес устройства, на этот раз с четким битом запроса на запись, а затем получив один байт данных, за которым немедленно следует "не подтверждать" (NACK) для завершения передачи.

Внутренние регистры организованы так, как показано в следующей таблице:

register table

Вот мое мнение о коде. Он хорошо компилируется, но, очевидно, я не могу проверить, действительно ли он работает, так как у меня нет датчика. Я удалил процедуру масштабирования, поскольку было бы разумно сначала довести ее до некоторого уровня, прежде чем внедрять менее существенные функции.

#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 ().

,

Спасибо , я действительно попробую это, и повторю вам, какая доза выйдет!!!!!, @Shripad Puntambekar

Привет, Джеймс, мы работали в соответствии с вашим решением, но получили результат, поскольку lsb все больше формируется от 3 до 61 при давлении 0 мбар, а msb остается постоянным 65535 продолжение.поэтому я запутался, как получить точный вывод.Пожалуйста, помогите другим способом. Спасибо заранее., @Shripad Puntambekar

@ShripadPuntambekar Я не могу помочь никаким другим способом, так как у меня нет датчика. Мой код выводит только комбинированное значение, поэтому вы, должно быть, изменили код, чтобы получить отдельный байт со старшими битами и другой с младшими битами. Не могли бы вы, пожалуйста, проверить, работает ли мой код, **без его изменения**? Я нашел возможный источник ошибок в библиотеке проводов arduino, над которой я работал в обновлении вышеупомянутого кода, поэтому, пожалуйста, скопируйте приведенный выше код еще раз., @jms


2

Извини, если опоздал на вечеринку. Я решил это много лет назад. Вот мой YT video demo со ссылкой на Google Drive на код в описании видео. Он работает со всей серией датчиков SM58XX. Просто введите параметры для вашей конкретной модели в верхних строках кода, и вы отправитесь на гонки. https://www.youtube.com/watch?v=Xb2J1puSOwk

,