mirror of
https://github.com/JADE-Jerry/jcalendar.git
synced 2025-12-06 09:32:48 +08:00
1.1.1
This commit is contained in:
@@ -29,8 +29,11 @@ Bilibili连接:https://www.bilibili.com/video/BV1wHDhYoE3G/<br>
|
||||
* 其他
|
||||
* 按钮->(PIN_14, GND)
|
||||
* LED->22(板载)
|
||||
* 电池ADC->32
|
||||
2. 三色墨水屏排线插入时注意针脚方向,屏幕排线和驱动板排线1号针脚均是悬空,注意对齐。
|
||||
3. 电池接口需要是ph2.0,且注意正负极(开发板上有标注),如果电池的正负极反了,可以用镊子调整电池插头。
|
||||
1. 可选:电池电压检测电路,需要通过两个相同的大电阻(建议500K以上)串联,通过分压进行检测电池电压。如图
|
||||
<img src="./assets/img/battery_adc.png" width="30%"><br>
|
||||
4. 烧录固件<br>
|
||||
使用ESP32的烧录工具flash_download_tool烧录固件. [Flash Download Tools](https://www.espressif.com/en/support/download/other-tools?keys=flash+download+tools)
|
||||
1. 选择烧录的文件和烧录地址(bootloader.bin与partitions.bin烧录过一次后,就不需要重复烧录了)
|
||||
@@ -123,6 +126,8 @@ A: 2025年3月1日后注册的和风天气账户有API Host限制,请下载1.0
|
||||
A: 在系统运行状态下(状态灯常亮),单击按键,稍等即可切换课程表的展示。
|
||||
|
||||
## Releases
|
||||
### 1.1.1
|
||||
* New Featue: 增加对电池的测量和显示。
|
||||
### 1.1.0
|
||||
* New Feature: 课程表。
|
||||
* Refine: 对针脚统一配置。
|
||||
|
||||
BIN
assets/img/battery_adc.png
Normal file
BIN
assets/img/battery_adc.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
6
include/battery.h
Normal file
6
include/battery.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef __BATTERY_H__
|
||||
#define __BATTERY_H__
|
||||
|
||||
int readBatteryVoltage();
|
||||
|
||||
#endif
|
||||
@@ -10,4 +10,6 @@ void si_weather();
|
||||
int si_screen_status();
|
||||
void si_screen();
|
||||
|
||||
void print_status();
|
||||
void print_status();
|
||||
|
||||
void si_warning(const char* str);
|
||||
@@ -2,8 +2,32 @@
|
||||
#ifndef __WIRING_H__
|
||||
#define __WIRING_H__
|
||||
|
||||
// #define J_INKSCREEN_PRO
|
||||
#define LOLIN32_LITE
|
||||
|
||||
#ifdef J_INKSCREEN_PRO
|
||||
// Output PIN
|
||||
#define SPI_MOSI GPIO_NUM_23
|
||||
#define SPI_MISO GPIO_NUM_19
|
||||
#define SPI_SCK GPIO_NUM_18
|
||||
#define SPI_CS GPIO_NUM_5
|
||||
#define SPI_DC GPIO_NUM_17
|
||||
#define SPI_RST GPIO_NUM_16
|
||||
#define SPI_BUSY GPIO_NUM_4
|
||||
// I2C
|
||||
#define I2C_SDA GPIO_NUM_21
|
||||
#define I2C_SCL GPIO_NUM_22
|
||||
// Other PIN
|
||||
#define KEY_M GPIO_NUM_14 // 注意:由于此按键负责唤醒,因此需要选择支持RTC唤醒的PIN脚。
|
||||
#define KEY_L GPIO_NUM_35
|
||||
#define KEY_R GPIO_NUM_13
|
||||
|
||||
#define PIN_LED_R GPIO_NUM_33
|
||||
#define PIN_LED_B GPIO_NUM_25
|
||||
#define PIN_LED_G GPIO_NUM_26
|
||||
|
||||
#define PIN_ADC GPIO_NUM_32 // ADC
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LOLIN32_LITE
|
||||
@@ -20,8 +44,10 @@
|
||||
#define I2C_SDA GPIO_NUM_21
|
||||
#define I2C_SCL GPIO_NUM_22
|
||||
// Other PIN
|
||||
#define PIN_BUTTON GPIO_NUM_14 // 注意:由于此按键负责唤醒,因此需要选择支持RTC唤醒的PIN脚。
|
||||
#define PIN_LED GPIO_NUM_22
|
||||
#define KEY_M GPIO_NUM_14 // 注意:由于此按键负责唤醒,因此需要选择支持RTC唤醒的PIN脚。
|
||||
#define PIN_LED_R GPIO_NUM_22
|
||||
|
||||
#define PIN_ADC GPIO_NUM_32 // ADC
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,6 +25,7 @@ lib_deps =
|
||||
mathertel/OneButton@^2.6.1
|
||||
https://github.com/JADE-Jerry/nongli.git
|
||||
https://github.com/tignioj/ArduinoUZlib
|
||||
https://github.com/Wh1teRabbitHU/RX8010SJ
|
||||
|
||||
[env:z98]
|
||||
build_type = release
|
||||
|
||||
35
src/battery.cpp
Normal file
35
src/battery.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
电压 (V) 近似剩余电量 状态说明
|
||||
4.20 100% 刚刚充满,充电器断开
|
||||
4.10 ~90% 电量非常充足
|
||||
4.00 ~80% 电量充足
|
||||
3.90 ~60% 中等电量
|
||||
3.80 ~50% 中等电量(接近标称电压)
|
||||
3.75 ~40% 电量偏低
|
||||
3.70 ~30% 标称电压点,但电量已不多
|
||||
3.65 ~20% 低电量
|
||||
3.50 ~10% 极低电量,应立即充电
|
||||
3.30 0% 放电截止电压,继续放电将损坏电池
|
||||
|
||||
充电截止电压 4.2
|
||||
放电截止电压 3.3
|
||||
*/
|
||||
#include "driver/adc.h"
|
||||
#include "esp_adc_cal.h"
|
||||
|
||||
/**
|
||||
* 获取电池电压(mV)
|
||||
*/
|
||||
int readBatteryVoltage() {
|
||||
esp_adc_cal_characteristics_t adc_chars;
|
||||
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_11db, ADC_WIDTH_BIT_12, 1100, &adc_chars);
|
||||
|
||||
static const adc1_channel_t channel = ADC1_CHANNEL_4; // GPIO32
|
||||
adc1_config_width(ADC_WIDTH_BIT_12);
|
||||
adc1_config_channel_atten(channel, ADC_ATTEN_11db);
|
||||
int adc_val = adc1_get_raw(channel);
|
||||
int voltage = esp_adc_cal_raw_to_voltage(adc_val, &adc_chars);
|
||||
voltage *= 2;
|
||||
|
||||
return voltage;
|
||||
}
|
||||
28
src/led.cpp
28
src/led.cpp
@@ -8,7 +8,7 @@ int8_t BLINK_TYPE;
|
||||
|
||||
void led_init()
|
||||
{
|
||||
pinMode(PIN_LED, OUTPUT);
|
||||
pinMode(PIN_LED_R, OUTPUT);
|
||||
}
|
||||
|
||||
void task_led(void *param)
|
||||
@@ -18,42 +18,42 @@ void task_led(void *param)
|
||||
switch(BLINK_TYPE)
|
||||
{
|
||||
case 0:
|
||||
digitalWrite(PIN_LED, HIGH); // Off
|
||||
digitalWrite(PIN_LED_R, HIGH); // Off
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
break;
|
||||
case 1:
|
||||
digitalWrite(PIN_LED, LOW); // On
|
||||
digitalWrite(PIN_LED_R, LOW); // On
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
break;
|
||||
case 2:
|
||||
digitalWrite(PIN_LED, LOW); // On
|
||||
digitalWrite(PIN_LED_R, LOW); // On
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
digitalWrite(PIN_LED, HIGH); // Off
|
||||
digitalWrite(PIN_LED_R, HIGH); // Off
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
break;
|
||||
case 3:
|
||||
digitalWrite(PIN_LED, LOW); // On
|
||||
digitalWrite(PIN_LED_R, LOW); // On
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
digitalWrite(PIN_LED, HIGH); // Off
|
||||
digitalWrite(PIN_LED_R, HIGH); // Off
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
break;
|
||||
case 4:
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
digitalWrite(PIN_LED, LOW); // On
|
||||
digitalWrite(PIN_LED_R, LOW); // On
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
digitalWrite(PIN_LED, HIGH); // Off
|
||||
digitalWrite(PIN_LED_R, HIGH); // Off
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
digitalWrite(PIN_LED, LOW); // On
|
||||
digitalWrite(PIN_LED_R, LOW); // On
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
digitalWrite(PIN_LED, HIGH); // Off
|
||||
digitalWrite(PIN_LED_R, HIGH); // Off
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
digitalWrite(PIN_LED, LOW); // On
|
||||
digitalWrite(PIN_LED_R, LOW); // On
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
digitalWrite(PIN_LED, HIGH); // Off
|
||||
digitalWrite(PIN_LED_R, HIGH); // Off
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
break;
|
||||
default:
|
||||
digitalWrite(PIN_LED, HIGH); // Off
|
||||
digitalWrite(PIN_LED_R, HIGH); // Off
|
||||
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||
}
|
||||
}
|
||||
|
||||
35
src/main.cpp
35
src/main.cpp
@@ -7,6 +7,8 @@
|
||||
|
||||
#include <wiring.h>
|
||||
|
||||
#include "battery.h"
|
||||
|
||||
#include "led.h"
|
||||
#include "_sntp.h"
|
||||
#include "weather.h"
|
||||
@@ -16,7 +18,7 @@
|
||||
#include "version.h"
|
||||
|
||||
#include "OneButton.h"
|
||||
OneButton button(PIN_BUTTON, true);
|
||||
OneButton button(KEY_M, true);
|
||||
|
||||
void IRAM_ATTR checkTicks() {
|
||||
button.tick();
|
||||
@@ -54,7 +56,7 @@ void print_wakeup_reason() {
|
||||
Serial.println("Wakeup caused by ULP program");
|
||||
break;
|
||||
default:
|
||||
Serial.printf("Wakeup was not caused by deep sleep.\n");
|
||||
Serial.printf("Wakeup was not caused by deep sleep.\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +84,7 @@ void setup() {
|
||||
button.attachDoubleClick(buttonDoubleClick, &button);
|
||||
// button.attachMultiClick()
|
||||
button.attachLongPressStop(buttonLongPressStop, &button);
|
||||
attachInterrupt(digitalPinToInterrupt(PIN_BUTTON), checkTicks, CHANGE);
|
||||
attachInterrupt(digitalPinToInterrupt(KEY_M), checkTicks, CHANGE);
|
||||
|
||||
Serial.printf("***********************\r\n");
|
||||
Serial.printf(" J-Calendar\r\n");
|
||||
@@ -91,8 +93,24 @@ void setup() {
|
||||
Serial.printf("Copyright © 2022-2025 JADE Software Co., Ltd. All Rights Reserved.\r\n\r\n");
|
||||
|
||||
led_init();
|
||||
led_fast();
|
||||
led_on();
|
||||
delay(1000);
|
||||
int voltage = readBatteryVoltage();
|
||||
Serial.printf("Battery: %d mV\r\n", voltage);
|
||||
if(voltage < 1000) {
|
||||
Serial.println("[WARN]无电池。");
|
||||
} else if(voltage < 3000) {
|
||||
Serial.println("[WARN]电量低于3v,系统休眠。");
|
||||
go_sleep();
|
||||
} else if (voltage < 3300) {
|
||||
// 低于3.3v,电池电量用尽,屏幕给警告,然后关机。
|
||||
Serial.println("[WARN]电量低于3.3v,警告并系统休眠。");
|
||||
si_warning("电量不足,请充电!");
|
||||
go_sleep();
|
||||
}
|
||||
|
||||
Serial.println("Wm begin...");
|
||||
led_fast();
|
||||
wm.setHostname("J-Calendar");
|
||||
wm.setEnableConfigPortal(false);
|
||||
wm.setConnectTimeout(10);
|
||||
@@ -350,12 +368,7 @@ void go_sleep() {
|
||||
}
|
||||
|
||||
esp_sleep_enable_timer_wakeup(p * (uint64_t)uS_TO_S_FACTOR);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
esp_sleep_enable_ext0_wakeup(PIN_BUTTON, 0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||
esp_deep_sleep_enable_gpio_wakeup(PIN_BUTTON, ESP_GPIO_WAKEUP_GPIO_HIGH);
|
||||
gpio_set_direction(PIN_BUTTON, GPIO_MODE_INPUT);
|
||||
#endif
|
||||
esp_sleep_enable_ext0_wakeup(KEY_M, 0);
|
||||
|
||||
// 省电考虑,关闭RTC外设和存储器
|
||||
// esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF); // RTC IO, sensors and ULP, 注意:由于需要按键唤醒,所以不能关闭,否则会导致RTC_IO唤醒失败
|
||||
@@ -363,7 +376,7 @@ void go_sleep() {
|
||||
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_FAST_MEM, ESP_PD_OPTION_OFF);
|
||||
|
||||
// 省电考虑,重置gpio,平均每针脚能省8ua。
|
||||
gpio_reset_pin(PIN_LED); // 减小deep-sleep电流
|
||||
gpio_reset_pin(PIN_LED_R); // 减小deep-sleep电流
|
||||
gpio_reset_pin(SPI_CS); // 减小deep-sleep电流
|
||||
gpio_reset_pin(SPI_DC); // 减小deep-sleep电流
|
||||
gpio_reset_pin(SPI_RST); // 减小deep-sleep电流
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
#include "screen_ink.h"
|
||||
|
||||
|
||||
#include <weather.h>
|
||||
#include <API.hpp>
|
||||
#include "holiday.h"
|
||||
#include "nongli.h"
|
||||
|
||||
#include "battery.h"
|
||||
int voltage;
|
||||
|
||||
#include <_preference.h>
|
||||
|
||||
#include <U8g2_for_Adafruit_GFX.h>
|
||||
@@ -71,6 +75,11 @@ struct
|
||||
int16_t cdDayX;
|
||||
int16_t cdDayY;
|
||||
|
||||
int16_t statusX;
|
||||
int16_t statusY;
|
||||
int16_t statusW;
|
||||
int16_t statusH;
|
||||
|
||||
int16_t weatherX;
|
||||
int16_t weatherY;
|
||||
int16_t weatherW;
|
||||
@@ -115,6 +124,11 @@ void init_cal_layout_size() {
|
||||
calLayout.tW = 60;
|
||||
calLayout.tH = calLayout.topH / 2;
|
||||
|
||||
calLayout.statusX = 300;
|
||||
calLayout.statusY = 0;
|
||||
calLayout.statusW = display.width() - calLayout.weatherX;
|
||||
calLayout.statusH = 14;
|
||||
|
||||
calLayout.weatherX = 300;
|
||||
calLayout.weatherY = calLayout.topY;
|
||||
calLayout.weatherW = display.width() - calLayout.weatherX;
|
||||
@@ -575,6 +589,7 @@ void draw_cd_day(String label, String date) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void draw_special_day() {
|
||||
String str = "Special Days!!!";
|
||||
|
||||
@@ -802,6 +817,38 @@ void draw_err(bool partial) {
|
||||
}
|
||||
}
|
||||
|
||||
void draw_status(bool partial) {
|
||||
if (partial) {
|
||||
display.setPartialWindow(calLayout.statusX, calLayout.statusY, calLayout.statusW, calLayout.statusH);
|
||||
display.firstPage();
|
||||
display.fillScreen(GxEPD_WHITE);
|
||||
}
|
||||
u8g2Fonts.setFontMode(1);
|
||||
u8g2Fonts.setFontDirection(0);
|
||||
u8g2Fonts.setBackgroundColor(GxEPD_WHITE);
|
||||
u8g2Fonts.setForegroundColor(GxEPD_BLACK);
|
||||
u8g2Fonts.setFont(u8g2_font_siji_t_6x10);
|
||||
|
||||
// 电池icon
|
||||
String iconStr = "";
|
||||
if(voltage >= 4100) { // 满电
|
||||
iconStr = "\ue24b";
|
||||
} else if (voltage >= 3900) { // 多电
|
||||
iconStr = "\ue249";
|
||||
} else if (voltage >= 3700) { // 中电量
|
||||
iconStr = "\ue247";
|
||||
} else if (voltage >= 3500) { // 低电量
|
||||
iconStr = "\ue245";
|
||||
} else { // 空
|
||||
iconStr = "\ue242";
|
||||
}
|
||||
u8g2Fonts.drawUTF8(400 - 12 - 4, 10, iconStr.c_str());
|
||||
|
||||
if (partial) {
|
||||
display.nextPage();
|
||||
}
|
||||
}
|
||||
|
||||
void drawStudySchedule() {
|
||||
int i = _study_schedule.substring(0, 3).toInt();
|
||||
Serial.printf("%d\r\n", i);
|
||||
@@ -1000,6 +1047,8 @@ int si_calendar_status() {
|
||||
void task_screen(void* param) {
|
||||
Serial.println("[Task] screen update begin...");
|
||||
|
||||
voltage = readBatteryVoltage();
|
||||
|
||||
display.init(115200); // 串口使能 初始化完全刷新使能 复位时间 ret上拉使能
|
||||
display.setRotation(ROTATION); // 设置屏幕旋转1和3是横向 0和2是纵向
|
||||
u8g2Fonts.begin(display);
|
||||
@@ -1022,8 +1071,9 @@ void task_screen(void* param) {
|
||||
|
||||
if (weather_status() == 1) {
|
||||
draw_weather(false);
|
||||
} else if (weather_status() == 2) {
|
||||
draw_err(false);
|
||||
}
|
||||
if (voltage > 1000) {
|
||||
draw_status(false);
|
||||
}
|
||||
} while (display.nextPage());
|
||||
|
||||
@@ -1067,3 +1117,39 @@ void print_status() {
|
||||
Serial.printf("Calendar: %d\n", si_calendar_status());
|
||||
Serial.printf("Screen: %d\n", si_screen_status());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void si_warning(const char* str) {
|
||||
Serial.println("Screen warning...");
|
||||
display.init(115200); // 串口使能 初始化完全刷新使能 复位时间 ret上拉使能
|
||||
display.setRotation(ROTATION); // 设置屏幕旋转1和3是横向 0和2是纵向
|
||||
u8g2Fonts.begin(display);
|
||||
|
||||
display.setFullWindow();
|
||||
display.fillScreen(GxEPD_WHITE);
|
||||
do {
|
||||
u8g2Fonts.setFontMode(1);
|
||||
u8g2Fonts.setFontDirection(0);
|
||||
u8g2Fonts.setBackgroundColor(GxEPD_WHITE);
|
||||
u8g2Fonts.setForegroundColor(GxEPD_BLACK);
|
||||
|
||||
u8g2Fonts.setFont(u8g2_font_open_iconic_all_4x_t);
|
||||
int space = 8;
|
||||
int w = u8g2Fonts.getUTF8Width("\u0118") + space;
|
||||
u8g2Fonts.setFont(FONT_TEXT);
|
||||
w += u8g2Fonts.getUTF8Width(str);
|
||||
|
||||
u8g2Fonts.setForegroundColor(GxEPD_RED);
|
||||
u8g2Fonts.setFont(u8g2_font_open_iconic_all_4x_t);
|
||||
u8g2Fonts.setCursor((display.width() - w) / 2, (display.height() + 32) / 2);
|
||||
u8g2Fonts.print("\u0118");
|
||||
|
||||
u8g2Fonts.setForegroundColor(GxEPD_BLACK);
|
||||
u8g2Fonts.setCursor(u8g2Fonts.getCursorX() + space, u8g2Fonts.getCursorY() - 5);
|
||||
u8g2Fonts.setFont(FONT_TEXT);
|
||||
u8g2Fonts.print(str);
|
||||
} while (display.nextPage());
|
||||
|
||||
display.powerOff();
|
||||
}
|
||||
Reference in New Issue
Block a user