2021-11-24 micropython esp32休眠假死 唤醒 rtc nvs btree数据保持

首先本次记录时MICROPYTHON 在ESP32环境下的记录,这里需要声明你使用的micropython 的版本固件不应该太古老,根据我的经验,有些早期固件不支持以下测试,或者不具备相应功能,固件嘛一般都是新的好,新的功能以及更少的BUG, 不像语言,太新的版本反而会出现兼容问题。我本次的固件版本为2021年9月版本的固件,已经证实的是2018年的固件不能支持下面的内容。

本次记录是一些关于低功耗方面的偏向于底层控制,大量的使用了machine模块,以及如何唤醒与数据保持的零散记录。

  1. 命令重启指令,这个是遇到异常的补救手段,因主动性强放在首位
machine.reset() # 命令重启
machine.reset_cause()	#复位原因:返回数字1-5 ,1-5意思见如下说明
复位原因	说明
1 machine.PWRON_RESET	电源复位  
2 machine.HARD_RESET	硬重置(断电)
3 machine.WDT_RESET	看门狗复位
4 machine.DEEPSLEEP_RESET	深度睡眠
5 machine.SOFT_RESET	软复位
  1. 改变频率运行,在节省功耗的部分情况下可以调整CPU运行频率,但是也可能因为对频率调整后影响某些时序封装后的指令,所以可以尝试使用,有异常优先调整回默认频率~
machine.freq()  #查询运行频率
#默认为160MHZ
machine.freq(160000000)  #设置运行频率 可设定参数为 20MHz, 40MHz, 80Mhz, 160MHz ,240MHz 
  1. 硬件休眠 ,分为假死状态和全死状态~~里面的参数是保持死状态的毫秒时间 ,5000就是5秒,不带参数就是死下去,等待设定好条件状态唤醒。
machine.sleep(5000)	停止CPU并禁用除了WLAN(如果存在)之外的全部外设。(不推荐)
machine.lightsleep (5000) 假死状态,随时唤醒,功耗大幅度降低(据说降低到百分之一不到),优点是保持了系统一定活性,不丢失运行数据也可以从睡眠点继续执行程序,类似假死
machine.deepsleep(5000)	停止 CPU 和所有外设 (包括网络)。全死状态(据说功耗和关机差不多),唤醒时类似复位一样从头运行,可以 reset_cause() 了解复位原因是不是深度睡眠

复活术:中断复活,可以复活两种低功耗的死状态,采用的是中断触发的方式,这个引脚可不是随便用的,不支持会报错的大约可用的引脚是 14 ,12 ,13,25啥的,自己测试,记得报错了就换引脚,程序肯定没问题

import esp32 , machine ,time
wake1 = machine.Pin(25, mode = machine.Pin.IN)
esp32.wake_on_ext0(pin = wake1, level = esp32.WAKEUP_ALL_LOW)
#esp32.wake_on_ext0  中断唤醒 ,这个比较常用
#esp32.wake_on_ext1  据说是WLAN唤醒。。。。没测试觉得没啥大用
#pin = 传入一个PIN输入对象
#level = esp32.WAKEUP_ALL_LOW  低电平唤醒
#level = esp32.WAKEUP_ANY_HIGH 高电平唤醒
print('10秒后失眠~')
time.sleep(10)
#主函数没有这个睡眠小心一睡不起只能刷固件~~~
machine.deepsleep() # machine.ligthsleep()
  1. RTC存储器,这是一个不断电就能持续保持数据的存储器,
    尤其是其可以在deepsleep状态下保持数据,只要不断电就能保持,但是板子的RST复位按钮引起的复位数据会丢失,它的用法如下,注意:只能接受字符串类型,我们可以用JSON把数据包装好给他,也很方便
import machine
import json
rtc = machine.RTC()
data=json.dumps([1,2,3,4,5])
rtc.memory(data)  # 写入存储器
#rtc.memory('12345')
rec_data=rtc.memory() #从存储器读出数据
  1. NVS非易失存储
    首先,这个是非易失存储也就是断电不掉的存储方式,这个方式可以长期保持数据,理论上可以存储数字和字符串但是~
import esp32
a=esp32.NVS('abc') # abc是命名空间,也就是实例化的开辟了一个叫abc的世界
a.set_i32('a1',1) # 在实例化的命名空间中存入一个键值对,值必须为32位有正负的整数  {'a1':1}
a.set_blob('a2','sdf') #存入一个字符串型的键值对
a.commit() #### 把存好的数据刷入实例化的命名空间,必须有这个否则不存
a.get_i32('a1') #在实例化的空间中取出'a1'的值
a.erase_key('a1') #删除这个键值

下面这部分是关于取出.set_blob()这部分的,这部分资料比较少官方文档也说得不清不楚的,我就单独写一下取出字符串部分的具体流程,重点有俩,1、存的时候COMMIT()别忘记2、取字符串内容先建立缓冲区再去取,返回值是长度,内容在缓冲区里边,解码即可获取。

from esp32 import NVS

nvs = NVS("abc")

blob1 = "wo shi yi ge xiao niao "  #要写入NVS的字符串

nvs.set_blob("blob1", blob1)   #写入方式

nvs.commit()  #刷入NVS

buf1 = bytearray(50) #准备缓冲区,大小为50

len1 = nvs.get_blob("blob1", buf1)  #取出blob1的内容,写入缓冲区buf1中,返回长度给len1

print(len1,buf1.decode()) #打印下长度和内容,注意必须解码

buf1[:len1] #如果直接存入bytearray类型的数据就不用解码,按照左边的写法就能截取,这个地方DS18B20多设备挂在一个口上时作为设备地址存储时测试的。
例如如下情况:
>>> from esp32 import NVS
>>>> n=NVS('KK')
>>> n.set_blob('ss',bytearray(b'(8a\x96\xf0\x01<2'))
>>> n.commit()
>>> yy=bytearray(100)
>>> kk=n.get_blob('ss',yy)
>>> kk
8
>>> yy[:kk]
bytearray(b'(8a\x96\xf0\x01<2')

  1. 然后,我平时断电保持一般会采用btree简单数据库的形式,下面这个是一次开发的读写封装的类,用它代替NVS就可以,如果要好好使用可以自行仔细改一改,这个数据库支持
import btree
class btree_r_w(object):
    def write_btree(self,b_id,b_name): #传入参数必须是二进制字符串例如 b'1',b'gao'
        try:
            f = open("mydb", "r+b")
        except OSError:
            f = open("mydb", "w+b")
        db = btree.open(f)
        db[b_id] =b_name
        db.flush()
        db.close()
        f.close()
    def read_btree(self,b_id): #传入参数必须是二进制字符串例如 b'1',有返回值
        try:
            f = open("mydb", "r+b")
        except OSError:
            f = open("mydb", "w+b")
        db = btree.open(f)
        name = db.get(b_id)
        db.close()
        f.close()
        return name
if __name__=='__main__':
	a=btree_r_w()#实例化
	a.write_btree(b'1',b'gk')#写
	data= a.read_btree(b'1')#读
	print(data)

下面是官方的btree例程文档粘贴在下面便于查询

import btree

# First, we need to open a stream which holds a database
# This is usually a file, but can be in-memory database
# using io.BytesIO, a raw flash partition, etc.
# Oftentimes, you want to create a database file if it doesn't
# exist and open if it exists. Idiom below takes care of this.
# DO NOT open database with "a+b" access mode.
try:
    f = open("mydb", "r+b")
except OSError:
    f = open("mydb", "w+b")

# Now open a database itself
db = btree.open(f)

# The keys you add will be sorted internally in the database
db[b"3"] = b"three"
db[b"1"] = b"one"
db[b"2"] = b"two"

# Assume that any changes are cached in memory unless
# explicitly flushed (or database closed). Flush database
# at the end of each "transaction".
db.flush()

# Prints b'two'
print(db[b"2"])

# Iterate over sorted keys in the database, starting from b"2"
# until the end of the database, returning only values.
# Mind that arguments passed to values() method are *key* values.
# Prints:
#   b'two'
#   b'three'
for word in db.values(b"2"):
    print(word)

del db[b"2"]

# No longer true, prints False
print(b"2" in db)

# Prints:
#  b"1"
#  b"3"
for key in db:
    print(key)

db.close()

# Don't forget to close the underlying stream!
f.close()

你可能感兴趣的:(micropython,python,开发语言,后端)