Clock speed for Nano Every

The specifications for the Nano Every state that it has a 20MHz clock frequency, but the boards.txt file shows it as 16 MHz.

Running the Blink sketch with a 30 second ON / 30 second OFF delay operates properly with the 16MHz setting in the boards.txt file, and is appropriately longer when changing to 20MHz, so it appears the clock is running at 16MHz.

There is no obvious crystal on the PC board, and the schematic in not yet available, so hard to verify.

Relevant section from the boards.txt file:

nona4809.name=Arduino Nano Every

nona4809.vid.0=0x2341
nona4809.pid.0=0x0058

nona4809.upload.tool=avrdude
nona4809.upload.protocol=jtag2updi
nona4809.upload.maximum_size=49152
nona4809.upload.maximum_data_size=6144
nona4809.upload.speed=115200
nona4809.upload.use_1200bps_touch=true
nona4809.upload.extra_params=-P{serial.port}

nona4809.build.mcu=atmega4809
nona4809.build.f_cpu=16000000L    //***************** f_cpu of 16,000,000 Hz *******************************
nona4809.build.board=AVR_NANO_EVERY
nona4809.build.core=arduino
nona4809.build.variant=nona4809
nona4809.build.text_section_start=.text=0x0
nona4809.build.extra_flags={build.328emulation} -DMILLIS_USE_TIMERB3 -DNO_EXTERNAL_I2C_PULLUP
#nona4809.build.extra_flags=-B{runtime.tools.atpack.path}/gcc/dev/{build.mcu}

nona4809.bootloader.tool=avrdude
nona4809.bootloader.file=atmega4809_uart_bl.hex
nona4809.bootloader.SYSCFG0=0xC9
nona4809.bootloader.BOOTEND=0x00
nona4809.bootloader.OSCCFG=0x01
nona4809.fuses.file=fuses_4809.bin

menu.mode=Registers emulation
nona4809.menu.mode.on=ATMEGA328
nona4809.menu.mode.on.build.328emulation=-DAVR_NANO_4809_328MODE
nona4809.menu.mode.off=None (ATMEGA4809)
nona4809.menu.mode.off.build.328emulation=

The Nano Every uses the internal PLL as a clock, rather than an external crystal. The maximum speed is 20 MHz, but, as you discovered, the board definition was configured by Arduino to run at 16 MHz.

I was told that you can change it to run at 20 MHz by simply changing:

nona4809.build.f_cpu=16000000L

to:

nona4809.build.f_cpu=20000000L

That seemed strange to me because the megaAVR 0-series datasheet says of the OSCCFG fuse in section 5.8.2.3:

Bits 1:0 – FREQSEL[1:0] Frequency Select
These bits select the operation frequency of the internal RC Oscillator (OSC20M) and determine the
respective factory calibration values to be written to CAL20M in CLKCTRL.OSC20MCALIBA and
TEMPCAL20M in CLKCTRL.OSC20MCALIBB.
Value Description
0x0 Reserved
0x1 Run at 16 MHz
0x2 Run at 20 MHz
0x3 Reserved

You can see that the OSCCFG fuse is set to 0x01 right there in boards.txt:

nona4809.bootloader.OSCCFG=0x01

maybe there is some mechanism in the core code for adjusting it purely based on the value of F_CPU, but I haven't seen anything like that. My suspicion is that you also need to change that line to:

nona4809.bootloader.OSCCFG=0x02

to make it run at 20 MHz. After that, it appears you can just do a standard upload to set the fuses, rather than having to do a Burn Bootloader as we must on the standard AVR boards.

I haven't gotten a Nano Every yet so I haven't been able to try it out myself. Let me know how it works for you.

That does appear to work correctly for changing the clock to 20MHz, apparently they left the settings the same as for the Uno Wifi Rev 2 board which is in the same boards.txt file.

I'll have to find the documentation for the fuse settings, being able to change the clock frequency while programming could be a convenient feature.

I'm glad to hear it works. That doesn't take much effort for a 25% speed increase!

For anyone else trying this, I should note that you need to restart the Arduino IDE after making changes to boards.txt before they will take effect. Also note that you'll need to redo this change every time you install a new version of Arduino megaAVR Boards.

