在嵌入式电子产品中制作无线项目变得非常重要和有用,因为没有杂乱的电线,这使得设备更加方便和便携。有各种无线技术,例如蓝牙、WiFi、433 MHz RF(射频)等。每种技术都有其自身的优缺点,例如成本、距离或范围传输、速度或吞吐量等。今天我们将使用STM32 的射频模块以无线方式发送和接收数据。
在这里,我们将连接一个 433MHz 射频无线模块与 STM32F103C8 微控制器。该项目分为两部分。发送器将与 STM32 连接,接收器将与 Arduino UNO 连接。发射和接收部分都会有不同的电路图和草图。
在本教程中,RF 发射器向接收器端发送两个值:使用超声波传感器测量的距离和电位计ADC值(0 到 4096),该值映射为(0 到 100)之间的数字。Arduino的RF 接收器接收这两个值并以无线方式在16x2 LCD 显示器中打印这些距离和数字值。
所需组件
STM32F103C8微控制器
Arduino UNO
433Mhz 射频发射器和接收器
超声波传感器 (HC-SR04)
16x2 液晶显示器
10k 电位器
面包板
连接电线
433Mhz 射频发射器和接收器模块)
射频发射器引脚:
射频接收器引脚:
433 MHz 模块规格:
接收器工作电压:3V 至 5V
发射器工作电压:3V 至 5V
工作频率:433 MHz
传输距离:3米(不带天线)至100米(最大)
调制技术:ASK(幅移键控)
数据传输速度:10Kbps
STM32F103C8射频发射器电路图
射频发射器和 STM32F103C8 之间的电路连接:
超声波传感器和 STM32F103C8 之间的电路连接:
STM32F103C8 连接一个10k 电位器,为 STM32 的 ADC 引脚 PA0 提供输入模拟值(0 至 3.3V)。
带有Arduino Uno的RF接收器电路图
射频接收器和 Arduino UNO 之间的电路连接:
16x2 LCD 和 Arduino UNO 之间的电路连接:
下面将简要解释编码。草图将分为两部分,第一部分是发射器部分,另一部分是接收器部分。所有草图文件和工作视频将在本教程结束时提供。要了解有关射频模块与 Arduino Uno 接口的更多信息,请点击链接。
为无线射频传输编程STM32F103C8
STM32F103C8 可以使用 Arduino IDE 进行编程。无需 FTDI 编程器或 ST-Link即可将代码上传到 STM32F103C8。只需通过 STM32 的 USB 端口连接到 PC 并开始使用ARDUINO IDE进行编程。
首先包含 Radiohead 库,可以从这里下载。因为这个库使用 ASK(幅移键控技术)来传输和接收数据。这使得编程非常容易。您可以通过进入 Sketch->include library->Add .zip library 在草图中包含库。
#include
正如在发射器端的本教程中一样,超声波传感器用于测量距离,因此定义了触发和回波引脚。
#define trigPin PB1
#define echoPin PB0
接下来,将 RH_ASK 库的对象名称设置为 rf_driver,并使用诸如速度 (2000)、RX 引脚 (PA9) 和 TX 引脚 (PA10) 等参数。
RH_ASK rf_driver(2000, PA9, PA10);
接下来,声明该程序所需的 Strings 变量。
字符串传输号码;
字符串传输距离;
字符串传输;
接下来在 void setup() 中,初始化 RH_ASK rf_driver 的对象。
rf_driver.init();
之后触发引脚设置为 OUTPUT 引脚,PA0(连接到电位器)和回波引脚设置为 INPUT 引脚。串行通信以 9600 的波特率开始。
序列号.开始(9600);
pinMode(PA0,输入);
pinMode(echoPin,输入);
pinMode(trigPin,输出);
接下来在 void loop() 中,首先将输入模拟电压的电位器值转换为数字值(找到 ADC 值)。由于STM32 的 ADC具有 12 位分辨率。因此,数字值从 (0 到 4096) 变化,映射到 (0 到 100)。
int 模拟输入 = 模拟读取(PA0);
int pwmvalue = map(模拟输入,0,4095,0,100);
接下来,使用超声波传感器测量距离,方法是设置触发器高低,延迟 2 微秒。
数字写入(trigPin,低);
延迟微秒(2);
digitalWrite(trigPin, HIGH);
延迟微秒(10);
数字写入(trigPin,低);
回波针感测反射回来的波,即触发波反射回来的持续时间用于使用公式计算物体的距离。通过点击链接了解更多超声波传感器如何计算距离。
持续时间长 = pulseIn(echoPin, HIGH);
浮动距离=持续时间*0.034/2;
现在测量的数据数量和距离都转换为字符串数据并存储在相应的字符串变量中。
传输数=字符串(pwm值);
传输距离 = 字符串(距离);
两个字符串都作为一行添加并存储在称为传输的字符串中,逗号“,”用于分隔两个字符串。
传输=传输_pwm +“,”+传输距离;
传输字符串被转换为字符数组。
const char *msg = transmit.c_str();
数据被传输并等待直到它被发送。
rf_driver.send((uint8_t *)msg, strlen(msg));
rf_driver.waitPacketSent();
发送的字符串数据也显示在串行监视器中。
序列号.println(msg);
将 Arduino UNO 编程为 RF 接收器
Arduino UNO 使用 Arduino IDE 进行编程。在接收器部分,从发射器部分发送并由 RF 接收器模块接收的数据和接收到的字符串数据被拆分为各自的数据(距离和数量)并显示在 16x2 LCD 显示屏上。
让我们简要地看一下接收器编码:
就像在发射器部分一样,首先包含 RadiohHead 库。因为这个库使用 ASK(幅移键控技术)来传输和接收数据。这使得编程非常容易。
#include
由于这里使用的是 LCD 显示器,所以还包括了液晶库。
#include
与 Arduino UNO 连接的 16x2 LCD 显示引脚使用 lcd 作为对象指定和声明。
液晶液晶(2,3,4,5,6,7);
接下来声明用于存储字符串数据的字符串数据变量。
字符串 str_receive;
字符串 str_number;
字符串 str_distance;
Radiohead 库的对象已声明。
RH_ASK 射频;
现在在void setup() 中,LCD 显示设置为 16x2 模式,并显示并清除欢迎消息。
lcd.开始(16,2);
lcd.print("电路文摘");
lcd.setCursor(0,1);
lcd.print("STM32 射频");
延迟(5000);
lcd.clear();
之后,初始化rf对象。
rf.init();
现在在void loop() 中,数组 buf[] 被声明为大小为 7。因为从发送器发送的数据有 7,包括“,”。因此,根据要传输的数据进行更改。
uint8_t buf[7];
uint8_t buflen = sizeof(buf);
如果该字符串在 rf 接收器模块中可用,则 if 函数会检查大小并执行。rf.recv()用于接收数据。
如果 (rf.recv(buf, &buflen))
buf具有接收到的字符串,因此接收到的字符串存储在str_receive字符串变量中。
str_receive = String((char*)buf);
如果检测到两个字符串之间的“,”,则此for循环用于将接收到的字符串分成两部分。
for (int i = 0; i < str_receive.length(); i++)
{
if (str_receive.substring(i, i+1) == ",")
{
str_number = str_receive.substring(0, i);
str_distance = str_receive.substring(i+1);
休息;
}
声明两个值的两个 char 数组,通过将字符串转换为字符数组,将分成两个的字符串存储在相关数组中。
字符数串[4];
字符距离字符串[3];
str_distance.toCharArray(distancestring,3);
str_number.toCharArray(numberstring,3);
之后使用 atoi() 将字符数组转换为整数
int 距离 = atoi(距离字符串);
int number = atoi(numberstring);
转换成整数值后,距离和数字值显示在 16x2 LCD 显示屏中
lcd.setCursor(0,0);
lcd.print("编号:");
lcd.print(数字);
lcd.setCursor(0,1);
lcd.print("距离:");
lcd.print(距离);
lcd.print("cm");
分别在STM32和Arduino UNO中上传发射器和接收器代码后,使用STM32测量的数字和物体距离等数据通过RF发射器传输到RF接收器,接收到的值以无线方式显示在LCD显示屏上。
测试基于 STM 32 的射频发射器和接收器
1.当数字为0且物体距离为6cm时。
2.当数字47和物体距离为3cm时。
发射器代码(STM32F103C8):
//433MHZ射频发射器与STM32F103C8
//发射机代码
//电路文摘
#include //RadioHead 库
#define trigPin PB1 //设置超声波传感器的Trigpin为PB1
#define echoPin PB0 //设置超声波传感器的echoPin为PB0
RH_ASK rf_driver(2000, PA9, PA10); //设置引脚PA9为接收器,PA10为发送器,2000为速度
字符串传输_pwm;//存储字符串值的字符串
字符串传输距离;
字符串传输;
无效设置()
{
// 初始化 ASK 对象
rf_driver.init();
序列号.开始(9600);
pinMode(PA0,输入);
pinMode(echoPin,输入);
pinMode(trigPin,输出);
}
无效循环()
{
int 模拟输入 = 模拟读取(PA0);// 来自连接到电位器的引脚 PA0 的 ADC 值
int pwmvalue = map(模拟输入,0,4096,0,100);// 将 0 到 4096 转换为 0 到 100
数字写入(trigPin,低);//将超声波的TrigPin设为LOW
延迟微秒(2);
digitalWrite(trigPin, HIGH); //使Ultrasonic HIGH的TrigPin
延迟微秒(10);
数字写入(trigPin,低);//将超声波的TrigPin设为LOW
持续时间长 = pulseIn(echoPin, HIGH); //接收反射的Echo信号
浮动距离=持续时间*0.034/2;//计算对象的CM距离
传输_pwm =字符串(pwm值);//将值转换为字符串
传输距离 = 字符串(距离);//将值转换为字符串
传输=传输_pwm +“,”+传输距离;//在一行中添加两个字符串
const char *msg = transmit.c_str(); //
rf_driver.send((uint8_t *)msg, strlen(msg)); //发送字符串
rf_driver.waitPacketSent();
序列号.println(msg); //用于调试的串行打印值
延迟(1000);
}
接收器代码(Arduino UNO):
//接收器Arduino代码
//433MHZ射频,STM32F103C8作为发射器
//电路文摘
#include //包含 RadioHead 库
#include //包含LCD显示库
液晶液晶(2,3,4,5,6,7); //使用连接到 Arduino 的引脚初始化 lcd
字符串 str_receive; //存储值的字符串
字符串 str_number;
字符串 str_distance;
RH_ASK 射频;//rf 作为 RG_ASK 的对象
无效设置()
{
lcd.开始(16,2);//液晶屏设置为16x2模式
lcd.print("电路文摘"); //显示欢迎信息
lcd.setCursor(0,1);
lcd.print("STM32 射频");
延迟(5000);
lcd.clear();
rf.init(); //初始化射频对象
}
无效循环()
{
uint8_t buf[7];
uint8_t buflen = sizeof(buf);
如果 (rf.recv(buf, &buflen))
{
str_receive = String((char*)buf); // 从发送器接收字符串
for (int i = 0; i < str_receive.length(); i++) // 将字符串拆分为两个字符串
{
if (str_receive.substring(i, i+1) == ",")
{
str_number = str_receive.substring(0, i);
str_distance = str_receive.substring(i+1);
休息;
}
}
字符数串[4];
字符距离字符串[3];
str_distance.toCharArray(distancestring,3); //将字符串转换为字符数组
str_number.toCharArray(numberstring,3);
int 距离 = atoi(距离字符串);//将数组转换成整数值
int number = atoi(numberstring);
lcd.setCursor(0,0);
lcd.print("编号:");
lcd.print(数字); //在LCD显示屏上显示数值
lcd.setCursor(0,1);
lcd.print("距离:");
lcd.print(距离);//在液晶显示屏上显示距离值
lcd.print("cm");
延迟(1500);
lcd.clear();
}
}