Browse Source

init proj

master
DESKTOP-B25GA9E\W35 1 year ago
parent
commit
5f1f9d35d8
  1. 10
      .vscode/settings.json
  2. BIN
      DocRes/1_0.jpg
  3. BIN
      DocRes/1_1.jpg
  4. BIN
      DocRes/1_2.jpg
  5. BIN
      DocRes/NodeMcu_Pinout.webp
  6. BIN
      Firmware/nodemcu-release-13-modules-2023-09-16-02-20-47-float.bin
  7. BIN
      Firmware/nodemcu-release-13-modules-2023-09-16-02-20-47-integer.bin
  8. 27
      GPIO.lua
  9. 81
      OLED_SSD1306.lua
  10. 77
      README.md
  11. 23
      Third_Part_License/Json.lua.txt
  12. 364
      Third_Part_License/json.lua
  13. 46
      UDPService.lua
  14. 46
      WifiMgr.lua
  15. 12
      init.lua

10
.vscode/settings.json vendored

@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
{
"Lua.diagnostics.globals": [
"wifi",
"net",
"u8g2",
"i2c",
"gpio",
"enduser_setup"
]
}

BIN
DocRes/1_0.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

BIN
DocRes/1_1.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

BIN
DocRes/1_2.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
DocRes/NodeMcu_Pinout.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
Firmware/nodemcu-release-13-modules-2023-09-16-02-20-47-float.bin

Binary file not shown.

BIN
Firmware/nodemcu-release-13-modules-2023-09-16-02-20-47-integer.bin

Binary file not shown.

27
GPIO.lua

@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
--Init GPIO params
function InitGPIO()
gpio.mode(0,gpio.OUTPUT);
gpio.mode(1,gpio.OUTPUT);
gpio.mode(2,gpio.OUTPUT);
gpio.mode(3,gpio.OUTPUT);
gpio.mode(4,gpio.OUTPUT);
gpio.write(0,gpio.LOW);
gpio.write(1,gpio.LOW);
gpio.write(2,gpio.LOW);
gpio.write(3,gpio.LOW);
gpio.write(4,gpio.LOW);
end
--Push gpio to high
function GPIOOn(gpioId)
if gpioId>=0 and gpioId<=4 then
gpio.write(gpioId,gpio.HIGH)
end
end
--Push gpio to low
function GPIOOff(gpioId)
if gpioId>=0 and gpioId<=4 then
gpio.write(gpioId,gpio.LOW)
end
end
InitGPIO();
print("gpio1-5 init over,turn all gpio to output,low")

81
OLED_SSD1306.lua

