Skip to main content
Arduino

Return to Answer

+ binary protocol.
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

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() as static, 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 the ADC 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() as static, 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 the ADC 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() as static, 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 the ADC 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.

+ optimization tips.
Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

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() as static, 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 the ADC 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() as static, 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 the ADC 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.

Source Link
Edgar Bonet
  • 45.1k
  • 4
  • 42
  • 81

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.

AltStyle によって変換されたページ (->オリジナル) /