干货!esp8266+ds3231低功耗解决方案,在特定时间唤醒

最近首次接触esp8266,也是第一次接触硬件,在一个墨水屏日历项目上遇到了低功耗问题,特此记录。
此墨水屏日历不需要一直处于启动状态,我希望它每几小时或者每天启动一次即可。

解决方案 1:仅使用内部 RTC

通过将GPIO16引脚与RST引脚连接,在内部使用ESP.deepSleep(微秒)进行倒计时唤醒,此方案有个很大的问题,就是8266内部的RTC非常不准确,受环境温度影响较大,每小时可能会偏差几分钟,同时,由于硬件限制,其最大只支持4294967295us,约 ~71 分钟左右,无法直接设置到预期时间再唤醒。

解决方案2:定期唤醒 MCU 并检查外部 RTC

通过外接ds3231高精度时钟来对时间进行精确控制,此方案需要频繁启动设备并读取外部RTC的时间(如每10分钟),时间未到则继续休眠,不是最优解

解决方案 3:在外部 RTC 上设置闹钟以唤醒 MCU

通过外接ds3231,并使用其闹钟功能唤醒MCU,但是在直接链接其SQW引脚到MUC的RST引脚上后发现,无法唤醒(中断也试过,在进入deepsleep模式后无法响应中断)
在阅读了这个页面Deep sleep wake ESP8266 with DS3231 RTC alarm后,我找到了答案
需要制作这样一个单稳态电路,小白看了也不要怕,只要认真看一看电路你也能做出来的
在这里插入图片描述
某宝下单:在这里插入图片描述
焊接,就得到了它:
在这里插入图片描述
根据电路图将引脚连接好后,测试,成功。
测试代码:

#include <DS3231.h>
#include <Wire.h>

DS3231 rtc;

#define SDA_PIN D6 // 针脚定义
#define SCL_PIN D7 // 针脚定义
#define DS3231VCC D5 // ds3231 vcc针脚定义,用于控制其外部电源

void setup()
{

  // Begin Serial communication
  Serial.begin(115200);
  pinMode(DS3231VCC, OUTPUT);
  delay(100);
  digitalWrite(DS3231VCC, HIGH);

  delay(1000);

  Wire.begin(SDA_PIN, SCL_PIN);

  delay(100);

  Serial.println("........");
  Serial.println("........");
  Serial.println("........");

  DateTime now = RTClib::now();
  Serial.print("现在:");
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  Serial.print(now.second(), DEC);
  Serial.println("");

  const uint32_t interval = 20;                     // 当前时间+20s后唤醒
  DateTime currentTime;                             
  currentTime = RTClib::now();                      
  uint32_t currentSeconds = currentTime.unixtime(); 
  DateTime alarmTime(currentSeconds + interval);

  Serial.print("唤醒时间:");
  Serial.print(alarmTime.hour(), DEC);
  Serial.print(':');
  Serial.print(alarmTime.minute(), DEC);
  Serial.print(':');
  Serial.print(alarmTime.second(), DEC);
  Serial.println("");

  rtc.setA1Time(
      alarmTime.day(),    
      alarmTime.hour(),  
      alarmTime.minute(), 
      alarmTime.second(), 
      0x00001110,         // AlarmBits = signal when the seconds match
      false,              // A1Dy  false = A1Day means the date in the month;
      //       true = A1Day means the day of the week
      false, // A1h12 false = A1Hour in range 0..23;
      //       true = A1Hour in range 1..12 AM or PM
      false // A1PM  false = A1Hour is a.m.;
            //       true = A1Hour is p.m.
  );

  rtc.turnOffAlarm(1); // clear the A1 enable bit in register 0Eh
  rtc.checkIfAlarm(1); // clear the A1 alarm flag bit in register 0Fh
  rtc.checkIfAlarm(2); // clear the A1 alarm flag bit in register 0Fh
  rtc.turnOnAlarm(1);  // set the A1 enable bit in register 0Eh

  digitalWrite(DS3231VCC, LOW);
  delay(100);

  Serial.println("进入睡眠");
  ESP.deepSleep(0);
}

void loop()
{
  // put your main code here, to run repeatedly:
}

因此我可以通过设置ds3231的闹钟,然后进入deepsleep,时间到达后,唤醒设备,继续重复运行。


美中不足,继续优化

但是在进入deepsleep时,ds3231依然运行,这也是耗电的一部分,我需要将vcc引脚连接到GPIO上,deepsleep时将ds3231的外部供电关闭,以达到最佳低功耗效果。

但是当我兴奋的改完代码->编译->上传->运行时发现,在ds3231断电后,单靠纽扣电池是无法触发闹钟唤醒设备的

幸运的是,我又看到了这两篇文章:
DS3231 - No Alarm when powered Off. Why?
Using a $1 DS3231 Real-time Clock Module with Arduino

将ds3231的上拉电阻移除,即可在纽扣电池供电时也能触发闹钟

在这里插入图片描述
我只移除了图片中1的上拉电阻组,如果你想实现完全将功耗降到最低,可以将2(led)3(电池充电电阻)一同拆下。
别忘了,还需要在SQW引脚接一个10K上拉电阻(就是将一个10K电阻一头接SQW,一头接MCU供电的VCC)
像这样修改单模态电路:在这里插入图片描述
这里的10K电阻在我购买的配件里正好有,接上即可

现在我可以实现在任意时间点唤醒,最长可以一个月唤醒一次。
此时就基本完成了。看一下我的项目运行日志:

2023-08-08 07:41:13
设备进入深度休眠,下次唤醒时间:2023-08-08 18:00:301691488830)
logTag:屏幕内容更新完成
2023-08-08 07:40:44
更新屏幕
2023-08-08 07:40:35
设备上线:{ "wakeupType": 2, "temperature": 29.75, "unixtime": 1691451635, "time": "2023-8-8 7:40:42", "lastGetdataTime": 1691424064 }

2023-08-08 00:01:13
设备进入深度休眠,下次唤醒时间:2023-08-08 07:40:3016914516302023-08-08 00:00:48
logTag:屏幕内容更新完成
2023-08-08 00:00:44
更新屏幕
2023-08-08 00:00:35
设备上线:{ "wakeupType": 2, "temperature": 30.5, "unixtime": 1691424035, "time": "2023-8-8 0:0:42", "lastGetdataTime": 1691409664 }

2023-08-07 20:01:13
设备进入深度休眠,下次唤醒时间:2023-08-08 00:00:3016914240302023-08-07 20:00:48
logTag:屏幕内容更新完成

如果您有更好的解决方案,请留言共同学习吧!

  • 7
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值