вторник, 3 марта 2015 г.

"Вечный" Wi-Fi логгер на базе ESP8266 с питанием от солнечной панели и ионисторов

Сегодня мы рассмотрим создание прототипа "вечного" Wi-Fi логгера на базе солнечной панели с повербанка, StepUP DC-DC преобразователя, ионисторов и модуля ESP-01 на базе SoC-чипа ESP8266 с экспортом данных - температуры, напряжения питания, состояния дискретных I/O и времени с момента включения до сна в облако. Что облегчает задачу разработчика и экономит время, так это то, что прошивки под данный модуль можно писать прямо в нем, благодаря интерпретатору Lua в NodeMCU и имеющейся EEPROM-ки на 4 мегабайта. Сам NodeMCU имеет встроенную файловую систему SPIFFS.

Видеодемонстрация кишков прототипа


Конструктив модуля ESP-01 с датчиком температуры DS18B20

 


Распиновка модуля ESP-01


Схема модуля и распределение GPIO по регистрам




Вопросы бесперебойного питания

Следует отметить, что сам чип ESP8266 может работать от 1.7 до 3.6 В, но вот 4-х мегабитная EEPROM Winbond W25Q40BV на плате модуля расчитана на рабочий диапазон напряжений 2.7...3.6 В. Сей факт определяет необходимость запитки модуля в ограниченных пределах 2.7...3.6 В источником мощностью не менее 0.522 ватт. Эта цифра получена исходя из токопотребления в пиковом режиме 145 мА в режиме передачи в стандарте 802.11g и напряжении питания 3.6 В. Понятно, что основное время модуль будет находиться либо в спящем режиме (токопотребление 10 мкА), либо в режиме приема (токопотребление до 60 мА). В эфир в режиме передачи модуль будет выходить редко, скажем раз в минуту на секунду-две и пики токопотребления вполне может сгладить накопительная емкость.


Изначально для питания предполагал взять комбинацию солнечной панели на 0.5 ватта и 5 вольт, ионистора на 2.7 В и DC-DC преобразователя со встроенным алгоритмом отслеживания точки получения максимальной мощности (MPPT). К примеру, SPV1040. Он примечателен тем, что начинает работать при минимальном входном напряжении 0.3 В до 5.5 В и предназначен для заряда аккумулятора от солнечной батареи. MPPT динамически подстраивает входное сопротивление преобразователя, автоматически поддерживая наилучшее согласование с фотоэлементом солнечной батареи:



Однако, взглянув на его стоимость за штуку от 5 баксов, решил взять просто "вампирчик" (Step-UP DC-DC) от дядюшки Али за 24 рубля, работающий от 0.9 до 5.5 В и выдающий стабильное выходное напряжение 5.1 В при КПД 92%. Также немаловажным фактором послужило то, что для SPV1040 самого по себе нужна дополнительная обвеска (см. схему выше), а "вампирчик" уже готов как модуль. Да сами взгляните:



Кроме того, выходное напряжение "вампирчика" нужно снизить с 5-ти до 3 вольт.  Для чего? Во-первых, для обеспечения режима питания модуля ESP-01, а во-вторых - для ионисторов нельзя превышать номинальное напряжение, приводящее к электрохимическому распаду электролита, это главный их недостаток при всех огромных достоинствах (быстрый заряд как у конденсаторов, "огромная" емкость как у аккумуляторов и возможность работы при отрицательных температурах, до -30 °C).

Схему "китайцы" на данный Step-UP DC-DC бустер не предоставляют, но реверсинг по печатной плате несложен. Отрисовал сам:


