Electric Imp — Делаем WiFi термометр

    Многие из вас знакомы с анонсом Electric Imp, который не так давно был на хабре, кроме того уже начинают появляться первые впечатления от его использования. Поскольку это устройство мне показалось перспективным и довольно интересным, я при первом появлении в продаже версии developer edition заказал себе чтобы немного поиграться и оценить возможности.


    Собираем


    Сам Electric Imp на момент покупки стоил $29.95, но чтобы начать им пользоваться придется в добавок приобрести плату, которую оценили в $19.95 (сейчас цена уменьшилась до $12.95).


    После прибытия комплекта вместо привычного “Hello, world!” моргания светодиодами решил сделать что-то более полезное. Немного пораскинув мозгами и просмотрев примеры остановился на датчике температуры. Порылся в закромах и нашел термистор 10КОм и DS18B20. С DS18B20 не сложилось так как в текущем API для Electric Imp отсутствует поддержка OneWire.
    Схема подключения термистора очень простая

    Схема подключения термистора (источник)

    Чтобы избавится от проводов, подключил аккумулятор на 750mAh, при этом на самой плате нужно джампером выставить питание от батареи. Получилось очень компактное устройство.




    Для визуального отображения температуры взял валявшийся без дела Raspberry Pi и 16х2 LCD индикатор из какого-то китайского набора.

    Схема подключения LCD 16x2 индикатора к Raspberry Pi (источник)

    Пришлось немного помучаться потому как мне попалась какая-то промежуточная ревизия малины и код с ходу не завелся. Оказалось что на плате Raspberry Pi поменяли назначение нескольких ног, одна из них как раз нужна была для подключения LCD.

    Программируем


    Код для работы с термистором довольно простой, все замечательно работает и результат можно наблюдать в планере на сайте electricimp. Теперь нужно отсылать результат туда, куда мне нужно, благо в API есть возможность слать HTTP запросы, но тут есть свои нюансы. Первым делом я попытался слать результат внутри своей локальной сети, и ничего не получил. После разбора полетов выяснилось что Imp запрос шлет не непосредственно, а через свой сервер. Выхода два, или пробрасывать порт на роутере внутрь локальной сети, или слать на свой внешний сервер, а локальным сервером периодически затягивать оттуда последние показания. Проброс портов накладывает определенные ограничения на использование, поэтому я решил поднять сервер с простеньким API на App Engine, попутно заставив его рисовать графики, что оказалось очень кстати.
    main.py
    #!/usr/bin/env python
    
    import webapp2
    import json
    import logging
    import utils
    import time
    import os
    import datetime
    
    from google.appengine.ext.webapp import template
    from google.appengine.ext import db
    
    class Sensor(db.Model):
        temperature = db.FloatProperty(required = True)
        battery     = db.FloatProperty(required = True)
        added       = db.DateTimeProperty(auto_now_add = True, indexed=True)
    
    class SensorRequestHandler(webapp2.RequestHandler):
        def post(self):
            data    = json.loads(self.request.body)
            params  = json.loads(data['value'])
            temp    = params['temp']
            battery = params['battery']
    
            sensor = Sensor(temperature = temp, battery = battery)
            sensor.put()
    
            self.response.out.write('OK')
    
        def get(self):
    
           sensors_data = Sensor.all().order('added').fetch(None)
    
            temperature_data = []
            battery_data     = []
    
            for item in sensors_data:
                temperature_data.append([int(time.mktime(item.added.timetuple()))*1000 ,round(item.temperature, 1)])
                battery_data.append([int(time.mktime(item.added.timetuple()))*1000, round(item.battery, 2)])
            
            path = os.path.join(os.path.dirname(__file__), 'templates/charts.html')
            self.response.out.write(template.render(path, {
                'temperature_data' : utils.GqlEncoder().encode(temperature_data), 
                'battery_data' : utils.GqlEncoder().encode(battery_data)
                }))
    
    class LastRequestHandler(webapp2.RequestHandler):
        def get(self):
            
            ordered_list = db.GqlQuery('select * from Sensor order by added desc limit 1')
            last = ordered_list.get()
    
            self.response.headers['Content-Type'] = 'application/json'
            self.response.out.write(utils.GqlEncoder().encode(last))
    
    class CleanRequestHandler(webapp2.RequestHandler):
        def get(self, bulk = 'old'):
            logging.debug("bulk: %s", bulk)
            try:
                while True:
                    q = Sensor.all()
    
                    if bulk != 'all':
                        q.filter('added <', datetime.date.today() - datetime.timedelta(days=60))
                    
                    assert q.count()
                    db.delete(q.fetch(200))
                    time.sleep(0.5)
            except Exception, e:
                self.response.out.write(repr(e)+'\n')
                pass
    
    
    app = webapp2.WSGIApplication([
        ('/sensor', SensorRequestHandler),
        ('/sensor/last', LastRequestHandler),
        ('/sensor/clean/?(all)?', CleanRequestHandler)
    ], debug=True)
    


    В итоге результат выглядит так:
    — Imp раз в 10 мин шлет на внешний сервер показания температуры
    — Сервер сохраняет это значение
    — Raspberry Pi раз в несколько минут подтягивает показания температуры и отображает ее на LCD дисплее.
    Параллельно с температурой решил собирать показания напряжения батареи, но оказалось что функция из API возвращает напряжение с самой платы (~ 3.25В).
    К сожалению текущие возможности выполнения HTTP запроса сильно ограничены, поэтому пришлось извратиться и паковать данные в JSON, который в свою очередь второй раз пакуется в JSON уже внутри HTTPRequest ноды.
    class Termistor
    {
        pin_num = null;
        
        constructor(pin){
            pin_num = pin
            hardware["pin" + pin_num].configure(ANALOG_IN);
        }
        
        function read(){
            return hardware["pin" + pin_num].read();
        }
        
        function getTemperature(){
            local temp = math.log(((655350000/read()) - 10000));
            temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * temp * temp ))* temp );
            temp = temp - 273.15;
            return temp;
        }
    }
    
    local sensor = Termistor(9);
    
    local output = OutputPort("Temperature", "string");
    
    imp.configure("Termistor 10K", [], [output]);
    
    function capture(){
        imp.wakeup(600.0, capture);
        local temp = sensor.getTemperature();
        local jsonOut = "{\"temp\":"+temp+", \"battery\":"+hardware.voltage()+"}";
        output.set(jsonOut);
        server.show(format("%1.1fºC", temp));    
    }
    
    capture();
    
    imp.sleep(2.0)
    
    server.sleepfor(600.0)
    


    Пожинаем плоды


    Графики стабильно строятся, выглядят так:


    Raspberry Pi выводит температуру


    Для более наглядной демонстрации снял небольшое видео (рекомендую смотреть в 720p и во весь экран):


    Энергосбережение


    Imp может запускаться в трех режимах

    Отключенный powersave mode (по умолчанию)


    В этом режиме WiFi модуль всегда включен. Это способствует низким сетевым зажержкам но приводит к высокому потреблению тока ~60-80мА для 3.3В

    Включенный powersave mode


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

    Глубокий сон


    В этом режиме Imp отключается от WiFi сети, перестает выполнять код, теряет контекст (кроме данных в специальной nv таблице) и переходит в режим очень низкого электропотребления (~6мкА). Вывести из сна может либо предварительно взведенный таймер, или wake-up пин. Старт и подключение к WiFi сети занимает около 2с.

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

    750/24*3 ~ 10 мА, что соответствует включенному powersave режиму.

    В режиме глубокого сна в качестве датчика температуры Imp трудится уже месяц, и напряжение упало с 4.2 до 3.68, то есть LiPo батареи на 750mAh должно хватить приблизительно на полтора месяца, что не может не радовать.

    Планы


    Добавить честный измеритель напряжения батареи (что особо актуально для LiPo батарей), прикрутить солнечную батарею и, пока особых планов нет, использовать как местный датчик температуры в одном из энтузиастских погодных проектов. Также возможно добавлю счетчик Гейгера.

    Вывод


    Устройство вышло очень интересным и перспективным, но на данный момент сильно ограничивает область применения жесткая привязка к собственным серверам Electric Imp и скудность API. Если предположить что эти недостатки будут исправлены, то Imp идеально подходит для применения совместно с различными сенсорами в системах умного дома.

    Полезные ссылки


    1. Исходный код на github
    1. Arduino + termistor
    2. Electric Imp Wiki
    3. Drive a 16x2 LCD with the Raspberry Pi

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 20

      +1
      У нас в декабре под минус 20, не как у вас :)
        +3
        Пока что это в квартире.
        0
        Можно усложнить задачу использованием цифрового датчика.
          0
          Это можно будет сделать не раньше появления поддержки 1-wire в Imp.
            0
            А что цифровых датчиков с другими интерфейсами нет? I2C SPI…
              0
              Есть, хотя судя по всему они не так сильно распространены.
                0
                Да в общем нет. Я использовал следующие:

                I2C:
                SHT21
                BMP085

                SPI:
                MPL115

                На китайских магазинах можно найти отладочные платы.
                  0
                  Я смотрел в местных магазинах, есть термисторы на любой вкус и DS18B20. То что в китайских магазинах можно найти все что угодно я не сомневаюсь :)
                    0
                    MPL115 это скорее термокомпенсированный барометр, тогда можно взять любой МК с термосенсором и подключить по любому интрефесу :)

                    UPD похоже это все не совсем датчики температуры, а интегрированные решения
            +2
            Понравилась Ваша реализация, не против добавить свою разработку в каталог устройств Народного мониторинга?

            Надо только немного «допилить» передачу показаний датчиков на Народный мониторинг дабы отображать показания еще и на карте будто браузер на ПК, планшете, текстовой мобильной версии, десктоп-трей-утилите для windows/wine и в скором будущем Андройд приложении. Протокол доступен на сайте участникам проекта.

            PS Все чаще и чаще обращаются с вопросами беспроводной реализации устройств замера и передачи данных. Ваша реализация вполне привлекательна в т.ч. и по цене на фоне завышенных цен на фирмовые устр-ва wifi.

              0
              Судя по всему это будет сделать достаточно просто потому как у Imp есть возможность напрямую общаться с cosm.com. Как только вынесу датчик на улицу, сразу же попробую добавить.
                0
                У меня тож есть 1 девайс с Cosm — CurrentCost EnviR, заранее предупреждаю, что их триггер работает порой нестабильно, т.е. порой данные не отправляются. В саппорт Cosm писал неоднократно — извинялись и обещали все исправить КТТС.
                +2
                Добавил отправку показаний с минимальными изменениями в коде.
                cosm.com/feeds/94900
                Осталось вынести на улицу и добавить датчик в народный мониторинг.
                  0
                  Отлично, как добавить устр-во с Cosm на сайте тож описано. Ну и в паблик вывести не забудьте уличный.
                0
                Потребление в режиме: «глубокий сон» впечатляет, можно использовать массив автономных датчиков для сбора сведений о состоянии чего либо крупного. Каково минимальное напряжение питания устройства?
                  0
                  Требуемое напряжение — 3.3В (в режиме работы от батареи)
                  0
                  Вся эта проприетарщина обречена. Через 3 года стартап помрет (вместе с их серверами) аль еще что — и весь рой железа придется выбрасывать.
                    +1
                    Есть надежда что появятся открытые аналоги, тогда да, в таком виде как сейчас жить не будет.
                      0
                      Не сочтите за некропостинг, но что-нибудь добавилось у производителя этих микродемонов? Появились ли аналоги?
                        0
                        Давно перестал активно следить, но периодически получаю рассылки и там мелькают изменения в API и новые фичи. Плюс ребята активно участвуют на различных DIY ярмарках, так что похоже развиваются и дальше.

                        Из аналогов — некоторые появились, некоторые вот-вот появляются, например Intel Edison, Spark Core, те же Arduino с встроенным WiFi.

                  Only users with full accounts can post comments. Log in, please.