How is frequency of transmission obtained from Serial.begin?

In one of the library examples of the MPU-6050 RAW sketch, i'm quoting part of the code which is confusing to me. I'm wondering how the 8 MHz or 16 MHz was obtained from 38400 serial baud rate.

// initialize serial communication
    // 38400 chosen because it works as well at 8MHz as it does at 16MHz
    Serial.begin(38400);

From my understanding, the 38400 means that data is transmitted over serial port at a rate of 38400 bps.
And i assume that the reason that the developer mentioned 8 MHz and 16 MHz, is due to the different Arduino boards featuring the ATmega168/ATmega328P working at those 2 different frequencies. I am using an Arduino UNO R3.

My questions:

  1. What's the calculation or method to obtain or relate it to a working frequency of 8 MHz or 16 MHz from 38400 bps?
    I know that, frequency = 1 / Time period or the number of cycles per second. So, 38400 bps would mean a frequency of 38400 Hz?

  2. When Serial.begin is set to 38400, is that a constant rate of 38400 bps or is that a maximum rate of 38400 bps?

  3. How is the ideal serial speed chosen? Should it be relative to the MCU speed?

I’m wondering how the 8 MHz or 16 MHz was obtained from 38400 serial baud rate.

You’ve got it the wrong way round.

TheMemberFormerlyKnownAsAWOL:
You've got it the wrong way round.

OK, so i should obtain 38400 bps from 8 MHz...

8 MHz is (8 x (10^6)) cycles per second. I'm not sure how can that translate into bits per second?

The division will be by 208, giving a small error.
The error is taken care of by receiver margin.

TheMemberFormerlyKnownAsAWOL:
The division will be by 208, giving a small error.
The error is taken care of by receiver margin.

I'm lost. I searched but i couldn't find a guide or tutorial on this data rate/process conversion. I don't understand why divide by 208? What do you mean by the receiver margin? And, how is the same rate good at 8 Mhz but also at 16 MHz?

I think that the answer you are looking for, and I could be misreading it, is that the example sketch author is saying that slower processors cannot reliably achieve data rates faster than 38400.

I don't know of an Arduino board that runs less than 16MHz, but the AVR chip could be used in a custom board running slower clock speeds. The board designer could do this because slower clock speeds run cooler and uese less fuel. I.E. can run longer on battery power.

I disassembled an expired medical device (I disassemble everything before it goes to recycling) and was a bit surprised to see a 1MHz crystal. The operational information said that it "takes a reading every minute", telling me that the processor is in deep-sleep most of the time. But the battery, a CR2032, lasted more than five years.

DryRun:
My questions:

  1. What's the calculation or method to obtain or relate it to a working frequency of 8 MHz or 16 MHz from 38400 bps?
    I know that, frequency = 1 / Time period or the number of cycles per second. So, 38400 bps would mean a frequency of 38400 Hz?

  2. When Serial.begin is set to 38400, is that a constant rate of 38400 bps or is that a maximum rate of 38400 bps?

  3. How is the ideal serial speed chosen? Should it be relative to the MCU speed?

Q1. The speed of UART (Baud Rate = Bd/BAUD) is related with Arduino's/MCU's working frequency (fosc) and UBRR (UART Baud Rate Register) by the formula of Fig-1. The value of fosc and UBRR must chosen in such a way (Fig-2) so that there is minimum transmission error (in BAUD Rate). This is the ideal speed (in bps = bit/baud per sec).
bdFor.png
Figure-1: Bd formula.

bdT1.png
bdT2.png
Figure-2: Tables fosc vs UBRR

Q2. This is the constant speed of data/frame transmission until the Bd is changed.

Q3. See answer of Q1.

bdFor.png

bdT2.png

bdT1.png

Microprocessors derive serial clocks by dividing down the system clock by an integer factor. Because the division is in integers, the exact target serial clock rate (baud rate) is not always attainable. The ATmega328P datasheet has tables showing error for many common baud rates for a wide variety of system clock rates. For the 8 MHz and 16 MHz system clocks the lowest exact rate is 250,000 baud. That is quite fast and beyond the range of SoftwareSerial. The common rates below 250K are off by between 0.2% and 8.5%. The highest rate with an error of only 0.2% at 8 MHz and 16 MHz is 38400.

Receiver margin is the amount of mismatch between the nominal line bit rate and the receiver’s actual bit rate that can be tolerated.

The way a UART works is that it samples the line at a much higher rate than the bit rate, often 16 times.
The UART looks for the leading edge of a start bit, then samples the line eight clock periods later (half a bit period). This should be near the centre of the start bit.
The UART then successively samples the data bits at sixteen clock period intervals, as close as possible to centre of the bit period.
If there is too great a mismatch between the receiver clock and the transmitter clock, then successive samples will be either too early or too late, and the later bits in the stream will be missed entirely, as errors accumulate.

Margin is calculated as 50.(1 - (1/(n-2))), where n is the baud rate division factor, in the example above, 16, giving a margin of just over 46%