Как снизить выходное напряжение? Самое простое и тупое - поставить по выходу два диода последовательно, тем самым погасив излишек напряжения. Но дьявол кроется в мелочах, при этом мы теряем драгоценную энергию. Не говоря уже о том, что при снижении напряжения по выходу преобразователя с номинальных выходных пяти вольт (вследствие снижения светового потока вечером) на величину падения на переходах двух диодов получим отсутствие заряда при вполне еще рабочем напряжении нашего логгера порядка 2.7 В. Ибо после двух диодов это уже будет 1.3 В (для кремниевых структур падение по 0.6...0.7 вольт, да еще и плавающее по температуре ). Корректнее же будет сместить порог по входу 3 преобразователя DA1 резистором *R2 со стандартным номиналом 47 кОм для 5 В и 91 кОм для 3-х, входящим в состав делителя R2-R3. Чем ниже сопротивление R2, тем выше выходное напряжение преобразователя.

Ограничения ионисторов

Современные ионисторы (см. даташит) работают в широком диапазоне температур: от -40 до +60 градусов Цельсия, имеют сотни тысяч циклов заряд-разряда при незначительной потере емкости и практически нечувствительны к разрядным токам. Правда следует оговорить немаловажное влияние ESR (собственное внутреннее сопротивление конденсатора с двойным электрическим слоем), которое хоть и меньше, чем у аккумуляторов, но значительно выше, чем у конденсаторов. В лучших образцах ионисторов ESR может достигать 300 мкОм, а в ширпотребовских до 30-100 Ом. К чему это приводит? Да к ограничению выдаваемого тока в нагрузку и быстрому падению напряжения.

Приведем первый пример: энергия, запасаемая в емкости равна C*U*U/2, допустим взяли ионистор на 1000 Фарад и 5 вольт, получаем 1000*25/2 = 12 500 Дж. Допустим внутреннее сопротивление среднего по параметрам равно 30 Ом и ток потребления 60 мА, тогда с учетом падения напряжения на ионисторе выходное напряжение составит 5-(30*0.06) = 3.2 вольта. При данном напряжении мы еще можем комфортно работать (напомним, наш минимум 2.7 вольт). Разрядное время ионистора при работе на нагрузку с постоянным разрядным током равно С*(Vн-Vк)/Iн = 1000 * (5-3.2) / 0.06 = 30 000 сек ~ 8.33 часов. Неплохо, но мы еще не учли ток саморазряда ионистора. 

Приведем второй пример: допустим внутреннее сопротивление равно 100 Ом и ток потребления 60 мА, тогда с учетом падения напряжения на ионисторе выходное напряжение составит 5-(100*0.06) = -1 вольт. Дальше считать смысла нет, не проходим для таких разрядных токов в постоянном режиме. Делаем вывод, что ширпотребовские ионисторы с высоким ESR подходят лишь для работы на малые разрядные токи. 

Как прошивать?

Для заливки альтернативной прошивки NodeMCU в ESP8266-01 использован готовый преобразователь USB/UART с TTL-уровнями на базе FTDI.

Для работы понадобится:
  1. LuaLoader для загрузки скриптов Lua https://github.com/GeoNomad/LuaLoader
  2. ESP8266Flasher для прошивки интерпретатора Lua в модуль ESP-01 https://github.com/nodemcu/nodemcu-flasher


Скрипт отправки данных на два тренда визуализации, проверки обрыва связи и считывания дискретного I/O
-- sleep us = 40 sec
COUNTSLEEP = 40000000
-- registr = 8, pin - gpio15
dpin = 8
gpio.mode(dpin,gpio.INPUT,gpio.PULLUP)
-- temperature
tpin = 4
require('ds18b20')
ds18b20.setup(tpin)
-- первый вызов необходим для устранения глюка в данных при появлении питания на датчик
t=ds18b20.read()
function sendData()
t=ds18b20.read()
r=gpio.read(dpin)
print("Temp:"..t.." C\n")

if wifi.sta.getip()== nil then
print("IP unavaiable, Waiting...")
else
-- conection to thingspeak.com
print("Sending data to thingspeak.com")
conn=net.createConnection(net.TCP, 0)
conn:on("receive", function(conn, payload) print(payload) end)
-- api.thingspeak.com 184.106.153.149
conn:connect(80,'184.106.153.149')
conn:send("GET /update?key=MYKEYAPI&field1="..t.."&field2="..r.." HTTP/1.1\r\n")
conn:send("Host: api.thingspeak.com\r\n")
conn:send("Accept: */*\r\n")
conn:send("User-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n")
conn:send("\r\n")
conn:on("sent",function(conn)
print("Closing connect")
conn:close()
-- print("Sleep 40 sec down...")
-- node.dsleep(COUNTSLEEP) -- закомментировал, см. комментарии ниже

end)
conn:on("disconnection", function(conn)
print("Disconnect...")
end)
end
end

-- send data every 60000 ms to thing speak
tmr.alarm(0, 60000, 1, function()
sendData()
end)
-- локальный сервер доступен в течении 20 sec на порту 8080
srv=net.createServer(net.TCP)
srv:listen(8080,function(conn)
t=ds18b20.read()
r=gpio.read(dpin)
conn:send("Temperature RAMEDIA: "..t.." C\n\nGPIO15: "..r.."\n\n")
conn:on("sent",function(conn) conn:close() end)
end)
Фикс дробной части

Следует отметить, что в Lua используется целочисленное деление и в стандартном скрипте работы с датчиком DS18B20 на выходе будет целое значение после масштабирования на старых прошивках NodeMCU. Как результат игнорирование промежуточных значений (см. рисунок):


В то же время, сам датчик позволяет проводить измерения с шагом (но не точностью) 0.0625 градусов Цельсия. Как вернуть промежуточные величины? Простая хитрость - считать отдельно остаток и присоединить его к целочисленному результату масштабирования. Масштабирование в исходном скрипте реализуется простым делением (найдите строку):
t = t/ 10000
Теперь перепишите ее следующим образом:
t = (t/10000).."."..(t%10000)
Конечно, сам компилятор NodeMCU съест впереди стоящие нули, но результат уже получше:


А что в итоге? Сообщество разработчиков пошевелилось и выпустило версию NodeMCU с поддержкой операций с плавающей точкой - nodemcu_float_0.9.6-dev_20150704. Вот так просто )

Проблема чтения аналогового входа или... мониторинг напряжения питания модуля

Есть такая функция в официальной доке - node.readvdd33(). Предназначена для получения напряжения питания модуля в милливольтах. Во-первых, документация устарела и функция перенесена из главного модуля node в adc, т.е. правильно будет вызывать как - adc.readvdd33(). Во-вторых, собака порылась в том, что ее вызов требует прерывания, которое занято при работе модуля в режиме точки доступа или режиме по-умолчанию, когда не запрещен режим автоконнекта. Так вот неискушенный разраб пишет ничего не подозревая ее вызов в теле опроса своих датчиков и получает сообщение об ошибке "PANIC: unprotected error in call to Lua API (httpsender.lua: attempt to call field 'readvdd33' (a nil value))". Не разобравшись с документацией и причинами появления таких месседжей, не почитав гитхаб, разраб начинает кричать на каждом углу по форумам о глючности NodeMCU. То голова у тя глючная. Как решить? Все просто:
  1. Либо перевести из точки доступа в режим запрета автоконнекта, а потом вернуть.
  2. Либо сначала запретить все через wifi.sta.disconnect() и wifi.sta.autoconnect(0), а потом уже работать в штатном режиме.
Поскольку в нашем случае предусмотрена работа модуля в спящем режиме, то подобную операцию лучше провести до начала работы прямо в стартовом init.lua (по окончании таймера сна тянется RESET, модуль заново инициализируется):
-- читаем ADC до активации коннекта (вызывает сброс после)
wifi.sta.disconnect()
wifi.sta.autoconnect(0)
u=adc.readvdd33()/1000
-- registr = 3, pin - GPIO0 na plus optron cherez 1 kOm
dpin=3
gpio.mode(dpin, gpio.OUTPUT);
gpio.write(dpin, gpio.HIGH);
-- GPIO2 (используем для настройки, подтянут к 1)
tpin=4
gpio.mode(tpin,gpio.INPUT,gpio.PULLUP)

