Chinese Board Advice (Clock drift)

Post here first, or if you can't find a relevant section!
Post Reply
macarion
Posts: 11
Joined: Mon Nov 28, 2022 4:09 pm

Chinese Board Advice (Clock drift)

Post by macarion »

Hola!, I found the pefect SMT32 STM32G030C8 board for my project, I'm looking to boot from power off as fast as possible and this model boot up into the loop in under 2ms , however I realize that clock accuracy it's way off, I'm talking about 150ms drift every 100 seconds :shock:

I don't know if this may be counterfit chip? or maybe crystal quality? I would like to listen your opinion, would be great if I can just replace the component myself in order to get more accuracy

I understand this can't be a software related thing but anyway I made a ino test where I connect to my oscilloscope, I'm enabling a gpio output every 10 seconds and from oscilloscope I get arround 9988ms everytime, so 12ms off in just 10secs

Code: Select all

unsigned long power_on = 0;
void setup()
{
pinMode(PC13, OUTPUT);
power_on=millis();
digitalWrite(PC13, HIGH); 
delay(2);
digitalWrite(PC13, LOW);
}

void loop()
{
if (millis()-power_on >= 10000){  
power_on=millis();
digitalWrite(PC13, HIGH); 
delay(2);
digitalWrite(PC13, LOW);
}
delay(0);
}
Last edited by macarion on Sun Apr 16, 2023 3:02 am, edited 3 times in total.
dannyf
Posts: 446
Joined: Sat Jul 04, 2020 7:46 pm

Re: Board Advice (Clock drift)

Post by dannyf »

your code is to blame.

try this instead:

Code: Select all

power_on+=10000; //increment the power_on time
macarion
Posts: 11
Joined: Mon Nov 28, 2022 4:09 pm

Re: Board Advice (Clock drift)

Post by macarion »

dannyf wrote: Sat Apr 15, 2023 10:11 pm your code is to blame.

try this instead:

Code: Select all

power_on+=10000; //increment the power_on time
I don't got your point, anyway I tested with exactly same results
I'm not an expert and I understand my code may be not the best but I tested before upload here on an ESP32 and I got 10.000008, only 8us drift

Anyway thanks for the reply
ag123
Posts: 1653
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Chinese Board Advice (Clock drift)

Post by ag123 »

you have a delay(2) in there, it would add 2 ms every true condition in the if block
and

Code: Select all

power_on+=10000;
should be in the loop() part of the code.

either way instructions takes cycles to run and the call to millis() could consume quite a few every time the

Code: Select all

if(millis() - begin >= duration)
clause is checked.

if you want more precise intervals, maybe use a hardware timer
https://github.com/stm32duino/Arduino_C ... er-library

as cortex m0 normally don't have an on chip cache, unlike stm32f4xx, fetching codes from flash possibly takes several wait states e.g. 5.
so if say it runs at 8mhz, 8 / 5 ~ 1.6 mips in a worse case.
macarion
Posts: 11
Joined: Mon Nov 28, 2022 4:09 pm

Re: Chinese Board Advice (Clock drift)

Post by macarion »

ag123 wrote: Sun Apr 16, 2023 6:57 am you have a delay(2) in there, it would add 2 ms every true condition in the if block
and

Code: Select all

power_on+=10000;
should be in the loop() part of the code.

either way instructions takes cycles to run and the call to millis() could consume quite a few every time the

Code: Select all

if(millis() - begin >= duration)
clause is checked.

if you want more precise intervals, maybe use a hardware timer
https://github.com/stm32duino/Arduino_C ... er-library

as cortex m0 normally don't have an on chip cache, unlike stm32f4xx, fetching codes from flash possibly takes several wait states e.g. 5.
so if say it runs at 8mhz, 8 / 5 ~ 1.6 mips in a worse case.
I don't quite get it, I'm waiting 10000ms intervals to set pin to HIGH but and I'm measuring 9988ms intervals with osc so the system clock it's faster than realtime, if the drift problem was because my so inefficient code and the "heavy" instructions that millis() consumes, then I don't understand how the code run faster than it should be..

For that and also because this code it's working in another boards with uS precision, I think it's some chinese hardware thing related
dannyf
Posts: 446
Joined: Sat Jul 04, 2020 7:46 pm

Re: Chinese Board Advice (Clock drift)

