如何入手一台已开源的遥控系统(Code)(下)

ChangeCode
原创
发布时间: 2025-06-14 15:03:07 | 阅读数 0收藏数 0评论数 0
封面
基于STM32F4平台开发的一款名为XRC的开源遥控器。这款遥控器具有多功能性,支持ELRS高频头、Mavlink协议,并且拥有中文界面和3.5寸电容触摸屏等特性,适合用于无人机、机器人等设备的控制。

准备工作:

材料:


发射器组件

材料

数量

备注

STM32F103C8T6

1

/

NRF24L01 GT24 迷你版

1

/

E11 旋转编码器 (ENC)

1

/

贴片 8MHz 晶振 (3225)

1

/

FC-135 32.768kHz 晶体

1

/

CH340C 贴片机

1

/

Y1 (8050) NPN 晶体管

2

/

1AM (3904) NPN 晶体管

1

/

0.96 英寸 OLED 显示屏

1

/

10k 欧姆电阻器 (SMD)

4

/

1k 欧姆电阻器 (SMD)

4

/

100nF 电容器 (SMD)

20

/

蜂鸣器

1

/

AMS117 (3.3V 稳压器)

1

/

10uF 电容器

2

/

公接头

30

/

DJI Phantom 2 遥控器外壳

1

/



接收器 (PWM+PPM)

材料

数量

备注

1.STM32F103C8T6

1

/

2.NRF24L01 GT24 Mini

1

/

3.SMD 8MHz 晶体 (3225)

1

/

4.1AM (3904) NPN 晶体管

1

/

5.AMS117 (3.3V 稳压器)

1

/

6.10uF 电容器

2

/

7.100nF 电容器 (SMD)

4

/

8.公接头

30

/



接收器 (PPM+SBUS)

材料

数量

备注

1.STM32F103C8T6

1

/

2.NRF24L01 GT24 Mini

1

/

3.SMD 8MHz 晶体 (3225)

1

/

4.1AM (3904) NPN 晶体管

1

/

5.AMS117 (3.3V 稳压器)

1

/

6.10uF 电容器

2

/

7.100nF 电容器 (SMD)

4

/

8.公接头

30

/


1

setup()

此功能初始化所有必要的硬件外围设备并设置系统运行。

void setup() {
// Initialize the delay function for timekeeping
delayInit();
// Initialize USART for serial communication
usart1Init();
// Initialize timers for PWM and other timing-related functions
timer2Init();
timer3Init();
// Initialize DMA for memory transfers
dmaInit();
// Initialize ADC for analog reading (e.g., battery level)
adcInit();
// Initialize NRF24L01 for wireless communication
if (nrf24l01Init() == NRF_OK) {
nrf24l01SetModeTX(); // Set NRF to transmit mode
} else {
// Handle NRF24L01 initialization error
beepError();
}
// OLED display initialization and show start-up screen
oledInit();
oledShowLogo();
// Perform throttle self-check and configure NRF24L01 power mode
throttleSelfCheck();
// Set up low-power mode if necessary
lowPowerModeConfig();
}
2

loop()

在运行期间持续运行的主循环。它处理显示更新、信号强度检查和关键事件。

void loop() {
// Handle clock alarms and time display on the OLED
handleClockAlarm();
// Update OLED display with throttle values and battery percentage
displayThrottleValues();
displayBatteryLevel();
// Update signal strength display
updateSignalStrength();
// Check for key events and menu navigation
keyEventHandle();
// Handle menu events, if any
menuEventHandle();
// Small delay to avoid constant polling
delay(50);
}
3

keyEventHandle()

通过按键处理用户输入。此函数更新节流设置并处理菜单中的导航。

void keyEventHandle() {
if (isKeyPressed(KEY_LEFT)) {
// Adjust throttle channel for left-hand throttle
adjustThrottleLeft();
}
if (isKeyPressed(KEY_RIGHT)) {
// Adjust throttle channel for right-hand throttle
adjustThrottleRight();
}
// Update OLED display with new throttle or menu setting
oledRefresh();
// Save user data or preferences (e.g., throttle setting)
saveUserDataToFlash();
}
4

addSignalStrengthSa

将新样本添加到信号强度缓冲区中,并保持信号强度的移动平均值。


void addSignalStrengthSample(int newSignalStrength) {
// Add new signal strength to the sample buffer
signalStrengthBuffer[sampleIndex] = newSignalStrength;
// Update sample index for circular buffer
sampleIndex = (sampleIndex + 1) % SIGNAL_STRENGTH_BUFFER_SIZE;
}
5

getAverageSignalStr

根据收集的样本计算信号强度的移动平均值。

int getAverageSignalStrength() {
int sum = 0;
for (int i = 0; i < SIGNAL_STRENGTH_BUFFER_SIZE; i++) {
sum += signalStrengthBuffer[i];
}
return sum / SIGNAL_STRENGTH_BUFFER_SIZE;
}
6

displaySignalIcon()

根据信号强度百分比在 OLED 上显示信号强度图标。

void displaySignalIcon(int signalStrengthPercent) {
if (signalStrengthPercent >= 75) {
oledDrawIcon(iconSignal100);
} else if (signalStrengthPercent >= 50) {
oledDrawIcon(iconSignal75);
} else if (signalStrengthPercent >= 25) {
oledDrawIcon(iconSignal50);
} else if (signalStrengthPercent > 0) {
oledDrawIcon(iconSignal25);
} else {
oledDrawIcon(iconSignalOff);
}
}
7

nrf24l01InitAndCheck

初始化 NRF24L01 模块并将其设置为传输模式。

void nrf24l01InitAndCheck() {
// Initialize NRF24L01
if (nrf24l01Init() == NRF_OK) {
// Set NRF24L01 to transmit mode
nrf24l01SetModeTX();
} else {
// Handle NRF24L01 error by beeping and showing error message
beepError();
oledShowErrorMessage("NRF24L01 ERROR");
}
}
8

Sending Data Packets

该函数创建一个 32 字节的数据包,并使用 NRF24L01 模块发送。数据包包含数据头和通道值 (PWM 数据)。

u8 sendDataPacket(void)
{
u8 chPacket[32]; // Array to hold the data packet
u16 t = 0;
u8 sendIsOK; // Flag to check if sending is successful
for (t = 0; t < 16; t++)
{
if (t == 0) // Add data header (0x00)
{
chPacket[2 * t] = 0x00;
chPacket[2 * t + 1] = 0x00;
}
else if (t <= chNum) // Add PWM channel data
{
chPacket[2 * t] = (u8)(PWMvalue[t - 1] >> 8) & 0xFF; // High byte of 16-bit PWM value
chPacket[2 * t + 1] = (u8)PWMvalue[t - 1] & 0xFF; // Low byte of 16-bit PWM value
}
else // Fill unused bytes with 0xFF (padding)
{
chPacket[2 * t] = 0xFF;
chPacket[2 * t + 1] = 0xFF;
}
}
sendIsOK = NRF24L01_TxPacket(chPacket); // Transmit the packet
return sendIsOK; // Return status of the transmission (success or failure)
}
9

getSignalStrength()

此函数通过发送多个数据包并计算成功传输的百分比来测量信号强度。

int getSignalStrength(void)
{
const int totalPackets = 40; // Total number of packets to send
int successfulPackets = 0; // Counter for successful transmissions
if (setData.NRF_Mode == ON) // If the NRF mode is ON
{
NRF24L01_TX_Mode(setData.NRF_Power); // Set NRF to transmit mode
}
else
{
NRF24L01_LowPower_Mode(); // Otherwise, set it to low-power mode
}
// Loop to send multiple packets
for (int i = 0; i < totalPackets; i++)
{
if (sendDataPacket() == TX_OK) // If the packet was sent successfully
{
successfulPackets++; // Increment success counter
}
delay_us(700); // Short delay between transmissions
}
// Calculate signal strength as a percentage of successful packets
int signalStrength = (successfulPackets * 100) / totalPackets;
return signalStrength;
}
10

updateSignalStrength

更新信号强度显示并检查接收器是否已连接。它还会将新样本添加到信号强度缓冲区中。

void updateSignalStrength() {
// Get current signal strength from NRF24L01
int currentSignalStrength = nrf24l01GetSignalStrength();
// Add the sample to the signal strength buffer
addSignalStrengthSample(currentSignalStrength);
// Calculate the average signal strength
int avgSignalStrength = getAverageSignalStrength();
// Display the corresponding signal strength icon
displaySignalIcon(avgSignalStrength);
// Check if receiver is connected
if (avgSignalStrength > SIGNAL_STRENGTH_THRESHOLD) {
receiverConnected();
} else {
receiverDisconnected();
}
}
11

menuEventHandle()

处理用户界面菜单并响应用户输入以更改设置。

void menuEventHandle() {
// Check if a specific menu item is selected
if (isMenuItemSelected(MENU_ITEM_PWM_ADJUST)) {
adjustPWMSettings();
}
if (isMenuItemSelected(MENU_ITEM_CHANNEL_CALIBRATION)) {
calibrateChannels();
}
// Refresh OLED display with updated menu or settings
oledMenuRefresh();
}
12

Battery Voltage

根据电池电压更新 OLED 上的电池电量图标和百分比。

void displayBatteryLevel() {
float batteryVoltage = readBatteryVoltage();
int batteryPercent = convertVoltageToPercentage(batteryVoltage);
// Display the battery icon and percentage on the OLED
oledDrawBatteryIcon(batteryPercent);
if (batteryVoltage < BATTERY_WARNING_THRESHOLD) {
// Beep to warn low battery
beepWarning();
}
}
13

Clock and Alarm

处理时钟和闹钟功能,触发闹钟时发出蜂鸣声。

void handleClockAlarm() {
// Check if the clock alarm is active
if (isAlarmActive()) {
// Beep if the alarm time is reached
beepAlarm();
// Display alarm icon on the OLED
oledDrawIcon(iconAlarm);
}
// Update the time on the OLED display
displayCurrentTime();
}
14

软件

下载并安装 STMicroelectronics Flash Loader Demonstrator 软件:点击下载

15

步骤

将 USB 串行转换器插入 PC。按下 STM32 板上的重置按钮。在软件中选择 COM 端口。单击“下一步”、“下一步”和“下一步”。选择“下载到设备”。单击 3 个点并选择十六进制文件。选择 Global Erase.然后单击下一步在 15 秒内,代码将上传到设备。在完成 finsihed.单击 Close。

阅读记录0
点赞0
收藏0
禁止 本文未经作者允许授权,禁止转载
猜你喜欢
评论/提问(已发布 0 条)
评论 评论
收藏 收藏
分享 分享
pdf下载 下载