784 lines
24 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include SPI.h
#include MFRC522.h
#include FastLED.h
#include Arduino.h
#include driverledc.h
RFID引脚定义
#define RFID_RST_PIN 14 RC522 复位引脚
#define RFID_SS_PIN 10 RC522 片选引脚
#define RFID_MISO_PIN 13 MISO 引脚
#define RFID_MOSI_PIN 12 MOSI 引脚
#define RFID_SCK_PIN 11 SCK 引脚
LED定义
#define LED_PIN_1 4 1颗WS2812灯珠引脚
#define LED_PIN_2 5 160颗WS2812灯带引脚
#define LED_PIN_3 48 1颗WS2812灯珠引脚新增
#define LED_COUNT_1 1 1颗灯珠
#define LED_COUNT_2 186 160颗灯带
#define LED_COUNT_3 1 1颗灯珠新增
PWM定义
#define PWM_PIN 6 PWM输出引脚
#define PWM_CHANNEL 0 PWM通道
#define PWM_FREQ 1000 PWM频率(Hz)
#define PWM_RESOLUTION 10 PWM分辨率(位)
#define DEFAULT_DUTY 819 默认占空比(80%)
#define BTN0_PIN 15 按钮0引脚
#define WAKEUP1_PIN 16 唤醒引脚1
#define BTN1_PIN 17 按钮1引脚
#define BTN2_PIN 18 按钮2引脚
TaskHandle_t TaskRFID, TaskLED1, TaskLED2, TaskLED3, TaskPWM, TaskBTN0, TaskWAKEUP1, TaskBTN1, TaskBTN2;
MFRC522 rfid(RFID_SS_PIN, RFID_RST_PIN); RFID实例
CRGB leds1[LED_COUNT_1]; 1
CRGB leds2[LED_COUNT_2]; 160
CRGB leds3[LED_COUNT_3]; 1
CRGB frozenLeds2[LED_COUNT_2]; 5
uint8_t frozenBrightness = 255;
String lastCardData = ; RFID卡数据
int ledMode = 1; 1()
int pwmDuty = DEFAULT_DUTY; PWM占空比
bool btn0State = HIGH; 0
bool btn0LongPress = false; 0
bool wakeup1State = LOW; 1
bool btn1State = LOW; 1
bool btn2State = LOW; 2
int singleLedMode = 7; LED模式7()
static uint8_t rainbowHue = 0;
static int trainPos = 0;
static unsigned long lastUpdate = 0;
static const int TRAIN_LENGTH = 16;
static int trainPhase = 0; 0-1-2-3-4-5-
static const int VIRTUAL_LED_COUNT = LED_COUNT_2 + TRAIN_LENGTH;
LED亮度线性映射表 (0~100 26~255) - 10%
0-100%PWM值
LED完全不可见的问题
const uint8_t brightnessMapLinear[101] = {
0, 28, 31, 33, 36, 38, 41, 43, 46, 48, 0-9
51, 54, 56, 59, 61, 64, 66, 69, 71, 74, 10-19
77, 79, 82, 84, 87, 89, 92, 94, 97, 99, 20-29
102, 105, 107, 110, 112, 115, 117, 120, 122, 125, 30-39
128, 130, 133, 135, 138, 140, 143, 145, 148, 150, 40-49
153, 156, 158, 161, 163, 166, 168, 171, 173, 176, 50-59
179, 181, 184, 186, 189, 191, 194, 196, 199, 201, 60-69
204, 207, 209, 212, 214, 217, 219, 222, 224, 227, 70-79
230, 232, 235, 237, 240, 242, 245, 247, 250, 252, 80-89
253, 254, 254, 254, 255, 255, 255, 255, 255, 255, 90-99
255 100%
};
const uint8_t brightnessMap = brightnessMapLinear;
LED2亮度控制0-255
LED灯带的整体亮度1245
3使
uint8_t led2Brightness = 102; 40%10225540%
LED颜色数组
CRGB singleLedColors[8] = {
CRGBBlack, 0
CRGBBlue, 1
CRGBGreen, 2 绿
CRGBOrange, 3
CRGBRed, 4
CRGBPurple, 5
CRGBYellow, 6
CRGBWhite 7
};
RFID读取任务
void TaskRFIDcode(void pvParameters) {
for (;;) {
if (!rfid.PICC_IsNewCardPresent()) {
delay(10);
continue;
}
NUID是否可读
if (!rfid.PICC_ReadCardSerial()) {
delay(10);
continue;
}
String cardData = ;
MFRC522MIFARE_Key key;
for (byte i = 0; i 6; i++) key.keyByte[i] = 0xFF;
MFRC522StatusCode status;
status = rfid.PCD_Authenticate(MFRC522PICC_CMD_MF_AUTH_KEY_A, 4, &key, &(rfid.uid));
if (status != MFRC522STATUS_OK) {
Serial.print(F(Authentication failed ));
Serial.println(rfid.GetStatusCodeName(status));
rfid.PICC_HaltA();
rfid.PCD_StopCrypto1();
delay(100);
continue;
}
byte buffer[18];
byte size = sizeof(buffer);
status = rfid.MIFARE_Read(4, buffer, &size);
if (status != MFRC522STATUS_OK) {
Serial.print(F(Reading failed ));
Serial.println(rfid.GetStatusCodeName(status));
} else {
ASCII字符串
for (byte i = 0; i 16; i++) {
if (buffer[i] = 32 && buffer[i] = 126) { ASCII字符
cardData += (char)buffer[i];
}
}
cardData.trim();
if (cardData != lastCardData && !cardData.isEmpty()) {
lastCardData = cardData;
Serial.println(SORC_ + cardData);
}
}
使IC卡进入休眠状态
rfid.PICC_HaltA();
PCD
rfid.PCD_StopCrypto1();
delay(100);
}
}
TaskLEDUnifiedCode替代
setup()
LED1控制任务TaskLEDUnifiedCode统一处理
void TaskLED1code(void pvParameters) {
使
LED1的控制已集成到TaskLEDUnifiedCode中
vTaskDelete(NULL);
}
LED3控制任务TaskLEDUnifiedCode统一处理
void TaskLED3code(void pvParameters) {
使
LED3的控制已集成到TaskLEDUnifiedCode中
vTaskDelete(NULL);
}
PWM控制任务
void TaskPWMcode(void pvParameters) {
for (;;) {
PWM占空比
ledc_set_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)PWM_CHANNEL, pwmDuty);
ledc_update_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)PWM_CHANNEL);
delay(100);
}
}
0
void TaskBTN0code(void pvParameters) {
static unsigned long pressStartTime = 0;
static bool lastState = HIGH;
for (;;) {
bool currentState = digitalRead(BTN0_PIN);
沿()
if (lastState == HIGH && currentState == LOW) {
pressStartTime = millis();
btn0State = LOW;
Serial.println(SO_BT0_HIGH);
btn0LongPress = false;
}
沿()
else if (lastState == LOW && currentState == HIGH) {
btn0State = HIGH;
Serial.println(SO_BT0_LOW);
btn0LongPress = false;
}
else if (currentState == LOW && millis() - pressStartTime = 2000 && !btn0LongPress) {
btn0LongPress = true;
Serial.println(SO_BT0_HIGHL);
}
lastState = currentState;
delay(10);
}
}
WAKEUP1检测任务
void TaskWAKEUP1code(void pvParameters) {
static bool lastState = LOW;
for (;;) {
bool currentState = digitalRead(WAKEUP1_PIN);
沿
if (lastState == LOW && currentState == HIGH) {
wakeup1State = HIGH;
Serial.println(SO_WAKEUP1);
}
沿
else if (lastState == HIGH && currentState == LOW) {
wakeup1State = LOW;
Serial.println(SO_WAKEUP0);
}
lastState = currentState;
delay(10);
}
}
1
void TaskBTN1code(void pvParameters) {
static bool lastState = LOW;
for (;;) {
bool currentState = digitalRead(BTN1_PIN);
沿
if (lastState == LOW && currentState == HIGH) {
btn1State = HIGH;
Serial.println(SO_BT1_HIGH);
}
沿
else if (lastState == HIGH && currentState == LOW) {
btn1State = LOW;
Serial.println(SO_BT1_LOW);
}
lastState = currentState;
delay(10);
}
}
2
void TaskBTN2code(void pvParameters) {
static bool lastState = LOW;
for (;;) {
bool currentState = digitalRead(BTN2_PIN);
沿
if (lastState == LOW && currentState == HIGH) {
btn2State = HIGH;
Serial.println(SO_BT2_HIGH);
}
沿
else if (lastState == HIGH && currentState == LOW) {
btn2State = LOW;
Serial.println(SO_BT2_LOW);
}
lastState = currentState;
delay(10);
}
}
void handleSerialCommand() {
static String command = ;
while (Serial.available()) {
if (command.length() 64) {
Serial.println( 64);
command = ;
while (Serial.available()) Serial.read();
continue;
}
char c = Serial.read();
if (c == 'n') {
if (command.startsWith(MO_LED_)) {
String modeStr = command.substring(7);
int newMode = modeStr.toInt();
LED
if (newMode = 0 && newMode = 7) {
singleLedMode = newMode;
Serial.print(Single LED set to mode );
Serial.println(newMode);
} else {
Serial.println(Invalid single LED mode command);
}
} else if (command.startsWith(MO_LEDN_)) {
String modeStr = command.substring(8);
int newMode = modeStr.toInt();
0
if (newMode = 0 && newMode = 5) {
if (led2Brightness == 0) {
Serial.println(00);
} else {
ledMode = newMode;
if (newMode == 4) {
trainPos = -TRAIN_LENGTH;
trainPhase = 0;
rainbowHue = random8();
}
5LED2状态和亮度
if (newMode == 5) {
memcpy(frozenLeds2, leds2, sizeof(leds2));
frozenBrightness = led2Brightness;
}
Serial.print(LED strip set to mode );
Serial.println(newMode);
}
} else {
Serial.println(Invalid LED strip mode command);
}
} else if (command.startsWith(MO_PWM_)) {
String dutyStr = command.substring(7);
int newDuty = dutyStr.toInt();
PWM百分比
if (newDuty == 1) {
pwmDuty = 1023; 100%
} else if (newDuty == 0 newDuty == 20 newDuty == 40 newDuty == 60 newDuty == 80) {
pwmDuty = (newDuty 1023) 100;
} else {
Serial.println(Invalid PWM command);
}
Serial.print(PWM set to );
Serial.print((pwmDuty 100) 1023);
Serial.println(%);
}
else if (command.startsWith(MO_BRI_)) {
MO_BRI_前缀
String levelStr = command.substring(7);
levelStr.trim();
command = ;
if (levelStr.length() == 0) {
Serial.println( );
return;
}
bool isNumeric = true;
for (char c levelStr) {
if (!isdigit(c)) {
isNumeric = false;
break; 退
}
}
if (!isNumeric) {
Serial.println( );
return;
}
int level = levelStr.toInt();
if (level = 0 && level = 100) {
PWM范围
led2Brightness = brightnessMap[level]; 使
Serial.print(LED亮度 );
Serial.print(level);
Serial.println(%);
0
if (level == 0) {
Serial.println(0);
}
} else {
Serial.println( 0-100);
}
command = ;
}
command = ;
} else {
command += c;
}
}
}
LED控制任务
LED1LED2LED3
1. 30FPS稳定更新频率
2. 5
3.
4.
5. LED显示稳定
void TaskLEDUnifiedCode(void pvParameters) {
static unsigned long lastLEDUpdate = 0;
const unsigned long LED_UPDATE_INTERVAL = 33; ~30FPS
for (;;) {
unsigned long currentTime = millis();
CPU和闪烁问题
if (currentTime - lastLEDUpdate LED_UPDATE_INTERVAL) {
delay(5);
continue;
}
lastLEDUpdate = currentTime;
---- LED1 LED----
if (singleLedMode = 0 && singleLedMode = 7) {
leds1[0] = singleLedColors[singleLedMode];
} else {
leds1[0] = CRGBBlue;
}
---- LED3 ----
leds3[0] = CRGBBlack;
---- LED2 ----
switch (ledMode) {
case 0 0LED灯珠
fill_solid(leds2, LED_COUNT_2, CRGBBlack);
break;
case 1 1led2Brightness调节
fill_solid(leds2, LED_COUNT_2, CHSV(0, 0, led2Brightness));
break;
case 2 2沿
for (int i = 0; i LED_COUNT_2; i++) {
leds2[i] = CHSV(rainbowHue + i 256 LED_COUNT_2, 255, led2Brightness);
}
rainbowHue++;
break;
case 3 3
{
static unsigned long lastHueUpdate = 0;
static unsigned long lastBreathUpdate = 0;
static uint8_t breathingHue = 0;
static uint8_t breathPhase = 0;
unsigned long currentTime = millis();
300ms更新一次色相
if (currentTime - lastHueUpdate 300) {
breathingHue += 1;
lastHueUpdate = currentTime;
}
30ms更新一次呼吸相位
if (currentTime - lastBreathUpdate 30) {
breathPhase += 2;
lastBreathUpdate = currentTime;
}
led2Brightness的60%-100%
uint8_t minBrightness = led2Brightness 60 100;
uint8_t maxBrightness = led2Brightness;
uint8_t breathValue = map(sin8(breathPhase), 0, 255, minBrightness, maxBrightness);
for(int i = 0; i LED_COUNT_2; i++) {
leds2[i] = CHSV(breathingHue, 200, breathValue);
}
}
break;
case 4 4
if (millis() - lastUpdate 30) { 30ms更新间隔
lastUpdate = millis();
fill_solid(leds2, LED_COUNT_2, CRGBBlack);
switch (trainPhase) {
case 0 0
for (int i = 0; i TRAIN_LENGTH; i++) {
int pos = trainPos + i;
if (pos = 0 && pos LED_COUNT_2) {
uint8_t hue = rainbowHue + (i 256 TRAIN_LENGTH);
leds2[pos] = CHSV(hue, 255, led2Brightness);
}
}
trainPos++;
if (trainPos = 0) {
trainPhase = 1;
trainPos = 0;
}
break;
case 1 1
for (int i = 0; i TRAIN_LENGTH; i++) {
int pos = trainPos + i;
if (pos = 0 && pos LED_COUNT_2) {
uint8_t hue = rainbowHue + (i 256 TRAIN_LENGTH);
leds2[pos] = CHSV(hue, 255, led2Brightness);
}
}
trainPos++;
if (trainPos = LED_COUNT_2 - TRAIN_LENGTH) {
trainPhase = 2;
trainPos = LED_COUNT_2 - TRAIN_LENGTH;
}
break;
case 2 2
for (int i = 0; i TRAIN_LENGTH; i++) {
int displayPos = LED_COUNT_2 - 1 - i;
if (displayPos = trainPos) {
uint8_t hue = rainbowHue + (i 256 TRAIN_LENGTH);
leds2[displayPos] = CHSV(hue, 255, led2Brightness);
}
}
trainPos++;
if (trainPos = LED_COUNT_2) {
trainPhase = 3;
trainPos = 0;
rainbowHue += 64;
}
break;
case 3 3
for (int i = 0; i trainPos + 1; i++) {
int pos = LED_COUNT_2 - 1 - i;
if (pos = 0) {
uint8_t hue = rainbowHue + ((TRAIN_LENGTH - 1 - i) 256 TRAIN_LENGTH);
leds2[pos] = CHSV(hue, 255, led2Brightness);
}
}
trainPos++;
if (trainPos = TRAIN_LENGTH) {
trainPhase = 4;
trainPos = TRAIN_LENGTH;
}
break;
case 4 4
for (int i = 0; i TRAIN_LENGTH; i++) {
int pos = LED_COUNT_2 - trainPos + i;
if (pos = 0 && pos LED_COUNT_2) {
uint8_t hue = rainbowHue + ((TRAIN_LENGTH - 1 - i) 256 TRAIN_LENGTH);
leds2[pos] = CHSV(hue, 255, led2Brightness);
}
}
trainPos++;
if (trainPos = LED_COUNT_2) {
trainPhase = 5;
trainPos = 0;
}
break;
case 5 5
for (int i = 0; i TRAIN_LENGTH - trainPos; i++) {
int pos = i;
if (pos LED_COUNT_2) {
uint8_t hue = rainbowHue + ((TRAIN_LENGTH - 1 - i) 256 TRAIN_LENGTH);
leds2[pos] = CHSV(hue, 255, led2Brightness);
}
}
trainPos++;
if (trainPos = TRAIN_LENGTH) {
trainPhase = 0;
trainPos = -TRAIN_LENGTH;
rainbowHue += 64;
}
break;
}
}
break;
case 5 5
if (led2Brightness == 0) {
fill_solid(leds2, LED_COUNT_2, CRGBBlack); 0
} else {
uint16_t brightnessRatio = (uint16_t)led2Brightness 255 frozenBrightness;
if (brightnessRatio 255) brightnessRatio = 255;
使memcpy
for (int i = 0; i LED_COUNT_2; i++) {
leds2[i].r = (frozenLeds2[i].r brightnessRatio) 8;
leds2[i].g = (frozenLeds2[i].g brightnessRatio) 8;
leds2[i].b = (frozenLeds2[i].b brightnessRatio) 8;
}
}
break;
}
---- LED ----
FastLED刷新保护
FastLED.show();
---- ----
使LED显示稳定
delay(10); 10ms延时LED数据传输完成
}
}
void setup() {
Serial.begin(115200);
Serial.println(System starting...);
SPI总线
SPI.begin(RFID_SCK_PIN, RFID_MISO_PIN, RFID_MOSI_PIN, RFID_SS_PIN);
RFID
rfid.PCD_Init();
Serial.println(RFID initialized.);
LED
FastLED.addLedsWS2812, LED_PIN_1, GRB(leds1, LED_COUNT_1);
FastLED.addLedsWS2812, LED_PIN_2, GRB(leds2, LED_COUNT_2);
FastLED.addLedsWS2812, LED_PIN_3, GRB(leds3, LED_COUNT_3); LED3
LED状态
fill_solid(leds1, LED_COUNT_1, singleLedColors[singleLedMode]);
fill_solid(leds2, LED_COUNT_2, CHSV(0, 0, led2Brightness));
fill_solid(leds3, LED_COUNT_3, CRGBBlack); GPIO48的灯珠熄灭
FastLED.show();
Serial.println(LED initialized.);
PWM
LED控制器配置
ledc_timer_config_t ledc_timer = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.duty_resolution = (ledc_timer_bit_t)PWM_RESOLUTION,
.timer_num = (ledc_timer_t)PWM_CHANNEL,
.freq_hz = PWM_FREQ,
.clk_cfg = LEDC_AUTO_CLK
};
ledc_timer_config(&ledc_timer);
LED通道配置
ledc_channel_config_t ledc_channel = {
.gpio_num = PWM_PIN,
.speed_mode = LEDC_LOW_SPEED_MODE,
.channel = (ledc_channel_t)PWM_CHANNEL,
.intr_type = LEDC_INTR_DISABLE,
.timer_sel = (ledc_timer_t)PWM_CHANNEL,
.duty = 0,
.hpoint = 0
};
ledc_channel_config(&ledc_channel);
ledc_set_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)PWM_CHANNEL, pwmDuty);
ledc_update_duty(LEDC_LOW_SPEED_MODE, (ledc_channel_t)PWM_CHANNEL);
Serial.println(PWM initialized.);
pinMode(BTN0_PIN, INPUT_PULLUP);
pinMode(WAKEUP1_PIN, INPUT);
pinMode(BTN1_PIN, INPUT);
pinMode(BTN2_PIN, INPUT);
Serial.println(Inputs initialized.);
xTaskCreatePinnedToCore(
TaskRFIDcode,
TaskRFID,
4096,
NULL,
1,
&TaskRFID,
1); 1
xTaskCreatePinnedToCore(
TaskLEDUnifiedCode,
TaskLEDUnified,
8192,
NULL,
3, LED更新不被其他任务干扰
NULL,
1);
xTaskCreatePinnedToCore(
TaskPWMcode,
TaskPWM,
1024,
NULL,
1,
&TaskPWM,
1);
xTaskCreatePinnedToCore(
TaskBTN0code,
TaskBTN0,
2048,
NULL,
1,
&TaskBTN0,
0);
xTaskCreatePinnedToCore(
TaskWAKEUP1code,
TaskWAKEUP1,
2048,
NULL,
1,
&TaskWAKEUP1,
0);
xTaskCreatePinnedToCore(
TaskBTN1code,
TaskBTN1,
2048,
NULL,
1,
&TaskBTN1,
0);
xTaskCreatePinnedToCore(
TaskBTN2code,
TaskBTN2,
2048,
NULL,
1,
&TaskBTN2,
0);
Serial.println(Tasks created. System ready.);
}
void loop() {
handleSerialCommand();
CPU时间
delay(1);
}