Commit dceed526 authored by Vowstar's avatar Vowstar
Browse files

Merge pull request #470 from nodemcu/dev096

* Update SDK to 0.9.6
* Fix some bugs
* Update examples
* Add crypto module by @creationix 
parents 0ad57470 b0a4e4d3
No preview for this file type
No preview for this file type
--
-- Light sensor on ADC(0), RGB LED connected to gpio12(6) Green, gpio13(7) Blue & gpio15(8) Red.
-- This works out of the box on the typical ESP8266 evaluation boards with Battery Holder
--
-- It uses the input from the sensor to drive a "rainbow" effect on the RGB LED
-- Includes a very "pseudoSin" function
--
function led(r,Sg,b)
pwm.setduty(8,r)
pwm.setduty(6,g)
pwm.setduty(7,b)
end
-- this is perhaps the lightest weight sin function in existance
-- Given an integer from 0..128, 0..512 appximating 256 + 256 * sin(idx*Pi/256)
-- This is first order square approximation of sin, it's accurate around 0 and any multiple of 128 (Pi/2),
-- 92% accurate at 64 (Pi/4).
function pseudoSin (idx)
idx = idx % 128
lookUp = 32 - idx % 64
val = 256 - (lookUp * lookUp) / 4
if (idx > 64) then
val = - val;
end
return 256+val
end
pwm.setup(6,500,512)
pwm.setup(7,500,512)
pwm.setup(8,500,512)
pwm.start(6)
pwm.start(7)
pwm.start(8)
tmr.alarm(1,20,1,function()
idx = 3 * adc.read(0) / 2
r = pseudoSin(idx)
g = pseudoSin(idx + 43)
b = pseudoSin(idx + 85)
led(r,g,b)
idx = (idx + 1) % 128
end)
--
-- Simple NodeMCU web server (done is a not so nodeie fashion :-)
--
-- Highly modified by Bruce Meacham, based on work by Scott Beasley 2015
-- Open and free to change and use. Enjoy. [Beasley/Meacham 2015]
--
-- Meacham Update: I streamlined/improved the parsing to focus on simple HTTP GET request and their simple parameters
-- Also added the code to drive a servo/light. Comment out as you see fit.
--
-- Usage:
-- Change SSID and SSID_PASSPHRASE for your wifi network
-- Download to NodeMCU
-- node.compile("http_server.lua")
-- dofile("http_server.lc")
-- When the server is esablished it will output the IP address.
-- http://{ip address}/?s0=1200&light=1
-- s0 is the servo position (actually the PWM hertz), 500 - 2000 are all good values
-- light chanel high(1)/low(0), some evaluation boards have LEDs pre-wired in a "pulled high" confguration, so '0' ground the emitter and turns it on backwards.
--
-- Add to init.lua if you want it to autoboot.
--
-- Your Wifi connection data
local SSID = "YOUR WIFI SSID"
local SSID_PASSWORD = "YOUR SSID PASSPHRASE"
-- General setup
local pinLight = 2 -- this is GPIO4
gpio.mode(pinLight,gpio.OUTPUT)
gpio.write(pinLight,gpio.HIGH)
servo = {}
servo.pin = 4 --this is GPIO2
servo.value = 1500
servo.id = "servo"
gpio.mode(servo.pin, gpio.OUTPUT)
gpio.write(servo.pin, gpio.LOW)
-- This alarm drives the servo
tmr.alarm(0,10,1,function() -- 50Hz
if servo.value then -- generate pulse
gpio.write(servo.pin, gpio.HIGH)
tmr.delay(servo.value)
gpio.write(servo.pin, gpio.LOW)
end
end)
local function connect (conn, data)
local query_data
conn:on ("receive",
function (cn, req_data)
params = get_http_req (req_data)
cn:send("HTTP/1.1 200/OK\r\nServer: NodeLuau\r\nContent-Type: text/html\r\n\r\n")
cn:send ("<h1>ESP8266 Servo &amp; Light Server</h1>\r\n")
if (params["light"] ~= nil) then
if ("0" == params["light"]) then
gpio.write(pinLight, gpio.LOW)
else
gpio.write(pinLight, gpio.HIGH)
end
end
if (params["s0"] ~= nil) then
servo.value = tonumber(params["s0"]);
end
-- Close the connection for the request
cn:close ( )
end)
end
-- Build and return a table of the http request data
function get_http_req (instr)
local t = {}
local str = string.sub(instr, 0, 200)
local v = string.gsub(split(str, ' ')[2], '+', ' ')
parts = split(v, '?')
local params = {}
if (table.maxn(parts) > 1) then
for idx,part in ipairs(split(parts[2], '&')) do
parmPart = split(part, '=')
params[parmPart[1]] = parmPart[2]
end
end
return params
end
-- Source: http://lua-users.org/wiki/MakingLuaLikePhp
-- Credit: http://richard.warburton.it/
function split(str, splitOn)
if (splitOn=='') then return false end
local pos,arr = 0,{}
for st,sp in function() return string.find(str,splitOn,pos,true) end do
table.insert(arr,string.sub(str,pos,st-1))
pos = sp + 1
end
table.insert(arr,string.sub(str,pos))
return arr
end
-- Configure the ESP as a station (client)
wifi.setmode (wifi.STATION)
wifi.sta.config (SSID, SSID_PASSWORD)
wifi.sta.autoconnect (1)
-- Hang out until we get a wifi connection before the httpd server is started.
tmr.alarm (1, 800, 1, function ( )
if wifi.sta.getip ( ) == nil then
print ("Waiting for Wifi connection")
else
tmr.stop (1)
print ("Config done, IP is " .. wifi.sta.getip ( ))
end
end)
-- Create the httpd server
svr = net.createServer (net.TCP, 30)
-- Server listening on port 80, call connect function if a request is received
svr:listen (80, connect)
--[[
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]--
-- Your access point's SSID and password
local SSID = "xxxxxx"
local SSID_PASSWORD = "xxxxxx"
-- configure ESP as a station
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID,SSID_PASSWORD)
wifi.sta.autoconnect(1)
local TWILIO_ACCOUNT_SID = "xxxxxx"
local TWILIO_TOKEN = "xxxxxx"
local HOST = "iot-https-relay.appspot.com" -- visit http://iot-https-relay.appspot.com/ to learn more about this service
-- Please be sure to understand the security issues of using this relay app and use at your own risk.
local URI = "/twilio/Calls.json"
function build_post_request(host, uri, data_table)
local data = ""
for param,value in pairs(data_table) do
data = data .. param.."="..value.."&"
end
request = "POST "..uri.." HTTP/1.1\r\n"..
"Host: "..host.."\r\n"..
"Connection: close\r\n"..
"Content-Type: application/x-www-form-urlencoded\r\n"..
"Content-Length: "..string.len(data).."\r\n"..
"\r\n"..
data
print(request)
return request
end
local function display(sck,response)
print(response)
end
-- When using send_sms: the "from" number HAS to be your twilio number.
-- If you have a free twilio account the "to" number HAS to be your twilio verified number.
local function make_call(from,to,body)
local data = {
sid = TWILIO_ACCOUNT_SID,
token = TWILIO_TOKEN,
Body = string.gsub(body," ","+"),
From = from,
To = to
}
socket = net.createConnection(net.TCP,0)
socket:on("receive",display)
socket:connect(80,HOST)
socket:on("connection",function(sck)
local post_request = build_post_request(HOST,URI,data)
sck:send(post_request)
end)
end
function check_wifi()
local ip = wifi.sta.getip()
if(ip==nil) then
print("Connecting...")
else
tmr.stop(0)
print("Connected to AP!")
print(ip)
-- make a call with a voice message "your house is on fire"
make_call("15558976687","1334856679","Your house is on fire!")
end
end
tmr.alarm(0,2000,1,check_wifi)
-- test with cloudmqtt.com
m_dis={}
function dispatch(m,t,pl)
if pl~=nil and m_dis[t] then
m_dis[t](m,pl)
end
end
function topic1func(m,pl)
print("get1: "..pl)
end
function topic2func(m,pl)
print("get2: "..pl)
end
m_dis["/topic1"]=topic1func
m_dis["/topic2"]=topic2func
-- Lua: mqtt.Client(clientid, keepalive, user, pass)
m=mqtt.Client("nodemcu1",60,"test","test123")
m:on("connect",function(m)
print("connection "..node.heap())
m:subscribe("/topic1",0,function(m) print("sub done") end)
m:subscribe("/topic2",0,function(m) print("sub done") end)
m:publish("/topic1","hello",0,0) m:publish("/topic2","world",0,0)
end )
m:on("offline", function(conn)
print("disconnect to broker...")
print(node.heap())
end)
m:on("message",dispatch )
-- Lua: mqtt:connect( host, port, secure, auto_reconnect, function(client) )
m:connect("m11.cloudmqtt.com",11214,0,1)
tmr.alarm(0,10000,1,function() local pl = "time: "..tmr.time()
m:publish("/topic1",pl,0,0)
end)
-- test transfer files over mqtt.
m_dis={}
function dispatch(m,t,pl)
if pl~=nil and m_dis[t] then
m_dis[t](m,pl)
end
end
function pubfile(m,filename)
file.close()
file.open(filename)
repeat
local pl=file.read(1024)
if pl then m:publish("/topic2",pl,0,0) end
until not pl
file.close()
end
-- payload(json): {"cmd":xxx,"content":xxx}
function topic1func(m,pl)
print("get1: "..pl)
local pack = cjson.decode(pl)
if pack.content then
if pack.cmd == "open" then file.open(pack.content,"w+")
elseif pack.cmd == "write" then file.write(pack.content)
elseif pack.cmd == "close" then file.close()
elseif pack.cmd == "remove" then file.remove(pack.content)
elseif pack.cmd == "run" then dofile(pack.content)
elseif pack.cmd == "read" then pubfile(m, pack.content)
end
end
end
m_dis["/topic1"]=topic1func
-- Lua: mqtt.Client(clientid, keepalive, user, pass)
m=mqtt.Client()
m:on("connect",function(m)
print("connection "..node.heap())
m:subscribe("/topic1",0,function(m) print("sub done") end)
end )
m:on("offline", function(conn)
print("disconnect to broker...")
print(node.heap())
end)
m:on("message",dispatch )
-- Lua: mqtt:connect( host, port, secure, auto_reconnect, function(client) )
m:connect(192.168.18.88,1883,0,1)
-- usage:
-- another client(pc) subscribe to /topic2, will receive the test.lua content.
-- and publish below message to /topic1
-- {"cmd":"open","content":"test.lua"}
-- {"cmd":"write","content":"print([[hello world]])\n"}
-- {"cmd":"write","content":"print(\"hello2 world2\")\n"}
-- {"cmd":"write","content":"test.lua"}
-- {"cmd":"run","content":"test.lua"}
-- {"cmd":"read","content":"test.lua"}
--[[
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute,
sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]--
-- Your access point's SSID and password
local SSID = "xxxxxx"
local SSID_PASSWORD = "xxxxxx"
-- configure ESP as a station
wifi.setmode(wifi.STATION)
wifi.sta.config(SSID,SSID_PASSWORD)
wifi.sta.autoconnect(1)
local TWILIO_ACCOUNT_SID = "xxxxxx"
local TWILIO_TOKEN = "xxxxxx"
local HOST = "iot-https-relay.appspot.com" -- visit http://iot-https-relay.appspot.com/ to learn more about this service
-- Please be sure to understand the security issues of using this relay app and use at your own risk.
local URI = "/twilio/Messages.json"
function build_post_request(host, uri, data_table)
local data = ""
for param,value in pairs(data_table) do
data = data .. param.."="..value.."&"
end
request = "POST "..uri.." HTTP/1.1\r\n"..
"Host: "..host.."\r\n"..
"Connection: close\r\n"..
"Content-Type: application/x-www-form-urlencoded\r\n"..
"Content-Length: "..string.len(data).."\r\n"..
"\r\n"..
data
print(request)
return request
end
local function display(sck,response)
print(response)
end
-- When using send_sms: the "from" number HAS to be your twilio number.
-- If you have a free twilio account the "to" number HAS to be your twilio verified number.
local function send_sms(from,to,body)
local data = {
sid = TWILIO_ACCOUNT_SID,
token = TWILIO_TOKEN,
Body = string.gsub(body," ","+"),
From = from,
To = to
}
socket = net.createConnection(net.TCP,0)
socket:on("receive",display)
socket:connect(80,HOST)
socket:on("connection",function(sck)
local post_request = build_post_request(HOST,URI,data)
sck:send(post_request)
end)
end
function check_wifi()
local ip = wifi.sta.getip()
if(ip==nil) then
print("Connecting...")
else
tmr.stop(0)
print("Connected to AP!")
print(ip)
-- send a text message with the text "Hello from your esp8266"
send_sms("15558889944","15559998845","Hello from your ESP8266")
end
end
tmr.alarm(0,7000,1,check_wifi)
......@@ -2,9 +2,9 @@
-- setup I2c and connect display
function init_i2c_display()
-- SDA and SCL can be assigned freely to available GPIOs
sda = 5 -- GPIO14
scl = 6 -- GPIO12
sla = 0x3c
local sda = 5 -- GPIO14
local scl = 6 -- GPIO12
local sla = 0x3c
i2c.setup(0, sda, scl, i2c.SLOW)
disp = u8g.ssd1306_128x64_i2c(sla)
end
......@@ -15,9 +15,9 @@ function init_spi_display()
-- Hardware SPI MOSI = GPIO13
-- Hardware SPI MISO = GPIO12 (not used)
-- CS, D/C, and RES can be assigned freely to available GPIOs
cs = 8 -- GPIO15, pull-down 10k to GND
dc = 4 -- GPIO2
res = 0 -- GPIO16
local cs = 8 -- GPIO15, pull-down 10k to GND
local dc = 4 -- GPIO2
local res = 0 -- GPIO16
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0)
disp = u8g.ssd1306_128x64_spi(cs, dc, res)
......
......@@ -2,9 +2,9 @@
-- setup I2c and connect display
function init_i2c_display()
-- SDA and SCL can be assigned freely to available GPIOs
sda = 5 -- GPIO14
scl = 6 -- GPIO12
sla = 0x3c
local sda = 5 -- GPIO14
local scl = 6 -- GPIO12
local sla = 0x3c
i2c.setup(0, sda, scl, i2c.SLOW)
disp = u8g.ssd1306_128x64_i2c(sla)
end
......@@ -15,9 +15,9 @@ function init_spi_display()
-- Hardware SPI MOSI = GPIO13
-- Hardware SPI MISO = GPIO12 (not used)
-- CS, D/C, and RES can be assigned freely to available GPIOs
cs = 8 -- GPIO15, pull-down 10k to GND
dc = 4 -- GPIO2
res = 0 -- GPIO16
local cs = 8 -- GPIO15, pull-down 10k to GND
local dc = 4 -- GPIO2
local res = 0 -- GPIO16
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0)
disp = u8g.ssd1306_128x64_spi(cs, dc, res)
......@@ -91,17 +91,6 @@ function ascii_1()
end
end
function ascii_2()
local x, y, s
disp:drawStr(0, 0, "ASCII page 2")
for y = 0, 5, 1 do
for x = 0, 15, 1 do
s = y*16 + x + 160
disp:drawStr(x*7, y*10+10, string.char(s))
end
end
end
function extra_page(a)
disp:drawStr(0, 12, "setScale2x2")
disp:setScale2x2()
......@@ -131,8 +120,6 @@ function draw(draw_state)
elseif (component == 6) then
ascii_1()
elseif (component == 7) then
ascii_2()
elseif (component == 8) then
extra_page(bit.band(draw_state, 7))
end
end
......
......@@ -2,9 +2,9 @@
-- setup I2c and connect display
function init_i2c_display()
-- SDA and SCL can be assigned freely to available GPIOs
sda = 5 -- GPIO14
scl = 6 -- GPIO12
sla = 0x3c
local sda = 5 -- GPIO14
local scl = 6 -- GPIO12
local sla = 0x3c
i2c.setup(0, sda, scl, i2c.SLOW)
disp = u8g.ssd1306_128x64_i2c(sla)
end
......@@ -15,9 +15,9 @@ function init_spi_display()
-- Hardware SPI MOSI = GPIO13
-- Hardware SPI MISO = GPIO12 (not used)
-- CS, D/C, and RES can be assigned freely to available GPIOs
cs = 8 -- GPIO15, pull-down 10k to GND
dc = 4 -- GPIO2
res = 0 -- GPIO16
local cs = 8 -- GPIO15, pull-down 10k to GND
local dc = 4 -- GPIO2
local res = 0 -- GPIO16
spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8, 0)
disp = u8g.ssd1306_128x64_spi(cs, dc, res)
......
# DHTxx module
This module is compatible with DHT11, DHT21 and DHT22.
And is able to auto-select wheather you are using DHT11 or DHT2x
No need to use a resistor to connect the pin data of DHT22 to ESP8266.
##Integer Verison[When using DHT11, Float version is useless...]
......@@ -10,14 +12,13 @@ PIN = 4 -- data pin, GPIO2
DHT= require("dht_lib")
--dht.read11(PIN)
DHT.read22(PIN)
DHT.read(PIN)
t = DHT.getTemperature()
h = DHT.getHumidity()
if h == nil then
print("Error reading from DHT11/22")
print("Error reading from DHTxx")
else
-- temperature in degrees Celsius and Farenheit
......@@ -41,8 +42,7 @@ PIN = 4 -- data pin, GPIO2
DHT= require("dht_lib")
--dht.read11(PIN)
DHT.read22(PIN)
DHT.read(PIN)
t = DHT.getTemperature()
h = DHT.getHumidity()
......@@ -52,11 +52,12 @@ if h == nil then
else
-- temperature in degrees Celsius and Farenheit
-- floating point and integer version:
print("Temperature: "..t.." deg C")
print("Temperature: "..(t/10).." deg C")
print("Temperature: "..(9 * t / 50 + 32).." deg F")
-- humidity
print("Humidity: "..h.."%")
print("Humidity: "..(h/10).."%")
end
-- release module
......@@ -64,12 +65,10 @@ DHT = nil
package.loaded["dht_lib"]=nil
```
## Functions
### read11
read11(pin)
Read humidity and temperature from DHT11.
###read22
read22(pin)
Read humidity and temperature from DHT22/21.
###read
read(pin)
Read humidity and temperature from DHTxx(11,21,22...).
**Parameters:**
* pin - ESP8266 pin connect to data pin
......@@ -88,4 +87,3 @@ Returns the temperature of the last reading.
**Returns:**
* last temperature reading in(dht22) 0.1ºC (dht11)1ºC
*
......@@ -8,10 +8,13 @@
-- ***************************************************************************
--Support list:
--DHT11 Tested ->read11
--DHT21 Not Tested->read22
--DHT22 Tested->read22
--DHT11 Tested
--DHT21 Not Test yet
--DHT22(AM2302) Tested
--AM2320 Not Test yet
--Output format-> Real temperature times 10(or DHT22 will miss it float part in Int Version)
--==========================Module Part======================
local moduleName = ...
local M = {}
......@@ -37,8 +40,6 @@ local function read(pin)
bitStream[j] = 0
end
-- Step 1: send out start signal to DHT22
gpio.mode(pin, gpio.OUTPUT)
gpio.write(pin, gpio.HIGH)
......@@ -57,7 +58,7 @@ local function read(pin)
while (gpio_read(pin) == 0 ) do end
c=0
while (gpio_read(pin) == 1 and c < 500) do c = c + 1 end
-- Step 3: DHT22 send data
for j = 1, 40, 1 do
while (gpio_read(pin) == 1 and bitlength < 10 ) do
......@@ -69,67 +70,78 @@ local function read(pin)
while (gpio_read(pin) == 0) do end
end
end
---------------------------Convert the bitStream into Number through DHT11 Ways--------------------------
function M.read11(pin)
--As for DHT11 40Bit is consisit of 5Bytes
--First byte->Humidity Data's Int part
--Sencond byte->Humidity Data's Float Part(Which should be empty)
--Third byte->Temp Data;s Intpart
--Forth byte->Temp Data's Float Part(Which should be empty)
--Fifth byte->SUM Byte, Humi+Temp
---------------------------Check out the data--------------------------
----Auto Select the DHT11/DHT22 By check the byte[1] && byte[3] -------
---------------Which is empty when using DHT11-------------------------
function M.read(pin)
read(pin)
local checksum = 0
local checksumTest
--DHT data acquired, process.
local byte_0 = 0
local byte_1 = 0
local byte_2 = 0
local byte_3 = 0
local byte_4 = 0
for i = 1, 8, 1 do -- Byte[0]
if (bitStream[i] > 3) then
humidity = humidity + 2 ^ (8 - i)
byte_0 = byte_0 + 2 ^ (8 - i)
end
end
for i = 1, 8, 1 do -- Byte[2]
if (bitStream[i + 16] > 3) then
temperature = temperature + 2 ^ (8 - i)
for i = 1, 8, 1 do -- Byte[1]
if (bitStream[i+8] > 3) then
byte_1 = byte_1 + 2 ^ (8 - i)
end
end
for i = 1, 8, 1 do --Byte[4]
if (bitStream[i + 32] > 3) then
checksum = checksum + 2 ^ (8 - i)
for i = 1, 8, 1 do -- Byte[2]
if (bitStream[i+16] > 3) then
byte_2 = byte_2 + 2 ^ (8 - i)
end
end
if(checksum ~= humidity+temperature) then
humidity = nil
temperature = nil
end
end
---------------------------Convert the bitStream into Number through DHT22 Ways--------------------------
function M.read22( pin )
--As for DHT22 40Bit is consisit of 5Bytes
--First byte->Humidity Data's High Bit
--Sencond byte->Humidity Data's Low Bit(And if over 0x8000, use complement)
--Third byte->Temp Data's High Bit
--Forth byte->Temp Data's Low Bit
--Fifth byte->SUM Byte
read(pin)
local checksum = 0
local checksumTest
--DHT data acquired, process.
for i = 1, 16, 1 do
if (bitStream[i] > 3) then
humidity = humidity + 2 ^ (16 - i)
for i = 1, 8, 1 do -- Byte[3]
if (bitStream[i+24] > 3) then
byte_2 = byte_2 + 2 ^ (8 - i)
end
end
for i = 1, 16, 1 do
if (bitStream[i + 16] > 3) then
temperature = temperature + 2 ^ (16 - i)
for i = 1, 8, 1 do -- Byte[4]
if (bitStream[i+32] > 3) then
byte_4 = byte_4 + 2 ^ (8 - i)
end
end
for i = 1, 8, 1 do
if (bitStream[i + 32] > 3) then
checksum = checksum + 2 ^ (8 - i)
if byte_1==0 and byte_3 == 0 then
---------------------------Convert the bitStream into Number through DHT11's Way--------------------------
--As for DHT11 40Bit is consisit of 5Bytes
--First byte->Humidity Data's Int part
--Sencond byte->Humidity Data's Float Part(Which should be empty)
--Third byte->Temp Data;s Intpart
--Forth byte->Temp Data's Float Part(Which should be empty)
--Fifth byte->SUM Byte, Humi+Temp
if(byte_4 ~= byte_0+byte_2) then
humidity = nil
temperature = nil
else
humidity = byte_0 *10 -- In order to universe with the DHT22
temperature = byte_2 *10
end
end
else ---------------------------Convert the bitStream into Number through DHT22's Way--------------------------
--As for DHT22 40Bit is consisit of 5Bytes
--First byte->Humidity Data's High Bit
--Sencond byte->Humidity Data's Low Bit(And if over 0x8000, use complement)
--Third byte->Temp Data's High Bit
--Forth byte->Temp Data's Low Bit
--Fifth byte->SUM Byte
humidity = byte_0 * 256 + byte_1
temperature = byte_2 * 256 + byte_3
checksum = byte_4
checksumTest = (bit.band(humidity, 0xFF) + bit.rshift(humidity, 8) + bit.band(temperature, 0xFF) + bit.rshift(temperature, 8))
checksumTest = bit.band(checksumTest, 0xFF)
......@@ -143,9 +155,18 @@ function M.read22( pin )
if (checksumTest - checksum >= 1) or (checksum - checksumTest >= 1) then
humidity = nil
end
end
byte_0 = nil
byte_1 = nil
byte_2 = nil
byte_3 = nil
byte_4 = nil
end
--------------API for geting the data out------------------
---------------------------Check out the data--------------------------
function M.getTemperature()
return temperature
end
......@@ -153,5 +174,5 @@ end
function M.getHumidity()
return humidity
end
-------------Return Index------------------------------------
return M
# LM92 module
This module adds basic support for the LM92 +-0.33C 12bit+sign temperature sensor. More details in the [datasheet](http://www.ti.com/lit/ds/symlink/lm92.pdf).
Works:
- getting the temperature
- entering the chip's to shutdown mode (350uA -> 5uA power consumption)
- waking up the chip from shutdown
##Require
```lua
LM92 = require("lm92")
```
## Release
```lua
LM92 = nil
package.loaded["lm92"]=nil
```
##init()
####Description
Setting the i2c pins and address for lm92.
####Syntax
init(sda, scl, address)
####Parameters
sda: 1~12, IO index.<br />
scl: 1~12, IO index.<br />
address: 0x48~0x4b, i2c address (depends on tha A0~A1 pins)
####Returns
nil
####Example
```lua
LM92 = require("lm92")
gpio0 = 3
gpio2 = 4
sda = gpio0
scl = gpio2
addr = 0x48
LM92.init(sda, scl,addr)
```
##getTemperature()
####Description
Returns the temperature register's content.
####Syntax
getTemperature()
####Parameters
-
####Returns
Temperature in degree Celsius.
####Example
```lua
t = LM92.getTemperature()
print("Got temperature: "..t.." C")
```
##wakeup()
####Description
Makes the chip exit the low power shutdown mode.
####Syntax
wakeup()
####Parameters
-
####Returns
-
####Example
```lua
LM92.wakeup()
tmr.delay( 1 * 1000 * 1000 )
```
##shutdown()
####Description
Makes the chip enter the low power shutdown mode.
####Syntax
shutdown()
####Parameters
-
####Returns
-
####Example
```lua
LM92.shutdown()
```
#### TODO:
- add full support of the features, including interrupt and critical alert support
-- ******************************************************
-- LM92 module for ESP8266 with nodeMCU
--
-- Written by Levente Tamas <levente.tamas@navicron.com>
--
-- GNU LGPL, see https://www.gnu.org/copyleft/lesser.html
-- ******************************************************
-- Module Bits
local moduleName = ...
local M = {}
_G[moduleName] = M
-- Default ID
local id = 0
-- Local vars
local address = 0
-- read regs for len number of bytes
-- return table with data
local function read_reg(reg_addr, len)
local ret={}
local c
local x
i2c.start(id)
i2c.address(id, address ,i2c.TRANSMITTER)
i2c.write(id,reg_addr)
i2c.stop(id)
i2c.start(id)
i2c.address(id, address,i2c.RECEIVER)
c=i2c.read(id,len)
for x=1,len,1 do
tc=string.byte(c,x)
table.insert(ret,tc)
end
i2c.stop(id)
return ret
end
--write reg with data table
local function write_reg(reg_addr, data)
i2c.start(id)
i2c.address(id, address, i2c.TRANSMITTER)
i2c.write(id, reg_addr)
i2c.write(id, data)
i2c.stop(id)
end
-- initialize i2c
-- d: sda
-- c: scl
-- a: i2c addr 0x48|A1<<1|A0 (A0-A1: chip pins)
function M.init(d,c,a)
if (d ~= nil) and (c ~= nil) and (d >= 0) and (d <= 11) and (c >= 0) and ( c <= 11) and (d ~= l) and (a ~= nil) and (a >= 0x48) and (a <= 0x4b ) then
sda = d
scl = c
address = a
i2c.start(id)
res = i2c.address(id, address, i2c.TRANSMITTER) --verify that the address is valid
i2c.stop(id)
if (res == false) then
print("device not found")
return nil
end
else
print("i2c configuration failed") return nil
end
i2c.setup(id,sda,scl,i2c.SLOW)
end
-- Return the temperature data
function M.getTemperature()
local temperature
local tmp=read_reg(0x00,2) --read 2 bytes from the temperature register
temperature=bit.rshift(tmp[1]*256+tmp[2],3) --lower 3 bits are status bits
if (temperature>=0x1000) then
temperature= temperature-0x2000 --convert the two's complement
end
return temperature * 0.0625
end
-- Put the LM92 into shutdown mode
function M.shutdown()
write_reg(0x01,0x01)
end
-- Bring the LM92 out of shutdown mode
function M.wakeup()
write_reg(0x01,0x00)
end
return M
\ No newline at end of file
-- ***************************************************************************
-- Example for Yeelink Lib
--
-- Written by Martin
--
--
-- MIT license, http://opensource.org/licenses/MIT
-- ***************************************************************************
wifi.setmode(wifi.STATION) --Step1: Connect to Wifi
wifi.sta.config("SSID","Password")
dht = require("dht_lib") --Step2: "Require" the libs
yeelink = require("yeelink_lib")
yeelink.init(23333,23333,"You api-key",function() --Step3: Register the callback function
print("Yeelink Init OK...")
tmr.alarm(1,60000,1,function() --Step4: Have fun~ (Update your data)
dht.read(4)
yeelink.update(dht.getTemperature())
end)
end)
-- ***************************************************************************
-- Yeelink Updata Libiary Version 0.1.2 r1
--
-- Written by Martin
-- but based on a script of zhouxu_o from bbs.nodemcu.com
--
-- MIT license, http://opensource.org/licenses/MIT
-- ***************************************************************************
--==========================Module Part======================
local moduleName = ...
local M = {}
_G[moduleName] = M
--=========================Local Args=======================
local dns = "0.0.0.0"
local device = ""
local sensor = ""
local apikey = ""
--================================
local debug = true --<<<<<<<<<<<<< Don't forget to "false" it before using
--================================
local sk=net.createConnection(net.TCP, 0)
local datapoint = 0
--====DNS the yeelink ip advance(in order to save RAM)=====
if wifi.sta.getip() == nil then
print("Please Connect WIFI First")
tmr.alarm(1,1000,1,function ()
if wifi.sta.getip() ~= nil then
tmr.stop(1)
sk:dns("api.yeelink.net",function(conn,ip)
dns=ip
print("DNS YEELINK OK... IP: "..dns)
end)
end
end)
end
sk:dns("api.yeelink.net",function(conn,ip)
dns=ip
print("DNS YEELINK OK... IP: "..dns)
end)
--========Set the init function===========
--device->number
--sensor->number
-- apikey must be -> string <-
-- e.g. xxx.init(00000,00000,"123j12b3jkb12k4b23bv54i2b5b3o4")
--========================================
function M.init(_device, _sensor, _apikey)
device = tostring(_device)
sensor = tostring(_sensor)
apikey = _apikey
if dns == "0.0.0.0" then
tmr.alarm(2,5000,1,function ()
if dns == "0.0.0.0" then
print("Waiting for DNS...")
end
end)
return false
else
return dns
end
end
--========Check the DNS Status===========
--if DNS success, return the address(string)
--if DNS fail(or processing), return nil
--
--
--========================================
function M.getDNS()
if dns == "0.0.0.0" then
return nil
else
return dns
end
end
--=====Update to Yeelink Sever(At least 10s per sencods))=====
-- datapoint->number
--
--e.g. xxx.update(233.333)
--============================================================
function M.update(_datapoint)
datapoint = tostring(_datapoint)
sk:on("connection", function(conn)
print("connect OK...")
local a=[[{"value":]]
local b=[[}]]
local st=a..datapoint..b
sk:send("POST /v1.0/device/"..device.."/sensor/"..sensor.."/datapoints HTTP/1.1\r\n"
.."Host: www.yeelink.net\r\n"
.."Content-Length: "..string.len(st).."\r\n"--the length of json is important
.."Content-Type: application/x-www-form-urlencoded\r\n"
.."U-ApiKey:"..apikey.."\r\n"
.."Cache-Control: no-cache\r\n\r\n"
..st.."\r\n" )
end)
sk:on("receive", function(sck, content)
if debug then
print("\r\n"..content.."\r\n")
else
print("Date Receive")
end
end)
sk:connect(80,dns)
end
--================end==========================
return M
......@@ -41,7 +41,7 @@ class ESPROM:
# Maximum block sized for RAM and Flash writes, respectively.
ESP_RAM_BLOCK = 0x1800
ESP_FLASH_BLOCK = 0x100
ESP_FLASH_BLOCK = 0x400
# Default baudrate. The ROM auto-bauds, so we can use more or less whatever we want.
ESP_ROM_BAUD = 115200
......@@ -56,6 +56,12 @@ class ESPROM:
ESP_OTP_MAC0 = 0x3ff00050
ESP_OTP_MAC1 = 0x3ff00054
# Sflash stub: an assembly routine to read from spi flash and send to host
SFLASH_STUB = "\x80\x3c\x00\x40\x1c\x4b\x00\x40\x21\x11\x00\x40\x00\x80" \
"\xfe\x3f\xc1\xfb\xff\xd1\xf8\xff\x2d\x0d\x31\xfd\xff\x41\xf7\xff\x4a" \
"\xdd\x51\xf9\xff\xc0\x05\x00\x21\xf9\xff\x31\xf3\xff\x41\xf5\xff\xc0" \
"\x04\x00\x0b\xcc\x56\xec\xfd\x06\xff\xff\x00\x00"
def __init__(self, port = 0, baud = ESP_ROM_BAUD):
self._port = serial.Serial(port, baud)
......@@ -78,15 +84,7 @@ class ESPROM:
""" Write bytes to the serial port while performing SLIP escaping """
def write(self, packet):
buf = '\xc0'
for b in packet:
if b == '\xc0':
buf += '\xdb\xdc'
elif b == '\xdb':
buf += '\xdb\xdd'
else:
buf += b
buf += '\xc0'
buf = '\xc0'+(packet.replace('\xdb','\xdb\xdd').replace('\xc0','\xdb\xdc'))+'\xc0'
self._port.write(buf)
""" Calculate checksum of a blob, as it is defined by the ROM """
......@@ -132,11 +130,25 @@ class ESPROM:
# RTS = CH_PD (i.e reset)
# DTR = GPIO0
# self._port.setRTS(True)
# self._port.setDTR(True)
# self._port.setRTS(False)
# time.sleep(0.1)
# self._port.setDTR(False)
# NodeMCU devkit
self._port.setRTS(True)
self._port.setDTR(True)
self._port.setRTS(False)
time.sleep(0.1)
self._port.setRTS(False)
self._port.setDTR(False)
time.sleep(0.1)
self._port.setRTS(True)
time.sleep(0.1)
self._port.setDTR(True)
self._port.setRTS(False)
time.sleep(0.3)
self._port.setDTR(True)
self._port.timeout = 0.5
for i in xrange(10):
......@@ -209,16 +221,78 @@ class ESPROM:
self.flash_begin(0, 0)
self.flash_finish(reboot)
""" Read MAC from OTP ROM """
def read_mac(self):
mac0 = esp.read_reg(esp.ESP_OTP_MAC0)
mac1 = esp.read_reg(esp.ESP_OTP_MAC1)
if ((mac1 >> 16) & 0xff) == 0:
oui = (0x18, 0xfe, 0x34)
elif ((mac1 >> 16) & 0xff) == 1:
oui = (0xac, 0xd0, 0x74)
else:
raise Exception("Unknown OUI")
return oui + ((mac1 >> 8) & 0xff, mac1 & 0xff, (mac0 >> 24) & 0xff)
""" Read SPI flash manufacturer and device id """
def flash_id(self):
self.flash_begin(0, 0)
self.write_reg(0x60000240, 0x0, 0xffffffff)
self.write_reg(0x60000200, 0x10000000, 0xffffffff)
flash_id = esp.read_reg(0x60000240)
self.flash_finish(False)
return flash_id
""" Read SPI flash """
def flash_read(self, offset, size, count = 1):
# Create a custom stub
stub = struct.pack('<III', offset, size, count) + self.SFLASH_STUB
# Trick ROM to initialize SFlash
self.flash_begin(0, 0)
# Download stub
self.mem_begin(len(stub), 1, len(stub), 0x40100000)
self.mem_block(stub, 0)
self.mem_finish(0x4010001c)
# Fetch the data
data = ''
for _ in xrange(count):
if self._port.read(1) != '\xc0':
raise Exception('Invalid head of packet (sflash read)')
data += self.read(size)
if self._port.read(1) != chr(0xc0):
raise Exception('Invalid end of packet (sflash read)')
return data
""" Perform a chip erase of SPI flash """
def flash_erase(self):
# Trick ROM to initialize SFlash
self.flash_begin(0, 0)
# This is hacky: we don't have a custom stub, instead we trick
# the bootloader to jump to the SPIEraseChip() routine and then halt/crash
# when it tries to boot an unconfigured system.
self.mem_begin(0,0,0,0x40100000)
self.mem_finish(0x40004984)
# Yup - there's no good way to detect if we succeeded.
# It it on the other hand unlikely to fail.
class ESPFirmwareImage:
def __init__(self, filename = None):
self.segments = []
self.entrypoint = 0
self.flash_mode = 0
self.flash_size_freq = 0
if filename is not None:
f = file(filename, 'rb')
(magic, segments, _, _, self.entrypoint) = struct.unpack('<BBBBI', f.read(8))
(magic, segments, self.flash_mode, self.flash_size_freq, self.entrypoint) = struct.unpack('<BBBBI', f.read(8))
# some sanity check
if magic != ESPROM.ESP_IMAGE_MAGIC or segments > 16:
......@@ -246,7 +320,8 @@ class ESPFirmwareImage:
def save(self, filename):
f = file(filename, 'wb')
f.write(struct.pack('<BBBBI', ESPROM.ESP_IMAGE_MAGIC, len(self.segments), 0, 0, self.entrypoint))
f.write(struct.pack('<BBBBI', ESPROM.ESP_IMAGE_MAGIC, len(self.segments),
self.flash_mode, self.flash_size_freq, self.entrypoint))
checksum = ESPROM.ESP_CHECKSUM_MAGIC
for (offset, size, data) in self.segments:
......@@ -346,6 +421,12 @@ if __name__ == '__main__':
'write_flash',
help = 'Write a binary blob to flash')
parser_write_flash.add_argument('addr_filename', nargs = '+', help = 'Address and binary file to write there, separated by space')
parser_write_flash.add_argument('--flash_freq', '-ff', help = 'SPI Flash frequency',
choices = ['40m', '26m', '20m', '80m'], default = '40m')
parser_write_flash.add_argument('--flash_mode', '-fm', help = 'SPI Flash mode',
choices = ['qio', 'qout', 'dio', 'dout'], default = 'qio')
parser_write_flash.add_argument('--flash_size', '-fs', help = 'SPI Flash size in Mbit',
choices = ['4m', '2m', '8m', '16m', '32m'], default = '4m')
parser_run = subparsers.add_parser(
'run',
......@@ -369,11 +450,32 @@ if __name__ == '__main__':
help = 'Create an application image from ELF file')
parser_elf2image.add_argument('input', help = 'Input ELF file')
parser_elf2image.add_argument('--output', '-o', help = 'Output filename prefix', type = str)
parser_elf2image.add_argument('--flash_freq', '-ff', help = 'SPI Flash frequency',
choices = ['40m', '26m', '20m', '80m'], default = '40m')
parser_elf2image.add_argument('--flash_mode', '-fm', help = 'SPI Flash mode',
choices = ['qio', 'qout', 'dio', 'dout'], default = 'qio')
parser_elf2image.add_argument('--flash_size', '-fs', help = 'SPI Flash size in Mbit',
choices = ['4m', '2m', '8m', '16m', '32m'], default = '4m')
parser_read_mac = subparsers.add_parser(
'read_mac',
help = 'Read MAC address from OTP ROM')
parser_flash_id = subparsers.add_parser(
'flash_id',
help = 'Read SPI flash manufacturer and device ID')
parser_read_flash = subparsers.add_parser(
'read_flash',
help = 'Read SPI flash content')
parser_read_flash.add_argument('address', help = 'Start address', type = arg_auto_int)
parser_read_flash.add_argument('size', help = 'Size of region to dump', type = arg_auto_int)
parser_read_flash.add_argument('filename', help = 'Name of binary dump')
parser_erase_flash = subparsers.add_parser(
'erase_flash',
help = 'Perform Chip Erase on SPI flash')
args = parser.parse_args()
# Create the ESPROM connection object, if needed
......@@ -421,6 +523,12 @@ if __name__ == '__main__':
elif args.operation == 'write_flash':
assert len(args.addr_filename) % 2 == 0
flash_mode = {'qio':0, 'qout':1, 'dio':2, 'dout': 3}[args.flash_mode]
flash_size_freq = {'4m':0x00, '2m':0x10, '8m':0x20, '16m':0x30, '32m':0x40}[args.flash_size]
flash_size_freq += {'40m':0, '26m':1, '20m':2, '80m': 0xf}[args.flash_freq]
flash_info = struct.pack('BB', flash_mode, flash_size_freq)
while args.addr_filename:
address = int(args.addr_filename[0], 0)
filename = args.addr_filename[1]
......@@ -434,7 +542,11 @@ if __name__ == '__main__':
print '\rWriting at 0x%08x... (%d %%)' % (address + seq*esp.ESP_FLASH_BLOCK, 100*(seq+1)/blocks),
sys.stdout.flush()
block = image[0:esp.ESP_FLASH_BLOCK]
block = block + '\xe0' * (esp.ESP_FLASH_BLOCK-len(block))
# Fix sflash config data
if address == 0 and seq == 0 and block[0] == '\xe9':
block = block[0:2] + flash_info + block[4:]
# Pad the last block
block = block + '\xff' * (esp.ESP_FLASH_BLOCK-len(block))
esp.flash_block(block, seq)
image = image[esp.ESP_FLASH_BLOCK:]
seq += 1
......@@ -478,6 +590,11 @@ if __name__ == '__main__':
for section, start in ((".text", "_text_start"), (".data", "_data_start"), (".rodata", "_rodata_start")):
data = e.load_section(section)
image.add_segment(e.get_symbol_addr(start), data)
image.flash_mode = {'qio':0, 'qout':1, 'dio':2, 'dout': 3}[args.flash_mode]
image.flash_size_freq = {'4m':0x00, '2m':0x10, '8m':0x20, '16m':0x30, '32m':0x40}[args.flash_size]
image.flash_size_freq += {'40m':0, '26m':1, '20m':2, '80m': 0xf}[args.flash_freq]
image.save(args.output + "0x00000.bin")
data = e.load_section(".irom0.text")
off = e.get_symbol_addr("_irom0_text_start") - 0x40200000
......@@ -487,6 +604,17 @@ if __name__ == '__main__':
f.close()
elif args.operation == 'read_mac':
mac0 = esp.read_reg(esp.ESP_OTP_MAC0)
mac1 = esp.read_reg(esp.ESP_OTP_MAC1)
print 'MAC: 18:fe:34:%02x:%02x:%02x' % ((mac1 >> 8) & 0xff, mac1 & 0xff, (mac0 >> 24) & 0xff)
mac = esp.read_mac()
print 'MAC: %s' % ':'.join(map(lambda x: '%02x'%x, mac))
elif args.operation == 'flash_id':
flash_id = esp.flash_id()
print 'Manufacturer: %02x' % (flash_id & 0xff)
print 'Device: %02x%02x' % ((flash_id >> 8) & 0xff, (flash_id >> 16) & 0xff)
elif args.operation == 'read_flash':
print 'Please wait...'
file(args.filename, 'wb').write(esp.flash_read(args.address, 1024, int(math.ceil(args.size / 1024.)))[:args.size])
elif args.operation == 'erase_flash':
esp.flash_erase()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment