Сделать какой-нибудь беспроводный датчик, содержащий барометр, термометр, гигрометр или все в одном флаконе, с питанием от 220В — это не проблема. А вот запитать такое устройство от батареек или аккумуляторов уже интереснее. Ну а если это будет дисковая литиевая батарейка (таблетка) — вообще здорово, потому как устройство получится весьма компактным.
Единственным препятствием для использования «таблетки» является ее небольшая емкость. Но и среди «таблеток» есть вполне подходящие экземпляры, например CR2450, с заявленной емкостью 550-610 мАч.
Поскольку на момент изготовления устройства у меня уже был готовый комнатный и уличный датчики температуры и влажности, то я решил сделать Lighting-sensor на основе BH1750 и разместить его на балконе, дополнительно снабдив его датчиком температуры DS18B20.
Так как у меня все окна выходят на юг, то уличный датчик температуры и влажности подвержен значительному влиянию солнечных лучей, данное влияние приходится компенсировать за счет погодных данных получаемых из интернета, в дальнейшем, я планирую использовать информацию об уровне освещения для расчета компенсации.
Для максимального снижения потребляемой датчиком энергии было решено:
1. Отказаться от использования готовой Ардуинки и использовать непосредственно микроконтроллер ATmega 328P-PU с кварцем на 8МГц,. От использования внутреннего RC- генератора я отказался, т.к. из-за значительных перепадов внешней температуры, рабочая частота получается не стабильной.
2. Использовать библиотеку LowPower и задействовать для контроллера режим энергосбережения LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF)
3. Датчик DS18B20 запитать от цифрового вывода микроконтроллера и включать его непосредственно перед замером.
4. Радиомодуль и BH1750 запитать напрямую, использовав при этом, режимы энергосбережения, radio.powerDown() и Light.configure(BH1750_ONE_TIME_HIGH_RES_MODE) соответственно.
Вооружившись программатором USBasp,

прошил в контроллер фьюзы ну и конечно же загрузчик. Собрал прототип, набросал тестовый скетч и замерил потребляемые токи: в режиме сна получилось 14мкА, в режиме снятия показаний с датчиков — 3-4мА, в режиме передачи данных через nRF24 на метеостанцию — 16-18мА. С учетом того, что снимать показания с датчиков решил 1 раз в 3 минуты, а передавать раз в 10 минут — сенсор получается весьма экономичным.
Для изготовления конечного устройства использовал кусочек макетной платы и провод МГТФ. В результате вот что получилось:

Для контроля за состоянием батарейки используем встроенные возможности ATmega, хорошо описанные в этой статье.
Процесс прошивки загрузчика и фьюзов подробно освещен тут и тут.
Общая идея создания автономного сенсора позаимствована на сайте maniacbug.

Датчик уже второй месяц лежит (и работает) на балконе на подоконнике, исправно отправляет данные. Контроль питания сообщает о том, что за это время напряжение источника снизилось с 3,05V при первом включении до 2,98V. Однако днем, когда солнце прогревает балкон, напряжение может подняться вплоть до 3,00V. Жду холодов, посмотрим как покажет себя выбранная батарейка при отрицательных температурах.
При выбранной продолжительности режима sleep, получается что сенсор бодрствует всего 492-495 сек за 24 часа.
Устройство в сборе, но к сожалению пока без корпуса, не могу найти подходящий


Исходный код
#include <LowPower.h>
#include <SPI.h>
#include <RF24Network.h>   
#include <RF24.h>          
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Wire.h>
#include <BH1750.h>
/////// Сlass AVG //////////////////////////////////////////////////////////
class AVG {
  #define DEPTH_AVG 10
  private :
     int depth;
     long *mas;
     int cur;
     boolean first;
  public :
     boolean fDebug;  

