В мире встраиваемых систем часто возникает задача: собрать данные о температуре из множества точек, но при этом свести к минимуму количество проводов в жгуте. Решение есть — это фирменный интерфейс SMAART Wire™ от Texas Instruments и семейство цифровых датчиков TMP107TMP107-Q1.
Эта статья — подробный гид по технологии, который поможет вам с нуля разобраться в протоколе, подключении, адресации и программировании этих датчиков.
1. Интерфейс SMAART Wire™: Один провод для всего
SMAART Wire™ — это фирменный последовательный протокол связи от Texas Instruments. По своей сути это полудуплексный UART, работающий по одному проводу. Это означает, что данные передаются в обе стороны, но не одновременно, и для этого используется всего одна сигнальная линия.
1.1 Ключевые особенности:
-
Топология «Daisy-Chain» (последовательная цепь): датчики подключаются друг за другом, как в гирлянде.
-
Масштабируемость: Поддерживает до 32 устройств в одной цепи.
-
Дальность: Сигнал надежно передается на расстояние до 300 метров.
-
Автонастройка скорости (Auto-Baud): Датчик автоматически определяет скорость обмена, что упрощает настройку.
1.2 Физический уровень: всего три провода
Вся магия работает благодаря тому, что между устройствами нужны всего три проводника: DATA, VCC и GND.
Для обеспечения надежной работы на больших расстояниях Texas Instruments рекомендует простую, но эффективную схему обвязки:
-
Подтягивающий резистор (4.7 кОм): поднимает линию до логической «1», когда ни одно устройство не передает данные.
-
Резистор 100 Ом: защищает вход RX от повреждений при выбросах напряжения.
-
Резистор 10 Ом: сглаживает фронты сигналов, улучшая целостность данных.
2. Датчики семейства TMP107
Texas Instruments предлагает два основных варианта: TMP107 и его автомобильную версию TMP107-Q1. Оба датчика обладают внушительными характеристиками:
-
Высокая точность: без калибровки достигают ±0.4°C в диапазоне от -20°C до +70°C.
-
Высокое разрешение: 14 бит, что дает шаг в 0.015625°C.
-
Широкий диапазон: работают от -55°C до +125°C.
-
Широкий диапазон питания: от 1.7 В до 5.5 В.
3. Топология Daisy-Chain: Как это работает
В топологии «Daisy-Chain» (последовательная цепь) каждый датчик имеет два порта ввода-вывода (I/O1 и I/O2). Сигнал от хоста (вашего микроконтроллера) проходит через первый датчик, который ретранслирует его дальше, и так до конца цепи.
Главное преимущество такого подхода — автоматическое назначение адресов. Каждому датчику присваивается уникальный 5-битный адрес, который зависит исключительно от его физического положения в цепи.
4. Адресация и EEPROM: Сердце системы
4.1 Структура памяти
Каждый датчик TMP107 оснащен встроенной EEPROM, которая используется для нескольких целей:
- <p ">Хранение настроек: конфигурация, верхние и нижние температурные пороги (Trip Level Programming).
-
Уникальная адресация: здесь хранится тот самый 5-битный адрес, о котором мы говорили.
-
Пользовательское хранилище: 8 ячеек по 16 бит (всего 16 байт) полностью в вашем распоряжении. Вы можете хранить там что угодно: серийный номер, калибровочные коэффициенты, пользовательские настройки.
4.2 Важный нюанс: Где же адрес?
Адрес датчика хранится в служебной области EEPROM, которая недоступна для прямого чтения или записи пользователем. Вы не найдете регистра, прочитав который, получите адрес. Это сделано для надежности и защиты от случайного изменения. Вы можете лишь запустить процесс, который заново назначит адреса всем датчикам.
4.3 Запись в пользовательскую EEPROM
Чтобы записать данные в доступные вам 8 ячеек (адреса 0x06–0x0D), нужно выполнить специальную процедуру:
-
Разблокировать EEPROM для записи, установив бит
NUS(бит 0 в регистре температуры) в1. -
Записать нужные данные.
-
Заблокировать EEPROM обратно, записав в
NUS0. Это защитит память от случайных повреждений.
5. Процедура инициализации адресов
Это ключевой момент в настройке системы. Процедура инициализации — это "перепись населения" в вашей цепи датчиков.
5.1 Как это происходит
-
Хост (Arduino) отправляет калибровочный байт
0x55для определения скорости. -
Затем отправляется команда
Address Initialize(байт0x95). -
Далее следует байт, который назначает адрес первому устройству (например,
0x85для адреса 8). -
Хост "отпускает" шину и ждет ответа. Каждый датчик по очереди отвечает своим новым 5-битным адресом.
5.2 Когда нужно запускать инициализацию?
-
При первой сборке: это обязательный шаг для присвоения адресов.
-
После замены датчика: новый датчик имеет заводской адрес
0h, что нарушит уникальность адресов в цепи. -
После изменения порядка датчиков: их адреса должны соответствовать новому положению в цепи.
5.3 Важное предостережение
Инициализацию не нужно запускать при каждом включении питания! Адреса сохраняются в EEPROM и загружаются при каждом сбросе. EEPROM имеет ограниченный ресурс циклов записи, поэтому частая переинициализация может привести к преждевременному износу датчиков.
6. Практика: Arduino и библиотека SmaartWire
Для работы с датчиками TMP107 в среде Arduino существует готовая библиотека SmaartWire от разработчика Jan Gromeš.
6.1 Базовый код для работы с 15 датчиками
// ============================================================ // Базовый код для работы с 15 датчиками TMP107 // ============================================================ #define NUMBER_OF_SENSORS 15 // Количество датчиков #define DATA_PIN 4 // Пин для линии DATA #include <SmaartWire.h> // Создаём объект SmaartWire smaartWire(DATA_PIN); byte sensorAddresses[NUMBER_OF_SENSORS]; // ------------------------------------------------------------ // Инициализация адресов // ------------------------------------------------------------ void initSensorAddresses() { Serial.println("Инициализация адресов..."); // 1. Калибровочная фаза smaartWire.write(0x55); // Калибровочный байт[reference:48] // 2. Команда Address Initialize smaartWire.write(0x95); // Команда инициализации[reference:49] smaartWire.write(0x0D); // Address Assign // 3. Чтение назначенных адресов for (int i = 0; i < NUMBER_OF_SENSORS; i++) { // Адрес хранится в битах [7:3] sensorAddresses[i] = (smaartWire.read() & 0b11111000) >> 3; } delay(1250); // Вывод адресов for (int i = 0; i < NUMBER_OF_SENSORS; i++) { Serial.print("Датчик "); Serial.print(i); Serial.print(" -> адрес: 0x"); Serial.println(sensorAddresses[i], HEX); } } // ------------------------------------------------------------ // Чтение температуры // ------------------------------------------------------------ float readTemperature(byte address) { // Калибровочная фаза smaartWire.write(0x55); // Команда индивидуального чтения smaartWire.write(0x02 | (address << 3)); // Individual Read[reference:50] // Указатель на регистр температуры (0x00) smaartWire.write(0x00 | 0xA0); // Чтение двух байтов byte lsb = smaartWire.read(); byte msb = smaartWire.read(); // Преобразование 14-битного значения int raw = (msb << 6) | (lsb >> 2); // Если отрицательная температура (бит 13 = 1) if (msb & 0x80) { raw = ~((msb << 6) | (lsb >> 2)) + 1; raw &= 0x3FFF; return (float)raw * -0.015625; } else { return (float)raw * 0.015625; } } // ------------------------------------------------------------ // setup() // ------------------------------------------------------------ void setup() { Serial.begin(9600); smaartWire.begin(9600); // Инициализация адресов (выполняется один раз!) initSensorAddresses(); } // ------------------------------------------------------------ // loop() // ------------------------------------------------------------ void loop() { for (int i = 0; i < NUMBER_OF_SENSORS; i++) { float temp = readTemperature(sensorAddresses[i]); Serial.print("Датчик "); Serial.print(i); Serial.print(": "); Serial.print(temp, 2); Serial.println("°C"); } Serial.println("---"); delay(1000); }
6.2 Улучшенный подход: инициализация по команде
Чтобы не изнашивать EEPROM датчиков, лучше выполнять инициализацию только по необходимости. Для этого можно добавить проверку флага в EEPROM самого Arduino:
#include <EEPROM.h> #define EEPROM_INIT_FLAG_ADDR 0 bool isAddressesInitialized() { return EEPROM.read(EEPROM_INIT_FLAG_ADDR) == 0xAA; } void setAddressesInitialized() { EEPROM.write(EEPROM_INIT_FLAG_ADDR, 0xAA); } void setup() { // ... if (!isAddressesInitialized()) { initSensorAddresses(); setAddressesInitialized(); } // ... }
7. Заключение
Интерфейс SMAART Wire™ и датчики TMP107 — это мощное и гибкое решение для построения распределенных систем сбора температуры. Возможность подключить до 32 датчиков по трем проводам на расстояние до 300 метров, автоматическая адресация и наличие пользовательской EEPROM делают эту технологию идеальной для промышленной автоматизации, систем климат-контроля и многих других применений.