Как использовать датчик температуры M117 от mysentech?

Кто-нибудь может помочь мне расшифровать температуру чип M117 с сайта mysentech.com?

Я что-то пробовал, но получаю постоянное необработанное значение 0xFFFF, которое становится равным 1, когда применяется дополнение 2.

Чип обнаруживается по ожидаемому адресу (TEMP_SENSOR_ADDRESS равен 0x45) во время операции сканирования шины I2C.


    // Начать передачу I2C
    Wire.beginTransmission(TEMP_SENSOR_ADDRESS);
    // Выбор регистра данных
    Wire.write(0x00);
    // Остановить передачу I2C
    Wire.endTransmission();
    delay(300);

    // == Запрос необработанных временных 2 байт
    Wire.requestFrom(TEMP_SENSOR_ADDRESS, 2);
    const size_t count = Wire.available();
    log("%d bytes available", count);
    
    if (count!=2) {
        *ready = false;
        warn("I2c temp is not available");
    }
    else {
        *ready = true;
        // Получить необработанные данные как 16-битный код с обратным порядком байтов (MSB-LSB)
        byte data0 = Wire.read();
        byte data1 = Wire.read();
        const uint16_t raw = data0<<8 | data1;
        const int sign = raw>>15 == 1 ? -1 : 1;
        
        // Получить необработанную температуру в виде дополнения до 2 16-битного (MSB-LSB) значения
        const int16_t c2Raw = ~raw + 1;
            
        // Применение масштаба и смещения
        temperature = sign * float(c2Raw)/256.0 + 40;
        log("raw: %04x (%d) | Raw 2's complement  %04x (%d) | temperature: %f°C", 
            raw, raw, 
            c2Raw, c2Raw, 
            temperature
        );
    }

[ОБНОВЛЕНИЕ | СЕНТ. 2 2022] После обсуждения, которое я провел с @jsoleta, мой текущий код выглядит следующим образом. Но все равно получаю FFFF AC. AC является правильным CRC для FFFF. Может ли это быть результатом проблемы с проводкой компонента на нашей заказной печатной плате?

Журналы:

b5725|—|  Thermometer: Command: Writing to register command 0xCC44
b5725|—|  Thermometer: Command byte 0: cc
b5725|—|  Thermometer: Command byte 1: 44
b5725|—|  Thermometer: Command: register transmitted 2 bytes
b5725|—|  Thermometer: 3 bytes available
b5725|—|  Thermometer: Actually read 3 bytes: ff ff ac
b5725|—|  Thermometer:  CRC matched: computed: ac == read: ac
b5725|—|  Thermometer: raw: ffff (65535) | Raw 2's complement  0001 (1) | temperature: 39.996094°C
b5725|—|  Thermometer: raw: ffff (65535) | temperature: 39.996094°C
b5725|—|  Thermometer: Transmitting board temperature 40.0°C over the RS-485 bus (raw is 799 - 0x031f)

Обновленный код:

loat I2cThermometer :: readTemperature(bool *ready) {
    float temperature = 0;
  
    log("Command: Writing to register command 0xCC44");
    // Начать передачу I2C
    Wire.beginTransmission(TEMP_SENSOR_ADDRESS);
    
    // Выбрать регистр данных 0x00, конфиг 0x01

    const uint16_t command = 
        0xcc44  // Ожидание измерения температуры
        //0xf32d // Статус чтения
        //0x611d // Сигнал тревоги для результата измерения
    ;
    byte * data = (byte*)&command;
    Wire.write(data[1]); log("Command byte 0: %02x", data[1]);
    Wire.write(data[0]); log("Command byte 1: %02x", data[0]);


    // Остановить передачу I2C
    const auto readCount = Wire.endTransmission();
    log("Command: register transmitted %d bytes", readCount);
    delay(15);
    // == Запрос необработанного temp 2 байта + CRC
    Wire.requestFrom(TEMP_SENSOR_ADDRESS, 3);   // 2 байта данных + 1 байт CRC
    const size_t count = Wire.available();
    log("%d bytes available", count);
    

    if (count!=3) {
        *ready = false;
        warn("No temp data is not available");
    }
    else {
        *ready = true;


            // Получить необработанные данные как 16-битный код с обратным порядком байтов (MSB-LSB)
            byte data[3];
            const size_t r = Wire.readBytes(data, sizeof data);
            log("Actually read %d bytes: %02x %02x %02x", r, data[0], data[1], data[2]);
            const byte crc = MY_CRC8(data, 2);
            if (crc != data[2]) {
                warn("CRC mismatch: computed: %02x != read: %02x", crc, data[2]);
            }
            else {
                success("CRC matched: computed: %02x == read: %02x", crc, data[2]);
            }
            const uint16_t raw = *(uint16_t*)data;
            
            const int sign = raw>>15 == 1 ? -1 : 1;

            // Получить необработанную температуру как дополнение до 2 16-битного старшего английского (MSB-LSB)
            const int16_t c2Raw = ~raw + 1;
            
            // Применение масштаба и смещения
            temperature = sign * float(c2Raw)/256.0 + 40;
            #if LOG_LEVEL >= LOG_LEVEL_DEBUG
            log("raw: %04x (%d) | Raw 2's complement  %04x (%d) | temperature: %f°C", 
                raw, raw, 
                c2Raw, c2Raw, 
                temperature
            );
            #endif
        

        #if LOG_LEVEL >= LOG_LEVEL_DEBUG
        log("raw: %04x (%d) | temperature: %f°C", 
            raw, raw, 
            temperature
        );
        #endif
        
        writeBoardTemperatureMessage(temperature);
    }


    if (!(*ready)) {
        #if LOG_LEVEL >= LOG_LEVEL_INFO
        log("Temperature is not ready %d°C", temperature);
        #endif
        return temperature;
    }
        
    #if LOG_LEVEL >= LOG_LEVEL_INFO
    log("Temperature is %d°C", temperature);
    #endif

    return temperature;
}