  AVG(int d)
  {
    if( d == 0 || d > DEPTH_AVG)depth = DEPTH_AVG;
    else depth = d;
    mas = (long *)malloc(sizeof(long)*depth);
    first = true;
    cur   = 0;
    fDebug = false;
  }
  void Set(long x)
  {
    if( first )
    {
       for( int i=0; i<depth; i++ )mas[i] = x;
       cur = 0;
    }
    else
    {
    mas[cur++] = x;
    if( cur >= depth ) cur = 0; 
    }
    first = false;  
  }
  long Get()
  {
    long x=0;
    for( int i=0; i<depth; i++ )
          {
            x+=mas[i];
          }
    x/=depth;
    return(x);
  }
};
/////////////////////////////////////////////////////////////////////
#define pinPowerSensor 4    //Питание сенсора подключаем к Pin 4
#define ONE_WIRE_BUS 3
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
BH1750 Light;
RF24 radio(/*ce*/ 9, /*cs*/ 10);
RF24Network network(radio);
// Адрес нашего узла
uint16_t this_node = 02;
// Адрес, куда по умолчанию сливаем показания
uint16_t main_node = 0;
// Номер канала
const int Chanel = 11;
int ReadCount;
int iSend     = 3;    // Интервал отправки показаний 
int WaitCount = 24;   // Количество циклов сна по 8 сек.
bool allowSend = false; //признак разрешения на отправку
AVG vAVG(3);
AVG tAVG(3);
AVG lAVG(3);
struct StreetMeteoSensor
{
  char    ID[5];     //ИД устойства
  unsigned long UpTime;
  int   T;           //Температура
  long  L;           //Освещенность  (Lx) 
  int   V;           //уровень заряда батарейки (mV)
};
struct StreetMeteoSensor sensor;
RF24NetworkHeader header(main_node, 'I');
////////////////////////////////////////////
#define DEBUG_MODE     0
////////////////////////////////////////////
void setup(void)
{
    if (DEBUG_MODE) 
  {
    Serial.begin(115200);
    //tAVG.fDebug = true;  
    //lAVG.fDebug = true;      
    Serial.println("-- START --");  
    WaitCount = 5;
  }
  for (int i = 1; i < 15; i++)  
  {
    pinMode(i, OUTPUT);
    digitalWrite(i,LOW);
  }
  digitalWrite(pinPowerSensor,HIGH);
  char ID[5] = "LTS1";
  memcpy(sensor.ID, ID, 5);  
  ReadCount = iSend;
  SPI.begin();
  delay(500);
  radio.begin();
  network.begin( Chanel, this_node );  
  sensors.begin();  
  Light.begin(BH1750_ONE_TIME_HIGH_RES_MODE);
  delay(500);
  radio.powerDown();    
  digitalWrite(pinPowerSensor,LOW);  
  Light.configure(BH1750_POWER_DOWN);
  if (DEBUG_MODE)  Serial.println("-- End SETUP --"); 
}

