Template
initial commit
This commit is contained in:
@@ -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 */
|
||||||
|
}
|
||||||
@@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user