, 👍0

Обсуждение

не думайте, что "0xFFFF, который становится 1 после дополнения 2" ... вместо этого думайте, что "0xFFFF, это 11111111111111111. Я не читаю ни одного нуля", @jsotola

Не говоря уже о том, что FFFF равен 1, но два дополнения FFFf становятся равными 1. Необработанное значение — это дополнение до 2 16-битного числа, которое мы читаем., @Stéphane de Luca


2 ответа


Лучший ответ:

-1

Хорошо, я нашел кое-что странное. Мой код работает, если я запрашиваю датчик каждые 4 секунды максимум. Но если частота ниже, это не сработает.

Заменю датчик, откатившись на TMP112, как и раньше.

,

1

ВНИМАНИЕ: у меня нет возможности протестировать/проверить те части, которые непосредственно относятся к вашему чипу.

Выдать команду преобразования

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

Выполнение команды преобразования (опять же, я не могу это проверить):

void request_temperature_conversion() {
  Wire.beginTransmission(TEMP_SENSOR_ADDRESS);
  Wire.write(0xCC);
  Wire.write(0x44);
  const auto check_me = Wire.endTransmission();
  delay(15); // Убедитесь, что преобразование завершено.
}

Читать результат

Чтобы прочитать результат ценности самой последней конверсии:

uint16_t read_u16_temperature() {
  const auto read_count = Wire.requestFrom(
    TEMP_SENSOR_ADDRESS,
    3 // фактическая транзакция включает в себя 8-битную, а также 16-битную выборку
  );
  uint8_t temp_payload[2];  // 2, потому что я собираюсь игнорировать CRC.
  Wire.read(temp_payload, sizeof temp_payload);

  return uint16_t(temp_payload[0]) << 8 | temp_payload[1];
}

int16_t read_s16_temperature() {
  int16_t r;
  const uint16_t u = read_u16_temperature();
  memcpy(&r, &u, sizeof r);
  return r;
}

Вместе

Опять же, я не могу это проверить.

request_temperature_conversion();
temperature = 
  sign
  * float(read_s16_temperature()) / 256
  + 40;

Вероятно, вы можете и должны избегать использования типа с плавающей запятой. Если вы регистрируете эти данные и передаете эти данные куда-то еще для регистрации, вам может быть лучше передавать/сохранять необработанные значения, которые могут быть (повторно) интерпретированы позже, чем иметь разные версии вашего скетча, которые потенциально могут повлиять на то, как вычисление делается на значениях.

Документация производителя

На веб-сайте, на который вы ссылаетесь, есть техническое описание на китайском языке. Вы можете получить некоторую пользу от своего машинного перевода на английский (или любой другой). Google Диск на это способен. Вероятно, более полезными являются архивы примеров кода, предназначенные для STM32. Вот откуда взялась вся информация, включая, что особенно важно, использование команды 0xCC44 для запроса преобразования. Задержка в 15 мс также снята из того, что я прочитал в примере кода STM32 в rar-архиве с сайта; Я не особо задумывался о его значении или о том, как поведет себя эта часть, если не ждать достаточно долго. Вы должны прочитать его, потому что там больше информации о настройке чипа, CRC и т. д.

Центр загрузки Chip Maker с именами файлов M117 M117B Digital Temperature Chip Product Manual-Minyuan 202206.pdf, M117B_IIC_Samplecode_stm32-MY202203. rar, M117_MTS01_IIC_Samplecode_stm32-MY202202.rar

,

Спасибо за ответ. К сожалению, я уже пробовал CC44, но я внес некоторые коррективы в соответствии с вашим вводом в мой код, но это все равно дает необработанное значение 0xFFFF. CRC, который я получил, равен 0xAC (хотя я еще не проверял, все в порядке). По поводу техпаспорта, я его уже перевел с китайского. Я буду работать с версией STM, которую ты дашь на сайте., @Stéphane de Luca

Я изменил старый код CRC8, который у меня был для полинома генератора и начальных значений, указанных в таблице данных (0x31 и 0xFF соответственно), и это подтверждает, что 0xAC является правильным CRC для 0xFFFF. Также проверен их пример CRC 0xBEEF, 0x92. Таким образом , вы получаете хорошо сформированное входящее чтение I2C. Если у меня есть причина для редактирования, некоторые из них могут попасть в ответ., @timemage

Я подтверждаю, что AC является правильным CRC для FFFF. Текущий код программы кажется теперь правильным, но по-прежнему нет результата, кроме FFFF (я собираюсь обновить вопрос соответственно. Может ли это быть результатом чего-то неправильного в проводке нашей пользовательской печатной платы?, @Stéphane de Luca

Поскольку вы получаете правильный CRC, проблема с проводкой I2C кажется мне маловероятной. Если есть такая проблема, то вряд ли это проблема, которую нельзя смягчить, снизив скорость передачи данных I2C. Теперь мы хорошо обсудим ответ, написанный. Если я увижу что-то новое в вопросе, на который я могу ответить, я отвечу. Если вы пытаетесь поговорить со мной напрямую, меня часто можно найти на libera.chat., @timemage