TheMemberFormerlyKnownAsAWOL:
The way a UART works is that it samples the line at a much higher rate than the bit rate, often 16 times.

For 8251A SCC Controller, the inequality is:
fCLK>= 30fTXC/RXC at BRF =1 (Baud Rate Factor)
fCLK>= 4.5
fTXC/RXC at BRF =64

TheMemberFormerlyKnownAsAWOL:
The UART looks for the leading edge of a start bit, then samples the line eight clock periods later (half a bit period).

Is it not the trailing (falling) edge of the START bit?
asciiFrame.png

asciiFrame.png

GolamMostafa:
Is it not the trailing (falling) edge of the START bit?

The start bit may not have a trailing edge, if it is of the same polarity as the LS data bit.

Getting confused with the definitions of leading edge/rising edge and the trailing edge/falling edge of a digital signal. What I know that agrees with the following definition (found in net). edit.
ledge.png

In async frame, the idle state of the transmission line is always at HIGH state; the beginning of a new frame is indicated by pulling down (here the creation of a trailing edge/falling edge) the tx line to LOW state for 1-bit period. So, if the polarity of LSBit of the data item is LOW, the START bit will miss the leading edge/rising edge and not the trailing edge.

asyncFrame.png

ledge.png

asyncFrame.png

The leading edge of the start bit is the transition from the idle state of the line, to the start condition.
That may be either rising OR falling, depending on the logic of the connection under consideration.

Please stop trying to obfuscate.

This time, you have terribly failed to educate me. I was not joking -- I was sincere and serious!

I’m not sure to which party the failure belongs.

GolamMostafa:
This time, you have terribly failed to educate me. I was not joking -- I was sincere and serious!

Your definition of leading and trailing edges is simply wrong, and, worse, unworkable. Whether a rising or falling edge is the "leading" edge is ENTIRELY dependent upon the protocol definition.

In RS232, the FALLING edge is the "leading edge of the START bit, per the RS232 specification. There may, or may not be a rising edge at the end of the start bit, as that "edge" is determined by the state of the first data bit. If that data bit is a 1, then there will be a rising edge one bit time after the falling edge of the start bit. If that data bit is a 0, then there will be two bit-times of low signal.

Regards,
Ray L.

GolamMostafa:
Getting confused with the definitions of leading edge/rising edge and the trailing edge/falling edge of a digital signal. What I know that agrees with the following definition.

The 'leading edge' is the start of some period of interest. The 'trailing edge' is the end of some period of interest. EVERY edge is the trailing edge of one period and the leading edge of another. The serial diagram labels the edge where the Idle state ends and the Start bit begins as a 'trailing edge'. It IS the trailing edge of the Idle period but it is also the leading edge of the Start bit.

A 'rising edge' is the transition from a LOW signal to a HIGH signal. A 'falling edge' is the transition from a a HIGH signal to a LOW signal.

Depending on what you are trying to measure, the leading and trailing edges can be either rising or falling.

DryRun:
My questions:

  1. What's the calculation or method to obtain or relate it to a working frequency of 8 MHz or 16 MHz from 38400 bps?
    I know that, frequency = 1 / Time period or the number of cycles per second. So, 38400 bps would mean a frequency of 38400 Hz?

This is all explained in detail in the Atmega 328 datasheet. It has the formula and it has tables showing the percentage timing error at different baud rates and different clock speeds.

It may interest you to know that there is no timing error at 8MHz or 16MHz if you use 500,000 baud.

...R

DryRun:
My questions:

  1. What’s the calculation or method to obtain or relate it to a working frequency of 8 MHz or 16 MHz from 38400 bps?

The Arduino code is open-source, you can just grep them to answer this sort of question. For instance from HardwareSerial.cpp (admittedly in a rather old version of the Arduino software):

// Public Methods //////////////////////////////////////////////////////////////

void HardwareSerial::begin(unsigned long baud)
{
  uint16_t baud_setting;
  bool use_u2x = true;

#if F_CPU == 16000000UL
  // hardcoded exception for compatibility with the bootloader shipped
  // with the Duemilanove and previous boards and the firmware on the 8U2
  // on the Uno and Mega 2560.
  if (baud == 57600) {
    use_u2x = false;
  }
#endif

try_again:
  
  if (use_u2x) {
    *_ucsra = 1 << _u2x;
    baud_setting = (F_CPU / 4 / baud - 1) / 2;
  } else {
    *_ucsra = 0;
    baud_setting = (F_CPU / 8 / baud - 1) / 2;
  }
  
  if ((baud_setting > 4095) && use_u2x)
  {
    use_u2x = false;
    goto try_again;
  }

  // assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
  *_ubrrh = baud_setting >> 8;
  *_ubrrl = baud_setting;

  transmitting = false;

  sbi(*_ucsrb, _rxen);
  sbi(*_ucsrb, _txen);
  sbi(*_ucsrb, _rxcie);
  cbi(*_ucsrb, _udrie);
}
goto try_again;

Depressing, isn’t it?