initial commit

This commit is contained in:
ken
2022-07-04 16:23:14 -07:00
commit 327ee020f9
3 changed files with 502 additions and 0 deletions
@@ -0,0 +1,294 @@
/*
Airplane Data Logging for Dynon EFIS-D10A, Dynon EMS-D10, Garmin GNS430W
(c) 2022 Ken Staton
issue: hot insert drive not always starting. don't worry about remove and re-insert.
issue: clock sync.
how long does backup battery last??
use GPS time for RTC sync when drifts more than 20 seconds
measured data rates
G: GPS Rx1 115 bytes/sec message end: '\x003'
F: EFIS Rx2 3300 bytes/sec message end: '\n'
E: EMS Rx3 480 bytes/sec message end: '\n'
*/
#define DEBUG false // USB serial debug printing
// setup will BLOCK until USB serial starts
#define UTCm7 (7*60*60) // your timezone relative to UTC in seconds
#include "GPS_position.h"
#include <USBHost_t36.h>
#include <TimeLib.h>
// Setup USBHost_t36 and as many HUB ports as needed.
USBHost myusb;
// Instances for the number of hubs
USBHub hub1(myusb);
// Instances for the number of USB drives you are using.
USBDrive myDrive1(myusb);
// Instances for accessing the files on each drive
USBFilesystem myFiles1(myusb);
// Timer events
IntervalTimer myTimer;
// vvv GLOBALS vvv
File myFile;
volatile bool tick = false;
bool LED_ON = false;
// https://www.pjrc.com/teensy/td_uart.html
#define Serial1RxBufferSIZE 1024 // 10 seconds
char Serial1RxBuffer[Serial1RxBufferSIZE]; // global scope or static char. power of 2.
#define Serial2RxBufferSIZE 8192 // 2 seconds
char Serial2RxBuffer[Serial2RxBufferSIZE]; // global scope or static char. power of 2.
#define Serial3RxBufferSIZE 1024 // 2 seconds
char Serial3RxBuffer[Serial3RxBufferSIZE]; // global scope or static char. power of 2.
// ^^^ end GLOBAL ^^^
void TimerISR() { // callback for myTimer
tick = true; // only sets global
}
void setup()
{
int i;
char fname[16];
myTimer.begin(TimerISR, 100000); // period in microseconds = 0.1 sec
setSyncProvider(getTeensy3Time);
setSyncInterval(300); // default is 5 min. this call should force a sync
if (DEBUG) {
Serial.begin(115200);
while (!Serial) {
; // wait for Arduino Serial Monitor to connect.
}
}
if (DEBUG) RTCDisplay();
Serial1.begin(9600); // MUST match Garmin
Serial1.addMemoryForRead(Serial1RxBuffer, Serial1RxBufferSIZE);
Serial2.begin(115200); // MUST match Dynon EMS
Serial2.addMemoryForRead(Serial2RxBuffer, Serial2RxBufferSIZE);
Serial3.begin(115200); // MUST match Dynon EMS
Serial3.addMemoryForRead(Serial3RxBuffer, Serial3RxBufferSIZE);
SdFile::dateTimeCallback(dateTime);
myusb.begin();
// .begin(USBDrive) is a temporary feature, future USBFilesystem will begin automatically
if (DEBUG) Serial.println("\nInitializing USB drive 1...");
if (!myFiles1.begin(&myDrive1)) {
if (DEBUG) Serial.print("initialization failed with code: ");
if (DEBUG) myFiles1.printError(Serial);
return; // setup() is done!
}
if (DEBUG) Serial.printf(F(" connected: %d\n"), myDrive1.msDriveInfo.connected);
if (DEBUG) Serial.printf(F(" initialized: %d\n"), myDrive1.msDriveInfo.initialized);
if (DEBUG) Serial.printf(F(" fs started: %d\n"), myDrive1.filesystemsStarted());
if (DEBUG) Serial.printf("Find next file number...\n");
i=next_file_number();
sprintf(fname,"Log%04d.txt",i);
if (DEBUG) Serial.printf("Testing for file %s\n",fname);
myFile = myFiles1.open(fname, FILE_WRITE);
// see https://github.com/wwatson4506/UsbMscFat/blob/UsbMscFat-FS_DATES/examples/ReadWriteUSB/ReadWriteUSB.ino
if (myFile) {
if (DEBUG) Serial.printf("Writing to %s...\n",fname);
myFile.println("Log Started "); // first line
} else {
// if the file didn't open, print an error:
if (DEBUG) Serial.printf("error opening %s \n",fname);
}
if (DEBUG) RTCDisplay();
if (DEBUG) Serial.printf("t.s = %f\n", getdatetime());
if (DEBUG) Serial.println("init done...");
} // end of setup()
int next_file_number() {
// returns the first unused file number
char fname[16];
bool fileexists = true; // assume true
int i=0; // always start at 0
do {
sprintf(fname,"Log%04d.txt",i);
//Serial.printf("%s",fname);
if (myFiles1.exists(fname) == 0) {
fileexists=false;
} else {
i++;
}
} while (fileexists == true);
return(i);
}
void RTCDisplay() {
// display the time
Serial.print(year());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.println();
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
void toggleLED() {
if (LED_ON) {
digitalWrite(LED_BUILTIN, LOW);
LED_ON = false;
} else { /* LED_OFF */
digitalWrite(LED_BUILTIN, HIGH);
LED_ON = true;
}
}
void halt(int hz) {
int t_ms;
float period;
period = 1.0/hz;
t_ms = period * 1000/2;
//if (DEBUG) Serial.printf("blink period %d\n",t_ms);
// LED_BUILTIN interferes with I2C !!
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
while (true) {
toggleLED();
delay(t_ms);
}
}
// read about time https://www.pjrc.com/teensy/td_libs_Time.html
// /Applications/Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/Time/TimeLib.h
time_t getTeensy3Time()
{
return Teensy3Clock.get();
}
/*
* User provided date time callback function.
* See SdFile::dateTimeCallback() for usage.
*/
void dateTime(uint16_t* date, uint16_t* time) {
// User gets date and time from GPS or real-time
// clock in real callback function
time_t now();
// return date using FAT_DATE macro to format fields via parameter pointer
*date = FAT_DATE(year(), month(), day());
// return time using FAT_TIME macro to format fields via parameter pointer
*time = FAT_TIME(hour(), minute(), second());
}
time_t getdatetime(){
// gets time from GPS
// returns time_t with nanoseconds as a float
time_t t;
TimeElements tm;
t = 0
return(t);
}
void loop(void) {
int i;
char fname[16];
# process eom uart1
# process eom uart2
# process eom uart3
if (tick) {
tick = false;
if (myFile) {
if (msg1>0) {
myFile.print("G:");
# write(Rx1,msg1)
msg1=0;
}
if (msg2>0) {
myFile.print("F:");
# write(Rx2,msg2)
msg2=0;
}
if (msg3>0) {
myFile.print("E:");
# write(Rx3,msg3)
msg3=0;
}
} else { /* open a new file */
myDrive1.begin();
myDrive1.startFilesystems();
if (DEBUG) Serial.print("try opening new file...\n");
if (DEBUG) Serial.println("\nInitializing USB drive 1...");
if (DEBUG) Serial.printf(F(" connected: %d\n"), myDrive1.msDriveInfo.connected);
if (DEBUG) Serial.printf(F(" initialized: %d\n"), myDrive1.msDriveInfo.initialized);
if (DEBUG) Serial.printf(F(" fs start: %d\n"), myDrive1.filesystemsStarted());
if (!myFiles1.begin(&myDrive1)) {
if (DEBUG) Serial.print("initialization failed with code: ");
if (DEBUG) myFiles1.printError(Serial);
}
i=next_file_number();
sprintf(fname,"Log%04d.txt",i);
myFile = myFiles1.open(fname, FILE_WRITE);
myFile.println("Log Started "); // first line
} /* open new file */
} /* tick */
}
+197
View File
@@ -0,0 +1,197 @@
#include "mbed.h"
#include "MODSERIAL.h"
#include "MSCFileSystem.h"
//Serial uart1(p9, p10); // tx, rx
//Serial uart2(p13, p14);
//Serial uart3(p28, p27);
#define UART1_BAUD 9600 // GPS G:
#define TX1_PIN p9
#define RX1_PIN p10
#define UART2_BAUD 115200 //EMS E:
#define TX2_PIN p13
#define RX2_PIN p14
#define UART3_BAUD 115200 //EFIS F:
#define TX3_PIN p28
#define RX3_PIN p27
#define BUFSIZE 512 // 256 is MODSERIAL default
// GLOBALS!!!
bool sync;
bool bufOVF;
bool done;
int msg1;
int msg2;
int msg3;
int n;
char RX1[BUFSIZE];
char RX2[BUFSIZE];
char RX3[BUFSIZE];
// * Note that \ for multiline macro is not supported yet
#define fileprint(fh, buffer, fmt, ...) do { n=sprintf(buffer, fmt, ##__VA_ARGS__); fh->write(buffer,n); } while (0)
//#define fileprint(fh, buffer, fmt) do { n=sprintf(buffer, fmt); fh->write(buffer,n); } while (0)
DigitalOut led1(LED1);
DigitalOut led2(LED2);
Ticker tick1;
MODSERIAL pc(USBTX, USBRX);
MODSERIAL uart1(TX1_PIN, RX1_PIN, BUFSIZE);
MODSERIAL uart2(TX2_PIN, RX2_PIN, BUFSIZE);
MODSERIAL uart3(TX3_PIN, RX3_PIN, BUFSIZE);
//SDFileSystem sd(p5, p6, p7, p8, "sd", p22, SDFileSystem::SWITCH_NEG_NC); // mosi, miso, sclk, cs
MSCFileSystem fs("fs");
// CALLBACKS...
void rxOvrflow(MODSERIAL_IRQ_INFO *sii) {
//error("RX buffer overflow!");
bufOVF=true;
}
void pcRX(MODSERIAL_IRQ_INFO *sii){
done=true;
}
void uart1RX(MODSERIAL_IRQ_INFO *sii) {
MODSERIAL *sp = sii->serial;
msg1=sp->move(RX1,BUFSIZE);
}
void uart2RX(MODSERIAL_IRQ_INFO *sii) {
MODSERIAL *sp = sii->serial;
msg2=sp->move(RX2,BUFSIZE);
}
void uart3RX(MODSERIAL_IRQ_INFO *sii) {
MODSERIAL *sp = sii->serial;
msg3=sp->move(RX3,BUFSIZE);
}
void filesync(void) {
sync=true;
}
int next_file_number() {
FileHandle* fh;
char fname[16];
bool fileexists=true;
int i=0;
printf("Create filehandle to test if file exists...\n");
sprintf(fname,"Log%03d.txt",i);
printf("Testing for file %s\n",fname);
do {
sprintf(fname,"Log%03d.txt",i);
fh = fs.open(fname, O_RDONLY);
if (fh == NULL) {
fileexists=false;
} else {
i++;
fh->close();
}
} while (fileexists==true);
return(i);
}
int main() {
int i;
int n;
char strbuf[BUFSIZE];
char fname[16];
FileHandle* fh;
// define usb-serial first since stdout (printf) goes here!
pc.baud(115200);
pc.attach(&pcRX, MODSERIAL::RxIrq);
// start filesystem before the input serial data
// so buffers don't overflow during setup!
i=next_file_number();
pc.printf("\r\n\r\nHData Logger Started...\r\n");
sprintf(fname,"Log%03d.txt",i);
fh = fs.open(fname, O_WRONLY | O_CREAT | O_TRUNC);
if(fh == NULL) {
error("Could not open file for write\n");
}
fileprint(fh, strbuf, "Starting Log:\n");
fileprint(fh, strbuf, "filename = %s\n",fname);
//n=sprintf(strbuf,"Starting Log:\n");
//fh->write(strbuf,n);
msg1=0;
msg2=0;
msg3=0;
sync=false;
bufOVF=false;
tick1.attach(&filesync, 5.0); // sync file system every 5 seconds
uart1.baud(UART1_BAUD);
uart1.attach(&uart1RX, MODSERIAL::RxAutoDetect);
uart1.autoDetectChar('\x003');
uart1.attach(&rxOvrflow, MODSERIAL::RxOvIrq);
uart2.baud(UART2_BAUD);
uart2.attach(&uart2RX, MODSERIAL::RxAutoDetect);
uart2.autoDetectChar('\n');
uart2.attach(&rxOvrflow, MODSERIAL::RxOvIrq);
uart3.baud(UART3_BAUD);
uart3.attach(&uart3RX, MODSERIAL::RxAutoDetect);
uart3.autoDetectChar('\n');
uart3.attach(&rxOvrflow, MODSERIAL::RxOvIrq);
done=false;
//while (!done) {
while (true) { // always
if (msg1>0) {
//pc.printf("msg1 handler\r\n");
fileprint(fh, strbuf, "G:");
//fh->write("G:",2);
//n=sprintf(strbuf, RX1);
//msg1=-1;
fh->write(RX1,msg1);
msg1=0;
//fileprint(fh, strbuf, RX1);
//fh->write(RX1,strlen(RX1));
led1=!led1;
}
if (msg2>0) {
fileprint(fh, strbuf, "E:");
fh->write(RX2,msg2);
msg2=0;
led1=!led1;
}
if (msg3>0) {
fileprint(fh, strbuf, "F:");
fh->write(RX3,msg3);
msg3=0;
led1=!led1;
}
if (sync) {
sync=false;
led2=!led2;
fh->fsync();
}
if (bufOVF) {
fileprint(fh, strbuf, "BUFFER OVERFLOW!\n");
uart1.rxBufferFlush();
uart2.rxBufferFlush();
uart3.rxBufferFlush();
bufOVF=false;
}
}
//pc.printf("Done!\r\n");
}
+11
View File
@@ -0,0 +1,11 @@
# Airplane Data Logger
Logs data from Dynon EFIS-D10A, Dynon EMS-D10, and Garmin GNS430 to a USB thumb drive.
UART1 is GPS
messages are prefixed with "G:"
UART2 is EFIS
messages are prefixed with "F:"
UART3 is EMS
messages are prefixed with "E:"