Commit 212c18e7 authored by 957dd's avatar 957dd

Merge branch 'feature/person_add' into 'master'

个人版 See merge request !6
parents c1e07a1b 7506dac1
......@@ -60,8 +60,6 @@ public:
friend void audioPlayTask(void* pvParameters);
};
extern AudioManager audioManager;
// FreeRTOS 任务函数声明
void audioPlayTask(void* pvParameters);
......
......@@ -163,7 +163,7 @@ void DeviceControl::handleMQTTCommand(int message_Type, JsonObject body) {
void DeviceControl::updatecontrol_smoke() {
if(_smoke_index = true){
int smoke_i = _smoke_ms / 50;
int smoke_i = _smoke_ms / 20;
if(_smoke_count < smoke_i){
setPinValue(4,1);
}else setPinValue(4,0);
......@@ -196,10 +196,12 @@ void DeviceControl::update() {
// 简单的实现:每隔一定时间或阈值触发时发布
// static unsigned long lastSensorPublishTime = 0;
// const unsigned long sensorPublishInterval = 50; // 每 1 秒发布一次传感器数据
_shot_count++;
if(_shot_count < 6){
return ;
}
// _shot_count++;
// if(_shot_count < 6){
// return ;
// }else {
// _shot_count=7;
// }
// if (millis() - lastSensorPublishTime >= sensorPublishInterval) {
//double sensorVoltage = readSensor();
......@@ -213,11 +215,11 @@ void DeviceControl::update() {
} else {
Serial.println("MQTTManager not set, cannot publish sensor data.");
}
_shot_count=0;
//_shot_count=0;
}
// lastSensorPublishTime = millis();
// }
_shot_count=9;
}
......@@ -233,6 +235,6 @@ void devicePeriodicTask(void* pvParameters) {
for (;;) {
deviceControl->update(); // 调用 DeviceControl 的 update 方法
vTaskDelay(pdMS_TO_TICKS(50)); // 每 50 毫秒更新一次
vTaskDelay(pdMS_TO_TICKS(20)); // 每 50 毫秒更新一次
}
}
\ No newline at end of file
......@@ -35,8 +35,8 @@ const char* MQTT_BROKER = "119.45.167.177"; // 你的 MQTT Broker IP 或 Hostnam
const int MQTT_PORT = 1883; // MQTT 端口
const char* MQTT_USERNAME = "admin"; // 你的 MQTT 用户名
const char* MQTT_PASSWORD = "admin"; // 你的 MQTT 密码
const char* MQTT_SUBSCRIBE_TOPIC = "ser2dev/13990100000001"; // 你要订阅的 MQTT 主题
const char* MQTT_RELEASE_TOPIC = "13990100000001"; // 你要发布的 MQTT 主题
const char* MQTT_SUBSCRIBE_TOPIC = "ser2dev/CN040200000001"; // 你要订阅的 MQTT 主题
const char* MQTT_RELEASE_TOPIC = "CN040200000001"; // 你要发布的 MQTT 主题
// --- 创建类实例 ---
// 这些实例现在包含了之前分散的全局变量和相关函数
......
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
"version": "0.2.0",
"configurations": []
}
#include "AudioManager.h"
// 构造函数实现
AudioManager::AudioManager(int bckPin, int lrcPin, int dinPin, int sampleRate, int dmaBufCount, int dmaBufLen)
: _bckPin(bckPin), _lrcPin(lrcPin), _dinPin(dinPin),
_sampleRate(sampleRate), _dmaBufCount(dmaBufCount), _dmaBufLen(dmaBufLen) {
// 构造函数体
}
// 初始化 I2S 实现
bool AudioManager::begin() {
Serial.println("Initializing I2S...");
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), // 设置为主机模式,发送数据
.sample_rate = _sampleRate, // 设置采样率
.bits_per_sample = (i2s_bits_per_sample_t)_bitsPerSample, // 设置每个采样点的位数
.channel_format = _channelFormat, // 通道格式
.communication_format = _commFormat, // 通信格式
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // 中断分配标志
.dma_buf_count = _dmaBufCount, // DMA缓冲区数量
.dma_buf_len = _dmaBufLen, // 每个DMA缓冲区的长度
.use_apll = false, // 不使用APLL
.tx_desc_auto_clear = true, // 自动清除已发送的TX描述符
.fixed_mclk = 0 // 不使用固定的MCLK
};
// 安装I2S驱动
esp_err_t err = i2s_driver_install(_i2sPort, &i2s_config, 0, NULL);
if (err != ESP_OK) {
Serial.printf("I2S driver install failed: %d\n", err);
return false;
}
Serial.println("I2S driver installed.");
// 配置I2S引脚
i2s_pin_config_t pin_config = {
.bck_io_num = _bckPin, // 位时钟引脚
.ws_io_num = _lrcPin, // 左右时钟/字选择引脚
.data_out_num = _dinPin, // 数据输出引脚
.data_in_num = I2S_PIN_NO_CHANGE // 不使用数据输入引脚
};
err = i2s_set_pin(_i2sPort, &pin_config);
if (err != ESP_OK) {
Serial.printf("I2S pin setting failed: %d\n", err);
return false;
}
Serial.println("I2S pins set.");
return true;
}
// 请求爆炸声音播放实现
void AudioManager::requestPlay() {
_audioplay_index =false;
_playRequested = true;
}
// 请求滴滴声音声音播放实现
void AudioManager::requestPlay_Drip() {
_audioplay_index =true;
_playRequested = true;
}
// 检查是否正在播放(简单实现)
bool AudioManager::isPlaying() const {
// 更精确的实现需要跟踪播放状态,这里只是基于请求标志
return _playRequested; // 在play()函数结束时需要将此标志设回false
}
// 内部播放函数实现,暂定播放滴滴声
void AudioManager::play_Drip_sound() {
Serial.println("Start playing_Drip_sound audio...");
size_t bytes_written = 0;
int current_pos = 0;
// 创建一个RAM缓冲区,用于从PROGMEM拷贝数据块
uint8_t ram_buffer[_dmaBufLen];
// 循环直到所有音频数据都被发送
while (current_pos < pcm_sound_data_len_Drip) {
int bytes_to_copy = _dmaBufLen;
if (current_pos + bytes_to_copy > pcm_sound_data_len_Drip) {
bytes_to_copy = pcm_sound_data_len_Drip - current_pos;
}
// 从PROGMEM拷贝数据到RAM缓冲区
memcpy_P(ram_buffer, &pcm_sound_data_Drip[current_pos], bytes_to_copy);
// 将RAM缓冲区中的数据写入I2S总线
esp_err_t result = i2s_write(_i2sPort, ram_buffer, bytes_to_copy, &bytes_written, portMAX_DELAY);
if (result != ESP_OK) {
Serial.printf("I2S write error: %d\n", result);
break;
}
// if (bytes_written < bytes_to_copy) {
// Serial.printf("I2S write incomplete: Wrote %d / %d bytes\n", bytes_written, bytes_to_copy);
// }
current_pos += bytes_written; // 更新当前位置
}
// 播放完毕后,清空DMA缓冲区确保静音
i2s_zero_dma_buffer(_i2sPort);
Serial.println("Audio playback finished.");
_playRequested = false; // 重置播放请求标志
// 播放结束后,如果 MQTTManager 指针有效,发送播放结束消息
// if (_mqttManager) {
// Serial.println("Publishing audio play end message...");
// _mqttManager->publishJson("audioplayend", 1);
// }
}
// 内部播放函数实现
void AudioManager::play() {
Serial.println("Start playing audio...");
size_t bytes_written = 0;
int current_pos = 0;
// 创建一个RAM缓冲区,用于从PROGMEM拷贝数据块
uint8_t ram_buffer[_dmaBufLen];
// 循环直到所有音频数据都被发送
while (current_pos < pcm_sound_data_len) {
int bytes_to_copy = _dmaBufLen;
if (current_pos + bytes_to_copy > pcm_sound_data_len) {
bytes_to_copy = pcm_sound_data_len - current_pos;
}
// 从PROGMEM拷贝数据到RAM缓冲区
memcpy_P(ram_buffer, &pcm_sound_data[current_pos], bytes_to_copy);
// 将RAM缓冲区中的数据写入I2S总线
esp_err_t result = i2s_write(_i2sPort, ram_buffer, bytes_to_copy, &bytes_written, portMAX_DELAY);
if (result != ESP_OK) {
Serial.printf("I2S write error: %d\n", result);
break;
}
// if (bytes_written < bytes_to_copy) {
// Serial.printf("I2S write incomplete: Wrote %d / %d bytes\n", bytes_written, bytes_to_copy);
// }
current_pos += bytes_written; // 更新当前位置
}
// 播放完毕后,清空DMA缓冲区确保静音
i2s_zero_dma_buffer(_i2sPort);
Serial.println("Audio playback finished.");
_playRequested = false; // 重置播放请求标志
// 播放结束后,如果 MQTTManager 指针有效,发送播放结束消息
// if (_mqttManager) {
// Serial.println("Publishing audio play end message...");
// _mqttManager->publishJson("audioplayend", 1);
// }
}
// FreeRTOS 任务函数实现
// 这个函数运行在一个单独的核心上,负责检查播放请求并调用播放函数
void audioPlayTask(void* pvParameters) {
AudioManager* audioManager = static_cast<AudioManager*>(pvParameters);
if (!audioManager) {
Serial.println("AudioPlay Task: Invalid parameter!");
vTaskDelete(NULL); // 删除当前任务
return;
}
for (;;) {
if (audioManager->_playRequested) {
if(audioManager->_audioplay_index == false) audioManager->play();
if(audioManager->_audioplay_index == true ) audioManager->play_Drip_sound();
}
vTaskDelay(pdMS_TO_TICKS(30)); // 短暂延时,避免忙等
}
}
\ No newline at end of file
#ifndef AUDIO_MANAGER_H
#define AUDIO_MANAGER_H
#include <Arduino.h>
#include "pcm.h" // 包含你的PCM音频数据头文件
#include "driver/i2s.h" // 包含ESP32 I2S驱动头文件
class AudioManager {
private:
// I2S 配置参数
i2s_port_t _i2sPort = I2S_NUM_0; // 使用I2S端口0 (可配置)
int _sampleRate = 8000; // 音频采样率 (Hz) (可配置)
int _bitsPerSample = I2S_BITS_PER_SAMPLE_16BIT; // 每个采样点的位数
i2s_channel_fmt_t _channelFormat = I2S_CHANNEL_FMT_ONLY_LEFT;//I2S_CHANNEL_FMT_RIGHT_LEFT; // 通道格式
i2s_comm_format_t _commFormat = I2S_COMM_FORMAT_STAND_I2S; // 通信格式
int _dmaBufCount = 8; // DMA缓冲区数量 (可配置)
int _dmaBufLen = 2048; // 每个DMA缓冲区的长度 (字节) (可配置)
// I2S 引脚
int _bckPin;
int _lrcPin;
int _dinPin; // MAX98357A 不需要 DIN
bool _audioplay_index = false;
bool _playRequested = false; // 播放请求标志
// 内部播放爆炸函数(在任务中调用)
void play();
// 内部播放滴滴函数(在任务中调用)
void play_Drip_sound();
public:
// 构造函数
AudioManager(int bckPin, int lrcPin, int dinPin, int sampleRate = 16000, int dmaBufCount = 8, int dmaBufLen = 1024);
// 初始化 I2S
bool begin();
// 请求播放爆炸音频(任务会检查此标志)
void requestPlay();
// 请求播放滴滴音频(任务会检查此标志)
void requestPlay_Drip();
// 检查当前是否正在播放(如果play()是阻塞的,这个可能没意义,除非在play()内部设置标志)
bool isPlaying() const;
// FreeRTOS 任务函数(需要在主文件或单独的.cpp中实现,并友元声明)
// Friend declaration to allow the task function to access private members if needed
friend void audioPlayTask(void* pvParameters);
};
// FreeRTOS 任务函数声明
void audioPlayTask(void* pvParameters);
#endif // AUDIO_MANAGER_H
\ No newline at end of file
#include "DeviceControl.h"
// #include "AudioManager.h"
// #include <ArduinoJson.h> // 需要用于 handleMQTTCommand
// 构造函数实现
DeviceControl::DeviceControl(int K1, int K2, int K3, int K4, int pin1, int pin2, int pin3, int pin4,int sensorPin)
: _sensorPin(sensorPin) {
_outputPins[0] = K1;
_outputPins[1] = K2;
_outputPins[2] = K3;
_outputPins[3] = K4;
_outputPins[4] = pin1;
_outputPins[5] = pin2;
_outputPins[6] = pin3;
_outputPins[7] = pin4;
}
// begin 方法实现
void DeviceControl::begin() {
Serial.println("DeviceControl initializing...");
// 配置引脚模式
for (int i = 0; i < 4; ++i) {
pinMode(_outputPins[i], INPUT_PULLUP);
}
for (int i=4 ;i<8;i++){
pinMode(_outputPins[i], OUTPUT);
}
pinMode(_sensorPin, INPUT); // 传感器引脚设为输入
Serial.println("DeviceControl initialized.");
}
// 设置数字输出实现 (1-4 对应 _outputPins 数组索引 0-3)
void DeviceControl::setPinValue(int pinIndex, int val) {
if (pinIndex >= 1 && pinIndex <= 4) {
//Serial.printf("Setting digital pin %d (%d) to %d\n", pinIndex, _outputPins[pinIndex - 1], val);
digitalWrite(_outputPins[pinIndex + 4 - 1], val == 1 ? HIGH : LOW);
} else {
Serial.printf("Warning: Invalid pin index for digital write: %d\n", pinIndex);
}
}
// 设置 PWM 输出实现 (1-4 对应 _outputPins 数组索引 0-3)
void DeviceControl::setPWMValue(int pinIndex, int val) {
if (pinIndex >= 1 && pinIndex <= 4) {
// analogWrite 在 ESP32 上是 8 位分辨率 (0-255)
int analogVal = constrain(val * 255 / 100, 0, 255); // 将输入的 0-100 值映射到 0-255
//Serial.printf("Setting PWM pin %d (%d) to %d (scaled to %d)\n", pinIndex, _outputPins[pinIndex - 1], val, analogVal);
analogWrite(_outputPins[pinIndex - 1], analogVal);
} else {
Serial.printf("Warning: Invalid pin index for PWM write: %d\n", pinIndex);
}
}
// 更新 LED 血量效果实现
void DeviceControl::updateLedBlood() {
// 这个函数需要在周期性的任务中被调用,比如每几十毫秒一次
_led_count++; // 每次调用都递增计数器
if (_led_count > 20) _led_count = 0; // 闪烁周期计数器
if (_ledblood >= 6) { // 满血或更高,3个灯全亮
setPinValue(1,1);
setPinValue(2,1);
setPinValue(3,1);
} else if (_ledblood == 5){ // 5格血,灯1闪烁,灯2、3常亮
setPinValue(1, (_led_count < 10)); // 计数器 < 10 时为高电平
setPinValue(2,1);
setPinValue(3,1);
} else if (_ledblood == 4){ // 4格血,灯1灭,灯2、3常亮
setPinValue(1,0);
setPinValue(2,1);
setPinValue(3,1);
} else if (_ledblood == 3){ // 3格血,灯2闪烁,灯3常亮,灯1灭
setPinValue(2, (_led_count < 10));
setPinValue(1,0);
setPinValue(3,1);
} else if (_ledblood == 2){ // 2格血,灯3常亮,灯1、2灭
setPinValue(1,0);
setPinValue(2,0);
setPinValue(3,1);
} else if (_ledblood == 1){ // 1格血,灯3闪烁,灯1、2灭
setPinValue(3, (_led_count < 10));
setPinValue(1,0);
setPinValue(2,0);
} else { // ledblood <= 0,所有灯灭
setPinValue(1,0);
setPinValue(2,0);
setPinValue(3,0);
}
}
int DeviceControl::read_gpio() {
if(digitalRead(_outputPins[0])==LOW) {
vTaskDelay(pdMS_TO_TICKS(40));
if(digitalRead(_outputPins[0])==LOW) return 0;
}
if(digitalRead(_outputPins[1])==LOW) {
vTaskDelay(pdMS_TO_TICKS(40));
if(digitalRead(_outputPins[1])==LOW) return 1;
}
if(digitalRead(_outputPins[2])==LOW) {
vTaskDelay(pdMS_TO_TICKS(40));
if(digitalRead(_outputPins[2])==LOW) return 2;
}
if(digitalRead(_outputPins[3])==LOW) {
vTaskDelay(pdMS_TO_TICKS(40));
if(digitalRead(_outputPins[3])==LOW) return 3;
}
return -1;
// put your main code here, to run repeatedly:
}
// 读取传感器值实现
int DeviceControl::readSensor() {
// int rawValue = analogRead(_sensorPin);
// // 将读数转换为电压(假设 ADC 12位,参考电压 3.3V 或 2.5V)
// // ESP32C3 ADC 可以是 12位 (0-4095),参考电压通常是 3.3V 内部或外部。
// // 原始代码使用了 2.5,我们假设是 2.5V 参考电压,或者原始代码有误。
// // 使用 3.3V 参考电压是更常见的做法: rawValue * 3.3 / 4095.0
// // 如果你的电路使用了外部 2.5V 参考或其他方式,请调整下面的乘数
// const double referenceVoltage = 3.3; // 假设使用 3.3V 参考电压
// double voltage = (double)rawValue * referenceVoltage / 4095.0;
// Serial.printf("Sensor raw: %d, Voltage: %.2fV\n", rawValue, voltage); // 调试信息
int digitalValue = digitalRead(_sensorPin);
return (digitalValue == HIGH) ? 1 : 0;
// return voltage;
}
void DeviceControl::updatecontrol_smoke() {
int _smoke_ms=_smoke_time*(1000/_sleep_ms);
if(_smoke_index = true){
if(_smoke_ms != 0){
setPinValue(4,1);
}else setPinValue(4,0);
_smoke_ms--;
if(_smoke_ms = 0) {
_smoke_ms =0;
}
}
}
// 更新方法,在周期性任务中调用
void DeviceControl::update() {
// 更新 LED 状态
updateLedBlood();
// 更新 烟雾 状态
updatecontrol_smoke();
_led_index ++;
if (_ledblood > 0 &&readSensor() == 1&&_led_index>40){
Serial.printf("shotend");
_ledblood =_ledblood-1;
_audiomanager->requestPlay();
if(_ledblood<0) _ledblood =0;
_led_index =0;
}
if(_led_index>200)_led_index=201;
}
// FreeRTOS 任务函数实现
void devicePeriodicTask(void* pvParameters) {
DeviceControl* deviceControl = static_cast<DeviceControl*>(pvParameters);
if (!deviceControl) {
Serial.println("Device Periodic Task: Invalid parameter!");
vTaskDelete(NULL);
return;
}
for (;;) {
deviceControl->update(); // 调用 DeviceControl 的 update 方法
vTaskDelay(pdMS_TO_TICKS(deviceControl->_sleep_ms)); // 每 50 毫秒更新一次
}
}
\ No newline at end of file
#ifndef DEVICE_CONTROL_H
#define DEVICE_CONTROL_H
#include <Arduino.h>
#include "AudioManager.h"
// #include "MQTTManager.h" // 需要与 MQTTManager 交互以发布传感器数据
class AudioManager;
// class MQTTManager; // 前向声明
class DeviceControl {
private:
int _outputPins[8]; // 存储输出引脚的 GPIO 编号
int _sensorPin; // 存储传感器输入引脚的 GPIO 编号
int _ledblood = 6; // 用于控制 LED "血量" 效果的状态变量
int _led_count = 0; // LED 闪烁效果的计数器 (用于 updateLedBlood)
int _smoke_count = 0;
int _smoke_ms = 0;
bool _smoke_index =false;
int _led_index=0;
// int _beat_count=0;
int _shot_count=0;
int _smoke_time=0;
int _sleep_ms=25;
AudioManager *_audiomanager=nullptr;
//MQTTManager* _mqttManager = nullptr; // MQTT 管理器指针,用于发布传感器数据
// 内部函数
void setPinValue(int pinIndex, int val); // 控制数字输出
void setPWMValue(int pinIndex, int val); // 控制 PWM 输出
// 更新 LED 血量效果
void updateLedBlood();
// 读取传感器值
int readSensor();
public:
// 构造函数
// 传入输出引脚和传感器引脚的 GPIO 编号
DeviceControl(int K1, int K2, int K3, int K4, int pin1,int pin2,int pin3,int pin4, int sensorPin);
void devicecontrolaudio(AudioManager *audio_device){_audiomanager=audio_device;}
// 初始化引脚模式等
void begin();
void set_smoke_index(bool index){_smoke_index = index;}
void set_smoke_time(int time){_smoke_time=time;}
int getLedBlood() const {
return _ledblood;
}
void setledblood(int led){
_ledblood=led;
}
bool getsmoke() const {
return _smoke_index;
}
int read_gpio();
//心跳函数
//void updatebeartheat();
// 设置 MQTTManager 指针
// void setMQTTManager(MQTTManager* mqttManager) { _mqttManager = mqttManager; }
// 从外部设置 LED 血量值 (例如来自 MQTT)
void setLedBlood(int blood) { _ledblood = constrain(blood, 0, 6); _led_count = 0; } // 限制范围,重置计数器
// 处理来自 MQTT 的控制指令(例如设置引脚或 PWM)
//void handleMQTTCommand(int message_type, JsonObject body);
// 在周期性任务中调用,更新LED状态并读取/发布传感器数据
void update();
// FreeRTOS 任务函数(需要 在主文件或单独的.cpp中实现,并友元声明)
friend void devicePeriodicTask(void* pvParameters);
//烟雾传感器
void updatecontrol_smoke();
};
// FreeRTOS 任务函数声明
void devicePeriodicTask(void* pvParameters);
#endif // DEVICE_CONTROL_H
\ No newline at end of file
// #include "AudioManager.h"
#include <Arduino.h>
#include <freertos/FreeRTOS.h> // FreeRTOS 实时操作系统核心库
#include <freertos/task.h> // FreeRTOS 任务管理库
#include "DeviceControl.h"
#include "AudioManager.h"
#include "oled1306.h"
#define I2C_SDA 4
#define I2C_SCL 5
#define K4_PUSH 3
#define K3_PUSH 7
#define K2_PUSH 6
#define K1_PUSH 10
#define PIN_1 12
#define PIN_2 18
#define PIN_3 19
#define PIN_4 8
#define SERIOR 2
// -- I2S 引脚 --
#define I2S_BCLK 13// I2S 位时钟引脚
#define I2S_LRC 1// I2S 左右时钟引脚
#define I2S_DIN 0// I2S 数据输入引脚 (MAX98357A 不使用)
DeviceControl deviceControl(K1_PUSH,K2_PUSH,K3_PUSH,K4_PUSH,PIN_1,PIN_2,PIN_3,PIN_4,SERIOR);
oledcontrol oledcontrol(I2C_SCL,I2C_SDA);
AudioManager audioManager(I2S_BCLK,I2S_LRC,I2S_DIN);
void setup() {
Serial.begin(115200);
delay(1000);
deviceControl.begin();
oledcontrol.begin();
audioManager.begin();
oledcontrol.setdevicecontrol(&deviceControl);
deviceControl.devicecontrolaudio(&audioManager);
// initialize the pushbutton pin as an input:
xTaskCreate(audioPlayTask, "AudioPlay", 4096, (void*)&audioManager, 1, NULL);
xTaskCreate(oledPeriodicTask, "oledcontrol", 2048, (void*)&oledcontrol, 1, NULL); // 将 实例地址传递给按键任务
xTaskCreate(devicePeriodicTask, "DevicePeriodic", 2048, (void*)&deviceControl, 1, NULL); // 将 deviceControl 实例地址传递给设备任务
// put your setup code here, to run once:
audioManager.requestPlay_Drip(); // 请求播放启动音
oledcontrol.oledinit();
}
void loop() {
delay(1000);
}
#include "DeviceControl.h"
#include "oled1306.h"
oledcontrol::oledcontrol(int scl, int sda)
: display(128, 64, &Wire, -1), // 必须在这里初始化
_device_control(nullptr) {
_iic_pin[0] = sda;
_iic_pin[1] = scl;
}
int oledcontrol::begin() {
Wire.begin(_iic_pin[0], _iic_pin[1]);
Serial.println("SSD1306 init attempt");
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println("SSD1306 init failed");
return -1;
}
display.clearDisplay();
display.display();
return 0; // 必须明确返回值
}
void oledcontrol::update(){
if(_device_control->read_gpio()==0){
if(key_j==0){
key_i = (key_i > 0) ? key_i - 1 : 0;
_oled_index=0;
}
else if(key_j==1)key_i = (key_i > 0) ? key_i - 1 : 0;
}else if(_device_control->read_gpio()==1){
if(key_j==0) {
key_i = (key_i < 5) ? key_i + 1 : 4;
_oled_index=0;
}
else if(key_j==1) {
key_i = (key_i < 100) ? key_i + 1 : 99;
}
}else if(_device_control->read_gpio()==2){
key_j = (key_j > 0) ? key_j - 1 : 0;
if(key_j==0) key_i=0;
_oled_index=0;
}else if(_device_control->read_gpio()==3){
key_j = (key_j < 3) ? key_j + 1 : 2;
if(key_j<2) _oled_index=0;
}
}
void oledcontrol::oledinit() {
display.clearDisplay();
display.setTextSize(1); //设置字体大小为1:3
display.setTextColor(SSD1306_WHITE); //设置字体颜色为白色
display.setCursor(22, 0);
display.print("-----menu-----"); //打印输入的字符
display.setCursor(10, 12);
display.print("1- blood set"); //打印输入的字符
display.setCursor(90, _oled_count);
display.print("*"); //打印输入的字符
display.setCursor(10, 24);
display.print("2- smoke set");
display.setCursor(10, 36);
display.print("3- restart");
display.setCursor(10, 48);
display.print("4- reboot");
display.display();
}
void oledcontrol::oled_booldset(int blood) {
display.clearDisplay();
display.setTextSize(1); //设置字体大小为1:3
display.setTextColor(SSD1306_WHITE); //设置字体颜色为白色
display.setCursor(22, 0);
display.print("--blood set--");
display.setCursor(10, 12);
display.fillRect(10, 12,20, 12, SSD1306_BLACK);
if(blood>6)blood=6;
display.print("blood:");
display.setCursor(90, 12);
display.print(blood);
display.setCursor(10, 50);
display.print("#:return *:save");
display.display();
}
void oledcontrol::oled_update(){
if(key_j==0&&_oled_index==0){
oledinit();
display.fillRect(90, _oled_count,20, 12, SSD1306_BLACK);
if(key_i == 0)_oled_count=12;
else if(key_i == 1)_oled_count=24;
else if(key_i == 2)_oled_count=36;
else if(key_i == 3)_oled_count=48;
// display.setTextSize(1); //设置字体大小为1:3
// display.setTextColor(SSD1306_WHITE); //设置字体颜色为白色
display.setCursor(90, _oled_count);
display.print("*"); //打印输入的字符
display.display(); // 刷新屏幕
//Serial.println("down");
_oled_index==1;
}
if(key_i==0&&key_j>=1&&_oled_index==0){
_oled_index=3;
}else if(key_i==1&&key_j>=1&&_oled_index==0){
_oled_index=4;
} else if(key_i==2&&key_j>=1&&_oled_index==0){
Serial.println("reset");
_device_control->setLedBlood(6);
key_j=0;
_oled_index=1;
} else if(key_i==3&&key_j>=1&&_oled_index==0){
Serial.println("reboot");
ESP.restart();
key_j=0;
_oled_index=1;
}
if(_oled_index==3){
oled_booldset(key_i);
if(key_j>=2) {
Serial.println("save");
_preferences.begin("led_save", false);
_preferences.putInt("led_blood", key_i);
_preferences.end();
_device_control->setLedBlood(key_i);
key_j=0;
key_i=0;
_oled_index=0;
}
}else if(_oled_index==4){
}
}
void oledPeriodicTask(void* pvParameters){
oledcontrol* OLEDcontrol = static_cast<oledcontrol*>(pvParameters);
if (!OLEDcontrol) {
Serial.println("OLED Periodic Task: Invalid parameter!");
vTaskDelete(NULL);
return;
}
while(1){
OLEDcontrol->update();
OLEDcontrol->oled_update();
vTaskDelay(pdMS_TO_TICKS(50)); // 每 50 毫秒更新一次
}
}
#ifndef OLED1306_H
#define OLED1306_H
#include <Arduino.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Preferences.h> // Flash 非易失性存储库,用于保存WiFi配置
#include <Wire.h>
// 前向声明代替包含头文件
class DeviceControl;
class oledcontrol {
private:
int _iic_pin[2];
Adafruit_SSD1306 display;
DeviceControl* _device_control = nullptr;
int _oled_count=12;
int _oled_index=0;
int key_i=0;
int key_j=0;
Preferences _preferences;
void oled_booldset(int boold);
public:
oledcontrol(int scl, int sda);
int begin();
void setdevicecontrol(DeviceControl* device_control){_device_control=device_control;}
void update();
void oledinit();
void oled_update();
friend void oledPeriodicTask(void* pvParameters);
};
void oledPeriodicTask(void* pvParameters);
#endif
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
#ifndef PCM_H
#define PCM_H
extern unsigned int pcm_sound_data_len;
extern unsigned char pcm_sound_data[];
extern unsigned int pcm_sound_data_len_Drip ;
extern unsigned char pcm_sound_data_Drip[];
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment