RS485转UART:如何在arduino和microbit 主控上使用风速仪与风向...
本帖最后由 川山甲的壳 于 2022-2-14 11:20 编辑如何在arduino和microbit 主控上使用风速仪与风向仪?————RS485转UART 这应该是今年的第一贴,首先祝大家新年快乐,虎年大吉。背景: 前一段时间,有位老师想做一个气象站的项目,但是他选的风速仪和风向仪接口不兼容Arduino和micro:bit主控。后面他就找到我,问我有没有什么解决办法?RS485风向变送器-传感器模组-DFRobot创客商城RS485风速变送器-传感器模组-DFRobot创客商城
当看见他发过来的图片时,方案就已经在脑海里呈现了,对于这个问题,只需要加一个Gravity:RS485转UART有源隔离型信号转换模块 就行了。因为风向变送器和风速变送器是RS485接口,协议是Modbus协议,所以需要使用RS485转UART 模块,其作用就是将RS485接口转换成UART输出。
下面我就分享一下,如何在arduino和micro:bit主控上使用风向变送器和风速变送器。首先我们根据下图将风向变送器和风速变送器连接在Gravity:RS485转UART有源隔离型信号转换模块上。注:风向变送器和风速变送器的接线方式一样。Arduino uno 上的使用方法
测量风向软硬件准备硬件:
DFRduino UNO R3-Arduino控制器IO 传感器扩展板 V7.1-Arduino扩展板
RS485风向变送器-传感器模组Gravity:RS485转UART有源隔离型信号转换模块
软件:· Arduino IDE 点击下载Arduino IDE· MIND+ 点击下载 mindplus硬件连接ArduinoIDE——样例代码1. 将风向变送器,RS485转UART模块,uno R3按照上面的方式连接在一起。2. 打开Arduino IDE,将下面的代码上传到DFRduino uno R3上。3. 打开串口,将波特率调至115200,通过串口观察结果。4. 数值对应的方向。#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //定义软串口,3号端口为TX,2号端口为RX,
uint8_tAddress = 0x03;
void setup()
{
Serial.begin(115200);
mySerial.begin(9600);
ModifyAddress(0x00, Address);//设备地址修改,修改地址后请注释掉这句重新上电。
}
void loop()
{
Serial.println(readWindDirection(Address)); //读取风向
delay(1000);
}
size_t readN(uint8_t *buf, size_t len)
{
size_t offset = 0, left = len;
int16_t Tineout = 1500;
uint8_t*buffer = buf;
long curr = millis();
while (left) {
if (mySerial.available()) {
buffer = mySerial.read();
offset++;
left--;
}
if (millis() - curr > Tineout) {
break;
}
}
return offset;
}
/**
@brief计算CRC16_2检验值
@parambuf 需要计算校验值的数据包
@paramlen 需要校验的数据长度。
@return返回一个16位的校验结果。
*/
uint16_t CRC16_2(uint8_t *buf, int16_t len)
{
uint16_t crc = 0xFFFF;
for (int pos = 0; pos < len; pos++)
{
crc ^= (uint16_t)buf;
for (int i = 8; i != 0; i--)
{
if ((crc & 0x0001) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
crc = ((crc & 0x00ff) << 8) | ((crc & 0xff00) >> 8);
return crc;
}
/**
@brief为数据包末尾添加CRC_16校验
@parambuf 需要添加校验值的数据包
@paramlen 需要添加校验的数据长度。
@return无
*/
void addedCRC(uint8_t *buf, int len)
{
uint16_t crc = 0xFFFF;
for (int pos = 0; pos < len; pos++)
{
crc ^= (uint16_t)buf;
for (int i = 8; i != 0; i--)
{
if ((crc & 0x0001) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
buf = crc % 0x100;
buf = crc / 0x100;
}
/**
@brief读取风向
@paramAddress 读取的设备地址。
@return风向单位m/s,读取超时返回—1.
*/
int readWindDirection(uint8_t Address)
{
uint8_t Data = {0}; //储存传感器返回的原始数据包
uint8_t COM = {0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; //读取风向的指令
boolean ret = false; //风向获取成功标志位
int WindDirection = 0;
long curr = millis();
long curr1 = curr;
uint8_t ch = 0;
COM = Address; //参考通讯协议将指令包添加完整。
addedCRC(COM , 6); //为读取风向指令包添加CRC_16校验
mySerial.write(COM, 8);//发送读取风向的指令
while (!ret) {
if (millis() - curr > 1000) {
WindDirection = -1; //如果整个超过1000毫秒还未读取到风向将视为超时,并返回—1.
break;
}
if (millis() - curr1 > 100) {
mySerial.write(COM, 8);//如果上一条读取风向的指令发出超过100毫秒还未收到返回指令将从新发送读取风向的指令
curr1 = millis();
}
if (readN(&ch, 1) == 1) {
if (ch == Address) { //读取并判断包头。
Data = ch;
if (readN(&ch, 1) == 1) {
if (ch == 0x03) { //读取并判断包头。
Data = ch;
if (readN(&ch, 1) == 1) {
if (ch == 0x02) { //读取并判断包头。
Data = ch;
if (readN(&Data, 4) == 4) {
if (CRC16_2(Data, 5) == (Data * 256 + Data)) {//校验数据包
ret = true;
WindDirection = Data * 256 + Data;//计算风向
}
}
}
}
}
}
}
}
}
return WindDirection;
}
/**
@brief修改传感器设备地址
@paramAddress1 设备修改前的地址。使用0x00地址可以设置任何地址,设置后需要重新上电重新启动模块.
@paramAddress2 设备修改后的地址,范围0x00~0xFF,
@return返回true表示修改成功,返回false表示修改失败。
*/
boolean ModifyAddress(uint8_t Address1, uint8_t Address2)
{
uint8_t ModifyAddressCOM = {0x00, 0x10, 0x10, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00};
boolean ret = false;
long curr = millis();
long curr1 = curr;
uint8_t ch = 0;
ModifyAddressCOM = Address1;
ModifyAddressCOM = Address2;
addedCRC(ModifyAddressCOM , 9);
mySerial.write(ModifyAddressCOM, 11);
while (!ret) {
if (millis() - curr > 1000) {
break;
}
if (millis() - curr1 > 100) {
mySerial.write(ModifyAddressCOM, 11);
curr1 = millis();
}
if (readN(&ch, 1) == 1) {
if (ch == Address1) {
if (readN(&ch, 1) == 1) {
if (ch == 0x10 ) {
if (readN(&ch, 1) == 1) {
if (ch == 0x10) {
if (readN(&ch, 1) == 1) {
if (ch == 0x00) {
if (readN(&ch, 1) == 1) {
if (ch == 0x00) {
if (readN(&ch, 1) == 1) {
if (ch == 0x01) {
while (1) {
Serial.println("请给传感器重新上电。");
delay(1000);
}
ret = true ;
}
}
}
}
}
}
}
}
}
}
}
}
}
return ret;
}
效果展示:注意:安装时传感器上白点必须朝向正北。如下图:串口打印的结果为13(西北偏西)
手机对应的方向为西北偏西,几乎一致。
注意:如果最终结果返回的是-1,需要将这句代码“ModifyAddress(0x00, Address);//设备地址修改,修改地址后请注释掉这句重新上电。”注释掉,再重新上传与上电。
Mind+——样例代码1.打开mind+,添加主控板——arduino uno,;然后再去用户库添加——风向变送器库。
注:如果mind+的用户库没有找到风速变送器和风向变送器的库,可以在用户库中的搜索栏搜索“RS485风速变送器”与“RS485风向变送器”。
2.将下面的代码上传到DFRduino uno R3上。3.打开串口,将波特率调至9600,通过串口观察结果。效果展示:串口打印出来的结果显示北方。
手机对应的方向为北方,一致。
注意:如果最终结果返回的是-1,可以通过修改设备地址或者重新上电来解决。如下:
测量风速软硬件准备硬件:
DFRduino UNO R3-Arduino控制器IO 传感器扩展板 V7.1-Arduino扩展板
RS485风速变送器-传感器模组Gravity:RS485转UART有源隔离型信号转换模块
软件:· Arduino IDE 点击下载Arduino IDE· MIND+ 点击下载 mindplus硬件连接ArduinoIDE——样例代码1. 将风速变送器,RS485转UART模块,uno R3按照上面的方式连接在一起。2. 打开Arduino IDE,将下面的代码上传到DFRduino uno R3上。3. 打开串口,将波特率调至115200,通过串口观察结果。#include <SoftwareSerial.h>
SoftwareSerial mySerial(2, 3); //定义软串口,3号端口为TX,2号端口为RX,
uint8_tAddress = 0x10;
void setup()
{
Serial.begin(115200);
mySerial.begin(9600);
ModifyAddress(0x00, Address);//设备地址修改,修改地址后请注释掉这句重新上电。
}
void loop()
{
Serial.print(readWindSpeed(Address)); //读取风速
Serial.println("m/s");
delay(1000);
}
size_t readN(uint8_t *buf, size_t len)
{
size_t offset = 0, left = len;
int16_t Tineout = 1500;
uint8_t*buffer = buf;
long curr = millis();
while (left) {
if (mySerial.available()) {
buffer = mySerial.read();
offset++;
left--;
}
if (millis() - curr > Tineout) {
break;
}
}
return offset;
}
/**
@brief计算CRC16_2检验值
@parambuf 需要计算校验值的数据包
@paramlen 需要校验的数据长度。
@return返回一个16位的校验结果。
*/
uint16_t CRC16_2(uint8_t *buf, int16_t len)
{
uint16_t crc = 0xFFFF;
for (int pos = 0; pos < len; pos++)
{
crc ^= (uint16_t)buf;
for (int i = 8; i != 0; i--)
{
if ((crc & 0x0001) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
crc = ((crc & 0x00ff) << 8) | ((crc & 0xff00) >> 8);
return crc;
}
/**
@brief为数据包末尾添加CRC_16校验
@parambuf 需要添加校验值的数据包
@paramlen 需要添加校验的数据长度。
@return无
*/
void addedCRC(uint8_t *buf, int len)
{
uint16_t crc = 0xFFFF;
for (int pos = 0; pos < len; pos++)
{
crc ^= (uint16_t)buf;
for (int i = 8; i != 0; i--)
{
if ((crc & 0x0001) != 0)
{
crc >>= 1;
crc ^= 0xA001;
}
else
{
crc >>= 1;
}
}
}
buf = crc % 0x100;
buf = crc / 0x100;
}
/**
@brief读取风速
@paramAddress 读取的设备地址。
@return风速单位m/s,读取超时返回—1.
*/
float readWindSpeed(uint8_t Address)
{
uint8_t Data = {0}; //储存传感器返回的原始数据包
uint8_t COM = {0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00}; //读取风速的指令
boolean ret = false; //风速获取成功标志位
float WindSpeed = 0;
long curr = millis();
long curr1 = curr;
uint8_t ch = 0;
COM = Address; //参考通讯协议将指令包添加完整。
addedCRC(COM , 6); //为读取风速指令包添加CRC_16校验
mySerial.write(COM, 8);//发送读取风速的指令
while (!ret) {
if (millis() - curr > 1000) {
WindSpeed = -1; //如果整个超过1000毫秒还未读取到风速将视为超时,并返回—1.
break;
}
if (millis() - curr1 > 100) {
mySerial.write(COM, 8);//如果上一条读取风速的指令发出超过100毫秒还未收到返回指令将从新发送读取风速的指令
curr1 = millis();
}
if (readN(&ch, 1) == 1) {
if (ch == Address) { //读取并判断包头。
Data = ch;
if (readN(&ch, 1) == 1) {
if (ch == 0x03) { //读取并判断包头。
Data = ch;
if (readN(&ch, 1) == 1) {
if (ch == 0x02) { //读取并判断包头。
Data = ch;
if (readN(&Data, 4) == 4) {
if (CRC16_2(Data, 5) == (Data * 256 + Data)) {//校验数据包
ret = true;
WindSpeed = (Data * 256 + Data) / 10.00;//计算风速
}
}
}
}
}
}
}
}
}
return WindSpeed;
}
/**
@brief修改传感器设备地址
@paramAddress1 设备修改前的地址。使用0x00地址可以设置任何地址,设置后需要重新上电重新启动模块.
@paramAddress2 设备修改后的地址,范围0x00~0xFF,
@return返回true表示修改成功,返回false表示修改失败。
*/
boolean ModifyAddress(uint8_t Address1, uint8_t Address2)
{
uint8_t ModifyAddressCOM = {0x00, 0x10, 0x10, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00};
boolean ret = false;
long curr = millis();
long curr1 = curr;
uint8_t ch = 0;
ModifyAddressCOM = Address1;
ModifyAddressCOM = Address2;
addedCRC(ModifyAddressCOM , 9);
mySerial.write(ModifyAddressCOM, 11);
while (!ret) {
if (millis() - curr > 1000) {
break;
}
if (millis() - curr1 > 100) {
mySerial.write(ModifyAddressCOM, 11);
curr1 = millis();
}
if (readN(&ch, 1) == 1) {
if (ch == Address1) {
if (readN(&ch, 1) == 1) {
if (ch == 0x10 ) {
if (readN(&ch, 1) == 1) {
if (ch == 0x10) {
if (readN(&ch, 1) == 1) {
if (ch == 0x00) {
if (readN(&ch, 1) == 1) {
if (ch == 0x00) {
if (readN(&ch, 1) == 1) {
if (ch == 0x01) {
// while (1) {
Serial.println("请给传感器重新上电。");
// delay(1000);
// }
ret = true ;
}
}
}
}
}
}
}
}
}
}
}
}
}
return ret;
}效果展示:用手轻轻推动风速变送器,观察数据。Mind+——样例代码1.打开mind+,添加主控板——arduino uno,;然后再去用户库添加——风速变送器的库。2.将下面的代码上传到DFRduino uno R3上。3.打开串口,将波特率调至9600,通过串口观察结果。效果展示:用手轻轻推动风速变送器,观察数据。
micro:bit上的使用方法测量风向软硬件准备硬件:
micro:bit编程入门开发板-micro:bit开发板micro:IO Extend micro:bit 掌控板 IO扩展板
RS485风向变送器-传感器模组Gravity:RS485转UART有源隔离型信号转换模块
软件:· MIND+ 点击下载 mindplus硬件连接Mind+——样例代码1. 打开mind+,添加主控板——micro:bit,;然后再去用户库添加——风向变送器的库。2.将下面的代码上传到micro:bit上。3.打开串口,将波特率调至9600,通过串口观察结果。效果展示:用手轻轻推动风向变送器,观察数据。
测量风速软硬件准备硬件:
micro:bit编程入门开发板-micro:bit开发板micro:IO Extend micro:bit 掌控板 IO扩展板
RS485风速变送器-传感器模组Gravity:RS485转UART有源隔离型信号转换模块
软件:· MIND+ 点击下载 mindplus硬件连接Mind+——样例代码1. 打开mind+,添加主控板——micro:bit,;然后再去用户库添加——风速变送器的库。2.将下面的代码上传到micro:bit上。3.打开串口,将波特率调至9600,通过串口观察结果。效果展示:用手轻轻推动风速变送器,观察数据。
厉害厉害 这个好 正好能用上 666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666666
页:
[1]