#include <Wire.h>
#include <U8g2lib.h>
#include <Adafruit_AS7341.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#define OLED_ADDRESS 0x3C // OLED显示屏I2C地址
#define SENSOR_ADDRESS 0x39 // 传感器I2C地址
#define BUTTON_BACK 27 // 按钮连接的引脚10
#define BUTTON_SELECT 25 // 按钮连接的引脚2
#define BUTTON_UP 26 // 按钮连接的引脚20
#define BUTTON_DOWN 33 // 按钮连接的引脚21
bool buttonSelectPressed = 0;
bool buttonDownPressed = 0;
bool buttonUpPressed = 0;
bool buttonBACKPressed = 0;
/*******************************oled*******************************/
// 初始化U8g2库
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/U8X8_PIN_NONE, /* clock=*/22, /* data=*/21);
// 菜单项相关变量
const char* menuItems[] = {
"1 Temperature", "2 AS7341 Channel", "3 Heating",
"Menu Item 4", "Menu Item 5", "Menu Item 6",
"Menu Item 7", "Menu Item 8"
};
const int numMenuItems = sizeof(menuItems) / sizeof(menuItems[0]);
int selectedMenuItem = 0;
int pageStartIndex = 0; // 当前页面的起始菜单项索引
/*******************************as7341*******************************/
Adafruit_AS7341 as7341;
// 0 0 0 0 0 0 0 0
//as7341
uint8_t menu_flag = 0x00;
uint8_t channel_index = 0; // 当前显示的通道索引
uint16_t as7341_data[12]; //传感器数值
const char* channelNames[12] = {
"A0/F1 415",
"A1/F2 445",
"A2/F3 480",
"A3/F4 515",
"A4/F5 555",
"A5/F6 590",
"A6/F7 630",
"A7/F8 680",
"A8/Clear",
"A9/NIR",
"A10/Clear",
"A11/NIR"
};
/*******************************temperature*************************/
uint8_t set_tem_index = 0;
float current_tem = 0;
float SeT_Temperature[4] = {
37,
42,
50,
65
};
/*******************************time*******************************/
uint8_t current_min = 0;
uint8_t current_sec = 0;
int Heat_Time[4] = {
30,
30,
30,
30
};
unsigned long currentMillis = 0;
unsigned long pre_time = 0;
/*******************************setup******************************/
void setup() {
Wire.begin();
Serial.begin(115200); // 初始化串口监视器
if (!as7341.begin()) {
Serial.println("Could not find AS7341");
//while (1) { delay(10); }
}
as7341.setATIME(100);
as7341.setASTEP(999);
as7341.setGain(AS7341_GAIN_256X);
u8g2.begin(); // 初始化OLED显示屏
pinMode(BUTTON_UP, INPUT_PULLUP); // 初始化按钮引脚
pinMode(BUTTON_DOWN, INPUT_PULLUP);
pinMode(BUTTON_SELECT, INPUT_PULLUP);
pinMode(BUTTON_BACK, INPUT_PULLUP);
}
/*******************************LOOP******************************/
void loop() {
get_sensor_value(); //get sensor value
menu_display(); //显示菜单
scan_key(); //按键扫描
logic(); //获取按键扫描结果后处理逻辑
delay(50); // 主循环延时
}
/*******************************funtion******************************/
void logic() {
// 更新选中的菜单项
if (buttonUpPressed) {
selectedMenuItem--;
if (selectedMenuItem < 0) {
selectedMenuItem = numMenuItems - 1;
}
updatePageStartIndex();
delay(200); // 按钮去抖动
}
if (buttonDownPressed) {
selectedMenuItem++;
if (selectedMenuItem >= numMenuItems) {
selectedMenuItem = 0;
}
updatePageStartIndex();
delay(200); // 按钮去抖动
}
if (buttonSelectPressed) {
delay(20);
while (!digitalRead(BUTTON_SELECT))
;
// 在这里实现功能,根据选中的菜单项执行对应的操作
handleMenuSelection(selectedMenuItem);
delay(200); // 按钮去抖动
}
if (buttonBACKPressed) {
delay(200); // 按钮去抖动
}
}
void scan_key() {
// 读取按钮状态
buttonUpPressed = digitalRead(BUTTON_UP) == LOW;
buttonDownPressed = digitalRead(BUTTON_DOWN) == LOW;
buttonSelectPressed = digitalRead(BUTTON_SELECT) == LOW;
buttonBACKPressed = digitalRead(BUTTON_BACK) == LOW; // 读取确认按钮状态
}
void menu_display() {
// 更新OLED显示
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB08_tr); // 设置字体
for (int i = 0; i < 4; i++) {
int menuIndex = (pageStartIndex + i) % numMenuItems;
int yPos = (i + 1) * 15;
if (menuIndex == selectedMenuItem) {
u8g2.setDrawColor(1); // 设置绘制颜色为白色
u8g2.drawBox(0, yPos - 12, 122, 13); // 绘制反色矩形框,不遮挡滚动条
u8g2.setDrawColor(0); // 设置绘制颜色为黑色(反色)
} else {
u8g2.setDrawColor(1); // 设置绘制颜色为白色
}
int xPos = 0; // 左对齐显示
u8g2.setCursor(xPos, yPos - 2); // 设置光标位置
u8g2.print(menuItems[menuIndex]); // 打印菜单项
}
// 绘制滚动条
u8g2.setDrawColor(1); // 设置绘制颜色为白色 // 设置绘制颜色为白色
int scrollbarHeight = 15; // 滚动条高度
int scrollbarTop = map(pageStartIndex, 0, numMenuItems - 4, 0, 63 - scrollbarHeight); // 计算滚动条的顶部位置
u8g2.drawFrame(123, 0, 5, 63); // 绘制滚动条框架
u8g2.drawBox(123, scrollbarTop, 5, scrollbarHeight); // 绘制滚动条
u8g2.sendBuffer(); // 发送缓冲区内容到显示屏
}
void get_sensor_value() {
// // 显示传感器数据到串口
// Serial.print(channelNames[channel_index]);
// Serial.print(": ");
// Serial.print(as7341_data[channel_index]);
// Serial.print(" Pre_T=:");
// Serial.println(current_tem, 1);
current_tem = 30;
// if (!as7341.readAllChannels(readings)) { //Get AS7341value
// Serial.println("Error reading all channels!");
// return;
// }
}
// 显示提示信息
void display_Message(const char* message) {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB10_tr); // 设置字体
u8g2.setDrawColor(1); // 设置绘制白色
int16_t messageWidth = u8g2.getStrWidth(message); // 计算字符串宽度
int16_t xPos = (128 - messageWidth) / 2; // 计算居中位置
u8g2.setCursor(xPos, 32); // 设置光标位置,垂直居中显示
u8g2.print(message); // 显示提示信息
u8g2.sendBuffer(); // 发送缓冲区内容到显示屏
delay(1200); // 延时2秒钟显示提示信息
}
// 更新当前页面的起始菜单项索引
void updatePageStartIndex() {
if (selectedMenuItem < pageStartIndex) {
pageStartIndex = selectedMenuItem;
} else if (selectedMenuItem >= pageStartIndex + 4) {
pageStartIndex = selectedMenuItem - 3;
}
// 确保pageStartIndex不会超过边界
if (pageStartIndex > numMenuItems - 4) {
pageStartIndex = numMenuItems - 4;
}
if (pageStartIndex < 0) {
pageStartIndex = 0;
}
}
void function_display() {
switch (selectedMenuItem) {
case 0:
{
display_temperature_data();
break;
}
case 1:
{
display_as7341_data();
break;
}
case 2:
{
display_heating_menu();
break;
}
default:
break;
}
}
void display_temperature_data() {
unsigned long previousMillis = 0; // 上一次更新时间
const long interval = 1000; // 更新间隔1秒
while (1) {
// 清除屏幕
u8g2.clearBuffer();
// 绘制温度计图标
u8g2.drawFrame(10, 10, 20, 40); // 温度计外框
u8g2.drawBox(15, 40, 10, 10); // 温度计底部
u8g2.drawCircle(20, 55, 7, U8G2_DRAW_ALL); // 温度计底部圆形部分
// 绘制刻度线
for (int i = 0; i <= 5; i++) {
int y = 15 + i * 5;
u8g2.drawHLine(10, y, 5); // 左侧刻度线
u8g2.drawHLine(25, y, 5); // 右侧刻度线
}
// 绘制温度计水银柱(动态)
int mercuryHeight = (int)(current_tem / 100.0 * 30); // 根据温度计算水银柱高度
u8g2.drawBox(17, 45 - mercuryHeight, 6, mercuryHeight); // 绘制水银柱
// 计算华氏温度
float fahrenheit = current_tem * 1.8 + 32;
// 显示当前温度(摄氏度)
u8g2.setFont(u8g2_font_ncenB08_tr); // 设置字体
u8g2.setCursor(50, 15); // 设置光标位置
u8g2.print("Temperature:");
u8g2.setFont(u8g2_font_ncenB14_tr); // 更大字体显示温度值
u8g2.setCursor(50, 35); // 设置光标位置
u8g2.print(current_tem, 1); // 显示当前温度值
u8g2.print(" C"); // 显示单位
// 显示当前温度(华氏度)
u8g2.setFont(u8g2_font_ncenB14_tr); // 设置字体
u8g2.setCursor(50, 55); // 设置光标位置
u8g2.print(fahrenheit, 1); // 显示华氏温度值
u8g2.print(" F"); // 显示单位
// 发送缓冲区内容到显示屏
u8g2.sendBuffer();
// 读取传感器值 (这里假设有一个函数更新 current_tem 的值)
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
get_sensor_value(); // 每隔1秒更新一次温度
}
// 检查是否按下返回按钮
if (digitalRead(BUTTON_BACK) == LOW) {
delay(20);
while (!digitalRead(BUTTON_BACK))
;
break; // 退出死循环,返回主菜单
}
}
}
void display_as7341_data() {
bool dataPaused = false; // 标记数据是否暂停
unsigned long previousMillis = 0; // 上一次更新时间
const long interval = 1000; // 更新间隔1秒
while (1) {
// 清除屏幕
u8g2.clearBuffer();
// 显示4个通道的传感器数据
for (int i = 0; i < 4; i++) {
int channel = (channel_index + i) % 12;
u8g2.setFont(u8g2_font_ncenB08_tr); // 设置字体
u8g2.setCursor(2, 15 * (i + 1));
u8g2.print(channelNames[channel]);
u8g2.setCursor(65, 15 * (i + 1));
u8g2.print(as7341_data[channel]);
}
// 绘制滚动条
int scrollbarHeight = 15; // 滚动条高度
int scrollbarPosition = map(channel_index, 0, 12, 0, 63 - scrollbarHeight); // 滚动条位置
u8g2.drawFrame(118, 4, 6, 60); // 绘制滚动条框架
u8g2.drawBox(118, 4 + scrollbarPosition, 6, scrollbarHeight); // 绘制滚动条
// 发送缓冲区内容到显示屏
u8g2.sendBuffer();
// 检查是否按下暂停按钮
if (digitalRead(BUTTON_SELECT) == LOW) {
delay(20);
while (!digitalRead(BUTTON_SELECT))
;
if (!dataPaused) {
const char* message = "Pause!";
display_Message(message);
} else {
const char* message = "Pause Cancle!";
display_Message(message);
}
dataPaused = !dataPaused; // 切换数据暂停状态
}
// 读取传感器值 (如果数据未暂停)
if (!dataPaused) {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
get_sensor_value(); // 每隔1秒更新一次数据
}
}
// 检查是否按下返回按钮
if (digitalRead(BUTTON_BACK) == LOW) {
delay(20);
while (!digitalRead(BUTTON_BACK))
;
channel_index = 0; //重置channel_index
break; // 退出死循环,返回主菜单
}
// 检查上下按钮以切换通道
if (digitalRead(BUTTON_UP) == LOW) {
delay(20);
while (!digitalRead(BUTTON_UP))
;
channel_index = (channel_index - 1 + 12) % 12;
}
if (digitalRead(BUTTON_DOWN) == LOW) {
delay(20);
while (!digitalRead(BUTTON_DOWN))
;
channel_index = (channel_index + 1) % 12;
}
}
}
void startHeating() {
// 实现加热功能的函数
// 预留供加热控制使用
}
void heatingComplete() {
// 加热完成后的功能
// 用户自行实现具体功能
}
bool confirmCancelHeating() {
int confirmSelection = 0; // 0 for Yes, 1 for No
while (1) {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.setCursor(0, 10);
u8g2.setDrawColor(1);
u8g2.print("Cancel Heat?");
u8g2.setCursor(0, 30);
if (confirmSelection == 0) {
u8g2.setDrawColor(1);
u8g2.drawBox(0, 20, 60, 12);
u8g2.setDrawColor(0);
} else {
u8g2.setDrawColor(1);
}
u8g2.print("Yes");
u8g2.setCursor(70, 30);
if (confirmSelection == 1) {
u8g2.setDrawColor(1);
u8g2.drawBox(70, 20, 60, 12);
u8g2.setDrawColor(0);
} else {
u8g2.setDrawColor(1);
}
u8g2.print("No");
u8g2.sendBuffer();
if (digitalRead(BUTTON_UP) == LOW || digitalRead(BUTTON_DOWN) == LOW) {
delay(20);
while (digitalRead(BUTTON_UP) == LOW || digitalRead(BUTTON_DOWN) == LOW)
;
confirmSelection = !confirmSelection;
}
if (digitalRead(BUTTON_SELECT) == LOW) {
delay(20);
while (digitalRead(BUTTON_SELECT) == LOW)
;
return confirmSelection == 0;
}
if (digitalRead(BUTTON_BACK) == LOW) {
delay(20);
while (digitalRead(BUTTON_BACK) == LOW)
;
return false;
}
Serial.println(".");
}
}
void display_heating_menu() {
channel_index = 3; // 默认为4通道
unsigned long previousMillis = 0;
const long interval = 1000;
bool heating = false;
bool cancelConfirm = false;
unsigned long heatingStartMillis = 0;
int selectionIndex = 0;
bool editing = false;
unsigned long pressStartTime = 0;
while (1) {
u8g2.clearBuffer();
// 显示设定温度
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.setCursor(0, 10);
if (selectionIndex == 0) {
if (editing && (millis() / 500) % 2 == 0) {
u8g2.setDrawColor(0);
u8g2.drawBox(0, 0, 128, 12);
u8g2.setDrawColor(1);
} else {
u8g2.setDrawColor(1);
u8g2.drawBox(0, 0, 128, 12);
u8g2.setDrawColor(0);
}
} else {
u8g2.setDrawColor(1);
}
u8g2.print("Set: ");
u8g2.print(SeT_Temperature[set_tem_index], 1);
u8g2.print(" C");
// 显示当前温度
u8g2.setCursor(70, 10);
u8g2.print("Cru: ");
u8g2.print(current_tem, 1);
u8g2.print(" C");
// 显示AS7341通道数据
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.setCursor(0, 25);
if (selectionIndex == 1) {
if (editing && (millis() / 500) % 2 == 0) {
u8g2.setDrawColor(0);
u8g2.drawBox(0, 15, 128, 12);
u8g2.setDrawColor(1);
} else {
u8g2.setDrawColor(1);
u8g2.drawBox(0, 15, 128, 12);
u8g2.setDrawColor(0);
}
} else {
u8g2.setDrawColor(1);
}
u8g2.print(channelNames[channel_index]);
u8g2.setCursor(65, 25);
u8g2.print(as7341_data[channel_index]);
// 显示加热时间
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.setCursor(0, 40);
if (selectionIndex == 2) {
if (editing && (millis() / 500) % 2 == 0) {
u8g2.setDrawColor(0);
u8g2.drawBox(0, 30, 128, 12);
u8g2.setDrawColor(1);
} else {
u8g2.setDrawColor(1);
u8g2.drawBox(0, 30, 128, 12);
u8g2.setDrawColor(0);
}
} else {
u8g2.setDrawColor(1);
}
u8g2.print("Time: ");
if (heating) {
unsigned long elapsedMillis = millis() - heatingStartMillis;
int remainingMillis = Heat_Time[set_tem_index] * 60 * 1000 - elapsedMillis;
int display_min = remainingMillis / 60000;
int display_sec = (remainingMillis / 1000) % 60;
u8g2.print(display_min);
u8g2.print(":");
if (display_sec < 10) {
u8g2.print("0");
}
u8g2.print(display_sec);
} else {
u8g2.print(Heat_Time[set_tem_index]);
u8g2.print(":00");
}
// 显示加热和取消加热选项
u8g2.setFont(u8g2_font_ncenB08_tr);
u8g2.setCursor(0, 55);
if (selectionIndex == 3) {
u8g2.setDrawColor(1);
u8g2.drawBox(0, 45, 60, 12);
u8g2.setDrawColor(0);
} else {
u8g2.setDrawColor(1);
}
u8g2.print("Heat");
u8g2.setCursor(70, 55);
if (selectionIndex == 4) {
u8g2.setDrawColor(1);
u8g2.drawBox(70, 45, 60, 12);
u8g2.setDrawColor(0);
} else {
u8g2.setDrawColor(1);
}
u8g2.print("Cancel");
// 发送缓冲区内容到显示屏
u8g2.sendBuffer();
// 读取传感器值
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
get_sensor_value();
}
// 处理按钮按下事件
if (digitalRead(BUTTON_UP) == LOW) {
delay(20);
while (digitalRead(BUTTON_UP) == LOW)
;
if (editing) {
if (selectionIndex == 0) {
set_tem_index = (set_tem_index - 1 + 4) % 4;
} else if (selectionIndex == 1) {
channel_index = (channel_index - 1 + 12) % 12;
} else if (selectionIndex == 2) {
Heat_Time[set_tem_index] = (Heat_Time[set_tem_index] - 5 + 65) % 65;
if (Heat_Time[set_tem_index] == 0 || Heat_Time[set_tem_index] > 60) {
Heat_Time[set_tem_index] = 60;
}
}
} else {
do {
selectionIndex = (selectionIndex - 1 + 5) % 5;
} while (heating && (selectionIndex == 0 || selectionIndex == 2));
}
}
if (digitalRead(BUTTON_DOWN) == LOW) {
delay(20);
while (digitalRead(BUTTON_DOWN) == LOW)
;
if (editing) {
if (selectionIndex == 0) {
set_tem_index = (set_tem_index + 1) % 4;
} else if (selectionIndex == 1) {
channel_index = (channel_index + 1) % 12;
} else if (selectionIndex == 2) {
Heat_Time[set_tem_index] = (Heat_Time[set_tem_index] + 5) % 65;
if (Heat_Time[set_tem_index] == 0 || Heat_Time[set_tem_index] > 60) {
Heat_Time[set_tem_index] = 5;
}
}
} else {
do {
selectionIndex = (selectionIndex + 1) % 5;
} while (heating && (selectionIndex == 0 || selectionIndex == 2));
}
}
if (digitalRead(BUTTON_SELECT) == LOW) {
if (selectionIndex == 3 && !editing) {
if (pressStartTime == 0) {
pressStartTime = millis();
} else if (millis() - pressStartTime > 2000) {
if (!heating) {
heating = true;
heatingStartMillis = millis();
startHeating(); // 调用加热功能
display_Message("Heat Started");
}
}
} else if (selectionIndex == 4 && heating) {
delay(20);
while (digitalRead(BUTTON_SELECT) == LOW)
;
if (confirmCancelHeating()) {
heating = false;
display_Message("Heat Canceled");
}
} else if (selectionIndex == 4 && !editing) {
} else {
delay(20);
while (digitalRead(BUTTON_SELECT) == LOW)
;
pressStartTime = 0;
editing = !editing;
}
} else {
pressStartTime = 0;
}
if (digitalRead(BUTTON_BACK) == LOW) {
delay(100);
while (digitalRead(BUTTON_BACK) == LOW)
;
if (editing) {
editing = false;
} else if (heating) {
if (confirmCancelHeating()) {
heating = false;
display_Message("Heat Canceled");
}
} else {
break; // 退出死循环,返回主菜单
}
}
if (heating) {
unsigned long elapsedMillis = millis() - heatingStartMillis;
int remainingMillis = Heat_Time[set_tem_index] * 60 * 1000 - elapsedMillis;
if (remainingMillis <= 0) {
heating = false;
heatingComplete(); // 加热完成后的功能
display_Message("Heat Complete");
} else {
current_min = remainingMillis / 60000;
current_sec = (remainingMillis / 1000) % 60;
u8g2.setDrawColor(1);
u8g2.setCursor(0, 40); // 实时更新倒计时显示位置
u8g2.print("Time: ");
u8g2.print(current_min);
u8g2.print(":");
if (current_sec < 10) {
u8g2.print("0");
}
u8g2.print(current_sec);
u8g2.sendBuffer();
}
}
}
}
// 根据选中的菜单项执行对应的操作
void handleMenuSelection(int menuIndex) {
switch (menuIndex) {
case 0:
// 实现第一个菜单项的功能
selectedMenuItem = 0;
Serial.println("功能1");
break;
case 1:
selectedMenuItem = 1;
Serial.println("功能2");
break;
case 2:
// 实现第三个菜单项的功能
selectedMenuItem = 2;
Serial.println("功能3");
break;
case 3:
selectedMenuItem = 3;
// 实现第四个菜单项的功能
Serial.println("功能4");
break;
case 4:
selectedMenuItem = 4;
// 实现第五个菜单项的功能
Serial.println("功能5");
break;
case 5:
// 实现第六个菜单项的功能
Serial.println("功能6");
break;
case 6:
// 实现第七个菜单项的功能
Serial.println("功能7");
break;
case 7:
// 实现第八个菜单项的功能
Serial.println("功能8");
break;
case 8:
// 实现第九个菜单项的功能
Serial.println("功能9");
break;
default:
// 默认处理
break;
}
function_display();
}