print("Setting up Wi-Fi...")
wifi.setmode(wifi.STATION)
wifi.sta.config("SSID","password")
wifi.sta.connect()
local cnt=0
tmr.alarm(1, 1000, 1, function()
if wifi.sta.getip()==nil then
print("IP unavaiable, Waiting...")
cnt = cnt + 1if (cnt > 4) then tmr.stop(1) node.dsleep(COUNTSLEEP) end
else
tmr.stop(1)
print("Config done, IP is "..wifi.sta.getip())
dofile("httpsender.lua")
collectgarbage()
end
end)
Тогда скрипт 'httpsender.lua' чтения датчиков, автоотправки на сервис "умных вещей" и принудительного сна можно переписать следующим образом:
-- sleep us = 120-2 sec
local COUNTSLEEP = 118000000
-- temperature
require('ds18b20')
ds18b20.setup(tpin)
local t=ds18b20.read()

function sendData()
local g=gpio.read(dpin)
local r=tmr.now()
t=ds18b20.read()
print("Temperature: "..t.." C\n")

if wifi.sta.getip()== nil then
print("IP unavaiable, Waiting...")
print("Sleep 120 sec down...")
node.dsleep(COUNTSLEEP)
else
-- conection to thingspeak.com
print("Sending data to thingspeak.com")
conn=net.createConnection(net.TCP, 0)
conn:on("receive", function(conn, payload) print(payload) end)
-- api.thingspeak.com
conn:connect(80,'184.106.153.149')
conn:send("GET /update?key=apikey&field1="..t.."&field2="..u.."&field3="..g.."&field4="..r.." HTTP/1.1\r\n")
conn:send("Host: api.thingspeak.com\r\n")
conn:send("Accept: */*\r\n")
conn:send("User-Agent: Mozilla/4.0 (compatible; esp8266 Lua; Windows NT 5.1)\r\n")
conn:send("\r\n")
conn:on("sent",function(conn)
print("Closing connect")
conn:close()
end)
conn:on("disconnection", function(conn)
print("Disconnect...")
print("Sleep 120 sec down...")
node.dsleep(COUNTSLEEP)
end)
end
end

-- Wait 2000 ms for Init DS18B20 and last send to thingspeak
tmr.alarm(0, 2000, 1, function()
sendData()
end)
Результат работы мониторинга напряжения вы можете увидеть на следущем тренде (по сути, это не что иное как остаток напряжения на ионисторах):



Видеодемонстрация работы локального сервера




















Ресурсы по тематике
  1. Даташит на SPV1040.
  2. Даташит на W25Q40BVSSIP.
  3. Даташит на ESP8266.
  4. NodeMCU https://github.com/nodemcu/nodemcu-firmware
  5. Realtime визуализация данных
  6. Тестирование паяльника на ионисторах
Проекты на базе ESP8266
  1. Прозрачный мост UART/Wi-Fi --- Wi-Fi/UART на базе ESP8266 на Lua 
  2. Wi-Fi лампа. Контроль DIO модуля ESP-01 (ESP8266) по Wi-Fi  
  3. Монтаж мезонином прозрачного моста Wi-Fi-UART на ESP8266
  4. Автономный датчик температуры по Wi-Fi на базе ESP8266
  5. Аномальная разрядная кривая ионисторов проекта "вечный" Wi-Fi логгер. Луна однако
  6. Работа "вечного" Wi-Fi логгера на солнечную панель из... аморфного кремния 
  7. #ESP.Meteo: Wi-Fi логгер с автономным питанием в Twitter-e  
  8. Вывод отладочной информации с ESP-12 на дисплей SSD1306