void loop(void)
{
  //считываем значения датчиков
 if (DEBUG_MODE) Serial.println("data read...");
  // Для BH1750 используем собственный режим энергосбережения, 
  Light.configure(BH1750_POWER_ON);                    // Включаем сенсор
  Light.configure(BH1750_ONE_TIME_HIGH_RES_MODE);     // Устанавливаем режим измерений
  digitalWrite(pinPowerSensor,HIGH);                  // Подаем питание на DS18B20
  sensors.setResolution(TEMP_9_BIT);   
  delay(250); 
  sensors.requestTemperatures();
  int T = sensors.getTempCByIndex(0);
  digitalWrite(pinPowerSensor,LOW);  // Отключаем питанеи DS18B20
  long L = Light.readLightLevel();  //Режим ONE_TIME автоматически отключает питание
  int V = readVcc();  
  /////////////////////////////////////////////////////////////
  int tt = tAVG.Get();
  int vv = vAVG.Get();
  long ll = lAVG.Get();
  if (L > 0 || ll > 0 || T < tt-2 || T > tt+2 || V < vv-100/*0.1V*/) 
  { // уменьшим кол-во передач в темное время
    tAVG.Set(T);
    lAVG.Set(L);
    vAVG.Set(V); 
    allowSend = true;     //Есть что отправить - Взведем флаг
    // Если освещенность изменилась с 0 (рассвет)
    if (ll == 0 &&  L > 0)
      lAVG.Set(L);  
  }
  ReadCount++;        
  /////////////////////////////////////////////////////////////
  if (DEBUG_MODE)
  {
    Serial.print("T= ");
    Serial.print(tAVG.Get());
    Serial.print(": ");
    Serial.print(T);    
    Serial.print("; L= ");
    Serial.print(lAVG.Get());
    Serial.print(": ");    
    Serial.print(L);    
    Serial.print("; V= ");
    Serial.print(vAVG.Get());
    Serial.print(": ");    
    Serial.print(V);        
    Serial.print("; ReadCount= ");    
    Serial.println(ReadCount);
  }  
  /////////////////////////////////////////////////////////////
  // считаем количество выполненных замеров
  if ( ReadCount >= iSend && allowSend )
  {
    // Отправка данных на базовый узел
    ReadCount = 0;
    allowSend = false;   
    radio.powerUp();
    delay(50);
    sensor.T = tAVG.Get();  
    sensor.L = lAVG.Get();
    sensor.V = vAVG.Get();    
    sensor.UpTime = millis()/1000;     
    network.write(header,&sensor,sizeof(sensor));
    radio.powerDown();  
  }    
  sleep();
}
// Переводим устройство в режим низкого энергопотребления
void sleep()
{
  if (DEBUG_MODE) {Serial.println("----- SLEEP -----");Serial.flush();}
  for (int i = 0; i < WaitCount; i++)  //впадаем в спячку 
  {
    LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); 
  }
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Измерение напряжения питания
int readVcc() 
{
  int result;
  // Read 1.1V reference against AVcc
  // set the reference to Vcc and the measurement to the internal 1.1V reference
  ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
  delay(75); // Wait for Vref to settle
  ADCSRA |= _BV(ADSC); // Start conversion
  while (bit_is_set(ADCSRA,ADSC)); // measuring
  result = ADCL;
  result |= ADCH<<8;
  if (DEBUG_MODE) {Serial.print("result=");Serial.println(result);}
  result =  1125300L / result; // (Kvcc * 1023.0 * 1000) (in mV);
  return result; 
}