@ -0,0 +1,81 @@ @@ -0,0 +1,81 @@
Id = 0
Sda = 5 -- GPIO14
Scl = 6 -- GPIO12
Sla = 0x3c
i2c.setup(Id, Sda, Scl, i2c.SLOW)
Disp = u8g2.ssd1306_i2c_128x64_noname(Id, Sla)
print("Oled Init Success!");
Screen_WIFINAME = "";
Screen_IPADDRESS = "";
Screen_VERSION = "";
--tips to user link-AP
function PageAPNet()
Disp:clearBuffer()
--Disp:setFont(u8g2.font_unifont_t_symbols);
Disp:setFont(u8g2.font_unifont_t_symbols);
Disp:drawStr(0,10,"AP-LinkMode");
Disp:setFont(u8g2.font_6x10_tf);
Disp:drawStr(0,26,"Please use your");
Disp:drawStr(0,36,"mobile phone search");
Disp:drawStr(0,46,"and link ap-point");
Disp:drawStr(0,56,"DY-Light-Controller");
Disp:updateDisplay();
end
--progress:1-100,tips loading and update from server
function PageLoading(progress)
Disp:clearBuffer();
--Disp:setFont(u8g2.font_unifont_t_symbols);
Disp:setFont(u8g2.font_unifont_t_symbols);
Disp:drawStr(40,10,"DYTech");
Disp:setFont(u8g2.font_6x10_tf);
Disp:drawStr(16,32,"Check for update");
Disp:drawFrame(12,42,104,10);
Disp:drawBox(14,44,progress,6);
Disp:updateDisplay();
end
--
function PageMainScene(wifiName,ipAddress,version)
Disp:clearBuffer();
DrawMainScene(wifiName,ipAddress,version)
Disp:updateDisplay();
Screen_WIFINAME = wifiName;
Screen_IPADDRESS = ipAddress;
Screen_VERSION = version;
--Disp:sendBuffer();
end
function DrawMainScene(wifiName,ipAddress,version)
--Disp:setFont(u8g2.font_unifont_t_symbols);
Disp:setFont(u8g2.font_unifont_t_symbols);
Disp:drawStr(40,10,"DYTech");
Disp:setFont(u8g2.font_6x10_tf);
Disp:drawStr(0,26,"Wifi:"..wifiName);
Disp:drawStr(0,36,"Light Ctrl-UDP"..version);
Disp:drawStr(0,46,"S:"..ipAddress..":5000");
end
function PageLight(lightArr)
Disp:clearBuffer();
DrawMainScene(Screen_WIFINAME,Screen_IPADDRESS,Screen_VERSION);
Disp:drawCircle(16,56,4,u8g2.U8G2_DRAW_ALL);
Disp:drawCircle(32,56,4,u8g2.U8G2_DRAW_ALL);
Disp:drawCircle(48,56,4,u8g2.U8G2_DRAW_ALL);
Disp:drawCircle(64,56,4,u8g2.U8G2_DRAW_ALL);
for index, value in ipairs(lightArr) do
if value then
Disp:drawDisc(16*index,56,4,u8g2.U8G2_DRAW_ALL);
end
end
Disp:sendBuffer();
--Disp:updateDisplayArea(0,0,64,64);
end
--PageMainScene("DF2","192.168.1.111","V1.0")
--LightArr = {[1]=true,[2]=false,[3]=true,[4]=true}
--PageLight(LightArr)
--LightArr[1] = false;
--PageLight(LightArr)
PageAPNet()

77
README.md

