Thanks! If you haven't, take a look at Quarto Troubleshooting Guide as it goes over what can cause the Quarto to crash and some solutions. The short version is to keep sending / receive USB data stuff out of interrupts.
If you just want to look at the most recent data point collected by the ADC, the easiest solution is to store it in a global and then read it back on demand. Something like:
double latestADC;
void getADC1(void) {
static double outputA = 0;
static double outputB = 0;
latestADC= readADC1_from_ISR(); //read ADC voltage
outputA = alphaA * latestADC + (1-alphaA) * outputA; //apply IIR filter on multiplied value
outputB = alphaB * latestADC + (1-alphaB) * outputB; //apply IIR filter on multiplied value
writeDAC(1,outputA);
writeDAC(2,outputB);
}
void readADC(qCommand& qC, Stream& S) {
S.printf("The latest ADC value is %f\n",latestADC);
}
If you setup qCommand to map that readADC function, you can read the latest ADC value on demand. If, instead, you want you print out the data at a specific internal, you can use a timer (see Pulsed Output Example for more details). Or you can put the print functionality in the main loop and it will print out data as fast as it can. If you want to look at, say, 100 ADC readings in a row, then you can use the same approach: create a global array to store all the 100 data points. Then in the getADC1 interrupt store each data point in the next element in that global array (but stop when full) and then another function can, on demand, read back the entire content of the array. And maybe another function is used to start taking another dataset.
If, however, you want to stream back all the read data over USB instead of just a selection of it, this becomes trickier. The fastest the Quarto can collect data is once per us. And that data is 16-bits, so to stream all the data back, you need the USB to be able to send 16Mbps. The USB has the bandwidth to stream this out, but it doesn't have much in excess of this bandwidth. This means that storing the ADC data as a float (4 bytes) instead of its raw int16 (2 bytes) doubles the data that needs to be sent per second. If you print out the data in ASCII the data rate gets even higher. Also important is that USB is efficient when sending lots of data in one go, but it very inefficient and stream lots of small data packets. So if your code has lots of small print lines, what happens is:
USB Start (Overhead)
Send 4 Bytes
USB End (Overhead)
USB Start (Overhead)
Send 4 Bytes
USB End (Overhead)
USB Start (Overhead)
Send 4 Bytes
USB End (Overhead)
If instead you buffer a chunk of data and send it in one burst with something like Serial.write(&array,1024); then that USB overhead is spread over the 1024 bytes that are sent in one go instead of just, say, 4 bytes and you can send data much faster.
In short, if you want to stream back all the ADC data, I would recommend sending it back in binary form (ideally at int16) and in chucks of at least 1k.
One way to do this is to create two arrays for storing data. The getADC1 ISR will store all new data in the first array until that array is full and then it will switch to the second array. When it does this, it sets a global that says the first array is full. When the second array is full, it sets a different global to signal that the second array is full and it switches to the beginning of the first array for storing data and so go. Meanwhile, in the main loop you constantly check for that global signal (just a bool probably) to see if either array is full and if one is, you steam it back over USB and clear the global that the ISR set. This basically lets the Quarto wait until there is enough data and once there is, sends it all back in one go. By splitting the data storage into two buckets we can send data back while new data is coming in to a different section in memory.
I hope this is helpful, but please let me know if you have more questions and want more details.