Go Down

Topic: Clock speed for Nano Every  (Read 5666 times) previous topic - next topic

david_2018

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.




pert

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.

david_2018

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.

Code: [Select]

#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.
Code: [Select]

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



david_2018

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.

RudolfAtRTC

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!

Code: [Select]
//========================================================
// 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
  }
}

RudolfAtRTC

To top the compleity of this thread, I get a warning - and I give up!.

david_2018

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!
Can you confirm that fuse2 is being written with 0x02 instead of 0x01?  Set the IDE to verbose output during upload and it will show the fuses being written - File > Preferences > Show verbose output during - put a check mark in the box beside "upload".
 
I modified your code to blink the built-in LED in addition to pin 2, and set the time interval to 60 seconds, and I don't see any significant timing difference between 16MHz and 20MHz, a 25% error would certainly be obvious.  I tested for both millis() and micros() with the same results.

RudolfAtRTC

Thank you - I am amazed and happy! This morning
 - with the same sketch
 - and the same analyser
after I upload it with "Show verbose output during upload" it works!
Yesterday I did a couple of uploads with varied timings, always with that bad result.
Yes - now the fuse 2 is set to 0x02.
Result: this forum is very helpful.

Go Up