Wi-Fi измеритель CO2 на ESP8266 + K-30


    В данной статье мы продолжим эксперименты с Wi-Fi модулем ESP8266 и попробуем реализовать опрос датчика CO2 K-30 через MODBUS.

    В первой части мы прошили в ESP8266 NodeMCU, подключили DS18b20 и научились отправлять данные о температуре в облако. Попробуем добавить опрос датчика CO2.
    Самое интересное реализовать весь функционал в ESP8266 не подключая внешний контроллер

    Hardware и подключение
    Добавляем к конфигу из предыдущей статьи датчик K-30.
    Соединяем UART RX, UART TX и GND у датчика K-30 и ESP8266. Питание у них будет разное.
    Сложность заключается в том, что UART у ESP8266 всего один, так что либо консоль и отладка, либо K-30
    Внимание! Питание у K-30 5-14В, у ESP8266 — 3.3В.
    Я решил данную проблему применив преобразователь 5->3.3В


    Программная часть

    1) init.lua — практически не изменился
    --init.lua
    print("Setting up WIFI...")
    wifi.setmode(wifi.STATION)
    --modify according your wireless router settings
    wifi.sta.config("YOUR_SSID","YOUR_PASSWD")
    wifi.sta.connect()
    tmr.alarm(1, 1000, 1, function() 
    	if wifi.sta.getip()== nil then 
    		print("IP unavaiable, Waiting...") 
    	else 
    		tmr.stop(1)
    		print("Config done, IP is "..wifi.sta.getip())
    		dofile("all.lua")
    	end 
    end)
    


    2) all.lua — код опроса датчиков и отправки данных на сервер
    pin = 6
    t = 0
    
    function read(addr, unit)
      ow.setup(pin)
      result = nil
      flag = false
      if(addr == nil) then
        ow.reset_search(pin)
        count = 0
        repeat
          count = count + 1
          addr = ow.search(pin)
          tmr.wdclr()
        until((addr ~= nil) or (count > 100))
        ow.reset_search(pin)
      end
      if(addr == nil) then
        return result
      end
      crc = ow.crc8(string.sub(addr,1,7))
      if (crc == addr:byte(8)) then
        if ((addr:byte(1) == 0x10) or (addr:byte(1) == 0x28)) then
          ow.reset(pin)
          ow.select(pin, addr)
          ow.write(pin, 0x44, 1)
          present = ow.reset(pin)
          ow.select(pin, addr)
          ow.write(pin,0xBE,1)
          data = nil
          data = string.char(ow.read(pin))
          for i = 1, 8 do
            data = data .. string.char(ow.read(pin))
          end
          crc = ow.crc8(string.sub(data,1,8))
          if (crc == data:byte(9)) then
    
            t = (data:byte(1) + data:byte(2) * 256) * 625
    
            t = t / 10000
            return t
          end
          tmr.wdclr()
        else
        end
      else
      end
      return result
    end
    
    
    
    function sendt(t,co,key)
     print("Temp:"..t.." C\n")
    conn=net.createConnection(net.TCP, 0) 
    conn:on("receive", function(conn, payload) print(payload) end)
    conn:connect(80,'184.106.153.149') 
    conn:send("GET /update?key="..key.."&field1="..t.."&field2="..co.." 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 connection")
                          conn:close()
                      end)
    conn:on("disconnection", function(conn)
                                  print("Got disconnection...")
      end)
    end
    
    
    uart.setup(0,9600,8,0,1,0)
    uart.on("data", 0, 
        function(data)
    	--print("receive from uart:", data)
    		if string.len(data) == 7 then
    			result = string.byte(data,4)*256 + string.byte(data,5)
    			print (result)
    			sendt(t,result,"YOUR_KEY")
    		end
        end, 0)
    
    
    function sendData()
    t = read()
    uart.write(0,0xFE,0x04,0x00,0x03,0x00,0x01,0xD5,0xC5)
    end
    
    tmr.alarm(0, 60000, 1, function() sendData() end )
     


    Алгоритм работы:
    • Инициализируем UART на 9600
    • Устанавливаем callback на получение данных из UART. В случае получения пакета из 7 байт(ответ K-30 по MODBUS) отправляем данные на thingspeak.com
    • Каждую минуту опрашиваем датчик температуры DS18b20 и отправляем в UART запрос данных по CO2. Запрос найден в даташите

    Раскидать по отдельным файлам не получилось, не хватало памяти, поэтому реализовал как смог. Lua для меня до сих пор тёмный лес.

    Результаты


    Получилось очень интересное устройство. Питание сделал от USB, соответственно можно брать куда угодно. PowerBank сегодня есть почти у каждого. По поводу Wi-Fi — поднимаем точку на телефоне и наш датчик снова в сети.

    По ощущениям — действительно появляется дискомфорт при превышении CO2 уровня в 800-1000 ppm.
    Поделиться публикацией
    Похожие публикации
    Никаких подозрительных скриптов, только релевантные баннеры. Не релевантные? Пиши на: adv@tmtm.ru с темой «Полундра»

    Зачем оно вам?
    Реклама
    Комментарии 16
    • 0
      Вопрос по питанию. Можно ли было просто взять линейный стабилизатор напряжения LM7803 и пару конденсаторов?
      • 0
        Не пробовал. Он дает 3V, а это нижняя граница для ESP8266 (судя по даташиту 3.0-3.6V).
        • 0
          Лучше LM7833, главное не 78_l_33.
          • 0
            А чем лучше? Для меня это актуально.
            • 0
              У меня на 3.12В барахлит, на форумах тоже пописывают что к питанию сильно чувствителен модуль. Мож и не в этом проблема…
              Попробовать просто же, ничего не сгорит на 3В
        • 0
          Сложность заключается в том, что UART у ESP8266 всего один

          Полтора (на втором доступен только TX), а если не использовать SPI-Flash то два.
          Второй находится по адресу 0x60000F00 и его TX торчит из GPIO2.
          • 0
            А что делать вот с этим «находится по адресу»? А то мне тут надо было инвертнуть уарт, но так и не понял как к регистрам получить доступ, пришлось транзистором инвертировать.
            • +1
              так и не понял как к регистрам получить доступ

              С SDK идут примеры, открываете какой-нибудь examples/IoT_Demo/driver/uart.c и видите что-то такое:
                  WRITE_PERI_REG(UART_CONF0(uart_no),    UartDev.exist_parity
                                 | UartDev.parity
                                 | (UartDev.stop_bits << UART_STOP_BIT_NUM_S)
                                 | (UartDev.data_bits << UART_BIT_NUM_S));
              

              Определения этих макросов — в include/eahle_soc.h и examples/IoT_Demo/include/driver/uart_register.h, это обычная запись в MMIO.
              • +1
                Хо хо, работает
                Только почему-то в uart_register.h ошибка, там бит инверсии прописан как 12-й. А вот тут как 22-й, и это правильно
                uart_init(BIT_RATE_9600, BIT_RATE_9600);
                SET_PERI_REG_MASK(UART_CONF0(0), BIT(22));
                
                • 0
                  Хо хо, работает

                  Поздравляю (:
                  Только почему-то в uart_register.h ошибка

                  Я не сильно удивлён; конечно лучше сверяться с документацией.
          • 0
            data = nil
            data = string.char(ow.read(pin))
            for i = 1, 8 do
               data = data .. string.char(ow.read(pin))
            end
            crc = ow.crc8(string.sub(data,1,8))
            


            Все же лучше так:

            local data = {}
            for i = 1, 8 do
               table.insert(data, ow.read(pin))
            end
            local crc = ow.crc8(table.concat(data))
            
            • 0
              Я как-то все не могу уловить смысл использования локальных переменных и функций.
              Так быстрее? Или это в целях экономии памяти?
            • +1
              harizanov.com/wiki/wiki-home/three-channel-wifi-relaythermostat-board

              Воот это, вероятно, очень хороший проект. Всё реализовано на ESP8266.
              • 0
                www.artik.io/developer — Однако, новое поколение. Можно сделать регистрацию себе и получить устройство.
                • 0
                  Сколько мА потребляет вся эта конструкция? Я так понимаю, что датчик CO2 находится во включенном состоянии все время?
                  • 0
                    На всех измерителях тока для USB пишет 0 мA(до 10), иногда мигает 50 — 100 ма Получается что жрет только ESP8266.
                    Работает двое суток от PowerBank емкостью ~ 5000 mAh, сожрал пока 35%.

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.