|
本帖最后由 devcang 于 2020-7-13 08:57 编辑
承传一贯作风,直接来图
串口和下载串口重复使用,所以弄个开关,下载时,停止传送GPS的消息。
本来还可以将电池或GPS放盒子内部,但懒得开gps的孔,而Nano两面都有元件,放电池又超高一点点,刚好顶到reset按键。
制作的目的,就是要记录。原因是手机程序,自从Android8/9版本后,后台运行不了,所以,有这记录仪的想法。
修改: 将MicroCard的1117换成622k,电压差更小。考虑是否要将Nano的1117也换成622k,或者不要降压、直接连接电池(328P电压是够宽的)。这样电池供电就不成问题了。先试验硬件、和程序,还没有工作指示led,但可从Nano的灯上看到工作情况。 GPIO有多余,但程序空间不是太多,不然可以做多些功能。看看还能不能增加只液晶屏。
程序是第1版
/*
GPS/SD card read/write
SD卡连接
** MOSI - D11
** MISO - D12
** CLK - D13
** CS - D10
**
**GPS连接,3线,电源+TX,其中TX带开关,连接到下载串口RX
**
**devcang
**试验版本
*/
//#define Led_on() digitalWrite(LED_BUILTIN, 1) // 和SPI冲突,不使用
//#define Led_off() digitalWrite(LED_BUILTIN, 0)
#include <SPI.h>
#include <SD.h>
// #define FUGPS_DEBUG
//#include <NeoSWSerial.h> //软串口
//NeoSWSerial gpsIn(8, 9); //uint8_t receivePin, uint8_t transmitPin
#include <FuGPS.h>
FuGPS fuGPS(Serial); // gpsIn Serial
void printDirectory(File dir ) {//列出SD卡中的文件,大小
while (true) {
File entry = dir.openNextFile();
if (! entry) { //没有文件了
break;
}
Serial.print(entry.name());
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
while (entry.available()) {
Serial.write(entry.read());
}
Serial.println("------------");
entry.close();
}
}
void setup() {
Serial.begin(9600);//74880 9600
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
//gpsIn.begin(9600);//软串口
// pinMode(LED_BUILTIN, OUTPUT);//pin GPIO13 --- LED_BUILTIN 冲突,不使用
Serial.print("Initializing SD card...");
// pinMode(10, OUTPUT); //这意思是,要不使用CS脚,置OUTPUT
// if (!SD.begin(4)){ //自定义的CS脚
if (SD.begin()) {
Serial.println(" done.");
if (! SD.exists("GPS.txt")) {
File fTmp = SD.open("GPS.txt", FILE_WRITE);
if (fTmp) {
fTmp.println("GPS Tracker BETA");
fTmp.close();
}// if (myFile)
}
File root = SD.open("/");
printDirectory(root);
} else {
Serial.println(" failed!");
}
// fuGPS.Hours = 0; //非必要
// fuGPS.Minutes = 0;
// fuGPS.Seconds = 0;
}
//Latitude纬度, Longitude经度
//纬度坐标1,经度坐标1, 纬度坐标2,经度坐标2
double Distance(double n1, double e1, double n2, double e2) {
const double jl_jd = 102834.74258026089786013677476285;
const double jl_wd = 111712.69150641055729984301412873;
double b = abs((e1 - e2) * jl_jd);
double a = abs((n1 - n2) * jl_wd);
return sqrt((a * a + b * b));
}
const String Zero = String("0"), Empty = "", Dashes = "-", Colon = ":", Space = " ", Comma = ",";
volatile unsigned long b = 0, tSaveFile = 0;
volatile float lastX, lastY;
String toStr(byte b) { //发现直接用String(),会有错误
if (b < 10) {
return Zero + (char)(b + '0');
} else {
char s = (char) (byte)((b / 10) % 10 + 0x30);
char g = (char) (byte)(b % 10 + 0x30);
return Empty + s + Empty + g;
}
}
void loop() {
if (fuGPS.read() ) {
// Serial.print("Quality: "); Serial.print(fuGPS.Quality); Serial.print(", Satellites: "); Serial.print(fuGPS.Satellites);
if ( fuGPS.hasFix() == true) { // 成功定位
if((fuGPS.Hours>23) && (fuGPS.Minutes>59) && (fuGPS.Seconds>59)){//有时候会收到错误的时间数值
fuGPS.Hours = 0;
fuGPS.Minutes = 0;
fuGPS.Seconds = 0;
}
String strDate = toStr(fuGPS.Years) + Dashes + toStr(fuGPS.Months) + Dashes + toStr(fuGPS.Days);
String strTime = toStr(fuGPS.Hours) + Colon + toStr(fuGPS.Minutes) + Colon + toStr(fuGPS.Seconds);
String str = strDate + Space + strTime + Space
+ String(fuGPS.Latitude, 6) /*纬度*/ + Comma + String(fuGPS.Longitude, 6) /*经度*/
+ Comma + "alt:" + String(fuGPS.Altitude)
+ Comma + "acc:" + String(fuGPS.Accuracy)
+ Comma + "spd:" + (fuGPS.Speed > 0 ? String(fuGPS.Speed) : Zero);
bool bSave = false; //下边作简单的过滤
bSave = (Distance(lastY, lastX, fuGPS.Latitude, fuGPS.Longitude) > 3) //3米
&& (fuGPS.Minutes > 0) && (fuGPS.Seconds > 0) && (fuGPS.Months >= 0) && (fuGPS.Days >= 0)
&& ((millis() - tSaveFile ) > 1000);
bSave = bSave || ((millis() - tSaveFile ) > 5000);//5秒
if (bSave) {
String fname = String("G") + toStr(fuGPS.Years) + toStr(fuGPS.Months) + toStr(fuGPS.Days) + ".txt";
File fGps = SD.open(fname, FILE_WRITE);
if (fGps) {
fGps.println(str);
fGps.close();
Serial.println(str);
} else {
Serial.println("error opening |" + fname + "|");
}// if (fGps)
tSaveFile = millis();
}
lastX = fuGPS.Longitude;//经度
lastY = fuGPS.Latitude; //纬度
return;
}
}
//较慢闪 LED_BUILT,再加上串口灯,还没定位 --- LED_BUILTIN 冲突,不使用
if (fuGPS.isAlive() ){// Default is 10 seconds
if (millis() - b >= 3000) {
String strTime = toStr(fuGPS.Hours) + Colon + toStr(fuGPS.Minutes) + Colon + toStr(fuGPS.Seconds);
// Led_on();
Serial.println(strTime);
// delay(680);
// Led_off();
b = millis();
}
// } else { //较慢闪 LED_BUILT,还没GPS消息 --- LED_BUILTIN 冲突,不使用
// if (millis() - b >= 1000) {
// Led_on();
// delay(15);
// Led_off();
// b = millis();
// }
}
}
//---END---
回头试试tinyGPS,看看哪个稳、准、狠。。。。
Arduino容易上手,本文也只是指引。
=================分割线==================
总结:
1、3.3的供电,换成622k,压差适合电池供电。电池给Nano的电,可以焊到USB的V+,一般有串联二极管再给328P供电的。
2、使用tinyGPS比较好,省内存又好操作。tinyGPSPlug“再封装”,操作更方便,但多用7、80字节的内存。
3、GPS的电源应该单独供电,一般情况下使用能控制省电,这样再启动不是冷启动,定位快。
4、arduino的time.h,可以方便转换时区,struct tm -> time_t -> +8h ->struct tm 。
5、使用硬串口,支持事件。
6、SD.h,创建文件时,其文件名长度≤8字符。
修改后的程序,主要是更换tinyGPS,写TF卡文件还是同样的。而tinyGPS自带的例子,可以取来用,修变起来也不难,就不贴了。
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
打赏
-
查看全部打赏
|