Bläddra i källkod

add readme.md

mrh 10 månader sedan
incheckning
d991173c8d
10 ändrade filer med 509 tillägg och 0 borttagningar
  1. 3 0
      .gitignore
  2. 18 0
      light-led.py
  3. 32 0
      light-sensor.py
  4. 10 0
      light-serial.py
  5. 23 0
      main.py
  6. 77 0
      mywifi.py
  7. 198 0
      readme-light-sensor.md
  8. 38 0
      readme.md
  9. 81 0
      test.py
  10. 29 0
      work_led.py

+ 3 - 0
.gitignore

@@ -0,0 +1,3 @@
+.mpyproject.json
+video
+.vscode

+ 18 - 0
light-led.py

@@ -0,0 +1,18 @@
+import time
+from machine import ADC,Pin
+adc = ADC(Pin(34), atten=ADC.ATTN_11DB)        # create an ADC object acting on a pin
+led = Pin(18, Pin.OUT)
+
+def ctrl_led(current):
+    if current > 30000:
+        led.off()
+    if current < 27000:
+        led.on()
+
+while True:
+    val = adc.read_u16()  # read a raw analog value in the range 0-65535
+    ctrl_led(val)
+    wdat = 'val:{}'.format(val)
+    print(wdat, end='\x08' * len(wdat))
+    time.sleep(0.03)
+    print(' ' * len(wdat), end='\x08' * len(wdat))

+ 32 - 0
light-sensor.py

@@ -0,0 +1,32 @@
+from sys import stdout
+from machine import ADC,Pin
+import uasyncio
+
+def led_s():
+    cn1 = Pin(18, Pin.OUT)
+    init_value = -1
+    pin_value = 0
+    def ctrl_led(current_value):
+        nonlocal init_value,pin_value
+        if init_value == -1:
+            init_value = current_value
+            print('led init_value:', init_value)
+        elif current_value > init_value + 3000:
+            cn1.off()
+        else:
+            cn1.on()
+    return ctrl_led
+
+async def sensor():
+    adc = ADC(Pin(34), atten=ADC.ATTN_11DB)        # create an ADC object acting on a pin
+    ctrl_led = led_s()
+    while True:
+        val = adc.read_u16()  # read a raw analog value in the range 0-65535
+        ctrl_led(val)
+        wdat = 'val:{}'.format(val)
+        print(wdat, end='\x08' * len(wdat))
+        await uasyncio.sleep_ms(50)
+        print(' ' * len(wdat), end='\x08' * len(wdat))
+
+if __name__ == '__main__':
+    uasyncio.run(sensor())

+ 10 - 0
light-serial.py

@@ -0,0 +1,10 @@
+from machine import Pin
+import time
+cn1 = Pin(18, Pin.OUT)
+while True:
+    cn1.on()
+    print('on')
+    time.sleep(1)
+    cn1.off()
+    print('off')
+    time.sleep(1)

+ 23 - 0
main.py

@@ -0,0 +1,23 @@
+import time
+#from mywifi import my_wifi
+from work_led import WorckLed
+
+class Device():
+    _instance = None
+    # 单例模式:WiFi实例化只能有一次,实例化多个 mywifi 对象将始终返回同一个-
+    def __new__(cls, *args, **kwargs):
+        if cls._instance is None:
+            cls._instance = super().__new__(cls)
+        return cls._instance   # 返回的是内存地址
+
+    def __init__(self) -> None:
+        print("device init")
+        self.wled= WorckLed(2)
+
+
+def main():    
+    wled= WorckLed(2)
+    
+
+if __name__ == '__main__':
+    main()

+ 77 - 0
mywifi.py