Стать подписчиком блога и быть в курсе актуальных разработок

19 комментариев:

  1. В дополнение к температурному http://api.thingspeak.com/channels/31814/charts/1?width=450&height=260&results=10&dynamic=true добавлен канал отслеживания статуса двери (GPIO15) http://api.thingspeak.com/channels/31814/charts/2?width=450&height=260&results=10&dynamic=true. Также исправлен баг потери точки доступа при ее выключении (веерные отключения электричества).

    ОтветитьУдалить
    Ответы
    1. Заказал ионисторы для ночного резерва ESP8266 и автономного питания, заряжать и питать будет моя солнечная батарея на 5W.

      Расчет таков: потребление в режиме приема 60mA, в режиме передачи 135, среднее ~70 при передаче раз в минуту (без перехода в спящий режим). Темное время суток для солнечной батареи ~9 часов. Требуемая емкость E=0.07*9 = 0.63A*h. По закону Кулона q=C*U=A*t [Amper*sec], откуда C=E*3600/U=0.63*3600/2.7~ 840 Farad. Итого, взял два ионистора по 500 Фарад.

      Удалить
    2. Кстати, перешел на СБ по 0.4Вт, удлинил время сна до 2 минут, хватает )
      Циклы по ссылкам выше.

      Удалить
  2. Пробовал перевод ESP8266 в спящий режим подачей XPD_DCDC на RESET и вызовом node.dsleep(). Работает, спит, перезагружается как положено. Реализовал 10 секунд работает (проснулось, нашло точку доступа, подключилось, получило значение с температурного датчика и дискретного входа, отправило на удаленную визуализацию и архивацию), 50 секунд спит.

    Однако, цикл пробуждение-сон-пробуждение-сон (и т.д.) ESP8266 повторяется так раз семь-восемь, после чего прошивка никак не отзывается, приходится перешивать NodeMCU. С питанием все в порядке, без использования спящего режима работа в режиме 24x7 без сбоев.

    ОтветитьУдалить
  3. Так-с, с последней прошивкой NMCU сбоев 24х7 циклов пробуждение-сон пока не отмечено (2-я неделя).

    ОтветитьУдалить
  4. я так понял, что батареи нет - все на ионисторах по 500 хватает? почему не один на 1000?

    ОтветитьУдалить
    Ответы
    1. 1- габариты больше по диаметру, 2- у того же продавана дешевле было взять несколько по 500 оптом, чем по одному на большую емкость (есть и на 3000 Фарад, но дэньги, дэньги).

      Удалить
    2. В последнем прототипе ионисторов всего 4 по 100 Фарад, итого общая емкость = 400 Фарад.

      Удалить
  5. Кстати, о "вечности": поскольку роутер практически постоянно включен и холодильник периодически вклинивается, то для компенсации их энергопотребления планируется использование дополнительной СП на 200W совместно с Grid Tie Invertor-ом (синхронным преобразователем), с возможностью дальнейшего наращивания.

    ОтветитьУдалить
  6. Этот комментарий был удален автором.

    ОтветитьУдалить
    Ответы
    1. Доброй ночи, Olga.
      1- смотря как на это посмотреть ) То, что в конструктиве платы не оттрассирован один проводник по печати - не означает, что вам запрещено взять паяльник в руки и припаять один проводник между XPD_DCDC и Reset. Да, мелковато для кого-то, но реализуемо.
      2- а чему удивляться, есть емкость вашего невозобновляемого источника питания, есть среднее потребление в режиме приема, делим их и * 0.7 и получаем ~ время работы с учетом разрядной кривой.
      3- температура на улице - достаточно инерционный параметр, тут скорости не нужны и даже 5 минут будет адекватным периодом измерений. Более того, в режиме сна на три порядка увеличит время автономной работы без подзарядки.

      Удалить
    2. Этот комментарий был удален автором.

      Удалить
    3. Да, завсегда пожалуйста.

      1- спиртным говорите... А вы уверены "Ольга", что вы Ольга? Да и профиль явно создан недавно под вопросы сюда, слишком уж пуст )
      4- вы невнимательны, он и отрабатывает один раз, как и положено после срабатывания таймера сна - тянется RESET и модуль заново инициализируется.

      Удалить
    4. Этот комментарий был удален автором.

      Удалить
    5. Спалились и скромно молчите. Вот даже не знаю как теперь обращаться )

      4- переход в сон происходит после 4-х неудачных попыток получения IP адреса с DHCP-сервера роутера (попыток подключения клиентом, ибо нет смысла постоянно жрать энергию, когда роутер отключен или недоступен): если клиент ESP получил адрес (т.е. подключился), то таймер останавливается и идет вызов кода чтения датчиков и отсылки, очистки памяти (те самые 7 строк). Если не подключился, то запускается таймер сна, по окончании которого модуль сбрасывается аппаратно и скрипт инициализации вызывается снова.

      Удалить
  7. ...а-яй-яй, псевдо"Ольга" свои комментарии с вопросами потерла. Так на каждый болт с хитрой левой резьбой, всегда найдется крутая гайка. Вопросы реципиента:

    1- "интересная информация, везде писали что засыпание в ESP01 не предусмотрено..."
    2- "у меня на 2х батарейках меньше суток работает, без сна конечно. и отсылает чаще, хотя в таймере 60000 стоит."
    3- "Спасибо за ответ..
    1) затариваюсь спиртным чтобы разглядеть GPIO16 )
    4) мне казалось что init отрабатывается только один раз, а затем все время крутится httpsender. Каким образом все-таки обновляеся"
    4- "если я правильно понимаю, переход в сон происходит по команде "node.dsleep(COUNTSLEEP)"
    и затем, как Вы говорите, reset. то есть оставшиеся 7 строк кода не выполняются никогда?"

    ОтветитьУдалить
  8. Перевел "вечный" Wi-Fi логгер в режим раз в 5 минут, уменьшил емкости ионисторов до 200F, тестирую на солнечную панель из пластин аморфного кремния https://pbs.twimg.com/media/CtGWk1IW8AAcb4r.jpg

    ОтветитьУдалить
  9. можно ссылку на "вампирчик" а то что то модель не могу найти кукую вы купили.

    ОтветитьУдалить
    Ответы
    1. Здравствуйте, Эдуард.
      Брал такой http://ru.aliexpress.com/item/Free-Shipping-DC-3V-to-5V-USB-Output-charger-step-up-Power-Module-Mini-DC-DC/1502737568.html, но сейчас уже появились бустеры дешевле (40 центов с бесплатной доставкой) https://ru.aliexpress.com/item/MT3608-2A-Max-DC-DC-Step-Up-Power-Module-Booster-Power-Module/32488635405.html?spm=2114.30010708.3.2.zXnmLf&ws_ab_test=searchweb0_0,searchweb201602_2_10039_10056_10065_10055_10068_10054_10069_10059_10073_10017_10070_10060_10061_10052_10062_10053_10050_10051,searchweb201603_4&btsid=27b6ad44-cd65-4baf-a705-f00ee0122d7c.

      Также обратите внимание на актуальную версию "вечного" Wi-Fi логгера и причины схемотехнического построения http://raxp2.blogspot.com/2016/10/esp8266-wi-fi.html

      Удалить

В комментариях уважайте собеседника, внимательно читайте посты и не додумывайте. Выход новых версий ПО, внешняя ссылка, переставшая работать с течением времени и т.п. не является основанием для претензий. Желающие спокойно подискутировать и высказаться — Welcome. Желающие спонсировать блог — Donate. Нарушение этих простых правил ведет к бану и удалению комментариев без предупреждения.