I was told the 16 MHz board definition for the Nano Every was an intentional choice for consistency with the classic Nano.

The "megaAVR 0-series Family Data Sheet" is on the Documents tab of this page:

pert:
I was told the 16 MHz board definition for the Nano Every was an intentional choice for consistency with the classic Nano.

That would be fine except that the webpage in the Store shows the clock frequency as 20MHz, which is what led to the confusion while I was trying to modify the Adafruit_NeoPixel library to work with a 20MHz clock.

Yes, I agree this statement on the product page is misleading. It caused a similar confusion in another forum thread where someone was working to unnecessarily modify the Adafruit TFTLCD library for 20 MHz to port it to the Nano Every. That's why I asked the Arduino developer in charge of Arduino megaAVR Boards to clarify whether the 16 MHz board definition for the Nano Every was an error, or whether the product page information should be updated to be more clear.

I reported the issue on the product page here:

Hopefully it will be updated soon.

Playing around with boards.txt a bit, it is convenient to add a clock speed option to the menu in the IDE.

Not very experienced with modifying boards.txt, but using ATTinyCore as an example the following appears to work when added to the end of the section for the Nano Every:

menu.clock=Clock
nona4809.menu.clock.16internal=16MHz
nona4809.menu.clock.16internal.build.f_cpu=16000000L
nona4809.menu.clock.16internal.bootloader.OSCCFG=0x01
nona4809.menu.clock.20internal=20MHz
nona4809.menu.clock.20internal.build.f_cpu=20000000L
nona4809.menu.clock.20internal.bootloader.OSCCFG=0x02

Yeah, that's nice if you are going to want to switch clock speeds occasionally.

I think eventually what will happen is MCUdude will get their 3rd party hardware package for the megaAVR 0-series in a functional state with support for the Nano Every and anyone who wants to run their Nano Every will be able to just install that package via Boards Manager and not need to mess with editing Arduino megaAVR Boards:

Hi all.
Added the 20 MHZ code options to the boards.txt as per above comments. Everything works, compiles OK and sketches upload BUT, again, incompatibility with the servo library, even when using a different timer. I suspect the PWM frequency being off by the clock change?

What exactly do you mean by "incompatibility with the servo library"?

Hi, please refer to this post for the servo.h incompatibility
https://forum.arduino.cc/index.php?topic=628126.0

Have not tested any servos with the Nano Every, but I didn't think the Servo library cared about the PWM frequency, the timer is used to tell it when the next servo output needs to be changed, not to drive the actual servo output as a PWM signal.

GianNos:
Hi all.
Added the 20 MHZ code options to the boards.txt as per above comments. Everything works, compiles OK and sketches upload BUT, again, incompatibility with the servo library, even when using a different timer. I suspect the PWM frequency being off by the clock change?

What exactly are you having a problem with? Other than a warning message from the servo library, which I get regardless of whether the tone library is being used, I don't seem to have a problem driving a servo and using tone at the same time, once the default timer for the Servo library has been changed.

The compiler warning from Servo is as follows:

In file included from /home/pi/Arduino/libraries/Servo/src/Servo.h:73:0,
                 from /tmp/arduino_modified_sketch_20226/Sweep.ino:10:
/home/pi/Arduino/libraries/Servo/src/megaavr/ServoTimers.h:36:24: warning: '_timer' defined but not used [-Wunused-variable]
 static volatile TCB_t* _timer =
                        ^~~~~~

GianNos:
Hi, please refer to this post for the servo.h incompatibility
Arduino NANO EVERY and Servo and Tone issues - Nano Every - Arduino Forum

In that thread, the compilation error you were having was clearly explained to you and you reported you had fixed the problem. None of that had anything to do with the clock speed. So I'll ask again: What exactly do you mean by "incompatibility with the servo library"?

pert:
In that thread, the compilation error you were having was clearly explained to you and you reported you had fixed the problem. None of that had anything to do with the clock speed. So I'll ask again: What exactly do you mean by "incompatibility with the servo library"?

You are too quick in your attempt to school someone.

Rather than just posting and complaining you should try to check if the poster has a valid point by trying to replicate an issue, e.g. run a simple sketch to move a servo.