@@ -0,0 +1,77 @@
+import network
+from machine import Timer
+SSID = "Xiaomi_eng"
+# SSID = "Mi11_eng"
+PASSWORD = "88888888"
+
+class MyWifi():
+    # _instance = None
+    # _first_init = True
+
+    # def __new__(cls, *args, **kwargs):
+    #     if cls._instance is None:
+    #         cls._instance = super().__new__(cls)
+    #     return cls._instance   # 返回的是内存地址
+
+    # WiFi 不能被初始化两次,否则会发生内部错误
+    # 注意,在重复导入模块时,已经被算作初始化了,如果另一个模块又导入了这个类,很容易重复实例化一个新的WiFi对象
+    # 避免重复 init,因为那些值会被重新初始化
+    def __init__(self, ssid=SSID, password=PASSWORD) -> None:
+        self.wlan = network.WLAN(network.STA_IF)            
+        self.ssid = ssid
+        self.password = password
+        self.tim = Timer(0)
+        self.s = {'status': 'start connect', 'count': 0, 'check_count': 3}
+        self.tim.init(period=1, mode=Timer.ONE_SHOT,callback=self.check_disconnect)
+
+
+    def check_disconnect(self, timer):
+        self.tim.init(period=1000, mode=Timer.ONE_SHOT,
+                    callback=self.check_disconnect)
+        if self.s['status'] == 'start connect':
+            if not self.wlan.isconnected():
+                print("Start connect to wifi:", self.ssid)
+                self.wlan.active(True)
+                self.wlan.connect(self.ssid, self.password)
+                print('connecting to network...', self.ssid)
+            self.s['status'] = 'check isconnected'
+            self.tim.init(period=1, mode=Timer.ONE_SHOT,
+                        callback=self.check_disconnect)
+        elif self.s['status'] == 'check isconnected':
+            if self.wlan.isconnected():
+                self.s['count'] = 0
+                self.s['status'] = 'recheck'
+                print('Connection successful:', self.wlan.ifconfig())
+            else:
+                print('try to connect to network...', self.s['count'])
+                self.s['count'] += 1
+                # 设置连接超时时间
+                if self.s['count'] > self.s['check_count']:
+                    self.s['status'] = 'recheck'
+                    self.s['count'] = 0
+        elif self.s['status'] == 'recheck':
+            if not self.wlan.isconnected():
+                self.wlan.active(False)
+                print('error: wifi disconnect')
+                self.s['status'] = 'start connect'
+
+    def _do_connect(self, recheck=False):
+        if not self.wlan.isconnected():
+            self.wlan.active(True)
+            self.wlan.connect(self.ssid, self.password)
+            print('connecting to network...', self.ssid)
+            while not self.wlan.isconnected():
+                pass
+        print('network config:', self.wlan.ifconfig())
+
+    def get_wifi_addr(self):
+        return self.get_wifi_ifconfig()[0]
+
+    def get_wifi_ifconfig(self):
+        # 等待 check_disconnect() WiFi连接成功再返回
+        while not self.s['status'] == 'recheck':
+            pass
+        # 返回: ('192.168.31.123', '255.255.255.0', '192.168.31.1', '192.168.31.1')
+        return self.wlan.ifconfig()
+    
+my_wifi = MyWifi()

+ 198 - 0
readme-light-sensor.md

