37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞不掂的问题,希望能够抛砖引玉。
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验七十四:GY-NEO-6MV2新款飞控GPS模块 (带陶瓷有源天线)
Arduino实验接线示意图
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验七十四:GY-NEO-6MV2新款飞控GPS模块 (带陶瓷有源天线)
程序十一:使用 TinyGPSCustom 对象数组监视所有可见的卫星
Arduino参考开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
程序十一:使用 TinyGPSCustom 对象数组监视所有可见的卫星
*/
#include <TinyGPSPlus.h>//导入驱动库
#include <SoftwareSerial.h>
static const int RXPin = 9, TXPin = 8;//定义软串口接脚
static const uint32_t GPSBaud = 9600;
// TinyGPSPlus 对象
TinyGPSPlus gps;
//与 GPS 设备的串行连接
SoftwareSerial ss(RXPin, TXPin);
/*
来自 http://aprs.gids.nl/nmea/:
$GPGSV
视野中的 GPS 卫星
例如:
$GPGSV,3,1,11,03,03,111,00,04,15,270,00,06,01,010,00,13,06,292,00*74 $GPGSV,3,2,11,14,25,170,00,16,57,208,39,18,67,296,40,19,40,246,00*74
$GPGSV,3,3,11,22,42,067,42,24,14,311,43,27,05,244,00,,,,*4D
1 = 此周期中此类消息的总数
2 = 消息编号
3 = 视图中的 SV 总数
4 = SV PRN 号码
5 = 以度为单位的仰角,最大 90
6 = 方位角,从真北的度数,000 到 359
7 = SNR,00-99 dB(不跟踪时为空)
8-11 = 关于第二个 SV 的信息,与字段 4-7 相同
12-15=关于第三个 SV 的信息,与字段 4-7 相同
16-19= 关于第四个 SV 的信息,与字段 4-7 相同
*/
static const int MAX_SATELLITES = 40;
TinyGPSCustom totalGPGSVMessages(gps, "GPGSV", 1); // $GPGSV 句子,第一个元素
TinyGPSCustom messageNumber(gps, "GPGSV", 2); // $GPGSV 句子,第二个元素
TinyGPSCustom satsInView(gps, "GPGSV", 3); // $GPGSV 句子,第三个元素
TinyGPSCustom satNumber[4]; // 稍后初始化
TinyGPSCustom elevation[4];
TinyGPSCustom azimuth[4];
TinyGPSCustom snr[4];
struct{
bool active;
int elevation;
int azimuth;
int snr;
} sats[MAX_SATELLITES];
void setup(){
Serial.begin(9600);
ss.begin(GPSBaud);
Serial.println(F("SatelliteTracker.ino"));
Serial.println(F("使用 TinyGPSCustom 监控卫星位置和信号强度"));
Serial.print(F("测试 TinyGPSPlus 库 v."));
Serial.println(TinyGPSPlus::libraryVersion());
Serial.println(F("GY-NEO6MV2模块准备就绪"));
Serial.println();
// 初始化所有未初始化的 TinyGPSCustom 对象
for (int i=0; i<4; ++i)
{
satNumber[i].begin(gps, "GPGSV", 4 + 4 * i); // offsets 4, 8, 12, 16
elevation[i].begin(gps, "GPGSV", 5 + 4 * i); // offsets 5, 9, 13, 17
azimuth[i].begin( gps, "GPGSV", 6 + 4 * i); // offsets 6, 10, 14, 18
snr[i].begin( gps, "GPGSV", 7 + 4 * i); // offsets 7, 11, 15, 19
}
}
void loop(){
// 初始化所有未初始化的 TinyGPSCustom 对象
if (ss.available() > 0)
{
gps.encode(ss.read());
if (totalGPGSVMessages.isUpdated())
{
for (int i=0; i<4; ++i)
{
int no = atoi(satNumber[i].value());
// Serial.print(F("SatNumber is ")); Serial.println(no);
if (no >= 1 && no <= MAX_SATELLITES)
{
sats[no-1].elevation = atoi(elevation[i].value());
sats[no-1].azimuth = atoi(azimuth[i].value());
sats[no-1].snr = atoi(snr[i].value());
sats[no-1].active = true;
}
}
int totalMessages = atoi(totalGPGSVMessages.value());
int currentMessage = atoi(messageNumber.value());
if (totalMessages == currentMessage)
{
Serial.print(F("Sats="));
Serial.print(gps.satellites.value());
Serial.print(F(" Nums="));
for (int i=0; i<MAX_SATELLITES; ++i)
if (sats[i].active)
{
Serial.print(i+1);
Serial.print(F(" "));
}
Serial.print(F(" 海拔="));//海拔
for (int i=0; i<MAX_SATELLITES; ++i)
if (sats[i].active)
{
Serial.print(sats[i].elevation);
Serial.print(F(" "));
}
Serial.print(F(" 方位角="));//方位角
for (int i=0; i<MAX_SATELLITES; ++i)
if (sats[i].active)
{
Serial.print(sats[i].azimuth);
Serial.print(F(" "));
}
Serial.print(F(" 信噪比="));//信噪比
for (int i=0; i<MAX_SATELLITES; ++i)
if (sats[i].active)
{
Serial.print(sats[i].snr);
Serial.print(F(" "));
}
Serial.println();
for (int i=0; i<MAX_SATELLITES; ++i)
sats[i].active = false;
}
}
}
}
实验串口返回情况
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验七十四:GY-NEO-6MV2新款飞控GPS模块 (带陶瓷有源天线)
程序十二:使用 TinyGPSCustom 提取任何 NMEA 字段
Arduino参考开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
程序十二:使用 TinyGPSCustom 提取任何 NMEA 字段
*/
#include <TinyGPSPlus.h>//导入驱动库
#include <SoftwareSerial.h>
static const int RXPin = 9, TXPin = 8;//定义软串口接脚
static const uint32_t GPSBaud = 9600;
// TinyGPSPlus 对象
TinyGPSPlus gps;
//与 GPS 设备的串行连接
SoftwareSerial ss(RXPin, TXPin);
/*
通过像这样声明 TinyGPSCustom 对象,我们宣布我们
对 $GPGSA 中的第 15、16 和 17 字段感兴趣
句子,分别是PDOP(F(“位置精度的稀释”)),
HDOP (F("horizontal...")) 和 VDOP (F("vertical..."))。
(计数从紧跟句子名称的字段开始,
即 $GPGSA。有关 NMEA 语句的更多信息,请咨询您的
GPS 模块的文档和/或 http://aprs.gids.nl/nmea/。)
如果你的 GPS 模块不支持 $GPGSA 语句,那么你
不会从此程序获得任何输出。
*/
TinyGPSCustom pdop(gps, "GPGSA", 15); // $GPGSA 句子,第 15 个元素
TinyGPSCustom hdop(gps, "GPGSA", 16); // $GPGSA 句子,第 16 个元素
TinyGPSCustom vdop(gps, "GPGSA", 17); // $GPGSA 句子,第 17 个元素
void setup() {
Serial.begin(9600);
ss.begin(GPSBaud);
Serial.println(F("UsingCustomFields.ino"));
Serial.println(F("使用 TinyGPSCustom 提取任何 NMEA 字段"));
Serial.print(F("测试 TinyGPSPlus 库 v."));
Serial.println(TinyGPSPlus::libraryVersion());
Serial.println(F("GY-NEO6MV2模块准备就绪"));
Serial.println();
}
void loop() {
// 每次更新任何内容时,打印所有内容。
if (gps.altitude.isUpdated() || gps.satellites.isUpdated() ||
pdop.isUpdated() || hdop.isUpdated() || vdop.isUpdated())
{
Serial.print(F("ALT=")); Serial.print(gps.altitude.meters());
Serial.print(F(" PDOP=")); Serial.print(pdop.value());
Serial.print(F(" HDOP=")); Serial.print(hdop.value());
Serial.print(F(" VDOP=")); Serial.print(vdop.value());
Serial.print(F(" SATS=")); Serial.println(gps.satellites.value());
}
while (ss.available() > 0)
gps.encode(ss.read());
}
实验串口返回情况
Arduino实验场景图
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验七十四:GY-NEO-6MV2新款飞控GPS模块 (带陶瓷有源天线)
程序十三:在OLED上显示日期、时间、纬度和经度
Arduino参考开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
程序十三:在OLED上显示日期、时间、纬度和经度
*/
#include <TimeLib.h>//导入驱动库
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <U8glib.h>
//用于连接GY-NEO6MV2模块的引脚D9/D8
static const int RXPin = 9, TXPin = 8;
// TinyGPS++ 对象
TinyGPSPlus gps;
// GPS模块的串口连接
SoftwareSerial Serial_GPS(RXPin, TXPin);
//OLED显示设置
U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_FAST);
void draw() {
//设置时间/时区
GPS_Timezone_Adjust();
//显示的图形命令必须放在这里aqui
u8g.setFont(u8g_font_8x13B);
u8g.drawRFrame(0, 0, 128, 64, 4);
//日期线
u8g.drawStr(10, 14, "D: ");
u8g.setPrintPos(34, 14);
//显示日期
if (day() < 10)
{
u8g.print("0");
}
u8g.print(day());
u8g.drawStr(51, 14, "/");
u8g.setPrintPos(60, 14);
//显示月份
if (month() < 10)
{
u8g.print("0");
}
u8g.print(month());
u8g.drawStr(76, 14, "/");
u8g.setPrintPos(85, 14);
//显示年份
u8g.print(year());
// 时间线
u8g.drawStr(10, 29, "H: ");
u8g.setPrintPos(45, 29);
//开始时间
if (hour() < 10)
{
u8g.print("0");
}
u8g.print(hour());
u8g.drawStr(61, 28, ":");
u8g.setPrintPos(70, 29);
//显示分钟
if (minute() < 10)
{
u8g.print("0");
}
u8g.print(minute());
u8g.drawStr(86, 28, ":");
u8g.setPrintPos(95, 29);
//显示秒数
if (second() < 10)
{
u8g.print("0");
}
u8g.print(second());
//纬度
u8g.drawStr(10, 44, "Lat: ");
u8g.setPrintPos(45, 44);
u8g.print(gps.location.lat(), 5);
//经度
u8g.drawStr(10, 59, "Lon: ");
u8g.setPrintPos(45, 59);
u8g.print(gps.location.lng(), 5);
}
//根据地区调整时区
const int UTC_offset = -3;
void setup() {
// Arduino 波特率
Serial.begin(9600);
//波特率GPS模块
Serial_GPS.begin(9600);
//在串口监视器上显示初始信息
Serial.println(F("日期、时间、纬度和经度"));
Serial.println(F("GPS 模块 GY-NEO6MV2"));
Serial.print(F("TinyGPS++ 驱动库 v."));
Serial.println(TinyGPSPlus::libraryVersion());
Serial.println();
//OLED显示设置
if ( u8g.getMode() == U8G_MODE_R3G3B2 )
{
u8g.setColorIndex(255); // 白色的
}
else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {
u8g.setColorIndex(3); // 最大强度
}
else if ( u8g.getMode() == U8G_MODE_BW ) {
u8g.setColorIndex(1); //像素开启
}
else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {
u8g.setHiColorByRGB(255, 255, 255);
}
}
void loop() {
//与GPS模块连接
while (Serial_GPS.available() > 0)
if (gps.encode(Serial_GPS.read()))
displayInfo();
if (millis() > 5000 && gps.charsProcessed() < 10)
{
Serial.println(F("未检测到 GPS:检查接线。"));
while (true);
}
//调用屏幕上的绘图例程
u8g.firstPage();
do
{
draw();
}
while ( u8g.nextPage() );
delay(1000);
}
void displayInfo() {
//在串口监视器中显示信息
Serial.print(F("位置:"));
if (gps.location.isValid())
{
Serial.print(gps.location.lat(), 6); //latitude
Serial.print(F(","));
Serial.print(gps.location.lng(), 6); //longitude
}
else
{
Serial.print(F("无效"));
}
Serial.print(F(" 日期/时间: "));
if (gps.date.isValid())
{
Serial.print(gps.date.day()); //天
Serial.print(F("/"));
Serial.print(gps.date.month()); //月
Serial.print(F("/"));
Serial.print(gps.date.year());//年
}
else
{
Serial.print(F("无效"));
}
Serial.print(F(" "));
if (gps.time.isValid())
{
if (gps.time.hour() < 10) Serial.print(F("0"));
Serial.print(gps.time.hour()); //小时
Serial.print(F(":"));
if (gps.time.minute() < 10) Serial.print(F("0"));
Serial.print(gps.time.minute()); //分钟
Serial.print(F(":"));
if (gps.time.second() < 10) Serial.print(F("0"));
Serial.print(gps.time.second()); //第二
Serial.print(F("."));
if (gps.time.centisecond() < 10) Serial.print(F("0"));
Serial.print(gps.time.centisecond());
}
else
{
Serial.print(F("无效"));
}
Serial.println();
}
void GPS_Timezone_Adjust() {
while (Serial_GPS.available())
{
if (gps.encode(Serial_GPS.read()))
{
int Year = gps.date.year();
byte Month = gps.date.month();
byte Day = gps.date.day();
byte Hour = gps.time.hour();
byte Minute = gps.time.minute();
byte Second = gps.time.second();
//根据GPS数据调整日期和时间
setTime(Hour, Minute, Second, Day, Month, Year);
//应用偏移来设置日期和时间
//根据时区
adjustTime(UTC_offset * SECS_PER_HOUR);
}
}
}
实验串口返回情况(放在电脑桌上,没有GPS信号)
实验场景图 (放在电脑桌上,没有GPS信号)
实验串口返回情况(模块放在窗口,接收到GPS信号)
实验场景图(模块放在窗口,接收到GPS信号)
实验接线示意图(GPS软串口接在D9/D8)