@ -1,3 +1,78 @@ @@ -1,3 +1,78 @@
# WiFiLightController
基于NodeMcu开发的ESP8266物联网LED灯控制设备,接入SSD1306作为配网以及服务显示功能,后续会增加更多功能
---
基于NodeMcu开发的ESP8266物联网LED灯控制设备,接入SSD1306作为配网以及服务显示功能,后续会增加更多功能
## 1.准备工作🧐
#### 1.1设备清单
`数据线等烧录用不在此列`
| 设备名称 | 数量 | 设备型号 |
| ----------- | ------ | --------------------- |
| ESP8266 | 1 | ESP-12F,其他ESP8266可用型号 |
| led灯珠 | 4-5个 | 3v3最低耐压 |
| 电线 | 12-16条 | 常用杜邦线或者其他相似参数 |
| I2C协议OLED屏幕 | 1 | SSD1306_12864_noname |
| USB供电(可选) | 1 | 3.3v引脚供电&5VUSB供电 |
#### 1.2固件烧录
先从该连接,下载 Flash下载工具(flash_download_tool_3.9.5_0.zip),如果有新版本可能名称会有所不同。
[工具 | 乐鑫科技 ](https://www.espressif.com.cn/zh-hans/support/download/other-tools)
下载完之后,将工程下的flash_download_tool_3.9.5.exe打开
![](DocRes\1_1.jpg)
选择ESP8266
![](DocRes\1_2.jpg)
进入如下界面,点击第一项,选择工程下 Firmware里对应的固件文件,由于程序使用的固件版本为float,但未曾写过使用float类型的程序。int没有测试过,保险起见可以选择float版本,右边填0。选择如下所示,串口检测到后点击对应的串口进行烧录即可。
![](DocRes/1_0.jpg)
烧录的波特率默认为115200,运行以及开发用的波特率同理。
#### 1.3程序烧录
首先去github上下载ESPlorer,右侧release可以下载最新的发布版本,可能需要翻墙。
[ESPlorer](https://github.com/4refr0nt/ESPlorer)
下载完成后运行ESPlorer.bat,即可打开该开发工具,然后打开工程的所有lua文件并保存到ESP8266中。目前还处于手动配置网络的阶段,后续会继续优化该配网功能。
## 2.接线说明🔌
NodeMCU开发板引脚图
![](DocRes/NodeMcu_Pinout.webp)
#### 2.1GPIO-LED接线说明
GPIO控制D0-D4,一共五路GPIO供电开关。
| 接线方式 | LED引脚 | ESP8266引脚 |
| ---- | ----- | --------- |
| 直连 | 负极 | GND |
| 直连 | 正极 | D0 |
| 直连 | 正极 | D1 |
| 直连 | 正极 | D2 |
| 直连 | 正极 | D3 |
| 直连 | 正极 | D4 |
#### 2.2SSD1306-12864-I2C接线说明
oled显示屏用于显示配网参数以及连接状态,指示灯状态等信息,方便更快找到设备故障原因。
| 接线方式 | SSD1306-12864-I2C引脚 | ESP8266引脚 |
| ---- | ------------------- | --------- |
| 直连 | GND | GND |
| 直连 | VCC | 3v3 |
| 直连 | SCL | D6 |
| 直连 | SDA | D5 |
`如有其他设备需要接线后续补充`

23
Third_Part_License/Json.lua.txt

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
--
-- json.lua
--
-- Copyright (c) 2020 rxi
--
-- 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.
--

364
Third_Part_License/json.lua

@ -0,0 +1,364 @@ @@ -0,0 +1,364 @@
local json = { _version = "0.1.2" }
-------------------------------------------------------------------------------
-- Encode
-------------------------------------------------------------------------------
local encode
local escape_char_map = {
[ "\\" ] = "\\",
[ "\"" ] = "\"",
[ "\b" ] = "b",
[ "\f" ] = "f",
[ "\n" ] = "n",
[ "\r" ] = "r",
[ "\t" ] = "t",
}
local escape_char_map_inv = { [ "/" ] = "/" }
for k, v in pairs(escape_char_map) do
escape_char_map_inv[v] = k
end
local function escape_char(c)
return "\\" .. (escape_char_map[c] or string.format("u%04x", c:byte()))
end
local function encode_nil(val)
return "null"
end
local function encode_table(val, stack)
local res = {}
stack = stack or {}
-- Circular reference?
if stack[val] then error("circular reference") end
stack[val] = true
if rawget(val, 1) ~= nil or next(val) == nil then
-- Treat as array -- check keys are valid and it is not sparse
local n = 0
for k in pairs(val) do
if type(k) ~= "number" then
error("invalid table: mixed or invalid key types")
end
n = n + 1
end
if n ~= #val then
error("invalid table: sparse array")
end
-- Encode
for i, v in ipairs(val) do
table.insert(res, encode(v, stack))
end
stack[val] = nil
return "[" .. table.concat(res, ",") .. "]"
else
-- Treat as an object
for k, v in pairs(val) do
if type(k) ~= "string" then
error("invalid table: mixed or invalid key types")
end
table.insert(res, encode(k, stack) .. ":" .. encode(v, stack))
end
stack[val] = nil
return "{" .. table.concat(res, ",") .. "}"
end
end
local function encode_string(val)
return '"' .. val:gsub('[%z\1-\31\\"]', escape_char) .. '"'
end
local function encode_number(val)
-- Check for NaN, -inf and inf
if val ~= val or val <= -math.huge or val >= math.huge then
error("unexpected number value '" .. tostring(val) .. "'")
end
return string.format("%.14g", val)
end
local type_func_map = {
[ "nil" ] = encode_nil,
[ "table" ] = encode_table,
[ "string" ] = encode_string,
[ "number" ] = encode_number,
[ "boolean" ] = tostring,
}
encode = function(val, stack)
local t = type(val)
local f = type_func_map[t]
if f then
return f(val, stack)
end
error("unexpected type '" .. t .. "'")
end
function json.encode(val)
return ( encode(val) )
end
-------------------------------------------------------------------------------
-- Decode
-------------------------------------------------------------------------------
local parse
local function create_set(...)
local res = {}
for i = 1, select("#", ...) do
res[ select(i, ...) ] = true
end
return res
end
local space_chars = create_set(" ", "\t", "\r", "\n")
local delim_chars = create_set(" ", "\t", "\r", "\n", "]", "}", ",")
local escape_chars = create_set("\\", "/", '"', "b", "f", "n", "r", "t", "u")
local literals = create_set("true", "false", "null")
local literal_map = {
[ "true" ] = true,
[ "false" ] = false,
[ "null" ] = nil,
}
local function next_char(str, idx, set, negate)
for i = idx, #str do
if set[str:sub(i, i)] ~= negate then
return i
end
end
return #str + 1
end
local function decode_error(str, idx, msg)
local line_count = 1
local col_count = 1
for i = 1, idx - 1 do
col_count = col_count + 1
if str:sub(i, i) == "\n" then
line_count = line_count + 1
col_count = 1
end
end
error( string.format("%s at line %d col %d", msg, line_count, col_count) )
end
local function codepoint_to_utf8(n)
-- http://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=iws-appendixa
local f = math.floor
if n <= 0x7f then
return string.char(n)
elseif n <= 0x7ff then
return string.char(f(n / 64) + 192, n % 64 + 128)
elseif n <= 0xffff then
return string.char(f(n / 4096) + 224, f(n % 4096 / 64) + 128, n % 64 + 128)
elseif n <= 0x10ffff then
return string.char(f(n / 262144) + 240, f(n % 262144 / 4096) + 128,
f(n % 4096 / 64) + 128, n % 64 + 128)
end
error( string.format("invalid unicode codepoint '%x'", n) )
end
local function parse_unicode_escape(s)
local n1 = tonumber( s:sub(1, 4), 16 )
local n2 = tonumber( s:sub(7, 10), 16 )
-- Surrogate pair?
if n2 then
return codepoint_to_utf8((n1 - 0xd800) * 0x400 + (n2 - 0xdc00) + 0x10000)
else
return codepoint_to_utf8(n1)
end
end
local function parse_string(str, i)
local res = ""
local j = i + 1
local k = j
while j <= #str do
local x = str:byte(j)
if x < 32 then
decode_error(str, j, "control character in string")
elseif x == 92 then -- `\`: Escape
res = res .. str:sub(k, j - 1)
j = j + 1
local c = str:sub(j, j)
if c == "u" then
local hex = str:match("^[dD][89aAbB]%x%x\\u%x%x%x%x", j + 1)
or str:match("^%x%x%x%x", j + 1)
or decode_error(str, j - 1, "invalid unicode escape in string")
res = res .. parse_unicode_escape(hex)
j = j + #hex
else
if not escape_chars[c] then
decode_error(str, j - 1, "invalid escape char '" .. c .. "' in string")
end
res = res .. escape_char_map_inv[c]
end
k = j + 1
elseif x == 34 then -- `"`: End of string
res = res .. str:sub(k, j - 1)
return res, j + 1
end
j = j + 1
end
decode_error(str, i, "expected closing quote for string")
end
local function parse_number(str, i)
local x = next_char(str, i, delim_chars)
local s = str:sub(i, x - 1)
local n = tonumber(s)
if not n then
decode_error(str, i, "invalid number '" .. s .. "'")
end
return n, x
end
local function parse_literal(str, i)
local x = next_char(str, i, delim_chars)
local word = str:sub(i, x - 1)
if not literals[word] then
decode_error(str, i, "invalid literal '" .. word .. "'")
end
return literal_map[word], x
end
local function parse_array(str, i)
local res = {}
local n = 1
i = i + 1
while 1 do
local x
i = next_char(str, i, space_chars, true)
-- Empty / end of array?
if str:sub(i, i) == "]" then
i = i + 1
break
end
-- Read token
x, i = parse(str, i)
res[n] = x
n = n + 1
-- Next token
i = next_char(str, i, space_chars, true)
local chr = str:sub(i, i)
i = i + 1
if chr == "]" then break end
if chr ~= "," then decode_error(str, i, "expected ']' or ','") end
end
return res, i
end
local function parse_object(str, i)
local res = {}
i = i + 1
while 1 do
local key, val
i = next_char(str, i, space_chars, true)
-- Empty / end of object?
if str:sub(i, i) == "}" then
i = i + 1
break
end
-- Read key
if str:sub(i, i) ~= '"' then
decode_error(str, i, "expected string for key")
end
key, i = parse(str, i)
-- Read ':' delimiter
i = next_char(str, i, space_chars, true)
if str:sub(i, i) ~= ":" then
decode_error(str, i, "expected ':' after key")
end
i = next_char(str, i + 1, space_chars, true)
-- Read value
val, i = parse(str, i)
-- Set
res[key] = val
-- Next token
i = next_char(str, i, space_chars, true)
local chr = str:sub(i, i)
i = i + 1
if chr == "}" then break end
if chr ~= "," then decode_error(str, i, "expected '}' or ','") end
end
return res, i
end
local char_func_map = {
[ '"' ] = parse_string,
[ "0" ] = parse_number,
[ "1" ] = parse_number,
[ "2" ] = parse_number,
[ "3" ] = parse_number,
[ "4" ] = parse_number,
[ "5" ] = parse_number,
[ "6" ] = parse_number,
[ "7" ] = parse_number,
[ "8" ] = parse_number,
[ "9" ] = parse_number,
[ "-" ] = parse_number,
[ "t" ] = parse_literal,
[ "f" ] = parse_literal,
[ "n" ] = parse_literal,
[ "[" ] = parse_array,
[ "{" ] = parse_object,
}
parse = function(str, idx)
local chr = str:sub(idx, idx)
local f = char_func_map[chr]
if f then
return f(str, idx)
end
decode_error(str, idx, "unexpected character '" .. chr .. "'")
end
function json.decode(str)
if type(str) ~= "string" then
error("expected argument of type string, got " .. type(str))
end
local res, idx = parse(str, next_char(str, 1, space_chars, true))
idx = next_char(str, idx, space_chars, true)
if idx <= #str then
decode_error(str, idx, "trailing garbage")
end
return res
end
return json

46
UDPService.lua

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
-- UDPSocket = nil;
-- UDPIP = nil;
-- UDPPort = nil;
require("GPIO");
function StartUDPService()
if UDPSocket == nil then
UDPSocket = net.createUDPSocket();
UDPSocket:listen(5000);
UDPSocket:on("receive", UDPService);
UDPPort, UDPIP = UDPSocket:getaddr();
else
UDPSocket:listen(5000);
UDPSocket:on("receive", UDPService);
UDPPort, UDPIP = UDPSocket:getaddr();
end
--print(string.format("local UDP socket address / port: %s:%d", UDPIP, UDPPort))
end
function UDPService(s, data, port, ip)
local commandSet = {};
for word in string.gmatch(data, "[^-]+") do
table.insert(commandSet,word);
end
print("get data count" .. #commandSet);
if string.match(data,"^Light") then
if #commandSet==3 then
print(tonumber(commandSet[2]).."-"..commandSet[3])
if commandSet[3]=="On" and tonumber(commandSet[2])~=nil then
GPIOOn(tonumber(commandSet[2]));
s:send(port, ip, "Light "..commandSet[2].." "..commandSet[3]);
elseif commandSet[3]=="Off" and tonumber(commandSet[2])~=nil then
GPIOOff(tonumber(commandSet[2]));
s:send(port, ip, "Light "..commandSet[2].." "..commandSet[3]);
else
s:send(port, ip, "CommandFaild");
end
end
end
end
function StopUDPService()
if UDPSocket ~= nil then
UDPSocket:close();
end
end
--StartUDPService();

46
WifiMgr.lua

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
StationCfg = {}
IpCfg = {}
function AutoLink()
wifi.setmode(wifi.STATION)
StationCfg.ssid="DF2"
StationCfg.pwd="wodepasstne?"
StationCfg.save=true
wifi.sta.config(StationCfg)
wifi.sta.connect()
end
--mobile setting ap and passwd
function AutoLinkByMobile()
wifi.setmode(wifi.STATIONAP)
wifi.ap.config({ssid="MyPersonalSSID", auth=wifi.OPEN})
enduser_setup.manual(true)
enduser_setup.start(
function()
print("Connected to WiFi as:" .. wifi.sta.getip())
end,
function(err, str)
print("enduser_setup: Err #" .. err .. ": " .. str)
end
)
print("init endUserServer")
end
--GetAPList
-- function Listap(t)
-- for k,v in pairs(t) do
-- print(k.." : "..v)
-- end
-- end
-- wifi.sta.getap(Listap)
function SetIP(ipAddress,netmask,gateway)
IpCfg = {
ip = ipAddress,
netmask = netmask,
gateway = gateway
}
wifi.sta.setip(IpCfg)
end
--SetIP("192.168.1.115","255.255.255.0","192.168.1.1")

12
init.lua

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
--Start with this file
--这个文件初始化会执行
require("GPIO")
require("OLED_SSD1306")
require("WifiMgr")
require("UDPService")
function Init()
SetIP("192.168.1.115","255.255.255.0","192.168.1.1");
AutoLink();
StartUDPService();
end
Init();
Loading…
Cancel
Save