You calculation of the data rate is wrong:
Serial.println()
adds CRLF (i.e. "\r\n") to terminate the line, That's 2 bytes, not one.- Each byte is sent by the serial port as one start bit, followed by 8 data bits, followed by one stop bit. That's 10 bits in terms of timing.
In the worst case scenario (value ≥ 1000), you are sending 6 bytes, or 60 bits: the fastest possible rate is 1920 samples per second. In the arguably most common case (100 ≤ value < 1000), you send 50 bits per sample at up to 2304 S/s.
Edit: Here are a few optimization tips, just to make sure your program is not CPU-bound:
- Declare
captureSample()
asstatic
, this way the compiler can inline it and save the call overhead. - Make
currentSample
unsigned, this way the compiler can optimize the modulo operation into a bitwise AND. - Replace
analogRead(0)
with a direct read of theADC
register, and start the next ADC conversion right away. This way you do not have to wait for 104 μs while the ADC does its work. - You may want to move the
Serial.println()
out of the ISR, otherwise you may be blocking interrupts for too long if the serial port cannot cope with the sampling rate. - Make some kind of binary protocol instead of using plain ASCII.
You may also trigger the ADC directly from a timer instead of going
through the timer ISR (see the datasheet for details). You would then
use ISR(ADC_vect)
to retrieve the ADC result. This way you get a very
steady (hardware controlled) sampling rate.
More about the binary protocol: you could send only two bytes per sample and remain ASCII-compatible (which is often desirable) by using 32 printable characters to represent 5 bits. This is the same idea used in base64, but simplified to use consecutive characters:
uint8_t high_5_bits = sample >> 5;
uint8_t low_5_bits = sample & 0x1f;
Serial.write('@' + high_5_bits);
Serial.write('@' + low_5_bits);
This gives a stream of characters in the range @A-Z[\]^_
. Then your
maximum sampling rate is 5760 S/s.
You calculation of the data rate is wrong:
Serial.println()
adds CRLF (i.e. "\r\n") to terminate the line, That's 2 bytes, not one.- Each byte is sent by the serial port as one start bit, followed by 8 data bits, followed by one stop bit. That's 10 bits in terms of timing.
In the worst case scenario (value ≥ 1000), you are sending 6 bytes, or 60 bits: the fastest possible rate is 1920 samples per second. In the arguably most common case (100 ≤ value < 1000), you send 50 bits per sample at up to 2304 S/s.
Edit: Here are a few optimization tips, just to make sure your program is not CPU-bound:
- Declare
captureSample()
asstatic
, this way the compiler can inline it and save the call overhead. - Make
currentSample
unsigned, this way the compiler can optimize the modulo operation into a bitwise AND. - Replace
analogRead(0)
with a direct read of theADC
register, and start the next ADC conversion right away. This way you do not have to wait for 104 μs while the ADC does its work. - You may want to move the
Serial.println()
out of the ISR, otherwise you may be blocking interrupts for too long if the serial port cannot cope with the sampling rate. - Make some kind of binary protocol instead of using plain ASCII.
You may also trigger the ADC directly from a timer instead of going
through the timer ISR (see the datasheet for details). You would then
use ISR(ADC_vect)
to retrieve the ADC result. This way you get a very
steady (hardware controlled) sampling rate.
You calculation of the data rate is wrong:
Serial.println()
adds CRLF (i.e. "\r\n") to terminate the line, That's 2 bytes, not one.- Each byte is sent by the serial port as one start bit, followed by 8 data bits, followed by one stop bit. That's 10 bits in terms of timing.
In the worst case scenario (value ≥ 1000), you are sending 6 bytes, or 60 bits: the fastest possible rate is 1920 samples per second. In the arguably most common case (100 ≤ value < 1000), you send 50 bits per sample at up to 2304 S/s.
Edit: Here are a few optimization tips, just to make sure your program is not CPU-bound:
- Declare
captureSample()
asstatic
, this way the compiler can inline it and save the call overhead. - Make
currentSample
unsigned, this way the compiler can optimize the modulo operation into a bitwise AND. - Replace
analogRead(0)
with a direct read of theADC
register, and start the next ADC conversion right away. This way you do not have to wait for 104 μs while the ADC does its work. - You may want to move the
Serial.println()
out of the ISR, otherwise you may be blocking interrupts for too long if the serial port cannot cope with the sampling rate. - Make some kind of binary protocol instead of using plain ASCII.
You may also trigger the ADC directly from a timer instead of going
through the timer ISR (see the datasheet for details). You would then
use ISR(ADC_vect)
to retrieve the ADC result. This way you get a very
steady (hardware controlled) sampling rate.
More about the binary protocol: you could send only two bytes per sample and remain ASCII-compatible (which is often desirable) by using 32 printable characters to represent 5 bits. This is the same idea used in base64, but simplified to use consecutive characters:
uint8_t high_5_bits = sample >> 5;
uint8_t low_5_bits = sample & 0x1f;
Serial.write('@' + high_5_bits);
Serial.write('@' + low_5_bits);
This gives a stream of characters in the range @A-Z[\]^_
. Then your
maximum sampling rate is 5760 S/s.
You calculation of the data rate is wrong:
Serial.println()
adds CRLF (i.e. "\r\n") to terminate the line, That's 2 bytes, not one.- Each byte is sent by the serial port as one start bit, followed by 8 data bits, followed by one stop bit. That's 10 bits in terms of timing.
In the worst case scenario (value ≥ 1000), you are sending 6 bytes, or 60 bits: the fastest possible rate is 1920 samples per second. In the arguably most common case (100 ≤ value < 1000), you send 50 bits per sample at up to 2304 S/s.
Edit: Here are a few optimization tips, just to make sure your program is not CPU-bound:
- Declare
captureSample()
asstatic
, this way the compiler can inline it and save the call overhead. - Make
currentSample
unsigned, this way the compiler can optimize the modulo operation into a bitwise AND. - Replace
analogRead(0)
with a direct read of theADC
register, and start the next ADC conversion right away. This way you do not have to wait for 104 μs while the ADC does its work. - You may want to move the
Serial.println()
out of the ISR, otherwise you may be blocking interrupts for too long if the serial port cannot cope with the sampling rate. - Make some kind of binary protocol instead of using plain ASCII.
You may also trigger the ADC directly from a timer instead of going
through the timer ISR (see the datasheet for details). You would then
use ISR(ADC_vect)
to retrieve the ADC result. This way you get a very
steady (hardware controlled) sampling rate.
You calculation of the data rate is wrong:
Serial.println()
adds CRLF (i.e. "\r\n") to terminate the line, That's 2 bytes, not one.- Each byte is sent by the serial port as one start bit, followed by 8 data bits, followed by one stop bit. That's 10 bits in terms of timing.
In the worst case scenario (value ≥ 1000), you are sending 6 bytes, or 60 bits: the fastest possible rate is 1920 samples per second. In the arguably most common case (100 ≤ value < 1000), you send 50 bits per sample at up to 2304 S/s.
You calculation of the data rate is wrong:
Serial.println()
adds CRLF (i.e. "\r\n") to terminate the line, That's 2 bytes, not one.- Each byte is sent by the serial port as one start bit, followed by 8 data bits, followed by one stop bit. That's 10 bits in terms of timing.
In the worst case scenario (value ≥ 1000), you are sending 6 bytes, or 60 bits: the fastest possible rate is 1920 samples per second. In the arguably most common case (100 ≤ value < 1000), you send 50 bits per sample at up to 2304 S/s.
Edit: Here are a few optimization tips, just to make sure your program is not CPU-bound:
- Declare
captureSample()
asstatic
, this way the compiler can inline it and save the call overhead. - Make
currentSample
unsigned, this way the compiler can optimize the modulo operation into a bitwise AND. - Replace
analogRead(0)
with a direct read of theADC
register, and start the next ADC conversion right away. This way you do not have to wait for 104 μs while the ADC does its work. - You may want to move the
Serial.println()
out of the ISR, otherwise you may be blocking interrupts for too long if the serial port cannot cope with the sampling rate. - Make some kind of binary protocol instead of using plain ASCII.
You may also trigger the ADC directly from a timer instead of going
through the timer ISR (see the datasheet for details). You would then
use ISR(ADC_vect)
to retrieve the ADC result. This way you get a very
steady (hardware controlled) sampling rate.
You calculation of the data rate is wrong:
Serial.println()
adds CRLF (i.e. "\r\n") to terminate the line, That's 2 bytes, not one.- Each byte is sent by the serial port as one start bit, followed by 8 data bits, followed by one stop bit. That's 10 bits in terms of timing.
In the worst case scenario (value ≥ 1000), you are sending 6 bytes, or 60 bits: the fastest possible rate is 1920 samples per second. In the arguably most common case (100 ≤ value < 1000), you send 50 bits per sample at up to 2304 S/s.