tni / teensy-samples

BSD 2-Clause "Simplified" License
8 stars 5 forks source link

Compile Error #6

Closed paqwalsh closed 5 years ago

paqwalsh commented 5 years ago

Hi, I'm trying to compile your example code in file named "SdFatSDIO_low_latency_logger.ino" using Arduino IDE but keep getting the following error.

error: 'SdFatSdioEX' does not name a type

Can you give any advice on how to compile this correctly? Maybe sdfat beta has changed since you published? Thinking this might be the case I changed back to the current version of Bill's SdFat library and now I'm getting different error as follows:

error: 'LogEntry' does not name a type

I'd be grateful if you could advise on how this can be compiled as excited to log data a high frequency without frequent lulls due to SD card writes. Thanks.

tni commented 5 years ago

If you get the 'SdFatSdioEX' error, you have the wrong SdFat version. I'm using the git version:

https://github.com/greiman/SdFat

Everything compiles just fine for me with a clean installation of the current Arduino 1.8.9 / TD 1.4.6.

Please turn on 'Show verbose output during compilation' in the Arduino IDE settings and post the full output.

paqwalsh commented 5 years ago

Ooops, sorry about that. I haven't had any problems with libraries over the past year or two so don't normally update my IDE. After an update of both Arduino IDE and Teensyduino, the compile works perfectly and is recording fine. Thanks for the guidance.

On slightly different note, is there any guidance on converting the recorded bin file to an ascii file for reading? Thanks.

tni commented 5 years ago

You could just write a small C++ program. If you don't care about portability, Teensy ARM is using little endian, same as Intel x86 / x64. A memcpy from a read buffer to a struct would work (the reverse of what the logging code does).

Or you could use something like QDataStream:

https://doc.qt.io/qt-5/qdatastream.html

paqwalsh commented 5 years ago

Thanks, maybe you could provide a little more info to help with with conversion. I tried what you suggested via directly copying bytes into a copy of the structure used to record data but don't think I'm getting correct output. If you could have a quick browse i'm sure you'll know where I'm going wrong. Thanks.

Below is a copy of the code I added to your library, it simply adds a call to dumpdata within the void loop() function so the Teensy 3.6 will convert data back to readable format and then dump it to serial. If I can get this working I can edit it to send it to a file on sd card instead or do similiar on pc program for conversions. Hope you can help. Thanks.

// Running when an error is encountered or when logging is finished.
void loop() {
    digitalWrite(LED_BUILTIN, HIGH);
    delay(200);
    digitalWrite(LED_BUILTIN, LOW);
    delay(200);

    if (Serial.available()){
      uint8_t input = Serial.read();
      switch (input){
        case 'd': dumpData(); break;
        default: break;
        }
      }
}

// Make a copy of structure for reading logs 1 by 1, plan to change this to an array to use 512 byte buffer once working. 
LogEntry current_log; 

// Simply open the binfile that was created, memcpy data into current_log using binFile.read function, and then dump data to serial port.  
void dumpData(){
  SdBaseFile binFile;
  binFile.open("log.bin");
  if (!binFile.isOpen()) {
    Serial.println();
    Serial.println(F("No current binary file"));
    return;
    }
    binFile.rewind();
  Serial.println();
  Serial.println(F("Type any character to stop"));
  delay(1000);
  //printHeader(&Serial);
  while(Serial.available()) Serial.read();
  while (!Serial.available() && binFile.read(&current_log , sizeof(current_log) == sizeof(current_log))) {
    Serial.print(current_log.counter);
    Serial.print(", ");
    Serial.print(current_log.record_offset);
    Serial.print(", ");
    Serial.print(current_log.time);
    Serial.print(", ");
    Serial.println(current_log.dummy); 
    }
  Serial.println(F("Done"));
  binFile.close();
  }

and the output looks like this:

190, 999, 16298644, 1 192, 999, 16298644, 1 159, 999, 16298644, 1 0, 999, 16298644, 1 66, 999, 16298644, 1 66, 999, 16298644, 1 66, 999, 16298644, 1 66, 999, 16298644, 1 42, 999, 16298644, 1 180, 999, 16298644, 1 2, 999, 16298644, 1 0, 999, 16298644, 1 89, 999, 16298644, 1 66, 999, 16298644, 1 43, 999, 16298644, 1 0, 999, 16298644, 1 200, 999, 16298644, 1 192, 999, 16298644, 1 159, 999, 16298644, 1

tni commented 5 years ago

while (!Serial.available() && binFile.read(&current_log , sizeof(current_log) == sizeof(current_log)))

That's clearly wrong. It should just the sizeof.

This is what the documentation for 'SdBaseFile::read(void* buf, uint16_t nbyte)' says:

For success read() returns the number of bytes read. A value less than nbyte, including zero, will be returned if end of file is reached. If an error occurs, read() returns -1. ...

So your loop termination is also wrong. You want very good and explicit error handling when working with SdFat. Things can fail in mysterious ways.

paqwalsh commented 5 years ago

Okay, well spotted, the line was meant to read:

while (!Serial.available() && binFile.read(&current_log , sizeof(current_log)) == sizeof(current_log)) {

bracket in the wrong place!!! But good news is that after changing this then it reads as expected. Thanks very much for you help with this.

Just one last thing that hopefully you can comment on. I set up a simple test where I use a second Teensy device (Teensy 3.1) to generate an analog sine wave output using interrupts and then reading the signal in using your code recording at 25us interval or 40kHz. I set the recording ISR to capture the voltage of 2nd Teensy pin (grounds of both Teensy boards are common), also recorded the microsecond count using micros() function and added another variable that reports time duration spent in the recording ISR which started at about 22us for 1st two/three recordings and then reduced to a steady at 18us. After looking at the resulting data I see that it captures the sine wave beautifully, however there is something happening at times where some of the sine wave is missing (it looks like dropped data, could it be? ) Below is a graph showing a section of the recording with the missing data.

DAQ_Error

Also, when looking at the data stream where this discontinuity occurs it looks like that shown below. The first column is just a dummy number 1, the second column shows the time duration spent in the last ISR, the third column gives the timestamp in microseconds from the recording Teensy 3.6, and the fourth column gives a 16 bit number corresponding to the recorded voltage from 0-3.3V on the analog input.

1, 18, 22853956, 63430
1, 18, 22853981, 63461
1, 18, 22854006, 63466
1, 18, 22854031, 63485
1, 18, 22854056, 63473
1, 18, 22854081, 63484
1, 18, 22854106, 63482
1, 18, 22854131, 63511
1, 18, 22854156, 63504
1, 18, 22854181, 63532
1, 18, 22854206, 63540
1, 18, 22854231, 63553
1, 18, 22854231148
1, 18, 24285181, 31194
1, 18, 24285206, 31212
1, 18, 24285231, 31220
1, 18, 24285256, 31268
1, 18, 24285281, 31286
1, 18, 24285306, 31331
1, 18, 24285331, 31338
1, 18, 24285356, 31390
1, 18, 24285381, 31395
1, 18, 24285406, 31453

As you can see something weird is happening with the timestamp (or maybe it's due to some flaw in my data conversion process?). The time duration in the last ISR remains at 18us but the micros() function is reporting some really large number and the analog reading is missing! Also, after this happens you'll notice that the micros timestamp jumps forward by over 2 full seconds which is a substantial data loss.

Have you noticed anything like this before? Or any suggestions for what could be causing this? Maybe the use of micros() function within the recording ISR?? Hope you have some advice.

Thanks again for you help so far, much appreciated.