Единственным препятствием для использования «таблетки» является ее небольшая емкость. Но и среди «таблеток» есть вполне подходящие экземпляры, например 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)
Alexeyslav
12.10.2015 09:10+2Небольшую солнечную батарею, и батарейка расходоваться будет меньше — только в ночные часы.
prostosergik
13.10.2015 14:21Вот кстати здравая мысль. Поставить тупо в параллель солнечную батарейку, и неэнергоемкие операции будут вполне удовлетворяться энергией СБ.
Alexeyslav
13.10.2015 14:53В парралель не выйдет, неосвещённая СБ имеет токи утечки и будет разряжать батарею. Нужна обязательная диодная развязка, а диод заберёт на себя 0.3-0.4В батарейки, чем уменьшит доступную ёмкость батареи и в пору ставить вопрос о том стоит ли овчинка выделки?
prostosergik
13.10.2015 15:24+1Батарейке диод и не нужен. Достаточно будет одного Шотки на СБ. Когда напряжение на ней превысит батарейку, диод отопрется и будет питать МК. Если света будет недостаточно, то нагрузку возьмет Li-батарейка.
shtirlitsus
13.10.2015 16:33+1А как батарейка отнесётся к заряду? Обратный ток СБ очень незначителен. Я бы поставил Шоттки на Li батарейку. Как заходит Солнце — включается Li
Alexeyslav
13.10.2015 16:39+1и через диод разряжается на тёмную СБ… разряд не устранили, напряжение диодом понизили.
На СБ можно и кремниевый диод поставить, а на обычную батарейку можно и шоттки. Хотя какие преимущества у диода шоттки на малых токах? Тогда уж, германиевый диод типа Д9, или полевик.shtirlitsus
13.10.2015 16:46на практике не заметил какого-либо значительного разряда через СБ
Alexeyslav
13.10.2015 22:26+1Значит хорошая панелька попалась, из очень чистого материала. Или просто прибор у вас микроамперы не измеряет. Первая попавшаяся под руку СБ из брелка площадью 6кв.см — 0.3 мкА при 3.7В
Вторая батарейка, поликристаллический кремний площадь 40кв.см, ток утечки при 4.2В — 1300 мкА!!!shtirlitsus
14.10.2015 09:23С прибором всё в порядке. Тут можно и эмпирический подход применить. Заряженный ионистор с подключенной СБ помещаешь в темноту на определенное время. Затем меряешь изменение напряжения. Но Ваш опыт учту, спасибо.
Alexeyslav
14.10.2015 13:20Достаточно просто замерить ток утечки. Ионистор может иметь сам по себе ток утечки еще больший чем у СБ. И это тоже является частью проблемы.
Alexeyslav
13.10.2015 16:36+1СБ тогда начнёт заряжать батарейку, а для этого типа батарей допустимый зарядный ток — десяток микроампер. Так за несколько циклов СБ просто попортит батарейку и та потечёт.
alexpp
12.10.2015 10:32Возьмите в качестве корпуса распределительную коробку, подходящую по размерам. Их много в любом строительном.
avs24rus
12.10.2015 10:39А прозрачную крышку для коробки где взять? Ведь нужно что бы на BH1750 попадал свет. Если дырку делать — придется что то типа линзы вклеивать.
Alexeyslav
12.10.2015 10:53+2Выставлять всю конструкцию на солнечный свет — плохая идея… материалы компонентов плохо относятся к солнечному УФ, и за пару лет конструкция будет представлять из себя жалкое зрелище.
Закрыть всё в непрозрачную коробку, для датчика освещенности проделать световод из световода под индикатор питания бытовой техники(в ЭЛТ мониторах часто используют световоды под индикатор питания) либо сделать из медицинского стекла(трубочки, сам не знаю где достать но их продают только оптом, легко плавятся пламенем турбозажигалки и придаётся необходимая форма/размер в домашних условиях) или на крайний случай — из прозрачного герметика.avs24rus
12.10.2015 13:00Про то что все выгорит по действием УФ — я не подумал. Видимо и правда лучше запихать конструкцию в обычный корпус и позаботиться о доставке света к датчику.
Rumlin
А почему бы солнечную батарею с аккумулятором/ионистором не поставить и забыть о датчике навсегда?
Alexeyslav
Аккумуляторы дохнут со временем, солнечная батарея деградирует. Экономически оправдано просто менять батарейки. Раз в год или около того.
Rumlin
По цене Яндекс маркет показывает цены CR2450 от 30 р до 875(!!!) р. У китайцев — 1,7$.
Liion аккумулятор 100mAh — 2,9$
Думаю аккумулятор продержится намного дольше CR2450.
Alexeyslav
Литиевый аккумулятор выдержит суровую зиму? -20 градусов… или летнюю жару, когда внутря прогреваются до 70 градусов.
Rumlin
Откуда +70? Белая коробка с вентиляционными отверстиями не прогреется намного выше воздуха в тени.
У аккумуляторов обычно диапазон рабочих температур от -25..20 до +60 градусов Цельсия.
Alexeyslav
У меня обычный металлический козырёк подоконника нагревается так что рукой прикоснуться невозможно. Кроме отверстий в коробе, нужно еще обеспечивать движение воздуха. В штиль и без принудительной тяги считай что отверстий и нет.
Кроме того, пластик этих коробов, даже якобы стойкий для наружного применения рассыпается чуть ли не в пыль через год-два на солнце и даже довольно щадящим перепадом температур воздуха(-15...+30). Стоят только металлические короба, и на тех краска облупливается и они начинают ржаветь — т.е. необходимо периодическое обслуживание.
Rumlin
Нагревается верхняя поверхность. Передать тепло вниз сложно:
Наконец наклеить/натянуть сверху металлизированный вспененный полиэтилен из строймагазина. Солнечные лучи будет замечательно отражать защищая пластик от нагрева и разрушения.
Alexeyslav
Зато замечательная конвекция идет от нагретой стены дома… если этаж не первый, температура растёт.
Rumlin
Поэтому есть четкие правила размещения метеорологического оборудования. Даже у китайской метеостанции в инструкции написано — не на прямых солнечных лучах, в метре от стены.
В идеале как психрометрическая будка
gleb_l
Поставить микровентилятор и продувать им блок снизу вверх лишней энергией от СБ )
av0000
Литиевый аккумулятор не заряжается в отрицательные температуры.
Я пытался выбрать между LiFePo (только они заряжаются в минусовых температурах) и ионисторами для своей поделки, но пока забросил. Ионистор проще заряжать, но меньше ёмкость и выше цена. LiFePo, вроде, дешевле в пересчете на емкость, но не было дешевых и мелких решений по зарядке (для литиевых есть неплохой вариант TP4056, а для LiFePo не нашлось)
shtirlitsus
А есть где почитать про деградацию солнечной батареи? у меня 2 зимы пережил беспроводной термометр с ионистором
Alexeyslav
2 зимы еще незаметно, вот лет через 5 можно будет заметить что батарея отдаёт меньше энергии чем прежде. Но в суровых условиях заметить это будет трудно — она ведь и так работает с огромным запасом.
Чтобы заметить деградацию, необходимо измерять её параметры (ток К.З.) при строго известной освещенности. Через 5...10 лет возможно заметите что батареи уже не хватает на зимнюю продолжительность дня, например.
Rumlin
За 10 лет это сколько денег уйдет на CR2450? А тут один раз в 10 лет и может у новых деталей характеристики будут еще лучше.
avs24rus
На голой солнечной батарее не выжить, а аккумулятор при минусе за бортом долго не протянет. Но попробовать можно, надо только найти небольшую солнечную батарею.
Rumlin
Как вариант NiCd — самые морозоустойчивые. Вопрос только в реализации схемы заряда во избежание эффекта памяти…
Хотя может просто не так часто опрашивать датчики, хотя бы ночью. А днем пользоваться солнечной батарей.
isden
> NiCd
Еще можно попробовать компактные свинцовые гелевые аккумуляторы. Не будет характерных для NiCd проблем.
shtirlitsus
Ионистор вполне справляется. Запас по эффективности заложить и счастье будет.
isden
А в нем заряда, скажем, на ночь + пасмурный день (а то и два-три) хватит? И по габаритам как?
Alexeyslav
Ионисторы гораздо больше по размерам чем аккумуляторы.
Можно легко посчитать. Требуемое время определяется емкостью ионистора в ватт-часах на необходимом диапазоне напряжений(контроллер при 1 вольте уже не будет работать, хотя энергии в ионисторе будет еще дофига) поэтому перед рассчетом надо задаться диапазоном рабочих напряжений.
Потом надо оценить энергетическую емкость потребителя — сколько энергии тратится на спящий режим и на активный с учетом желаемого количества циклов активности. Сравнить результаты и делать выводы.
shtirlitsus
в моём случае заряда хватало на 3-е суток в самый короткий зимний день. Всё зависит от потребителя
avs24rus
1. Хотел максимум компактности.
2. Интересно было сколько реально протянет на таблетке, особенно при минусе за окном.