Signed-off-by: myperworld <myperworld@126.com>

This commit is contained in:
myperworld committed 2025-10-06 12:34:26 +08:00
1 parent 0986832fd1
commit aacd052c06
3403 files changed
+597376 -12

No files matched your search

@@ -0,0 +1,11 @@
This directory is intended for PlatformIO Test Runner and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PlatformIO Unit Testing:
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
@@ -0,0 +1,288 @@
#include <Arduino.h>
#include "mapdata.h"
#include "espnow.h"
#include "ws2812_FASTLED.h"
#include "wemos_oled.h" //注意可能需要改屏幕的地址0x3C或0x3D等,若屏幕不亮可以试试用wire库中的示例程序扫描地址
#include "esp_wifi.h" // 添加WiFi库以设置信道
// 函数声明
// void coordinates_to_Leds();
// void joy1_map_led();
// void joy2_map_led();
// void joy1_led_blink();
// void joy2_led_blink();
void zero_test();
void eeprom_ini();
void eeprom_broadcastAddress();
unsigned long previousMillis1 = 0;
unsigned long previousMillis2 = 0;
unsigned long previousMillis3 = 0;
const long LEDdelay=40; //(milliseconds)LED变化时间间隔
int fade = 1; //呼吸效果
//摇杆坐标转化为离原点距离
int J1_dis = 0;
int J2_dis = 0;
//摇杆坐标转化为0-360的角度
int J1_angle = 0;
int J2_angle = 0;
//摇杆角度转化为左右摇杆LED序号
int J1_led_num = 0;
int J2_led_num = 0;
//摇杆离原点距离转化为左右摇杆LED亮度
int J1_led_bright = 0;
int J2_led_bright = 0;
//**********************Setup*************************
void setup() {
pinmode_pullup();
FastLED_ini(); //FastLED初始化
Serial.begin(115200);
delay(100);
eeprom_ini(); //EEPROM初始化
Serial.print(" LX_zero: ");Serial.print(EEPROM.read(1));
Serial.print(" LY_zero: ");Serial.print(EEPROM.read(2));
Serial.print(" RX_zero: ");Serial.print(EEPROM.read(3));
Serial.print(" RY_zero: ");Serial.println(EEPROM.read(4));
// 初始化 ESP-NOW
Serial.println("Initializing ESP-NOW...");
delay(100);
WiFi.mode(WIFI_STA);
// 设置WiFi信道为6
esp_wifi_set_channel(6, WIFI_SECOND_CHAN_NONE);
Serial.println("Set WiFi channel to 6");
Serial.println("InitESPNow");
// This is the mac address of the Master in Station Mode
Serial.print("STA MAC: "); Serial.println(WiFi.macAddress());
// Init ESPNow with a fallback logic
InitESPNow();
// 设置发送数据回调函数
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Trasnmitted packet
esp_now_register_send_cb(OnDataSent);
// 设置接收数据回调函数
// Once ESPNow is successfully Init, we will register for recv CB to
// get recv packer info.
// esp_now_register_recv_cb(OnDataRecv);
//配对连接pair with another ESP-NOW device
// pair_device();
BroadcastMode();//启动时默认为广播模式
// // In the loop we scan for slave
// ScanForSlave();
// // If Slave is found, it would be populate in `slave` variable
// // We will check if `slave` is defined and then we proceed further
//
// `slave` is defined
// Add slave as peer if it has not been added already
manageSlave();
// pair success or already paired
resetData();
// Serial.print("Data Size: "); Serial.print(sizeof(data));Serial.println(" Bytes");
// Serial.print(" LX: ");Serial.print(data.j1PotX);
// Serial.print(" LY: ");Serial.print(data.j1PotY);
// Serial.print(" RX: ");Serial.print(data.j2PotX);
// Serial.print(" RY: ");Serial.print(data.j2PotY);
// Serial.print(" // R1: ");Serial.print(data.buttonR1);
// Serial.print(" R2: ");Serial.print(data.buttonR2);
// Serial.print(" J1: ");Serial.print(data.j1Button);
// Serial.print(" J2: ");Serial.print(data.j2Button);
// Serial.print(" LB: ");Serial.print(data.buttonLB);
// Serial.print(" RB: ");Serial.print(data.buttonRB);
// Serial.print(" T1: ");Serial.println(data.tSwitch1);
run_OLED_on_Core_0();//在CORE0上运行OLED相关程序避免延迟影响
}
void loop() {
read_joydata();
/*********************************************************************************************/
LX_to_send = map_normal(LX_read, 0, LX_zero, 255, LX_inverted);
LY_to_send = map_normal(LY_read, 0, LY_zero, 255, LY_inverted);
RX_to_send = map_normal(RX_read, 0, RX_zero, 255, RX_inverted);
RY_to_send = map_normal(RY_read, 0, RY_zero, 255, RY_inverted);
/*********************************************************************************************/
LX_to_send = constrain(LX_to_send,0,255);
LY_to_send = constrain(LY_to_send,0,255);
RX_to_send = constrain(RX_to_send,0,255);
RY_to_send = constrain(RY_to_send,0,255);
data.j1PotX = LX_to_send;
data.j1PotY = LY_to_send;
data.j2PotX = RX_to_send;
data.j2PotY = RY_to_send;
data.buttonR1 = digitalRead(R1);
data.buttonR2 = digitalRead(R2);
data.j1Button = digitalRead(LS);
data.j2Button = digitalRead(RS);
data.buttonLB = digitalRead(LB);
data.buttonRB = digitalRead(RB);
data.tSwitch1 = digitalRead(BK);
// coordinates_to_Leds(); //坐标转换为LED控制
/************************************************/
//同时按下四键及拨动开关3秒后进行摇杆原点纠偏,此时不要碰摇杆
// if (!data.buttonR1&&!data.buttonR2&&!data.buttonLB&&!data.buttonRB&&!data.tSwitch1){
// delay (3000);
// if (!data.buttonR1&&!data.buttonR2&&!data.buttonLB&&!data.buttonRB&&!data.tSwitch1){
// zero_test();
// }
// }
//同时按下四键后变换背光RGB模式
// if (!data.j1Button&&!data.j2Button&&!data.buttonLB&&!data.buttonRB){
// delay (300);
// if (!data.j1Button&&!data.j2Button&&!data.buttonLB&&!data.buttonRB){
// lightState += 1;
// if (lightState>3) lightState = 0;
// }
// }
/************************************************/
/*
Serial.print(EEPROM.read(0));
Serial.print(" ");Serial.print(EEPROM.read(1));
Serial.print(" ");Serial.print(EEPROM.read(2));
Serial.print(" ");Serial.print(EEPROM.read(3));
Serial.print(" ");Serial.print(EEPROM.read(4));
/*
Serial.print(" LX: ");Serial.print(data.j1PotX);
Serial.print(" LY: ");Serial.print(data.j1PotY);
Serial.print(" RX: ");Serial.print(data.j2PotX);
Serial.print(" RY: ");Serial.print(data.j2PotY);
Serial.print(" // R1: ");Serial.print(data.buttonR1);
Serial.print(" R2: ");Serial.print(data.buttonR2);
Serial.print(" J1: ");Serial.print(data.j1Button);
Serial.print(" J2: ");Serial.print(data.j2Button);
Serial.print(" LB: ");Serial.print(data.buttonLB);
Serial.print(" RB: ");Serial.print(data.buttonRB);
Serial.print(" T1: ");Serial.println(data.tSwitch1);
/*
Serial.print(" J1_dis: ");Serial.print(J1_dis);Serial.print(" J2_dis: ");Serial.print(J2_dis);
Serial.print(" // J1_angle: ");Serial.print(J1_angle);Serial.print(" J2_angle: ");Serial.println(J2_angle);
Serial.print(" J1_led_num: ");Serial.print(J1_led_num);Serial.print(" J2_led_num ");Serial.print(J2_led_num);
Serial.print(" // J1_led_bright: ");Serial.print(J1_led_bright);Serial.print(" J2_led_bright: ");Serial.println(J2_led_bright);
*/
//*****************************************************
unsigned long currentMillis = millis();
if (currentMillis - previousMillis1 >= LEDdelay) {
previousMillis1 = currentMillis;
runLED();
if (J1_dis<10&&J2_dis<10){
if (voltage>3.50){ //电池电压高于3.5V时星闪模式
// joy1_led_blink();
// joy2_led_blink();
} else { //否则省电关灯
fill_solid (leds1,NUM_LEDS,CRGB::Black); //关灯
fill_solid (leds2,NUM_LEDS,CRGB::Black); //关灯
FastLED.show();
}
} else {
// joy1_map_led();
// joy2_map_led();
}
}
if (currentMillis - previousMillis2 >= 100) {//每100ms发送一次
previousMillis2 = currentMillis;
// ESP-NOW发送数据
sendData();
}
if (currentMillis - previousMillis3 >= 5000) {//每5秒更新一次电量
previousMillis3 = currentMillis;
batteryLevel(); //读电池电量
}
}
// void coordinates_to_Leds(){
// //摇杆坐标转化为离原点距离
// J1_dis = joy_distance((data.j1PotX-127),(data.j1PotY-127));
// J2_dis = joy_distance((data.j2PotX-127),(data.j2PotY-127));
// //摇杆坐标转化为0-360的角度
// J1_angle = coordinates_to_angle(((J1_dis<15) ? 0 :(data.j1PotX-127)),((J1_dis<15) ? 0 :(data.j1PotY-127)));
// J2_angle = coordinates_to_angle(((J2_dis<15) ? 0 :(data.j2PotX-127)),((J2_dis<15) ? 0 :(data.j2PotY-127)));
// //摇杆角度转化为左右摇杆LED序号
// J1_led_num = angle_to_lednum1(J1_angle);
// J2_led_num = angle_to_lednum2(J2_angle);
// //摇杆离原点距离转化为左右摇杆LED亮度
// J1_led_bright = (J1_dis<15)? 0 : (map (J1_dis,0,127,0,max_bright));
// J2_led_bright = (J2_dis<15)? 0 : (map (J2_dis,0,127,0,max_bright));
// }
// void joy1_map_led(){
// fill_solid (leds1,NUM_LEDS,CRGB::Black); //关灯
// leds1[J1_led_num] = ColorFromPalette( RainbowColors_p, beatsin8(1, 0, 255), J1_led_bright, LINEARBLEND);
// leds1[(J1_led_num+1)>7 ? 0 : (J1_led_num+1)] = ColorFromPalette( RainbowColors_p, beatsin8(1, 0, 255), J1_led_bright/8, LINEARBLEND);
// leds1[(J1_led_num-1)<0 ? 7 : (J1_led_num-1)] = ColorFromPalette( RainbowColors_p, beatsin8(1, 0, 255), J1_led_bright/8, LINEARBLEND);
// FastLED.show();
// }
// void joy2_map_led(){
// fill_solid (leds2,NUM_LEDS,CRGB::Black); //关灯
// leds2[J2_led_num] = ColorFromPalette( RainbowColors_p, beatsin8(1, 0, 255), J2_led_bright, LINEARBLEND);
// leds2[(J2_led_num+1)>7 ? 0 : (J2_led_num+1)] = ColorFromPalette( RainbowColors_p, beatsin8(1, 0, 255), J2_led_bright/8, LINEARBLEND);
// leds2[(J2_led_num-1)<0 ? 7 : (J2_led_num-1)] = ColorFromPalette( RainbowColors_p, beatsin8(1, 0, 255), J2_led_bright/8, LINEARBLEND);
// FastLED.show();
// }
//void eeprom_ini(){
// EEPROM.begin(EEPROM_SIZE);
//
// if( EEPROM.read(0) != 55){ //判断是否首次使用(新的所有地址貌似是255的值)
//
// zero_test(); //启动一次自动纠偏,但此时大多没有将开发板装到遥控器上,所以数据不对
// eeprom_broadcastAddress(); //存入广播模式MAC地址
//
// EEPROM.write(0, 55);
// EEPROM.commit();
// }
//
// LX_zero = EEPROM.read(1);
// LY_zero = EEPROM.read(2);
// RX_zero = EEPROM.read(3);
// RY_zero = EEPROM.read(4);
//
// Serial.print("已储存并用来配对的MAC地址:");
// for (int i = 0; i < 6; i++) {
// broadcastAddress[i]=EEPROM.read(MAC_ADDRESS_OFFSET + i);
// Serial.print(EEPROM.read(MAC_ADDRESS_OFFSET + i), HEX); // 以16进制格式打印MAC地址
// if (i < 5) {
// Serial.print(":"); // 每2个字节之间用"-"分隔
// }
// }
// Serial.println();
//
//}
//
//void eeprom_broadcastAddress(){
// for (int i = 0; i < 6; i++) {
// EEPROM.write(MAC_ADDRESS_OFFSET + i, broadcastAddress[i]);
// }
//}
@@ -0,0 +1,286 @@
#ifndef MAPDATA_H
#define MAPDATA_H
#include <EEPROM.h>
#define EEPROM_SIZE 64
// TRIGGER BUTTONS
#define LB 19
#define RB 25
// LEFT-JOYSTICK
#define LH 34
#define LV 35
#define LS 5
// RIGHT-JOYSTICK
#define RH 36
#define RV 32
#define RS 4
#define R1 2
#define R2 13
// BATTERY VOLTAGE
#define ADC 39 //电池ADC
// RGB
//#define DATA_PIN 17
//OTHERS
#define BK 23 //拨动开关
int buttons[7] = {R1,R2,LS,RS,LB,RB,BK};
const int numberOfPotSamples = 5; // Number of pot samples to take (to smooth the values)
const int delayBetweenSamples = 2; // Delay in milliseconds between pot samples
int LX_read = 0;
int LY_read = 0;
int RX_read = 0;
int RY_read = 0;
byte LX_zero = 127;
byte LY_zero = 127;
byte RX_zero = 127;
byte RY_zero = 127;
int LX_to_send = 0;
int LY_to_send = 0;
int RX_to_send = 0;
int RY_to_send = 0;
bool LY_inverted = false;
bool LX_inverted = false;
bool RY_inverted = false;
bool RX_inverted = false;
int counter = 0;
int invert_counter = 0;
float voltage = 3.00;
int percentage = 0;
void pinmode_pullup(){
for (int i = 0; i < 7; i++) {
pinMode(buttons[i], INPUT_PULLUP);
}
}
/**************************************************/
int map_normal(int val, int lower, int middle, int upper, bool reverse)
{
val = constrain(val, lower, upper);
if ( val < middle )
val = map(val, lower, middle, 0, 127);
else
val = map(val, middle, upper, 127, 255);
return ( reverse ? 255 - val : val );
}
// Returns a corrected value for a joystick position that takes into account
// the values of the outer extents and the middle of the joystick range.
int map_exponential(int val, bool reverse)
{
val = constrain(val, 0, 1023);
float cube = ((pow((val - 512),3)/520200) + 258.012) / 2;
return ( reverse ? 255 - cube : cube );
}
/**************************************************/
void read_joydata(){
int potValues[numberOfPotSamples];
for (int i = 0 ; i < numberOfPotSamples ; i++) {
potValues[i] = analogRead(LH);
delay(delayBetweenSamples);
}
int potValue = 0;
for (int i = 0 ; i < numberOfPotSamples ; i++) {
potValue += potValues[i];
}
potValue = potValue / numberOfPotSamples;
LX_read = map(potValue, 0, 4095, 255, 0);
int potValues2[numberOfPotSamples];
for (int i = 0 ; i < numberOfPotSamples ; i++) {
potValues2[i] = analogRead(LV);
delay(delayBetweenSamples);
}
int potValue2 = 0;
for (int i = 0 ; i < numberOfPotSamples ; i++) {
potValue2 += potValues2[i];
}
potValue2 = potValue2 / numberOfPotSamples;
LY_read = map(potValue2, 0, 4095, 255, 0);
int potValues3[numberOfPotSamples];
for (int i = 0 ; i < numberOfPotSamples ; i++) {
potValues3[i] = analogRead(RH);
delay(delayBetweenSamples);
}
int potValue3 = 0;
for (int i = 0 ; i < numberOfPotSamples ; i++) {
potValue3 += potValues3[i];
}
potValue3 = potValue3 / numberOfPotSamples;
RX_read = map(potValue3, 0, 4095, 255, 0);
int potValues4[numberOfPotSamples];
for (int i = 0 ; i < numberOfPotSamples ; i++) {
potValues4[i] = analogRead(RV);
delay(delayBetweenSamples);
}
int potValue4 = 0;
for (int i = 0 ; i < numberOfPotSamples ; i++) {
potValue4 += potValues4[i];
}
potValue4 = potValue4 / numberOfPotSamples;
RY_read = map(potValue4, 0, 4095, 255, 0);
}
void zero_test(){ //摇杆原点纠偏程序
Serial.println(" joy_zero_testing... ");
read_joydata();
delay (300);
LX_to_send = map_normal(LX_read, 0, 127, 255, 0);
LY_to_send = map_normal(LY_read, 0, 127, 255, 0);
RX_to_send = map_normal(RX_read, 0, 127, 255, 0);
RY_to_send = map_normal(RY_read, 0, 127, 255, 0);
LX_to_send = constrain(LX_to_send,0,255);
LY_to_send = constrain(LY_to_send,0,255);
RX_to_send = constrain(RX_to_send,0,255);
RY_to_send = constrain(RY_to_send,0,255);
LX_zero = LX_to_send;
LY_zero = LY_to_send;
RX_zero = RX_to_send;
RY_zero = RY_to_send;
Serial.println(" Writing in EEPROM... ");
delay (300);
if( EEPROM.read(1) != LX_zero) EEPROM.write(1, LX_zero);
if( EEPROM.read(2) != LY_zero) EEPROM.write(2, LY_zero);
if( EEPROM.read(3) != RX_zero) EEPROM.write(3, RX_zero);
if( EEPROM.read(4) != RY_zero) EEPROM.write(4, RY_zero);
EEPROM.commit();
Serial.println(" Done... ");
Serial.print(" LX_zero: ");Serial.print(EEPROM.read(1));
Serial.print(" LY_zero: ");Serial.print(EEPROM.read(2));
Serial.print(" RX_zero: ");Serial.print(EEPROM.read(3));
Serial.print(" RY_zero: ");Serial.println(EEPROM.read(4));
}
void eeprom_ini(){
EEPROM.begin(EEPROM_SIZE);
if( EEPROM.read(0) != 55){ //判断是否首次使用(新的所有地址貌似是255的值)
zero_test();
EEPROM.write(0, 55);
EEPROM.commit();
}
LX_zero = EEPROM.read(1);
LY_zero = EEPROM.read(2);
RX_zero = EEPROM.read(3);
RY_zero = EEPROM.read(4);
}
void batteryLevel() {
int sensorValue = analogRead(ADC);
voltage = sensorValue/4095.0 * 7.27; //7.23乘数具体数值用万用表实测纠偏
percentage = (voltage-3.2) * 100;
// percentage = 2808.3808 * pow(voltage,4) - 43560.9157 * pow(voltage,3) + 252848.5888 * pow(voltage,2)
// - 650767.4615 * voltage + 626532.5703; //这段计算公式参考https://www.youtube.com/watch?v=qKUrXwkr3cc
if (voltage>4.19) percentage = 100; //限制到0-100范围
if (voltage<3.20) percentage = 0;
if (voltage>3.00){
// Serial.print("Lipo: ");Serial.print(voltage);Serial.print("V || ");
// Serial.print(percentage);Serial.println("%");
}
// bleGamepad.setBatteryLevel(percentage);
// if (percentage < 60) {
// Serial.println("LOW battery");
// for (uint8_t i = 30; i < 220; i++) {
// for (int j = 0; j < 6; j++) {
// leds[j] = CHSV( HUE_RED, 255, i);
// }
// FastLED.show();
// delay(15);
// }
// for (uint8_t i = 220; i > 30; i--) {
// for (int j = 0; j < 6; j++) {
// leds[j] = CHSV( HUE_RED, 255, i);
// }
// FastLED.show();
// delay(15);
// }
// }
}
//摇杆坐标转化为离原点距离
int joy_distance(float coord_x,float coord_y){
int joy_dis=0;
joy_dis=sqrt(sq(coord_x)+sq(coord_y));
if (joy_dis < 5) joy_dis=0; //消除一些摇杆误差
return joy_dis;
}
//摇杆坐标转化为0-360的角度
int coordinates_to_angle(float coord_x,float coord_y){
int joy_angle=0;
if (coord_x>0&&coord_y>0){ //第一象限
joy_angle=asin(coord_y/sqrt(sq(coord_x)+sq(coord_y)))*180/3.14159;
}
if (coord_x<0&&coord_y>0){ //第二象限
joy_angle=180-asin(coord_y/sqrt(sq(coord_x)+sq(coord_y)))*180/3.14159;
}
if (coord_x<0&&coord_y<0){ //第三象限
joy_angle=180-asin(coord_y/sqrt(sq(coord_x)+sq(coord_y)))*180/3.14159; //此时Y坐标为负数
}
if (coord_x>0&&coord_y<0){ //第四象限
joy_angle=360+asin(coord_y/sqrt(sq(coord_x)+sq(coord_y)))*180/3.14159; //此时Y坐标为负数
}
return joy_angle;
}
//摇杆角度转化为左摇杆LED序号
int angle_to_lednum1(int angle){
int led_num=0;
if ((0<=angle&&angle<23)||(338<=angle&&angle<360)) led_num=0;
if (23<=angle&&angle<68) led_num=7;
if (68<=angle&&angle<113) led_num=6;
if (113<=angle&&angle<158) led_num=5;
if (158<=angle&&angle<203) led_num=4;
if (203<=angle&&angle<248) led_num=3;
if (248<=angle&&angle<293) led_num=2;
if (293<=angle&&angle<338) led_num=1;
return led_num;
}
//摇杆角度转化为右摇杆LED序号
int angle_to_lednum2(int angle){
int led_num=0;
if ((0<=angle&&angle<23)||(338<=angle&&angle<360)) led_num=4;
if (23<=angle&&angle<68) led_num=3;
if (68<=angle&&angle<113) led_num=2;
if (113<=angle&&angle<158) led_num=1;
if (158<=angle&&angle<203) led_num=0;
if (203<=angle&&angle<248) led_num=7;
if (248<=angle&&angle<293) led_num=6;
if (293<=angle&&angle<338) led_num=5;
return led_num;
}
#endif