View difference between Paste ID: DpwpxEfw and D9ABmmwD
SHOW: | | - or go back to the newest paste.
1
"""
2
Inspiriert von
3
BitBastelei #398 - Die "Magie" hinter PWM (analogWrite, Timer, Preload, etc)
4
https://www.youtube.com/watch?v=nf8MB7FkRaI
5
6
"""
7
8
9
import math
10
from collections import namedtuple
11
12
13
class Frequency:
14
    def __init__(self, value):
15
        self.value = value
16
        
17
    def __float__(self):
18
        return float(self.value)
19
    
20
    def __index__(self):
21
        return int(self.value)
22
        
23
    def __str__(self):
24
        units = ("Hz", "kHz", "MHz")
25
        value = self.value
26
        for unit in units:
27
            if value < 1000:
28
                break
29
            value /= 1000
30
        return f"{value:.3f} {unit}"
31
32
    def __repr__(self):
33
        return f"{self.__class__.__name__}({self.value})"
34
35
36
def pwm_calc(freq, bits=8, board_freq=16_000_000):    
37
    result = namedtuple(
38
        "Configuration",
39
        "board_freq scaled_freq prescaler count_bits count_start target_freq",
40
    )    
41
    increments = 2 ** bits
42
    counter_max = increments - 1
43
    
44
    for prescaler in (2 ** n for n in range(11)):
45
        if (current_freq := board_freq / prescaler / increments) < freq:
46
            break
47
    
48
    # math.ceil aufrunden, math.floor abrunden
49
    offset = round(counter_max * current_freq / freq)
50
    resulting_freq = current_freq / offset * counter_max
51
    return result(
52
        Frequency(board_freq),
53
        Frequency(current_freq),
54
        prescaler,
55
        bits,
56
        counter_max - offset,
57
        Frequency(resulting_freq),
58
    )
59
 
60
61
result = pwm_calc(420)
62
print("Prescaler:", result.prescaler)
63
print("Frequency:", result.target_freq)
64
print("Counter-Start:", result.count_start)
65
66
# Prescaler: 256
67
# Frequency: 420.648 Hz
68
# Counter-Start: 107
69