ATmega328PB Serial communication sending only (HEX) 00 and 80

Hi! I am successfully programming ATmega328PB using Arduino Uno.

I need to use a Serial port on the ATmega to interface RN4871 BLE module. To test the Serial port and make it work, I use CH340G based USB-TTL connector: Link

The wiring:
Pin 3 (PD3) - LED
Pin 4 (PD4) - LED
Pin 31 (TXD0) - RX of the USB-TTL adapter
Pin 32 (RXD0) - TX of the USB-TTL adapter
5V, GND are connected normally.

The code:

#define LED 3
#define LED2 4

// the setup function runs once when you press reset or power the board
void setup() {

  Serial.begin(115200);
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(LED, OUTPUT);
  pinMode(LED2, OUTPUT);

  digitalWrite(LED2, HIGH);
  delay(100);
  digitalWrite(LED2, LOW);
  delay(100);
  digitalWrite(LED2, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(50);                      // wait for a second
  digitalWrite(LED2, LOW);   // turn the LED off by making the voltage LOW
  delay(50);                      // wait for a second
  }


// the loop function runs over and over again forever
void loop() {
  digitalWrite(LED, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(300);                      // wait for a second
  digitalWrite(LED, LOW);   // turn the LED off by making the voltage LOW
  Serial.write("Hello");
  delay(300);                      // wait for a second
  
}

** The problem **
I use serial line monitors - Terra Term and a VS Code extension for serial monitoring. Both give the same output - in HEX 00 00 80 80 80 00 80 00 80 80 00 80 80 80 80 80, instead of the expected "Hello".

Is there an issue with the USB-TTL converter? It worked for me when I used it to interface from Terra Term to the RN4871 directly.

Any clues to why this does not work?
Thanks!

Try Serial.println("Hello");

It does the same thing.

I've tried to change the Clock frequency setting in the Arduino IDE when uploading the code and it gives a different outputs now; I think this is a matter of baud rate.

The problem is, right now I set up the Clock frequency as 1 MHz, which gives approximately correct timings on the delay() functions (estimate by eye). I have no clue how to set up the internal clock frequency to generate the right baud rate on the output without using an external crystal.

Which package are you using? Are you certain those pins are correct?

Are you using Minicore or some other board package?

No it does not do the same thing. There is a big difference between Serial write and serial print. They can not possibly do the same thing.

If you think there is no difference then you are not doing something correctly.

What’s your board’s real clock frequency?

In Arduino, this value is defined by the macro

#define F_CPU 16000000UL

for most ATmega328-based boards such as the Uno or Nano, meaning the microcontroller runs at 16 MHz. The Arduino IDE automatically defines F_CPU when you select the board type.

This constant is passed to the core and library code so timing functions (like delay(), micros(), millis()) and hardware drivers can compute accurate time intervals and baud rates.

In particular, the HardwareSerial implementation on the ATmega328 uses F_CPU to calculate the value of the UART baud rate registers (UBRRn). The formula is

UBRRn = (F_CPU / (16 * baud)) - 1

for standard speed (U2Xn = 0). So if F_CPU is 16 MHz and you set Serial.begin(115200), the code computes the proper divisor to generate that baud rate.

If the frequency definition is wrong, serial communication, timing, and PWM output will all be inaccurate.

You must also configure your terminal to the same baud rate (115200 baud here) to match what the UART hardware generates.

Have you set the same Baud rate on the your external monitors?

write() has an overload for char arrays that treat them as c-strings, so write("hello") gives the same output as print("hello").

I would disagree with that, it does not match my experience in any way with the Arduino.

Not with a const char * as parameter…

See print just calls write

Which calls write with the buffer and size

So in that particular case they are the same.

sorry I meant the output of the script is the same or very similar, so it does not solve the problem. I'll try to me more specific next time, thanks.

Yes, and I checked that I matched the default parity and stop bits

Thanks, I thought it would have something to do with the clock frequency. Do you have an idea where I can find this divider?

Also I was under the impression that the default clock frequency for the ATmega328PB is 8 MHz but it uses a divider of 8 so it should be only 1 MHz. I have no idea where to find the actual and true frequency, and how to set it to make the system work.

An interesting update to the problem. The communication now works (i.e. I get the "Hello"), however, it only works if I set both to baud rate of 9600.

I guess it could be an issue of mis-match between the baud rate and a clock divisor or something that mis-times the UART baud rate such that non-sensical characters are sent at higher baud rates.

I have no clue how to set this up with the RN4871 yet as it uses 115200 by default, but I guess I can try to change that one and it will work

If you use minicore you can use the second serial port on the PB as Serial1 at any baudrate

Looking at the datasheet of the 328PB, TXD0 and RXD0 are pins 31 and 30.
And pins 3 and 4 are PE3 and Vcc respectively; PD3 and PD4 would be pins 1 and 2.

Not knowing the details of your board the numbers don't make much sense.

If you have a custom board based on an ATmega328PB with its own clock source, you probably cannot use an existing Arduino board profile directly because the clock frequency determines timing across the entire system. The Arduino IDE relies on the board definition to know the correct CPU frequency when compiling sketches, generating delays, or configuring peripherals.

If your board runs at a frequency different from standard values like 16 MHz or 8 MHz, you need to create a custom board definition so the IDE uses the right settings. This means adding an entry in boards.txt that specifies the correct build.f_cpu value corresponding to your oscillator or crystal. Without that, timing functions, serial communication, and delays will be inaccurate.

Once your custom definition is added to the Arduino hardware folder, your board will appear in the Tools → Board menu, and the IDE will compile and upload code using the proper timing for your hardware clock.

You can't run a 115200bps UART off a 1MHz clock.

See WormFood's AVR Baud Rate Calculator Ver. 2.1.1

You MIGHT get 125000bps - the maximum USART speed at 1MHz, but it's likely to run into CPU performance issues with significant traffic (equivalent to running a normal 16MHz Uno at 2Mbps), and is 8.5% off of 115200. The next lower bit rate is 62500. The maximum "standard" bitrate you can run at 1MHz is 9600...