37款传感器与执行器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止这37种的。鉴于本人手头积累了一些传感器和执行器模块,依照实践出真知(一定要动手做)的理念,以学习和交流为目的,这里准备逐一动手尝试系列实验,不管成功(程序走通)与否,都会记录下来—小小的进步或是搞不掂的问题,希望能够抛砖引玉。
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验七十四:GY-NEO-6MV2新款飞控GPS模块 (带陶瓷有源天线)
Arduino实验接线示意图
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验七十四:GY-NEO-6MV2新款飞控GPS模块 (带陶瓷有源天线)
程序七:TinyGPSPlus 对象的常规使用
Arduino参考开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
程序七:TinyGPSPlus 对象的常规使用
*/
#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);
void setup(){
Serial.begin(9600);//初始化串口
ss.begin(GPSBaud);
Serial.println(F("DeviceExample.ino"));
Serial.println(F("一个简单的 TinyGPSPlus 演示,带有 GPS 模块"));
Serial.print(F("测试 TinyGPSPlus 库 v."));
Serial.println(TinyGPSPlus::libraryVersion());
Serial.println(F("GY-NEO6MV2模块准备就绪"));
Serial.println();
}
void loop(){
//每次正确编码新数据时,此程序都会显示信息。
while (ss.available() > 0)
if (gps.encode(ss.read()))
displayInfo();
if (millis() > 5000 && gps.charsProcessed() < 10)
{
Serial.println(F("未检测到 GPS:检查接线。"));
while (true);
}
}
void displayInfo(){
Serial.print(F("位置: "));
if (gps.location.isValid())
{
Serial.print(gps.location.lat(), 6);
Serial.print(F(","));
Serial.print(gps.location.lng(), 6);
}
else
{
Serial.print(F("无效"));
}
Serial.print(F(" 日期/时间:"));
if (gps.date.isValid())
{
Serial.print(gps.date.month());
Serial.print(F("/"));
Serial.print(gps.date.day());
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();
}
(2)实验串口返回情况
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验七十四:GY-NEO-6MV2新款飞控GPS模块 (带陶瓷有源天线)
程序八:TinyGPSPlus 很多有趣功能的综合测试
Arduino参考开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
程序八:TinyGPSPlus 很多有趣功能的综合测试
*/
#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);
void setup() {
Serial.begin(9600);
ss.begin(GPSBaud);
Serial.println(F("FullExample.ino"));
Serial.println(F("TinyGPSPlus 很多有趣功能的综合测试"));
Serial.print(F("测试 TinyGPSPlus 库 v."));
Serial.println(TinyGPSPlus::libraryVersion());
Serial.println(F("GY-NEO6MV2模块准备就绪"));
Serial.println();
Serial.println(F("Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum"));
Serial.println(F(" (deg) (deg) Age Age (m) --- from GPS ---- ---- to London ---- RX RX Fail"));
Serial.println(F("----------------------------------------------------------------------------------------------------------------------------------------"));
}
void loop() {
static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
printInt(gps.satellites.value(), gps.satellites.isValid(), 5);
printFloat(gps.hdop.hdop(), gps.hdop.isValid(), 6, 1);
printFloat(gps.location.lat(), gps.location.isValid(), 11, 6);
printFloat(gps.location.lng(), gps.location.isValid(), 12, 6);
printInt(gps.location.age(), gps.location.isValid(), 5);
printDateTime(gps.date, gps.time);
printFloat(gps.altitude.meters(), gps.altitude.isValid(), 7, 2);
printFloat(gps.course.deg(), gps.course.isValid(), 7, 2);
printFloat(gps.speed.kmph(), gps.speed.isValid(), 6, 2);
printStr(gps.course.isValid() ? TinyGPSPlus::cardinal(gps.course.deg()) : "*** ", 6);
unsigned long distanceKmToLondon =
(unsigned long)TinyGPSPlus::distanceBetween(
gps.location.lat(),
gps.location.lng(),
LONDON_LAT,
LONDON_LON) / 1000;
printInt(distanceKmToLondon, gps.location.isValid(), 9);
double courseToLondon =
TinyGPSPlus::courseTo(
gps.location.lat(),
gps.location.lng(),
LONDON_LAT,
LONDON_LON);
printFloat(courseToLondon, gps.location.isValid(), 7, 2);
const char *cardinalToLondon = TinyGPSPlus::cardinal(courseToLondon);
printStr(gps.location.isValid() ? cardinalToLondon : "*** ", 6);
printInt(gps.charsProcessed(), true, 6);
printInt(gps.sentencesWithFix(), true, 10);
printInt(gps.failedChecksum(), true, 9);
Serial.println();
smartDelay(1000);
if (millis() > 5000 && gps.charsProcessed() < 10)
Serial.println(F("没有接收到 GPS 数据:检查接线"));
}
//这个自定义版本的 delay() 确保 gps 对象
//正在被“喂”有效的数据。
static void smartDelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
static void printFloat(float val, bool valid, int len, int prec)
{
if (!valid)
{
while (len-- > 1)
Serial.print('*');
Serial.print(' ');
}
else
{
Serial.print(val, prec);
int vi = abs((int)val);
int flen = prec + (val < 0.0 ? 2 : 1); // . and -
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i = flen; i < len; ++i)
Serial.print(' ');
}
smartDelay(0);
}
static void printInt(unsigned long val, bool valid, int len)
{
char sz[32] = "*****************";
if (valid)
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i = strlen(sz); i < len; ++i)
sz[i] = ' ';
if (len > 0)
sz[len - 1] = ' ';
Serial.print(sz);
smartDelay(0);
}
static void printDateTime(TinyGPSDate &d, TinyGPSTime &t)
{
if (!d.isValid())
{
Serial.print(F("********** "));
}
else
{
char sz[32];
sprintf(sz, "%02d/%02d/%02d ", d.month(), d.day(), d.year());
Serial.print(sz);
}
if (!t.isValid())
{
Serial.print(F("******** "));
}
else
{
char sz[32];
sprintf(sz, "%02d:%02d:%02d ", t.hour(), t.minute(), t.second());
Serial.print(sz);
}
printInt(d.age(), d.isValid(), 5);
smartDelay(0);
}
static void printStr(const char *str, int len)
{
int slen = strlen(str);
for (int i = 0; i < len; ++i)
Serial.print(i < slen ? str[i] : ' ');
smartDelay(0);
}
实验串口返回情况
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
实验七十四:GY-NEO-6MV2新款飞控GPS模块 (带陶瓷有源天线)
程序九:测试 TinyGPSPlus 的几乎所有功能
Arduino参考开源代码
/*
【Arduino】168种传感器模块系列实验(资料代码+仿真编程+图形编程)
程序九:测试 TinyGPSPlus 的几乎所有功能
*/
#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);
// 对于每 5 秒发生一次的统计数据
unsigned long last = 0UL;
void setup() {
Serial.begin(9600);
ss.begin(GPSBaud);
Serial.println(F("KitchenSink.ino"));
Serial.println(F("测试 TinyGPSPlus 的几乎所有功能"));
Serial.print(F("测试 TinyGPSPlus 库 v."));
Serial.println(TinyGPSPlus::libraryVersion());
Serial.println(F("GY-NEO6MV2模块准备就绪"));
Serial.println();
}
void loop(){
// 调度传入的字符
while (ss.available() > 0)
gps.encode(ss.read());
if (gps.location.isUpdated())
{
Serial.print(F("LOCATION Fix Age="));
Serial.print(gps.location.age());
Serial.print(F("ms Raw Lat="));
Serial.print(gps.location.rawLat().negative ? "-" : "+");
Serial.print(gps.location.rawLat().deg);
Serial.print("[+");
Serial.print(gps.location.rawLat().billionths);
Serial.print(F(" billionths], Raw Long="));
Serial.print(gps.location.rawLng().negative ? "-" : "+");
Serial.print(gps.location.rawLng().deg);
Serial.print("[+");
Serial.print(gps.location.rawLng().billionths);
Serial.print(F(" billionths], Lat="));
Serial.print(gps.location.lat(), 6);
Serial.print(F(" Long="));
Serial.println(gps.location.lng(), 6);
}
else if (gps.date.isUpdated())
{
Serial.print(F("DATE Fix Age="));
Serial.print(gps.date.age());
Serial.print(F("ms Raw="));
Serial.print(gps.date.value());
Serial.print(F(" Year="));
Serial.print(gps.date.year());
Serial.print(F(" Month="));
Serial.print(gps.date.month());
Serial.print(F(" Day="));
Serial.println(gps.date.day());
}
else if (gps.time.isUpdated())
{
Serial.print(F("TIME Fix Age="));
Serial.print(gps.time.age());
Serial.print(F("ms Raw="));
Serial.print(gps.time.value());
Serial.print(F(" Hour="));
Serial.print(gps.time.hour());
Serial.print(F(" Minute="));
Serial.print(gps.time.minute());
Serial.print(F(" Second="));
Serial.print(gps.time.second());
Serial.print(F(" Hundredths="));
Serial.println(gps.time.centisecond());
}
else if (gps.speed.isUpdated())
{
Serial.print(F("SPEED Fix Age="));
Serial.print(gps.speed.age());
Serial.print(F("ms Raw="));
Serial.print(gps.speed.value());
Serial.print(F(" Knots="));
Serial.print(gps.speed.knots());
Serial.print(F(" MPH="));
Serial.print(gps.speed.mph());
Serial.print(F(" m/s="));
Serial.print(gps.speed.mps());
Serial.print(F(" km/h="));
Serial.println(gps.speed.kmph());
}
else if (gps.course.isUpdated())
{
Serial.print(F("COURSE Fix Age="));
Serial.print(gps.course.age());
Serial.print(F("ms Raw="));
Serial.print(gps.course.value());
Serial.print(F(" Deg="));
Serial.println(gps.course.deg());
}
else if (gps.altitude.isUpdated())
{
Serial.print(F("ALTITUDE Fix Age="));
Serial.print(gps.altitude.age());
Serial.print(F("ms Raw="));
Serial.print(gps.altitude.value());
Serial.print(F(" Meters="));
Serial.print(gps.altitude.meters());
Serial.print(F(" Miles="));
Serial.print(gps.altitude.miles());
Serial.print(F(" KM="));
Serial.print(gps.altitude.kilometers());
Serial.print(F(" Feet="));
Serial.println(gps.altitude.feet());
}
else if (gps.satellites.isUpdated())
{
Serial.print(F("SATELLITES Fix Age="));
Serial.print(gps.satellites.age());
Serial.print(F("ms Value="));
Serial.println(gps.satellites.value());
}
else if (gps.hdop.isUpdated())
{
Serial.print(F("HDOP Fix Age="));
Serial.print(gps.hdop.age());
Serial.print(F("ms raw="));
Serial.print(gps.hdop.value());
Serial.print(F(" hdop="));
Serial.println(gps.hdop.hdop());
}
else if (millis() - last > 5000)
{
Serial.println();
if (gps.location.isValid())
{
static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
double distanceToLondon =
TinyGPSPlus::distanceBetween(
gps.location.lat(),
gps.location.lng(),
LONDON_LAT,
LONDON_LON);
double courseToLondon =
TinyGPSPlus::courseTo(
gps.location.lat(),
gps.location.lng(),
LONDON_LAT,
LONDON_LON);
Serial.print(F("伦敦 距离="));
Serial.print(distanceToLondon / 1000, 6);
Serial.print(F(" km Course-to="));
Serial.print(courseToLondon, 6);
Serial.print(F(" degrees ["));
Serial.print(TinyGPSPlus::cardinal(courseToLondon));
Serial.println(F("]"));
}
Serial.print(F("DIAGS Chars="));
Serial.print(gps.charsProcessed());
Serial.print(F(" Sentences-with-Fix="));
Serial.print(gps.sentencesWithFix());
Serial.print(F(" Failed-checksum="));
Serial.print(gps.failedChecksum());
Serial.print(F(" Passed-checksum="));
Serial.println(gps.passedChecksum());
if (gps.charsProcessed() < 10)
Serial.println(F("警告:没有 GPS 数据,检查接线。"));
last = millis();
Serial.println();
}
}
实验串口返回情况
【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;
static const int MAX_SATELLITES = 40;
static const int PAGE_LENGTH = 40;
// TinyGPSPlus 对象
TinyGPSPlus gps;
//与 GPS 设备的串行连接
SoftwareSerial ss(RXPin, TXPin);
TinyGPSCustom totalGPGSVMessages(gps, "GPGSV", 1); // $GPGSV 句子,第一个元素
TinyGPSCustom messageNumber(gps, "GPGSV", 2); // $GPGSV 句子,第二个元素
TinyGPSCustom satNumber[4]; // 稍后初始化
TinyGPSCustom elevation[4];
bool anyChanges = false;
unsigned long linecount = 0;
struct
{
int elevation;
bool active;
} sats[MAX_SATELLITES];
void setup(){
Serial.begin(9600);
ss.begin(GPSBaud);
Serial.println(F("SatElevTracker.ino"));
Serial.println(F("显示 GPS 卫星高度变化"));
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
}
}
void loop(){
// 调度传入的字符
if (ss.available() > 0)
{
gps.encode(ss.read());
if (totalGPGSVMessages.isUpdated())
{
for (int i=0; i<4; ++i)
{
int no = atoi(satNumber[i].value());
if (no >= 1 && no <= MAX_SATELLITES)
{
int elev = atoi(elevation[i].value());
sats[no-1].active = true;
if (sats[no-1].elevation != elev)
{
sats[no-1].elevation = elev;
anyChanges = true;
}
}
}
int totalMessages = atoi(totalGPGSVMessages.value());
int currentMessage = atoi(messageNumber.value());
if (totalMessages == currentMessage && anyChanges)
{
if (linecount++ % PAGE_LENGTH == 0)
printHeader();
TimePrint();
for (int i=0; i<MAX_SATELLITES; ++i)
{
Serial.print(F(" "));
if (sats[i].active)
IntPrint(sats[i].elevation, 2);
else
Serial.print(F(" "));
sats[i].active = false;
}
Serial.println();
anyChanges = false;
}
}
}
}
void IntPrint(int n, int len){
int digs = n < 0 ? 2 : 1;
for (int i=10; i<=abs(n); i*=10)
++digs;
while (digs++ < len)
Serial.print(F(" "));
Serial.print(n);
Serial.print(F(" "));
}
void TimePrint(){
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(" "));
}
else
{
Serial.print(F("(未知的)"));
}
}
void printHeader(){
Serial.println();
Serial.print(F("时间 "));
for (int i=0; i<MAX_SATELLITES; ++i)
{
Serial.print(F(" "));
IntPrint(i+1, 2);
}
Serial.println();
Serial.print(F("---------"));
for (int i=0; i<MAX_SATELLITES; ++i)
Serial.print(F("----"));
Serial.println();
}
实验串口返回情况
Arduino实验场景图