大佬问一下,这个可以防止gps限高限速吗?
“防止”?是想说“规避”吗?法规要自觉遵守哈~
飞控使用的GPS刷新率高达18Hz以上,使用UBX协议,除了能高速读出位置坐标,还能直接读出天向、东向、北向速度等信息,利于飞控使用。无人机上通常使用飞控板解码,不够灵活和微型化。本文报道Arduino单片机解码高速GPS,可组成更为简单灵活、微型化的飞控系统。
1,器材:
GPS模块,深圳市飞空科技RC12-B0带地磁,35元/片。
单片机采用Arduino Pro Micro或更小体积的Nano mini。
2,连线:
将GPS TX线连单片机D8脚,RX连D9,Vcc和GND分别连到单片机上。
3,代码:
使用软串口(8,9)读取GPS数据,UBX数据格式固定以B5 62开头,该GPS模块数据默认为NAV-PVT格式(码01 07)。数据头B5 62后面会接92个GPS数据,判断找到数据头后,逐个读出这些数据即可,详细数据格式可参考文章《UBX 协议报文整理》CIStoner。
注意每个读数操作后要加一个delay(1)延迟一下,不然数据不对,原因不明,实测有效。不需要的数据用for循环读,节约语句和内存。该示例中所有数据打印到串口显示,实际应用于飞控就不需要串口打印。
代码故意未做过多优化,利于初学者理解和调试,可以先写短一点只读最前面几个数,一步步调试,用串口打印如Serial.println(length),看看读出的数据对不对。
#include <SoftwareSerial.h>
SoftwareSerial gpsSerial(8, 9); // RX, TX
void setup() {
Serial.begin(115200);
gpsSerial.begin(115200);
}
void loop() {
if (gpsSerial.available()) {
if (gpsSerial.read() == 0xB5 ) {
delay(1);
if (gpsSerial.read() == 0x62 ) { // 同步字符判断
delay(1);
uint8_t msgClass = gpsSerial.read();
delay(1);
uint8_t msgId = gpsSerial.read();
delay(1);
uint8_t length = (gpsSerial.read());
delay(1);
gpsSerial.read();
delay(1);
Serial.println(length);
Serial.println(msgId);
if (msgClass == 0x01 && msgId == 0x07) { // NAV-PVT消息
for(int i=0;i<4;i++){
uint8_t Dt00 = gpsSerial.read();
delay(1);
}
uint8_t Dt1 = gpsSerial.read();
delay(1);
uint8_t Dt2 = gpsSerial.read();
delay(1);
uint8_t Dt3 = gpsSerial.read();
delay(1);
uint8_t Dt4 = gpsSerial.read();
delay(1);
uint8_t Dt5 = gpsSerial.read();
delay(1);
uint8_t Dt6 = gpsSerial.read();
delay(1);
uint8_t Dt7 = gpsSerial.read();
delay(1);
// 日期和时间信息...
Serial.print(Dt1+Dt2*256);
Serial.print("-");
Serial.print(Dt3);
Serial.print("-");
Serial.print(Dt4);
Serial.print(" ");
Serial.print(Dt5);
Serial.print("-");
Serial.print(Dt6);
Serial.print("-");
Serial.println(Dt7);
for(int i=0;i<12;i++){
uint8_t Dt00 = gpsSerial.read();
delay(1);
}
//经纬度信息…
uint8_t Dt8 = gpsSerial.read();
delay(1);
uint8_t Dt9 = gpsSerial.read();
delay(1);
uint8_t Dt10 = gpsSerial.read();
delay(1);
uint8_t Dt11 = gpsSerial.read();
delay(1);
uint8_t Dt12 = gpsSerial.read();
delay(1);
uint8_t Dt13 = gpsSerial.read();
delay(1);
uint8_t Dt14
delay(1);
uint8_t Dt15 = XXXXXXXXXXXXXXXXXXXXX();
delay(1);
uint8_t Dt16 = XXXXXXXXXXXXXXXXXXXXX();
delay(1);
Serial.print("卫星数");
Serial.println(Dt8);
Serial.print("经度");
Serial.println((1.0*Dt9+1.0*Dt10*256+1.0*Dt11*256*256+1.0*Dt12*256*256*256)/10000000.0);
Serial.print("纬度");
Serial.println((1.0*Dt13+1.0*Dt14*256+1.0*Dt15*256*256+1.0*Dt16*256*256*256)/10000000.0);
}
}
}
}
}
我只试过短时间加速(用橡皮筋弹射,0.2s加速),没失锁,现在又不怎么弄火箭了,加上是帝都有箭也不好发,需要找人合作打一两发实测一下才好
GPS串口通讯代码有更新,使用标准GPIO串口通讯函数uart及中断。单片机主频降至66.5MHz,在集成度高的情况下减少对GPS干扰。下面是读取日期时间及卫星数的例程:
#include <hardware/clocks.h>
#include "hardware/uart.h"
#include "hardware/irq.h"
uint16_t Yr;
uint8_t SA,Mt,Dy,Hr,Mn,Sd;
unsigned char GPS_buf[75];
void setup() {
set_sys_clock_khz(66500,true);
//使用Uart0串口及中断读GPS
uart_init(uart0, 115200); // 初始化 UART
gpio_set_function(12, GPIO_FUNC_UART); // 设置 GPIO 引脚为 UART 功能(例如 GP12 作为 TX,GP13作为 RX)
gpio_set_function(13, GPIO_FUNC_UART);
gpio_pull_up(13); // 确保 RX 引脚上拉,避免悬空输入
uart_set_irqs_enabled(uart0, true, false); // 启用 UART 中断,读数中断,写数不中断
irq_set_exclusive_handler(UART0_IRQ, GPS_Read); // 设置GPS读数中断处理函数
irq_set_enabled(UART0_IRQ, true); // 启用串口中断
delay(1000);
}
// GPS读数中断函数
void GPS_Read() {
while (uart_is_readable(uart0)) {
uint8_t ch = uart_getc(uart0); // 读取一个字
if (ch==0xB5){
ch = uart_getc(uart0); // 读取一个字
if (ch==0x62){
uint8_t msgClass = uart_getc(uart0);
uint8_t msgId = uart_getc(uart0);
uint8_t length = (uart_getc(uart0));
if (msgClass 0x01 && msgId 0x07) { // NAV-POSLLH消息
for(uint8_t i=0;i<73;i++){
GPS_buf[i] = uart_getc(uart0);
}
Yr = (GPS_buf[6]<<8)|GPS_buf[5];
Mt = GPS_buf[7];
Dy = GPS_buf[8];
Hr = GPS_buf[9]+8;
Mn = GPS_buf[10];
Sd = GPS_buf[11];
SA = GPS_buf[24];
}
}
}
}
}