Arduino скетч для работы с MQTT брокером. В этом скетче используется датчик температуры LM19 и 3-и relay модуля.

/*
 Arduino MQTT Relay Contorol
 В качестве датчика температуры в данном примере используется LM19.

*/

#include <SPI.h>
#include <Ethernet.h>
#include <PubSubClient.h>

byte mac[]    = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xFF };
char macstr[] = "deadbeeffeff";
byte ip[] = {192, 168, 0, 179 };
byte gateway[] = { 192, 168, 0, 1 };
byte subnet[] = { 255, 255, 255, 0 };


String clientName = String("arduino-179_") + macstr;
String topicTempName = String("/ard-179/temperature1");

// mqtt брокер
#define mqtt_server "192.168.0.170"
// порт подключения к mqtt
#define mqtt_port 1883
// Длинна имени топика обязательно 15 символов, для этого примера, иначе внести изменения в функцию callback()
#define mqtt_topic1 "/ard-179/relay1"
#define mqtt_topic2 "/ard-179/relay2"
#define mqtt_topic3 "/ard-179/relay3"


float tempF = 0.0;
float tempC = 0.0;
float humidity = 0.0;

EthernetClient ethClient;

PubSubClient client(ethClient);


const int domRelay1 = A1;
const int domRelay2 = A2;
const int domRelay3 = A3;

long lastMsg = 0;


void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic); // отправляем в монитор порта название топика
  Serial.print("] ");
  for (int i = 0; i < length; i++) { // отправляем данные из топика
    Serial.print((char)payload[i]);
  }
  Serial.println();

// работаем с реле

  if (topic[14] == '1') { // 15-ый символ массива номер реле
    if (payload[0] == '0') digitalWrite(domRelay1, LOW);
    else if (payload[0] == '1') digitalWrite(domRelay1, HIGH);
    else if (payload[0] == '2') digitalWrite(domRelay1, !digitalRead(domRelay1));
//    Serial.println("Relay1");
  } else if (topic[14] == '2') {
    if (payload[0] == '0') digitalWrite(domRelay2, LOW);
    else if (payload[0] == '1') digitalWrite(domRelay2, HIGH);
    else if (payload[0] == '2') digitalWrite(domRelay2, !digitalRead(domRelay2));
//    Serial.println("Relay2");
  } else if (topic[14] == '3') {
    if (payload[0] == '0') digitalWrite(domRelay3, LOW);
    else if (payload[0] == '1') digitalWrite(domRelay3, HIGH);
    else if (payload[0] == '2') digitalWrite(domRelay3, !digitalRead(domRelay3));
//    Serial.println("Relay3");
  }


}


// подключение к mqtt брокеру

void reconnect() {
  while (!client.connected()) { // крутимся пока не подключимся.
    Serial.print("Attempting MQTT connection...");

    char clientStr[34];
    clientName.toCharArray(clientStr,34);

    // подключаемся, в client.connect передаем ID, логин и пасс
    if (client.connect(clientStr)) {
      Serial.println("connected"); // если подключились
      client.subscribe(mqtt_topic1); // подписываемся на топик 1-го реле, в который же пишем данные
      client.subscribe(mqtt_topic2); // подписываемся на топик 2-го реле, в который же пишем данные
      client.subscribe(mqtt_topic3); // подписываемся на топик 3-го реле, в который же пишем данные
    } else { // иначе ругаемся в монитор порта  
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Ждем 5 секунд до следующей попытки

        delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);

  pinMode(domRelay1, OUTPUT);
  digitalWrite(domRelay1, LOW);
  pinMode(domRelay2, OUTPUT);
  digitalWrite(domRelay2, LOW);
  pinMode(domRelay3, OUTPUT);
  digitalWrite(domRelay3, LOW);

  Ethernet.begin(mac, ip);

  client.setServer(mqtt_server, mqtt_port); // указываем адрес брокера и порт
  client.setCallback(callback); // указываем функцию которая вызывается когда приходят данные от брокера
}


void loop() {

  if (!client.connected()) { // проверяем подключение к брокеру
    reconnect();
  }
  client.loop();

  long now = millis(); // каждые 10 секунд выполняем публиукцию температуры на брокере
  if (now - lastMsg > 10000) {
    lastMsg = now;
    getTemperatureData();

    String json = buildJson();
    char jsonStr[200];
    json.toCharArray(jsonStr,200);

    char topicStr[26];
    topicTempName.toCharArray(topicStr,26);

    boolean pubresult = client.publish(topicStr,jsonStr);
    Serial.print("attempt to send ");
    Serial.println(jsonStr);

  }

}


/////////////////////////////////////////////////////////

String buildJson() {
  String data = "{";
  data+= "\"d\": {";
  data+="\"SensorName\": \"LM19\",";
  data+="\"temperature\": ";
  data+=(float)tempC;
  data+= ",";
  data+="\"humidity\": ";
  data+=(float)humidity;
  data+="}";
  data+="}";

  return data;
}


void getTemperatureData() {
  float vin = 5.0 * analogRead(0) / 1024.0;
  tempC = (1.8663 - vin) / 0.01169;
  tempF = 1.8 * tempC + 32.0;
}

Дополнительно. Работа с датчиком LM19

LM19 является аналоговым датчиком температуры, который работает в определенном температурном диапазоне (от -55 до 130 по Цельсию). Его очень легко связать с микроконтроллером благодаря достаточно линейному выходному напряжению.

В следующем листинге кода показано, как получить показания температуры с датчика LM19 на Arduino. Код предполагает, что выход датчика подключен к аналоговому контакту 0.

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    float vin = 5.0 * analogRead(0) / 1024.0;
    Serial.print(vin);
    Serial.print("  ");
    float tempC = (1.8663 - vin) / 0.01169;
    float tempF = 1.8 * tempC + 32.0;
    Serial.print(tempC);
    Serial.print("  ");
    Serial.println(tempF);
    delay(100);
}

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

smarthouse_lm19_sensor_pic1

Для более точного измерения температуры во всем рабочем диапазоне можно использовать следующее уравнение:

smarthouse_lm19_sensor_pic2

Ссылки