So for my senior design project, we need to collect data and store it to an SD card. Our current implementation uses the Timer3 and SD libraries. It would seem, however, that these libraries are in conflict as (at some point) the code simply hangs up and ceases to function.
This occurs at different points in execution and has different effects (sometimes it hangs up in the interrupt, sometimes it hangs up while writing to the SD card, and sometimes it appears that loop() stops running although that may be a logic error on my part).
So it seems that SDFat is a faster library and I am having trouble attempting to use it. I really just need to know enough to be able to tell it when to write and how to write to it (after creating the file of course).
Please bear in mind I am not extremely knowledgeable on the finer aspects of programming or electronics as I am in my last year at university for mechanical engineering. When I look at the library I get overwhelmed and the lack of a simple API is frustrating. I do not understand the examples (mostly because the way it's written is not familiar at all to me and I don't have anyone to teach me).
Well that was certainly a helpful reply. I put that in there to let you all know that electronics is not something I've studied. It is an entirely new ballgame for me as well as my design team. I like learning new things, but this isn't for a typical lecture/class. We don't get lectures on how to do things, we're expected to go out and just get results. I've tried reading the library but the way it's written is something I've never seen before and as I don't have someone to show me in person I thought I'd ask on here. I'd like to use what you've written because I think that it will improve what I already have, but to someone who has no prior training in the subject, it is very difficult to use.
But hey, if you want to not be nice about it be my guest, I have other code that will work and is passable. I wanted to put in some more effort and get a better result. What a nice way to welcome newcomers to a potentially fun hobby.
I don't care how you do your project. I am amazed that a senior in ME is so deficient in electronics.
I spent 30 years at UC berkeley which has a fine ME department and early on in the program students take EE courses and labs in electronics and instrumentation.
Not looked at your code but your question sounds familiar. Typical answers indlude
you should do as minimal as possible in the interrupt.
use double buffering.
In the IRQ you fill one of two buffers (say A) and in the main loop() you write the other buffer (B) to SD card. And after a while A is full, the IRQ fills B and A is written.
The buffersize (per buffer) should be tuned to SD sector size - 512 bytes typically.
There's too much code there to properly digest for the moment but one thing I can see is that the timerIsr() ISR is huge, not only that but it includes 12 analogReads().
I see you are toggling a pin, have you looked at it with a scope to see just how long the ISR takes?
All this indexing into the buffers is really slow, IMO you should have a pointer to the current write buffer and a pointer to the current write position. That way there is almost no calculations to be done.
Also a stylistic thing
int numberToDo = 105;
This is a constant but I spent ages looking for where the variable was being changed. Constants are normally in UPPERCASE so you know not to bother searching for a variable.
@robtillaart
I am using two buffers as you are describing, though I did not size them as you have written. I will look into applying that to my code.
@Graynomad:
Yes, the ISR is a bit big, but here's the logic - we are trying to collect data from a number of sensors (primarily strain gauges, as well as [in the future] an accelerometer and gyroscope). Our current design uses wheatstone bridges for strain, so we need to measure the output voltage (the accelerometer and gyroscope are both SPI which are not included yet). It was suggested that we use ISRs as a way to regulate when we collect data and ensure a regular interval for later analysis. This also allows for easy tuning of the sample rate.
I did initially try to make code using SD in loop() to collect data by using delays and some math to start the loop at the correct time, however, SD is very slow and didn't allow for it while using ISRs allows us to bypass that slowness.
You are correct that toggling the pin is for oscilloscope use and for debugging purposes. Even with all that in the ISR, there is significant downtime and the total time to write one buffer is approximately .4 seconds. Given that the buffers are sized to be 105 sets of data, with a sampling rate of 110Hz, this means that there is still plenty of time between writes to the SD card, though there are a large number of interrupts during each write. It would appear that this is the problem and why I want to try using SDFat as I have read online that it is much faster, though more difficult to use. Also, it is clear that the constraint on sampling rate is the time it takes to write to the SD card (even with the current amount of code in the ISR, it is possible to push the sampling rate over 150Hz easily but we then run into memory problems and write speed problems).
buffer1Full is not set to false as I use an if-else structure in the ISR to determine where to write the new data. Without buffer2Full = false in loop(), I had instances where it would write the same buffer two times in a row. It is possible I made a logic control error somewhere and I will investigate again, but that wouldn't solve the problem of the arduino hanging up and ceasing all function.
Good idea on using a pointer for that function, that should reduce some time spent in the ISR. Thanks for the tips on style, I normally only write code for myself so I hadn't heard of this norm.