This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Question about ADC frequency

Other Parts Discussed in Thread: MSP430F47176


I made a program to measure AD input data, and output to PC terminal and writes to SD card media (9600bps).

The number of ADC I could achieve with OSR=128 was about 125/second.

On the other hand, when I made a program to measure AD input data and output through SPI, the program can achieve with OSR=64 about 2048/second.

In the former case, the modular frequency was about 16,000 (=128x125), and the latter case is 131,072 (=64*2048). They are largely different.

The question is, is it possible to achieve modular frequency of more than 100,000 even when the program uses SD card treatment (file open, write, file close).

Have anyone tried to make such a code (ADC of 100,000Hz, SD card write every second, PC output)?

I use uALFAT for SD card module, and MSP430F47176.

 

 

  • Well, 9600bps are 9600bps. This are only 960 bytes per second. Period. You cannot send more, including any binary-to-text conversion, linefeeds etc. Also, if you do not decouple conversion from sending, you'll waste additional time.

    Using SPI, however, you use a much higher data rate than 9600bd. (and even with 9600Bd, the throughput is 20% higher as SPI requires only 8 bit per byte while UART requires 10)

    It's not the conversion speed that's limiting your sampling frequency, it's the transfer of the results.

    In theory, you can write to an SD card with about 500KB/s, which is about 500* faster than the 9600bd UART. If you decouple writing from sampling (double-buffering and DMA background write/interrupt state machine for initing the transfer), you can reach really high sampling rates.

    The SD16, however, won't output 100.000 useful samples per second. It always requires at least 32x oversampling (It needs to feed the digital filter or you'll only get 1 bit effective resolution). With OSR=32, you'll get only 9 or 10 effective (usable) bits and you'll get a valid result at all only if the input frequency is by a factor 8 smaller than (Fsd16/OSR) and the filter is continuously stuffed. (digital filter settling time)

    The ADC12 gives sampling frequencies of up to 130ksps (for up to 75kHz input frequency), but for lower frequencies, it's precision does not grow. ADC12 sampling results are independent from each other.
    The SD16 gives better results the slower you sample (higher OSR) and the lower the input frequency is. The digital filter used to get the result form the oversamplied bitstream needs some settling time. SD16 conversions depend on the previous one. So it makes no sense taking just one sample. YOu'll need to take at least four and use the forth as the first usable. Or let it run continuously, and then picking one sample from the middle. Just start-sample-stop won't give a reliable result.
    Both have different signal targets and different usages.

    On the 1611 with ADC12, I do 12.000 conversions per second (actually more, but I use only 12.000) from 12 different channels. Every millisecond one sample per channel. Inclusive processing, it only takes about <5% of the CPU. I don't write them, however. I just check for changes, add resulting values to counters etc.
    It shouldn't be a problem to write them to SD card anyway (which in fact is a long-term goal I'll have to implement some day)

    As a short fix, I'd go for 115200bps on the usart.
    Then, decouple sampling and sending/writing to SD card. Do it in an ISR or use DMA (if available) with alternating buffers.
    Know the file system driver you're using, so you can avoid flash writes (which have to be done 512 byte-wise) at an unpleasant time. e.g. buffer 512 bytes locally and then push them at once into the file system. And be sure that the actual writing process is done in the background, so you can continue sampling data witout waiting for the flash write to be completed.

    Real-time-programming is different from PC application programming. Time won't wait. :)

  • Thank you very much, Jens-Michael.

     

    About writing speed of uALFAT (SD card module), I only write 1-second averaged data. I accumulate the analog data during the 125 (with OSR=128) ADCs and then average into the 1-second averaged values every second. So the data size written into SD per second is only in the order of 70 bytes or so (including date time values) .

    So, in this case, the writing into SD is not the problem, isn't?

    What I may make mistake seems treatment of interrupt. During the SD card writing, the ADC interrupt should be repeated also. However, if I set GIE=true during the SD writing with higher ADC frequency (>125 per second OSR=128), it seems that the SD writing get stopped in the middle. This may be possibly some trouble in the serial data communication interupted by the high frequency ADC interrupt.

    Is it problematic to set GIE=true during the SD treatment (SD FileOpen, FileWrite, FileClose)?

     

    Jens-Michael Gross said:

    The SD16, however, won't output 100.000 useful samples per second. It always requires at least 32x oversampling (It needs to feed the digital filter or you'll only get 1 bit effective resolution). With OSR=32, you'll get only 9 or 10 effective (usable) bits and you'll get a valid result at all only if the input frequency is by a factor 8 smaller than (Fsd16/OSR) and the filter is continuously stuffed. (digital filter settling time)

     

     I do not correctly understand this part.

    Can I obtain 19-bit effective resolution by averaging 1024 times (2 to the power of 10) of OSR32 data?

    Is the Fsd16 32"32768Hz, when I use 32kHz crystal? And do you mean for OSR32,  32 " 32768 / OSR32 / 8 = 4096 is the upper limit of ADC per second for the 9 or 10 effective bits?

     

    Jens-Michael Gross said:

    As a short fix, I'd go for 115200bps on the usart.
    Then, decouple sampling and sending/writing to SD card. Do it in an ISR or use DMA (if available) with alternating buffers.
    Know the file system driver you're using, so you can avoid flash writes (which have to be done 512 byte-wise) at an unpleasant time. e.g. buffer 512 bytes locally and then push them at once into the file system. And be sure that the actual writing process is done in the background, so you can continue sampling data witout waiting for the flash write to be completed.

    So when I use DMA, can I avoid waiting time of uALFAT writing and can execute ADCs?

     

  • OKY said:
    So the data size written into SD per second is only in the order of 70 bytes or so (including date time values) . So, in this case, the writing into SD is not the problem, isn't?

    Well, not really. As I often say, If you are set to zero Oxygen for just 5 minutes, you're dead, no matter how much is supplied afterwards or before.

    Writing to an SD card is done in chunks of 512 bytes. Also the file system will write in clusters of multiples of 512 bytes. This is more than a coincidence.

    If you write to a file system driver, it will take the first 70 bytes. An the second ones and the third ones etc. They are written into a ram buffer and the function almost immediately returns. But if you write your 70 bytes the eight time, a 512 byte block has been filled. Now the file system driver will write this block to the SD card. All in a whole. And maybe it will also update teh allocation table or whatever.

    Your application code is trapped in the middle of writing these 70 bytes for a loooong time (several milliseconds), then the remaining, unwritten 22 bytes are placed in the buffer for the next block write and the function returns. So every 7 ot 8 seconds you'll have a relatively long break in teh execution of your main loop, completely destroying the continuity of the data acquisition.

    OKY said:
    So when I use DMA, can I avoid waiting time of uALFAT writing and can execute ADCs?


    No, you can just reduce it as the transfer to the card goes much faster (yet the actual writing time of the block into the SD cards flash takes the same time). It reduces the problem and maybe shift it into a bearable region. It depends on your requirements.

    To ensure proper operation even during a write access, you need to do all the data acquisition and time-critical processing decoupled from the writing.

    e.g. collect data completely in ISRs and store it in a buffer large enough for 2 seconds of data. Every second, your main is triggered, does the necessary calculation over the first half of the buffer, then writes it to the sd card. next second, main is striggered by a timer ISR, calculates over the second half of the buffer (while the data aqcuisition happens in the first half of the buffer now), writes to the file and goes to sleep. And so on and so on.
    This way, you have a full second to do any calculation and any write access before you'll be called again. But of course you'll need lots of ram.

    You can also do the calculations inside the SD16 ISR when data comes in (if it is only adding-up the values or maybe simple multiplication). Then you'll have only two value sets. When the timer ISR kicks in, it switches the SD16 ISR from set 1 to set 2, wakes main and main can do any longer operation (such as a division) on set 1, write the data to disk, clear set 1 and sleep again.

    This mechanism is called double-buffering. To go back to the oxygen example above, this is why divers often have two oxygen bottles. They can change one while breathing from the other, not being pressed to finish the change before they go unconscious. Else one bigger bottle would be cheaper and weight less.

    OKY said:
    What I may make mistake seems treatment of interrupt. During the SD card writing, the ADC interrupt should be repeated also. However, if I set GIE=true during the SD writing with higher ADC frequency (>125 per second OSR=128), it seems that the SD writing get stopped in the middle. This may be possibly some trouble in the serial data communication interupted by the high frequency ADC interrupt.
    Is it problematic to set GIE=true during the SD treatment (SD FileOpen, FileWrite, FileClose)?


    It shouldn't be a problem. The advantage of being SPI master is that you provide the clock. If you slow down the clock, the slave will slow down its communication too. You can stop in the middle of a bit and it shouldn't do any harm. Only that you may not be faster than the slave supports.
    In any case, an ISR should do as much as necessary but as few things as possible. How much is necessary is up to you to decide.
    After all, you'll need to finish all other ISRs before the one with the highest frequency is triggered again.

    OKY said:
    Can I obtain 19-bit effective resolution by averaging 1024 times (2 to the power of 10) of OSR32 data?

    Well, not exactly. The formula is one more bit for every 4 times oversampling. Another 1024 oversampling would get you additional 5 bits. But only under certain circumstances.
    On individual conversions of a static signal, oversampling only acts as a low-pass You won't get additional bits. If you have a 12 bit ADC, you won't get 13 bits by averaging 4 samples. You'll only averaging the noise, making more of the 12 bits usable while reducing the bandwidth by a factor of 4 (well, a static signal already has zero frequency, so this doesn't matter).

    If you apply a high-frequent signal to the static signal, you will, however, really adding additional bits to the sample dones. Since if the static signal was already near the edge to the next sample value, the high-frequency signal will shift it over the edge for some and keep it below for other samples. In the average, you'll gain additional bits beyond the ADC resolution. You will not, however, reduce the signal-to-noise ratio of the individual conversions.

    The SD16, however, uses a 1-bit second order sigma-delta converter with a digital filter. Each clock cycle, s ingle bit is generated (don't ask me about how it is generated and what it actually means). This bit is fed into the digital filter and decimated. After 32 bits have been fed into the filter, the filter may output a result. it is, however, not too accurate. Using higher OSR gives better result, a better signal-to-noise ratio and at OSR=1024, the result has almost 16 usable bits. (SNR ~92dB, where 90dB is 15 bit and 96dB is 16 bit). Hence the name SD16 (Sigma-Delta-16bit).

    Simply averaging the results would not increase accuracy as the digital filter already selected the usable part of the generated sampling value, based on the OSR. You'll only reduce the bandwidth.

    OKY said:
    Is the Fsd16 32"32768Hz, when I use 32kHz crystal? And do you mean for OSR32,  32 " 32768 / OSR32 / 8 = 4096 is the upper limit of ADC per second for the 9 or 10 effective bits?


    No, if Fsd16 is 32768 Hz, then the maximum sampling frequency is 32768/32 =1024 samples per second (but for all channels simultaneously if supported - some SD16 have only one channel selected at a time and only one SD16MEM register). For OSR=1024 it is 32 samples then.
    But if you are sampling any waveform, you'll need at least two samples per wave, the maximum bandwidth is 512 bzw 16 Hz. The additional factor 4 was the digital filter settling time. If the signal is changing faster than the settling time, you'll get aliasing-like effects too. So with 32768Hz Fsd16 you shouldn't sample anything above 128Hz with 9 significant bits or 4 Hz with 16 bits. If you obey this limit, then you'll get 1024 or 32 samples per second (except for the first three after changing the SD16 settings).

    After all it's a complex task and I don't fully understand the mechanics myself (and those who do will surely nod now). Luckily I only have MSPs with ADC12 (while this may change in future), and the ADC12 is rather straightforward for high-frequency low-resolution sampling.

  • Thank you very much for your detailed reply, Jens-Michael.

     

    Jens-Michael Gross said:

    Writing to an SD card is done in chunks of 512 bytes. Also the file system will write in clusters of multiples of 512 bytes. This is more than a coincidence.

    Your application code is trapped in the middle of writing these 70 bytes for a loooong time (several milliseconds), then the remaining, unwritten 22 bytes are placed in the buffer for the next block write and the function returns. So every 7 ot 8 seconds you'll have a relatively long break in teh execution of your main loop, completely destroying the continuity of the data acquisition.

    So, the SD acts not in the same way for every second, based on the 512 bytes writing.

     

    Jens-Michael Gross said:

    To ensure proper operation even during a write access, you need to do all the data acquisition and time-critical processing decoupled from the writing.

    I will try to decouple the data acquisition and sd writing and use the "double-buffering".

    Jens-Michael Gross said:

    What I may make mistake seems treatment of interrupt. During the SD card writing, the ADC interrupt should be repeated also. However, if I set GIE=true during the SD writing with higher ADC frequency (>125 per second OSR=128), it seems that the SD writing get stopped in the middle. This may be possibly some trouble in the serial data communication interupted by the high frequency ADC interrupt.
    Is it problematic to set GIE=true during the SD treatment (SD FileOpen, FileWrite, FileClose)?

    It shouldn't be a problem. The advantage of being SPI master is that you provide the clock. If you slow down the clock, the slave will slow down its communication too. You can stop in the middle of a bit and it shouldn't do any harm. Only that you may not be faster than the slave supports.
    In any case, an ISR should do as much as necessary but as few things as possible. How much is necessary is up to you to decide.
    After all, you'll need to finish all other ISRs before the one with the highest frequency is triggered again.

    [/quote]

    So the ISR call in the middle of other ISR will be a problem? I need to finish each ISR to the end at a time.

     

     

    Jens-Michael Gross said:

    If you apply a high-frequent signal to the static signal, you will, however, really adding additional bits to the sample dones. Since if the static signal was already near the edge to the next sample value, the high-frequency signal will shift it over the edge for some and keep it below for other samples. In the average, you'll gain additional bits beyond the ADC resolution. You will not, however, reduce the signal-to-noise ratio of the individual conversions.

    The SD16, however, uses a 1-bit second order sigma-delta converter with a digital filter. Each clock cycle, s ingle bit is generated (don't ask me about how it is generated and what it actually means). This bit is fed into the digital filter and decimated. After 32 bits have been fed into the filter, the filter may output a result. it is, however, not too accurate. Using higher OSR gives better result, a better signal-to-noise ratio and at OSR=1024, the result has almost 16 usable bits. (SNR ~92dB, where 90dB is 15 bit and 96dB is 16 bit). Hence the name SD16 (Sigma-Delta-16bit).

    Simply averaging the results would not increase accuracy as the digital filter already selected the usable part of the generated sampling value, based on the OSR. You'll only reduce the bandwidth.

    So for higher resolution using the SD16, I should not do 1024 ADCs with OSR=32. Instead, I should do 32 ADCs with OSR=1024. And 1 ADCs with OSR=1024 has same precise bits with 32 ADCs with OSR=1024?

     

    Jens-Michael Gross said:

    No, if Fsd16 is 32768 Hz, then the maximum sampling frequency is 32768/32 =1024 samples per second (but for all channels simultaneously if supported - some SD16 have only one channel selected at a time and only one SD16MEM register). For OSR=1024 it is 32 samples then.
    But if you are sampling any waveform, you'll need at least two samples per wave, the maximum bandwidth is 512 bzw 16 Hz. The additional factor 4 was the digital filter settling time. If the signal is changing faster than the settling time, you'll get aliasing-like effects too. So with 32768Hz Fsd16 you shouldn't sample anything above 128Hz with 9 significant bits or 4 Hz with 16 bits. If you obey this limit, then you'll get 1024 or 32 samples per second (except for the first three after changing the SD16 settings).

    So, for upper 1024 samples, I should do only 128(=1024/8)Hz. And for upper 32 samples, I should do only 4(=32/8)Hz.  

  • OKY said:
    Thank you very much for your detailed reply, Jens-Michael.

    You're welcome. I order my own thoughts while answering this kind of questions, which helps me improve my own code or prepre future code. So it's not entirely unselfish :)

    OKY said:
    So, the SD acts not in the same way for every second, based on the 512 bytes writing.

    Indeed. It depends on the amount of data written and of course the implementation of the use file system does its own part.

    OKY said:
    So the ISR call in the middle of other ISR will be a problem? I need to finish each ISR to the end at a time.

    Normally, yes. If an ISR is executed, GIE is cleared and no other interrupts (except for an NMI, hence the name Non Maskable Interrupt) can happen.
    It is possible to nest ISRs. If you have an ISR which takes some time to execute, you may set GIE (EINT) inside this ISR, allowing it to be interrupted by a different ISR.
    But this requires additional stack space (for two ISRs at the same time) and you must take precaution that if the first ISR is interrupted by others, it may not be interrupted by itself too, which is very well possible (especially if you didn't clear the IFG flag that caused the original interrupt, but also if you jsut don't complete the job in time).
    A stack overflow will be the result if you fail to time everything properly.

    OKY said:
    So for higher resolution using the SD16, I should not do 1024 ADCs with OSR=32. Instead, I should do 32 ADCs with OSR=1024.

    Yes.
    OKY said:
    And 1 ADCs with OSR=1024 has same precise bits with 32 ADCs with OSR=1024?
    On a static signal, you will average the remaining noise, making the reading a bit more precise (e.g. eliminating the remaining noise in the lowest 1 or 2 bits, depenfing on input signal quality), on a higher-frequency signal, you'll just averaging it. Nothing more.

    OKY said:
    So, for upper 1024 samples, I should do only 128(=1024/8)Hz. And for upper 32 samples, I should do only 4(=32/8)Hz.  

    Not 'should do', but this is the maximum input signal waveform frequency which will not result in completely useless results. If you want to get anything that distantly resembles a 50Hz wave, you cannot go above OSR=64. It won't look much like a sine wave anyway, but noticeable a 50Hz wave of some form :)

  • Jens-Michael Gross said:

    You're welcome. I order my own thoughts while answering this kind of questions, which helps me improve my own code or prepre future code. So it's not entirely unselfish :)

     

    Thank you for saying so.

    I appreciate it.

     

    Jens-Michael Gross said:

    It is possible to nest ISRs. If you have an ISR which takes some time to execute, you may set GIE (EINT) inside this ISR, allowing it to be interrupted by a different ISR.
    But this requires additional stack space (for two ISRs at the same time) and you must take precaution that if the first ISR is interrupted by others, it may not be interrupted by itself too, which is very well possible (especially if you didn't clear the IFG flag that caused the original interrupt, but also if you jsut don't complete the job in time).
    A stack overflow will be the result if you fail to time everything properly.

    So incorrect implementation using the nested ISR will cause stack overflow.

    For me as a still beginner for MSP programe, it seems that I should not use the nested ISR. I will make code to use ISR as short as possible, then process the other part of the work in main() or functions called in main().

     

  • OKY said:
    For me as a still beginner for MSP programe, it seems that I should not use the nested ISR.

    Even experienced programmers hould not use nested interrupts if possible.

    The only place where I do it is in my multitasking core, where I need teh timer ISR which does the task switching must be interruptable by the timer interrupt which does the system clock. THis way I can go to sleep inside the task switch ISR (if all tasks are sleeping/waiting) and wake up by the timer.

    OKY said:
    I will make code to use ISR as short as possible, then process the other part of the work in main() or functions called in main().

    THat's indeed the best way.

    Sometimes, there are tasks which require periodic work (so a timer ISR is the first choice) but take some time. In this case, a state machine might be a solution. Do some of the work, and when a wait is required, increment the state cunter and exit the ISR. With the next interrupt, you can continue where you left.
    I do it for detecting an SD card change and initializing the SD card in the background. And for reading one register of an external hardware chip at each 1ms timer interrupt (and then skip 80) instead of all 20 together every 100 millliseconds.

  • Jens-Michael Gross said:

    Sometimes, there are tasks which require periodic work (so a timer ISR is the first choice) but take some time. In this case, a state machine might be a solution. Do some of the work, and when a wait is required, increment the state cunter and exit the ISR. With the next interrupt, you can continue where you left.
    I do it for detecting an SD card change and initializing the SD card in the background. And for reading one register of an external hardware chip at each 1ms timer interrupt (and then skip 80) instead of all 20 together every 100 millliseconds.

     

    Thank you very much for the advice.

    I may use the "state machine" if I need it in my future work.

  • Hello,

    I am facing similar challenges in my design on this thread
    http://e2e.ti.com/support/microcontrollers/msp43016-bit_ultra-low_power_mcus/f/166/t/156547.aspx#567717

    Could you please take a look and offer any advice you may have?

    Thank you very much!

**Attention** This is a public forum