Комментарии (39)


  1. Rumlin
    12.10.2015 08:55
    +2

    А почему бы солнечную батарею с аккумулятором/ионистором не поставить и забыть о датчике навсегда?


    1. Alexeyslav
      12.10.2015 09:12

      Аккумуляторы дохнут со временем, солнечная батарея деградирует. Экономически оправдано просто менять батарейки. Раз в год или около того.


      1. Rumlin
        12.10.2015 10:57

        По цене Яндекс маркет показывает цены CR2450 от 30 р до 875(!!!) р. У китайцев — 1,7$.
        Liion аккумулятор 100mAh — 2,9$
        Думаю аккумулятор продержится намного дольше CR2450.


        1. Alexeyslav
          12.10.2015 11:09

          Литиевый аккумулятор выдержит суровую зиму? -20 градусов… или летнюю жару, когда внутря прогреваются до 70 градусов.


          1. Rumlin
            12.10.2015 11:28

            Откуда +70? Белая коробка с вентиляционными отверстиями не прогреется намного выше воздуха в тени.
            У аккумуляторов обычно диапазон рабочих температур от -25..20 до +60 градусов Цельсия.


            1. Alexeyslav
              12.10.2015 14:39

              У меня обычный металлический козырёк подоконника нагревается так что рукой прикоснуться невозможно. Кроме отверстий в коробе, нужно еще обеспечивать движение воздуха. В штиль и без принудительной тяги считай что отверстий и нет.
              Кроме того, пластик этих коробов, даже якобы стойкий для наружного применения рассыпается чуть ли не в пыль через год-два на солнце и даже довольно щадящим перепадом температур воздуха(-15...+30). Стоят только металлические короба, и на тех краска облупливается и они начинают ржаветь — т.е. необходимо периодическое обслуживание.


              1. Rumlin
                12.10.2015 15:45

                Нагревается верхняя поверхность. Передать тепло вниз сложно:

                • конвекция вниз не передает — теплый воздух выходит через отверстия вверх
                • теплопроводимость воздуха очень низкая — передачи вниз не будет


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


                1. Alexeyslav
                  12.10.2015 15:58

                  Зато замечательная конвекция идет от нагретой стены дома… если этаж не первый, температура растёт.


                  1. Rumlin
                    12.10.2015 16:23

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

                    В идеале как психрометрическая будка
                    image

                    Психрометрическая будка сконструирована таким образом, чтобы резервуары термометров и других приборов находились на уровне двух метров — в приземном слое воздуха. Дверца будки всегда обращена на север.
                    Будка служит для защиты приборов от осадков, сильного ветра и солнечной радиации. Она выкрашена в белый цвет и имеет специальные жалюзи.


                1. gleb_l
                  12.10.2015 23:58

                  Поставить микровентилятор и продувать им блок снизу вверх лишней энергией от СБ )


          1. av0000
            12.10.2015 11:35

            Литиевый аккумулятор не заряжается в отрицательные температуры.

            Я пытался выбрать между LiFePo (только они заряжаются в минусовых температурах) и ионисторами для своей поделки, но пока забросил. Ионистор проще заряжать, но меньше ёмкость и выше цена. LiFePo, вроде, дешевле в пересчете на емкость, но не было дешевых и мелких решений по зарядке (для литиевых есть неплохой вариант TP4056, а для LiFePo не нашлось)


      1. shtirlitsus
        12.10.2015 11:05
        +1

        А есть где почитать про деградацию солнечной батареи? у меня 2 зимы пережил беспроводной термометр с ионистором


        1. Alexeyslav
          12.10.2015 11:13

          2 зимы еще незаметно, вот лет через 5 можно будет заметить что батарея отдаёт меньше энергии чем прежде. Но в суровых условиях заметить это будет трудно — она ведь и так работает с огромным запасом.
          Чтобы заметить деградацию, необходимо измерять её параметры (ток К.З.) при строго известной освещенности. Через 5...10 лет возможно заметите что батареи уже не хватает на зимнюю продолжительность дня, например.


          1. Rumlin
            12.10.2015 11:28

            За 10 лет это сколько денег уйдет на CR2450? А тут один раз в 10 лет и может у новых деталей характеристики будут еще лучше.


            1. avs24rus
              12.10.2015 13:07

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


              1. Rumlin
                12.10.2015 13:51

                Как вариант NiCd — самые морозоустойчивые. Вопрос только в реализации схемы заряда во избежание эффекта памяти…

                Хотя может просто не так часто опрашивать датчики, хотя бы ночью. А днем пользоваться солнечной батарей.


                1. isden
                  12.10.2015 14:03
                  +1

                  > NiCd

                  Еще можно попробовать компактные свинцовые гелевые аккумуляторы. Не будет характерных для NiCd проблем.


                  1. shtirlitsus
                    13.10.2015 11:33

                    Ионистор вполне справляется. Запас по эффективности заложить и счастье будет.


                    1. isden
                      13.10.2015 11:44

                      А в нем заряда, скажем, на ночь + пасмурный день (а то и два-три) хватит? И по габаритам как?


                      1. Alexeyslav
                        13.10.2015 12:00

                        Ионисторы гораздо больше по размерам чем аккумуляторы.

                        Можно легко посчитать. Требуемое время определяется емкостью ионистора в ватт-часах на необходимом диапазоне напряжений(контроллер при 1 вольте уже не будет работать, хотя энергии в ионисторе будет еще дофига) поэтому перед рассчетом надо задаться диапазоном рабочих напряжений.
                        Потом надо оценить энергетическую емкость потребителя — сколько энергии тратится на спящий режим и на активный с учетом желаемого количества циклов активности. Сравнить результаты и делать выводы.


                      1. shtirlitsus
                        13.10.2015 12:05

                        в моём случае заряда хватало на 3-е суток в самый короткий зимний день. Всё зависит от потребителя


    1. avs24rus
      12.10.2015 09:16

      1. Хотел максимум компактности.
      2. Интересно было сколько реально протянет на таблетке, особенно при минусе за окном.


  1. Alexeyslav
    12.10.2015 09:10
    +2

    Небольшую солнечную батарею, и батарейка расходоваться будет меньше — только в ночные часы.


    1. prostosergik
      13.10.2015 14:21

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


      1. Alexeyslav
        13.10.2015 14:53

        В парралель не выйдет, неосвещённая СБ имеет токи утечки и будет разряжать батарею. Нужна обязательная диодная развязка, а диод заберёт на себя 0.3-0.4В батарейки, чем уменьшит доступную ёмкость батареи и в пору ставить вопрос о том стоит ли овчинка выделки?


        1. prostosergik
          13.10.2015 15:24
          +1

          Батарейке диод и не нужен. Достаточно будет одного Шотки на СБ. Когда напряжение на ней превысит батарейку, диод отопрется и будет питать МК. Если света будет недостаточно, то нагрузку возьмет Li-батарейка.


          1. shtirlitsus
            13.10.2015 16:33
            +1

            А как батарейка отнесётся к заряду? Обратный ток СБ очень незначителен. Я бы поставил Шоттки на Li батарейку. Как заходит Солнце — включается Li


            1. Alexeyslav
              13.10.2015 16:39
              +1

              и через диод разряжается на тёмную СБ… разряд не устранили, напряжение диодом понизили.
              На СБ можно и кремниевый диод поставить, а на обычную батарейку можно и шоттки. Хотя какие преимущества у диода шоттки на малых токах? Тогда уж, германиевый диод типа Д9, или полевик.


              1. shtirlitsus
                13.10.2015 16:46

                на практике не заметил какого-либо значительного разряда через СБ


                1. Alexeyslav
                  13.10.2015 22:26
                  +1

                  Значит хорошая панелька попалась, из очень чистого материала. Или просто прибор у вас микроамперы не измеряет. Первая попавшаяся под руку СБ из брелка площадью 6кв.см — 0.3 мкА при 3.7В
                  Вторая батарейка, поликристаллический кремний площадь 40кв.см, ток утечки при 4.2В — 1300 мкА!!!


                  1. shtirlitsus
                    14.10.2015 09:23

                    С прибором всё в порядке. Тут можно и эмпирический подход применить. Заряженный ионистор с подключенной СБ помещаешь в темноту на определенное время. Затем меряешь изменение напряжения. Но Ваш опыт учту, спасибо.


                    1. Alexeyslav
                      14.10.2015 13:20

                      Достаточно просто замерить ток утечки. Ионистор может иметь сам по себе ток утечки еще больший чем у СБ. И это тоже является частью проблемы.


                      1. shtirlitsus
                        14.10.2015 14:46

                        Выходит, мне и с ионистором повезло.


          1. Alexeyslav
            13.10.2015 16:36
            +1

            СБ тогда начнёт заряжать батарейку, а для этого типа батарей допустимый зарядный ток — десяток микроампер. Так за несколько циклов СБ просто попортит батарейку и та потечёт.


  1. alexpp
    12.10.2015 10:32

    Возьмите в качестве корпуса распределительную коробку, подходящую по размерам. Их много в любом строительном.


    1. avs24rus
      12.10.2015 10:39

      А прозрачную крышку для коробки где взять? Ведь нужно что бы на BH1750 попадал свет. Если дырку делать — придется что то типа линзы вклеивать.


      1. Alexeyslav
        12.10.2015 10:53
        +2

        Выставлять всю конструкцию на солнечный свет — плохая идея… материалы компонентов плохо относятся к солнечному УФ, и за пару лет конструкция будет представлять из себя жалкое зрелище.
        Закрыть всё в непрозрачную коробку, для датчика освещенности проделать световод из световода под индикатор питания бытовой техники(в ЭЛТ мониторах часто используют световоды под индикатор питания) либо сделать из медицинского стекла(трубочки, сам не знаю где достать но их продают только оптом, легко плавятся пламенем турбозажигалки и придаётся необходимая форма/размер в домашних условиях) или на крайний случай — из прозрачного герметика.


        1. avs24rus
          12.10.2015 13:00

          Про то что все выгорит по действием УФ — я не подумал. Видимо и правда лучше запихать конструкцию в обычный корпус и позаботиться о доставке света к датчику.


  1. GarryC
    14.10.2015 16:10

    А беспроводная зарядка сюда не просится?