@@ -0,0 +1,198 @@
+# 硬件
+
+## 开发板
+
+参考:
+
+https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/hw-reference/esp32/get-started-devkitc.html
+
+![img](F:\Engineer\Engineer_sync\Typora-img\readme-light-sensor\esp32-devkitC-v4-pinout.png)
+
+
+
+### esp32 引脚图
+
+![img](https://img-blog.csdnimg.cn/20210717100620172.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTY1MjQ0NA==,size_16,color_FFFFFF,t_70)
+
+![img](https://img-blog.csdnimg.cn/20210717100659835.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NTY1MjQ0NA==,size_16,color_FFFFFF,t_70)
+
+
+
+
+
+## 电路图
+
+嘉立创EDA标准版 light-sensor
+
+
+
+# ADC
+
+MicroPython 参考:http://docs.micropython.org/en/latest/esp32/quickref.html#adc-analog-to-digital-conversion
+
+## 基准电压
+
+ADC的基准电压是1.8V,因此接3.3V分压光敏电阻,很难达到1.8V以下
+
+光敏分压始终在2~3.3V,参考MicroPython文档,可以将atten关键字设置增益,让它能读取超过1.8V的电压
+
+![image-20220720224520754](F:\Engineer\Engineer_sync\Typora-img\readme-light-sensor\image-20220720224520754.png)
+
+```Python
+    adc = ADC(Pin(34),atten=ADC.ATTN_11DB)        # create an ADC object acting on a pin
+
+    while True:
+        val = adc.read_u16()  # read a raw analog value in the range 0-65535
+        print('val16:', val)
+        time.sleep(1)
+```
+
+不过遗憾的是,在夜间开灯的情况下,分压仍有1.82V,val = 65536(8.5kΩ),意味着光线稍暗可能就一直检测不到了
+
+开了台灯直射,0.7V ,val = 47307(1.9KΩ),情况可能不好,因为如果氛围灯比较暗,可能就不行了
+
+解决办法:
+
+1. 更换亮电阻为 5K以下的光敏电阻
+2. 把电压改为1.8V,这样一来光敏电阻分压最高也只能达到1.8V
+3. 把分压电阻改为20K以上,10/(10+20) * 3.3 = 1.09
+
+
+
+**改用2~5K的光敏电阻**
+
+5506 光敏电阻
+
+https://detail.tmall.com/item.htm?id=536099588726&spm=a1z09.2.0.0.64fa2e8dKXGjcQ&_u=kucunghf639
+
+5/(5+20) * 3.3 = 0.66V
+
+
+
+# 方案评估
+
+## ADC电路
+
+### 直连ADC引脚
+
+单个光敏电阻时,直接连接ADC
+
+多个光敏电阻,连接多个IO口的ADC
+
+
+
+### 单片机IIC协议ADC
+
+可以在每个光敏接便宜的单片机,不过成本较高 0.4~0.8元,也需要额外开发程序
+
+
+
+### ADC芯片扩展IO口
+
+ADC芯片成本1.5元左右,最多能扩展6~8个ADC引脚,其实和单独连另一个单片机的方式差不多
+
+
+
+### ADC分时复用(推荐)
+
+#### 4 IO扩展8通道
+
+使用模拟开关多路复用芯片。成本 0.4元左右,如CD4051BM
+
+地址控制IO数量:3
+
+占用ADC引脚:1
+
+综上,仅需4个引脚就能扩展8个ADC
+
+#### 4 IO 扩展16+通道
+
+如果要扩展 16 个ADC,需要外接移位寄存器,如74HC595A (富满)0.4元,占用3个IO口SCK、RCK、SER,30MHZ,约9个时钟周期完成一次串行数据传输。每次传输大约耗费 1/30Mhz * 9 = 0.3 us
+
+
+
+
+
+## led及驱动
+
+### 彩灯灯串
+
+电压:2节1.25V = 2.5V
+
+电流:1.96ma
+
+电阻:单条电线4.6Ω
+
+灯串大约有30个LED灯,全部以并联的方式连接。
+
+灯串上没有接限流电阻,单条线仅4.6Ω,由伏安特性可知,LED是非线性元件,增加一点点电压会造成电流大幅度增加,当电压超过2V,如果没有加限流电阻,电流瞬间会达到几百毫安甚至几安,容易使灯串烧毁。
+
+![image-20220709033416930](F:\Engineer\Engineer_sync\Typora-img\readme-light-sensor\image-20220709033416930.png)
+
+上图是从立创商城的led 0603 数据手册截取而来,大多led灯典型电压都是 1.8~2.4V,不知道这个灯串为什么可以连接高达3V,甚至5V还能保持正常。猜测可能是LED款式不一样。
+
+通电 5V,15MA
+
+4.5,9.9
+
+4V,6.5MA
+
+
+
+
+
+
+
+### 三极管
+
+esp上电默认低电平,应选择NPN
+
+三极管自带管压降,需使用高于 3.3 + 0.7V 的电源,因为LED正常亮度需要 3.3V左右
+
+电流 200mA 以内
+
+价格:比较实惠,0.03元一个,限流电阻0.004忽略不计
+
+#### S9011三极管
+
+数字万用表测量:
+
+档位调整到hFE,确定万用表是NPN还是PNP,插入到数字万用表对应的孔位中,有数值显示说明电极对应。
+
+我的三极管s9011,圆弧面是背面,平面是正面,从左到右分别是EBC。
+
+PS:网上的引脚图不正确。
+
+平视图为三极管平面,从左到右接:正极、门极、负极
+
+工作时管压降1.7V
+
+**注意:led管压降为0.7V,而三极管导通时管压降有1.7V,串联到开关上意味着有2.4V的工作电压,如果电池串联电压低于2.4V,它们的PN结处于完全截止的状态,led是无法工作的。电源必须要大于截止电压才能工作**。
+
+实测2.6V时,灯串处于完全截止状态,看不到任何亮光。
+
+
+
+### ULN2003
+
+价格:0.7元 7路控制,平均每路 0.1 元
+
+每路电流 500mA
+
+
+
+
+
+### 74HC595
+
+74HC595是一款专用的led驱动芯片
+
+可以接单路50mA以内的负载,对于灯串绰绰有余
+
+占用IO口较少
+
+缺点是需要开发驱动程序,PWM调光更加麻烦
+
+
+
+综上,如果驱动通路较少,可以选用三极管

+ 38 - 0
readme.md

@@ -0,0 +1,38 @@
+# 光敏传感器与LED控制项目
+
+## 项目简介
+本项目基于 MicroPython,运行在 ESP32 开发板上,旨在通过光敏电阻检测环境光强度,并根据检测结果控制 LED 的行为(如闪烁或常亮)。项目适用于智能家居、自动化照明等场景。
+
+## 硬件需求
+- **开发板**:ESP32 DevKitC V4
+- **光敏电阻**:推荐使用 2~5K 的光敏电阻(如型号 5506)。
+- **LED 灯**:支持 PWM 控制的 LED 灯串。
+- **其他元件**:限流电阻、三极管(如 S9011)、ULN2003 驱动芯片(可选)。
+
+## 软件功能
+1. **光敏电阻读取**:通过 ADC 模块读取光敏电阻的电压值,判断环境光强度。
+2. **LED 控制**:根据光敏电阻的读数,动态调整 LED 的亮度或开关智能灯。
+3. **定时器功能**:使用定时器实现 LED 的周期性闪烁。
+
+## 文件结构
+```
+.
+├── main.py          # 主程序入口
+├── work_led.py      # LED 控制逻辑
+├── light-sensor.py  # 光敏电阻读取逻辑
+├── mywifi.py        # WiFi 配置(未启用)
+└── readme.md        # 项目说明文档
+```
+
+## 使用方法
+1. 将项目文件上传至 ESP32 开发板。
+2. 连接光敏电阻至指定 GPIO 引脚(如 GPIO34)。
+3. 连接 LED 灯至指定 GPIO 引脚(如 GPIO2)。
+4. 运行 `main.py`,观察 LED 的行为变化。
+
+## 参考资料
+- [ESP32 开发板参考](https://docs.espressif.com/projects/esp-idf/zh_CN/latest/esp32/hw-reference/esp32/get-started-devkitc.html)
+- [MicroPython ADC 文档](http://docs.micropython.org/en/latest/esp32/quickref.html#adc-analog-to-digital-conversion)
+
+---
+如有问题,请联系项目维护者。

+ 81 - 0
test.py

@@ -0,0 +1,81 @@
+# 线程
+import _thread#创建线程有关的函数
+import time#延时
+def testThread():#定义新建线程中执行的函数
+  while True:
+    print("Hello from thread")
+    time.sleep(2)#延时两秒
+
+_thread.start_new_thread(testThread, ())#启动线程
+print("start thread")
+
+# 文件/夹删除与创建
+import os
+help(os)
+os.mkdir("MicroWebSrv/www")
+os.listdir()
+os.rmdir('MicroWebSrv')
+# 递归删除
+def rmdir(dir):
+    #判断是否是文件夹,如果是,递归调用rmdir()函数
+    if(os.path.isdir(dir)):
+        #遍历地址下的所有文件及文件夹
+        for file in os.listdir(dir):
+            #进入下一个文件夹中进行删除
+            rmdir(os.path.join(dir,file))
+        #如果是空文件夹,直接删除
+        if (os.path.exists(dir)):
+            os.rmdir(dir)
+            print(dir,"文件夹删除成功")
+    #如果是文件,直接删除
+    else:
+        if(os.path.exists(dir)):
+            os.remove(dir)
+            print(dir,"文件删除成功")
+#调用定义函数
+rmdir("文件夹地址")
+
+
+
+# 查看内存空间
+import micropython
+micropython.mem_info()
+
+# 查看 flash 空间
+'''
+bsize:block size 块大小,文件存取的最小单位,4096 表示文件存取的最小单位为 4K。
+bfree:block free 剩余块。
+剩余空间计算公式:bsize * bfree,单位是字节
+'''
+import ubinascii
+import os
+statvfs_fields = ['bsize','frsize','blocks','bfree','bavail','files','ffree',]
+dict(zip(statvfs_fields, os.statvfs('/')))
+import gc
+gc.mem_free()
+
+
+# 读取文件
+import os
+with open('main.py', 'r+') as f:
+    c = f.read(1024)
+    print(c)
+import os
+help(print)
+os.listdir()
+os.remove('main.py')
+# 移动文件
+os.rename('microWebSrv.py', 'MicroWebSrv/microWebSrv.py')
+os.listdir('MicroWebSrv')
+os.remove('.mpyproject.json')
+import mywifi
+print(mywifi.MyWifi().get_ifconfig())
+
+# 定时器
+from machine import Timer
+def pt(tim):
+    print('ok')
+tim = Timer(0)
+tim.init(period=500, callback=pt)
+# 交互模式
+execfile('mywifi.py')

+ 29 - 0
work_led.py

@@ -0,0 +1,29 @@
+from machine import Pin, PWM
+import time
+from machine import Timer
+
+class WorckLed:
+    def __init__(self, pin_num) -> None:
+        self.led = Pin(pin_num, Pin.OUT)
+        self.led.value(0)
+
+        self.led = PWM(Pin(pin_num))
+        self.led.freq(1000)
+        self.led_status = 0
+        self.led_blink_time = {'on': 40, 'off': 800}
+        self.tim = Timer(1)
+        self.led_on(None)
+        
+    def led_on(self, timer):
+        self.led.duty(100)
+        self.tim.init(period=self.led_blink_time['on'], mode=Timer.ONE_SHOT,
+                      callback=self.led_off)
+
+    def led_off(self, timer):
+        self.led.duty(0)
+        self.tim.init(period=self.led_blink_time['off'], mode=Timer.ONE_SHOT,
+                      callback=self.led_on)
+
+
+if __name__ == '__main__':
+    WorckLed(2)