Ein Kollege fragte mich: „Kann man eigentlich auch den Raspberry Pi Pico übertakten?“. Ich konnte nur ihm nur versprechen, das herauszufinden.
Grundlagen
Die Grundlagen zur Übertaktung sind von den des Raspberry Pi 4B nicht sonderlich verschieden. Die zwei Kerne ARM Cortex M0+ des RP2040 Microcontroller sind ab Werk mit 125MHz getaktet.
Material
Ich benutze in diesem Post folgendes Material:
- Raspberry Pi Pico
- Datenkabel USB-A auf µUSB
- Kühlkörper zum Aufkleben
Mein größtes Problem war zunächst, ein µ-USB Datenkabel zu finden. Die meisten Kabel in meinem Bestand dienten mal zum Laden irgendwelcher Handys.
Der Pico wird mit MicroPython geflasht.
Warnung: Ein höherer Takt kann den Pico unter Umständen beschädigen! Die Raspberry Pi Foundation stellt sich in so einem Fall von der Garantie aus.
Pico übertakten
Im Gegensatz zum Raspi 4A gibt es beim Pico keine config.txt, in der wir die Taktfrequenz konfigurieren können. Daher ist jedes Programm selber verantwortlich, die Frequenz zu setzen.
Die Methode freq()
, die wir dafür benötigen, liegt im machine
Package. Ohne Parameter liefert diese Methode den aktuell eingestellten Takt in Hz zurück. Wir können ihr aber auch die gewünschte Frequenz (ebenfalls in Hz) übergeben.
Was wir jetzt brauchen ist eine Berechnung, die die CPU richtig unter Last setzt. Dazu eignet sich die Berechnung von Primzahlen mit dem Sieb des Eratosthenes. Der Algorithmus ist nicht unbedingt optimal, aber darum geht es hier nicht.
#Berechnung von Primzahlen mit dem Sieb des Eratosthenes.
def sieb_des_eratosthenes(limit):
# Erzeuge eine Liste, die angibt, ob eine Zahl eine Primzahl ist
is_prime = [True] * (limit + 1)
p = 2
while (p * p <= limit):
# Wenn is_prime[p] nicht verändert wurde, ist p eine Primzahl
if is_prime[p]:
# Alle Vielfachen von p können keine Primzahl sein.
for i in range(p * p, limit + 1, p):
is_prime[i] = False
p += 1
# Sammle alle Primzahlen in einer Liste.
prime_numbers = [p for p in range(2, limit + 1) if is_prime[p]]
return prime_numbers
Diese Methode wird von einer Methode gekapselt, die die Laufzeit auswertet.
# Methode zur Laufzeitbestimmung
def berechnung(limit):
ergebnis = {}
start_time = time.ticks_ms()
prime_numbers = sieb_des_eratosthenes(limit)
ergebnis['primzahlen'] = prime_numbers
end_time = time.ticks_ms()
running_time =time.ticks_diff(end_time,start_time)
ergebnis['laufzeit'] = running_time
return ergebnis
Die Methode liefert ein Dictionary mit zwei Einträgen zurück. In 'primzahlen'
befindet sich die Liste der berechneten Primzahlen, in 'laufzeit'
ist die Laufzeit der Berechnung in ms abgelegt.
Das Hauptprogramm führt die Berechnung zweimal durch, zunächst mit dem Standardtakt von 125MHz, danach mit 270MHz. Vor der Taktumschaltung blinkt die LED auf dem Pico kurz auf, um die Umschaltung zu signalisieren.
# sieve_oc.py
import time
import machine
from machine import Pin
led = Pin(25, Pin.OUT)
#Berechnung von Primzahlen mit dem Sieb des Eratosthenes.
def sieb_des_eratosthenes(limit):
# Erzeuge eine Liste, die angibt, ob eine Zahl eine Primzahl ist
is_prime = [True] * (limit + 1)
p = 2
while (p * p <= limit):
# Wenn is_prime[p] nicht verändert wurde, ist p eine Primzahl
if is_prime[p]:
# Alle Vielfachen von p können keine Primzahl sein.
for i in range(p * p, limit + 1, p):
is_prime[i] = False
p += 1
# Sammle alle Primzahlen in einer Liste.
prime_numbers = [p for p in range(2, limit + 1) if is_prime[p]]
return prime_numbers
# Methode zur Laufzeitbestimmung
def berechnung(limit):
ergebnis = {}
start_time = time.ticks_ms()
prime_numbers = sieb_des_eratosthenes(limit)
ergebnis['primzahlen'] = prime_numbers
end_time = time.ticks_ms()
running_time =time.ticks_diff(end_time,start_time)
ergebnis['laufzeit'] = running_time
return ergebnis
# Liefert den Clock-Speed in MHz
def get_speed():
return str(round(machine.freq()/1000000,1))
# Beispielverwendung: Finde alle Primzahlen bis 1000
print(f'Durchgang #1 mit {get_speed()}MHz')
limit = 10000
ergebnis1 = berechnung(limit)
laufzeit1 = ergebnis1['laufzeit']
print(f'Laufzeit: {laufzeit1}ms')
#Übertaktung auf 270MHz
led.on()
machine.freq(270000000)
print(f'Durchgang #2 mit {get_speed()}MHz')
ergebnis2 = berechnung(limit)
Stromverbrauch
Ein höherer Takt zieht immer auch eine höhere Stromaufnahme mit sich.
Ohne Übertaktung zeigt mir das zwischen Pico und Powerbank geschaltete Messgerät eine Spannung von 5,02V bei 0,03A Stromaufnahme an. Mit Übertaktung steigt die Spannung auf 5,1V bei 0,02A Stromverbrauch. Allerdings schwankt der Stromverbrauch gelegentlich, da der Pico nicht immer 100% Last hat.
In einer Situation, in der der Pico mit einem Akku betrieben wird, könnte das ins Gewicht fallen.
Fazit
In einer Situation, in der du auf eine höhere Rechenleistung des Pico angewiesen bist, kannst du programmatisch denTakt der beiden Kerne erhöhen.Ich würde dies aber immer nur situativ machen und danach wieder auf den Standardtakt zurückschalten.
MicroPython lässt einen höheren Takt als 275Mhz nicht zu. Die Methode machine_freq()
kommt bei höheren Werten nicht zurück. Vermutlich, um den Pico vor Beschädigung zu schützen.
Overclocking Spezialisten, die lange nach einem geeigneten Pico mit dem perfekten SoC suchen haben den Pico sogar auf 3GHz getaktet. Ich bezweifle aber, dass dann die I/O Kanäle noch richtig funktionieren.
Ich will hier keinen neuen Rekord aufstellen, sondern dir nur zeigen, wie es geht.