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.
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.
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.
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
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 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...