Had you have done so you would have discovered that when using the servo library with a 20 MHz clock rather than with a 16 MHz clock results in different positions for the same commands. For example a simple myservo.writeMicroseconds(1000); will not move the servo to your desired point. Fwiw the correct command for the 20 MHz clock would be very close to myservo.writeMicroseconds(1400); now.

I could explain why, or post the math for finding the correct shift but your tone makes me not want to make the effort.

1 Like

Ok, now that you have told us what the specific problem is, I can confirm that you are correct, and the different clock frequencies do give different positions for the servo, using both the servo.write and servo.writeMicroseconds commands.

Has nothing to do with the tone command, a sketch with only the servo commands will exhibit the behavior.

GianNos:
Rather than just posting and complaining you should try to check if the poster has a valid point by trying to replicate an issue, e.g. run a simple sketch to move a servo.

That would require that I own a Nano Every, which I don't.

It would also require me to spend time wiring up a servo. Why should I do all that when you're the one asking for help and you already know full well what the problem is? It's not too much to ask for the people asking for help to provide a description of their problem.

I'm not trying to "school" you (whatever that means). I was trying to help you.

It is a bug in the servo library. In the file Servo/src/megaavr/Servo.cpp, the calculation on line #6 is getting rounded off because of the integer math.

#define usToTicks(_us)    ((clockCyclesPerMicrosecond() / 16 * _us) / 4)                 // converts microseconds to tick

clockCyclesPerMicrosecond is 16 at 16MHz, 20 at 20MHz, but apparently the division by 16 is being rounded before the multiplication with _us, making the result the same regardless of the clock frequency.

Rearranging the equation fixes the problem, although you need to use a long instead of an integer because one of the calculations has _us = 20000.

#define usToTicks(_us)    (((int32_t)clockCyclesPerMicrosecond() * _us / 16) / 4 )                 // converts microseconds to tick

GianNos:
You are too quick in your attempt to school someone.

Rather than just posting and complaining you should try to check if the poster has a valid point by trying to replicate an issue, e.g. run a simple sketch to move a servo.

Had you have done so you would have discovered that when using the servo library with a 20 MHz clock rather than with a 16 MHz clock results in different positions for the same commands. For example a simple myservo.writeMicroseconds(1000); will not move the servo to your desired point. Fwiw the correct command for the 20 MHz clock would be very close to myservo.writeMicroseconds(1400); now.

I could explain why, or post the math for finding the correct shift but your tone makes me not want to make the effort.

The problem you are having is very obscure. You implied it had something to do with using Servo and tone together, which it does not, servo alone will produce the problem. It also requires that someone modify the boards.txt file to change the clock frequency, and then switch back and forth between the clock frequencies to make the problem obvious. There are very few people who actually have a Nano Every, and even fewer who have modified the boards.txt file to alter the frequency, and the code to easily switch between frequencies is something I came up with, so even fewer are using that.

This discussion goes away from the basic problem: The timing with 20 MHz seems not OK!!
I use a simple sketch to measure the micros() and the millis() timing. The behaviour is not OK.
I use the Saleae Logic Analyser for measurement of millis():
- With 50 ms it measures 63.45 ms
- with 100 ms it measures 125.9 ms
- ... and so on - always with a factor near 1.25x
Back calculation (20MHz/1.25x) gives 15,xx MHz.
I have changed the 2 lines in the "boards.txt" file and the compiler shows "-DF_CPU=20000000L" as expected. So I think it's not my mistake!

//========================================================
// Small sketch to check precision of micros()
//========================================================

long lTimer;  // Save the millis() for compare
bool bState;  // State of the Port (D2)

void setup() {

  pinMode(2,OUTPUT);  // This pin is used for Logic Analyser
  lTimer = millis();  // Initialise the time
}

void loop() {

  long lAct = millis();     // Collect the actual time
  if (lAct-lTimer > 200)    // If a limit is reached...
  {
    lTimer = lAct;          // Save the actual time for compare
    PinStatus state = bState ? HIGH : LOW;  // Hack for Every
    digitalWrite(2,state);  // Set the output to a new state
    bState = !bState;       //  ... and change it for next cycle
  }
}