Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
esp32project
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
957dd
esp32project
Commits
212c18e7
Commit
212c18e7
authored
Sep 03, 2025
by
957dd
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature/person_add' into 'master'
个人版 See merge request
!6
parents
c1e07a1b
7506dac1
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
820 additions
and
12 deletions
+820
-12
AudioManager.h
defence/AudioManager.h
+0
-2
DeviceControl.cpp
defence/DeviceControl.cpp
+11
-8
defence.ino
defence/defence.ino
+2
-2
launch.json
defence_person/defence_person/.theia/launch.json
+6
-0
AudioManager.cpp
defence_person/defence_person/AudioManager.cpp
+188
-0
AudioManager.h
defence_person/defence_person/AudioManager.h
+60
-0
DeviceControl.cpp
defence_person/defence_person/DeviceControl.cpp
+180
-0
DeviceControl.h
defence_person/defence_person/DeviceControl.h
+104
-0
defence_person.ino
defence_person/defence_person/defence_person.ino
+64
-0
oled1306.cpp
defence_person/defence_person/oled1306.cpp
+150
-0
oled1306.h
defence_person/defence_person/oled1306.h
+43
-0
pcm.cpp
defence_person/defence_person/pcm.cpp
+0
-0
pcm.h
defence_person/defence_person/pcm.h
+12
-0
No files found.
defence/AudioManager.h
View file @
212c18e7
...
...
@@ -60,8 +60,6 @@ public:
friend
void
audioPlayTask
(
void
*
pvParameters
);
};
extern
AudioManager
audioManager
;
// FreeRTOS 任务函数声明
void
audioPlayTask
(
void
*
pvParameters
);
...
...
defence/DeviceControl.cpp
View file @
212c18e7
...
...
@@ -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
/
5
0
;
int
smoke_i
=
_smoke_ms
/
2
0
;
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
(
5
0
));
// 每 50 毫秒更新一次
vTaskDelay
(
pdMS_TO_TICKS
(
2
0
));
// 每 50 毫秒更新一次
}
}
\ No newline at end of file
defence/defence.ino
View file @
212c18e7
...
...
@@ -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/
139901
00000001"
;
// 你要订阅的 MQTT 主题
const
char
*
MQTT_RELEASE_TOPIC
=
"
139901
00000001"
;
// 你要发布的 MQTT 主题
const
char
*
MQTT_SUBSCRIBE_TOPIC
=
"ser2dev/
CN0402
00000001"
;
// 你要订阅的 MQTT 主题
const
char
*
MQTT_RELEASE_TOPIC
=
"
CN0402
00000001"
;
// 你要发布的 MQTT 主题
// --- 创建类实例 ---
// 这些实例现在包含了之前分散的全局变量和相关函数
...
...
defence_person/defence_person/.theia/launch.json
0 → 100644
View file @
212c18e7
{
//
Use
IntelliSense
to
learn
about
possible
attributes.
//
Hover
to
view
descriptions
of
existing
attributes.
"version"
:
"0.2.0"
,
"configurations"
:
[]
}
defence_person/defence_person/AudioManager.cpp
0 → 100644
View file @
212c18e7
#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
defence_person/defence_person/AudioManager.h
0 → 100644
View file @
212c18e7
#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
defence_person/defence_person/DeviceControl.cpp
0 → 100644
View file @
212c18e7
#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
defence_person/defence_person/DeviceControl.h
0 → 100644
View file @
212c18e7
#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
defence_person/defence_person/defence_person.ino
0 → 100644
View file @
212c18e7
// #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
);
}
defence_person/defence_person/oled1306.cpp
0 → 100644
View file @
212c18e7
#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 毫秒更新一次
}
}
defence_person/defence_person/oled1306.h
0 → 100644
View file @
212c18e7
#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
defence_person/defence_person/pcm.cpp
0 → 100644
View file @
212c18e7
This source diff could not be displayed because it is too large. You can
view the blob
instead.
defence_person/defence_person/pcm.h
0 → 100644
View file @
212c18e7
#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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment