Как пощупать батарею по SMS

Тема в разделе "Глядите, что я сделал", создана пользователем andrei.mejov, 5 янв 2019.

  1. andrei.mejov

    andrei.mejov Нерд

    Привет всем!

    Решил поделиться собственной поделкой, которую, будучи человеком с относительно кучерявыми руками(и без паяльника), сумел-таки изготовить. Получилось простое, но работающее и практически полезное устройство.

    Итак, вводная:
    • не очень хорошо работающий котел в частном доме
    • уже начавшийся отопительный сезон, который надо пройти с тем что есть, оперативно реагируя на отключение отопления
    • ваш покорный слуга, практически без никаких навыков по железу
    В итоге, решил попробовать реанимировать свою же собственную, заброшенную, идею с контролем температуры отопления по SMS, собрав все на arduino с максимальным использованием готовых модулей и с минимальной работой руками.

    Состав "изделия" у меня получился следующим:
    • Iskra Neo
    • GRPS Shield
    • светодиод зеленый
    • пара резисторов (один в цепь к светодиоду на 220 Ом, второй, на 4.7кОм - к датчику температуры)
    • датчик температуры DS18B20
    • макетная плата для соединения без пайки
    • 3 одножильных провода "папа-мама", которые пошли на изготовление удлинителя для датчика температуры (единственное место где есть пайка)
    • пищевой контейнер в качестве корпуса
    • microUSB зарядка как блок питания
    • несколько болтов с гайками м3 и капроновых стяжек для фиксации внутри корпуса искры с шилдом, макетной платы и кабеля от зарядки с удлинителем.
    Схема получилась примерно такая, с поправкой на то, что в реальном устройстве сверху устанавливается GPRS шилд, через который уже идут все соединения:
    [​IMG]

    Вид в сборе без крышки:
    [​IMG]

    Все максимально просто, на основе примеров по каждому компоненту. Датчик снимает температуру с батареи, зеленый светодиод мигает, сигнализируя о нормальной работе основного цикла программы.При наличии SMS запроса формируется ответ со снятой температурой, при падении температуры ниже 30 (если до этого она поднималась выше) посылается SMS с предупреждением на номер забитый в скетче.

    Скетч:
    Код (C++):
    #include <GPRS_Shield_Arduino.h>
    #include <sim900.h>
    #include <OneWire.h>

    #define DEBUG 1
    #define ALERT_TEMP 30.0
    #define ALERT_PHONE "___"
    #define ALERT_PHONE_2 "___"

    OneWire ds(10);
    GPRS gprs(Serial1);

    char _message[160];
    char _phone[16];
    char _datetime[24];

    int alert_control = 0;

    void led_ok() {
        digitalWrite(12, HIGH);
        delay(1000);
        digitalWrite(12, LOW);
    }

    double get_term() {
        byte i;
        byte present = 0;
        byte type;
        byte data[12];
        byte addr[8];
        if (!ds.search(addr)) {
        if (DEBUG)
            Serial.println("No more adresses.");
            ds.reset_search();
            delay(250);
            return 0.0;
        }
        if (DEBUG) {
            Serial.print("ROM =");
            for (i = 0; i < 8; i++) {
                Serial.print(" ");
                Serial.print(addr[i], HEX);
            }
            Serial.println("");
        }
        ds.reset();
        ds.select(addr);
        ds.write(0x44);
        delay(1000);
        present = ds.reset();
        ds.select(addr);
        ds.write(0xBE);
        if (DEBUG) {
            Serial.print("Data = ");
            Serial.print(present, HEX);
            Serial.print(" ");
        }
        for (i = 0; i < 9; i++) {
            data[i] = ds.read();
            if (DEBUG)
            Serial.print(data[i], HEX);
        }
        if (DEBUG)
            Serial.println("");
        int16_t raw = (data[1] << 8) | data[0];
        byte cfg = (data[4] & 0x60);
        if (cfg == 0x00) {
            raw = raw & -7;
        } else if (cfg == 0x20) {
            raw = raw & -3;
        } else if (cfg == 0x40) {
            raw = raw & -1;
        }

        ds.reset_search();
        double term = (double)raw / 16.0;
        if (DEBUG) {
            Serial.print("T=");
            Serial.println(term);
        }
        return term;
    }

    char* has_request_from() {
        if (gprs.ifSMSNow()) {
            delay(100);
            gprs.readSMS(_message, _phone, _datetime);

            if (DEBUG) {
                Serial.print("From number: ");  
                Serial.println(_phone);
                Serial.print("Datetime: ");
                Serial.println(_datetime);
                Serial.print("Recieved Message: ");
                Serial.println(_message);
            }
            String s = String(_message);
            if (s == String("451")) {
                return _phone;
            } else {
                return 0;
            }
        }
        return 0;
    }

    void send_term(char *into, double term, int alert) {
        char term_str[10];
        char message[12];
        dtostrf(term,2,0,term_str);
        if (alert == 0) {
            sprintf(message, "T=%s", term_str);
        } else {
            sprintf(message, "AT=%s", term_str);
        }
        if (DEBUG) {
            Serial.print("Send SMS: ");
            Serial.print(message);
            Serial.println("");
        }
        gprs.sendSMS(into, message);
    }

    void setup() {
        pinMode(12, OUTPUT);
        Serial1.begin(9600);
        if (DEBUG)
            Serial.println("Serial init OK");
        gprs.powerOn();
        while (!gprs.init()) {
            delay(1000);
            if (DEBUG)
            Serial.println("Init error");
        }
        if (DEBUG)
            Serial.println("GPRS init success");
    }

    void loop() {
        led_ok();
        double term = get_term();
        if (alert_control == 0 && term >= ALERT_TEMP) {
            alert_control = 1;
        }
        char* from = has_request_from();
        if (from != 0) {
            if (DEBUG) {
                Serial.println("Send temperature!");
            }
            send_term(from, term, 0);
        }
        if (alert_control == 1 && term < ALERT_TEMP) {
            alert_control = 0;
            send_term(ALERT_PHONE, term, 1);
            send_term(ALERT_PHONE_2, term, 1);
        }
    }
    В принципе, на этом этапе уже был весь нужный мне функционал и взаимодействовать можно было с любого телефона через SMS, отправляя "451" в тексте, но хотелось большего и была написана отдельная программка для Android, реализующая некий пользовательский интерфейс поверх все тех же SMS, номер телефона опрашиваемой симки при этом задается в настройках:

    [​IMG]

    Исходники прилагаю.

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

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

    Вложения:

    • term.zip
      Размер файла:
      136,8 КБ
      Просмотров:
      16
    alp69 нравится это.