Post by dannyf »

so if say it runs at 8mhz, 8 / 5 ~ 1.6 mips in a worse case.
the chip sounds like running on HSI, given the error rate.

for stm32g0, some of them cannot use a crystal and has to be powered by an external oscillator. without knowing what the chip / board is, hard to tell for sure.
ag123
Posts: 1653
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Chinese Board Advice (Clock drift)

Post by ag123 »

I think @dannyf is right about it, I think a default setup for stm32g030 is more likely to be running on HSI.
Getting it to run on HSE would require some work in the SystemClock_Config()
https://github.com/stm32duino/Arduino_C ... figuration

my guess is millis may add a flat number of clock cycles each call, but that that is likely a 'constant' i.e. 'fixed' (sort of)
my guess is it won't add a lot to that 10000 millis()

HSI and HSE (i.e. crystal) can possibly be slightly different from its specified frequencies. My guess is less so for crystals.
(not true for some (cheap) 32k crystals I once bought on AliX, the 32k crystals drift (a lot) more than 5 minutes a month.
for that I wrote some codes to compensate for the drift (but it is on the old libmaple core)
https://github.com/rogerclarkmelbourne/ ... /RTCAdjust

Check if it SystemClock_Config() is defined in your variant, if you are using a generic variant, then it is more than likely just HSI.
Look in other boards as examples and adapt that to a SystemClock_Config() for your board. so that it runs on HSE (the crystal).
Chances are that it is more accurate than running on HSI.

normally, when i used codes such as

Code: Select all

if(millis() - begin >= duration)
, it is for 'timing insensitive' codes, e.g. I ignore the drift or inaccuracy, e.g. blinking a led, I don't need it to be milliseconds accurate.

If you need more precise timing, using a hardware timer would likely help.
dannyf
Posts: 446
Joined: Sat Jul 04, 2020 7:46 pm

Re: Chinese Board Advice (Clock drift)

Post by dannyf »

it is for 'timing insensitive' codes
that works most of the time. one trick is to advance the timing.

Most people do this:

Code: Select all

if(millis() - begin >= duration) {
  begin = millis();
  ...
  }
millis() could have change between the "if" statement and the "begin = ..." statement, accumulating errors along the way.

the right way to do it is:

Code: Select all

if(millis() - begin >= duration) {
  begin += duration;
  ...
  }
it may have jitters from cycle to cycle but it is long term accurate.
ag123
Posts: 1653
Joined: Thu Dec 19, 2019 5:30 am
Answers: 24

Re: Chinese Board Advice (Clock drift)

Post by ag123 »

There is another tactic which I occasionally use for 'timing insensitive' codes.

Code: Select all

void loop() {
  // ... do something
  sleep(10);
}

void sleep(int duration) {
long begin = millis();
while(millis() - begin < duration) 
  asm("wfi");
}
I tend to use this in place of

Code: Select all

delay()
, this would likely be context dependent e.g. works in libmaple and likely stm core.
the idea is to wait for interrupts (i.e. 'sleep'), and it dependence of the convenience that systick interrupt is set to fire every milliseconds.
so that

Code: Select all

asm("wfi")
wakes up roughly every millis(), possibly faster if there are other interrupts.
the chip tends to run cooler / lower power consumption with that

Code: Select all

asm("wfi")
macarion
Posts: 11
Joined: Mon Nov 28, 2022 4:09 pm

Re: Chinese Board Advice (Clock drift)

Post by macarion »

Thansk both to still help me out with this thing

I made another test, I created a 10000ms interval pulse from external generator, and I'm printing millis()/micros() interrupt from the stm32g030 and a esp32, esp32 prints 10000.0xx ms (few uS off) and stm32g030 prints 1003x ms (+30ms drift) , so again stm32 clocks run faster than realtime

@ag123 I follow your instructions with STM32CubeMX and I activated the HSE clock, replacing the systemclock stuff and works !! :mrgreen:
With the same code, now I'm getting a constant ~9999.800ms, still 200uS off/fast, but I can deal with that :) , I made some other test and there a drift of about 1ms/minute (-3 secs day, ~40ppm Equivalent) , By other hand, the startup time has increased from 1.7ms to 2.9ms, I guess it's the extra time the external osc need to stabilize

Thanks mate!!
Post Reply

Return to “General discussion”