-
Notifications
You must be signed in to change notification settings - Fork 3
/
pico_timer.py
102 lines (87 loc) · 3.39 KB
/
pico_timer.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# Pico MicroPython: reciprocal (time-interval) frequency measurement
# See https://iosoft.blog/picofreq_python for description
#
# Copyright (c) 2021 Jeremy P Bentham
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# v0.01 JPB 20/8/23 Adapted from pico_freq.py
# v0.02 JPB 21/8/23 Removed unneeded gate definitions
# v0.03 JPB 15/10/24 Adapted to work with RP2040 and RP2350
import time, pico_devices as devs
PWM_OUT_PIN, PWM_IN_PIN = 4, 3
# Output signal for testing
# Divisor value must be < 256, and wrap value < 65536
if devs.PICO2:
PWM_DIV = int(devs.CLOCK_FREQ/600e3) # 600 kHz
PWM_WRAP = 60000 - 1 # 600 kHz / 60000 = 10 Hz
else:
PWM_DIV = int(devs.CLOCK_FREQ/500e3) # 500 kHz
PWM_WRAP = 50000 - 1 # 500 kHz / 50000 = 10 Hz
PWM_LEVEL = (PWM_WRAP+1)//2 # 50% PWM
NTIMES = 9 # Number of time samples
time_data = devs.array32(NTIMES) # Time data
# Start a PWM output
def pwm_out(pin, div, level, wrap):
devs.gpio_set_function(pin, devs.GPIO_FUNC_PWM)
pwm = devs.PWM(pin)
pwm.set_clkdiv_int_frac(div, 0)
pwm.set_wrap(wrap)
pwm.set_chan_level(pwm.gpio_to_channel(pin), level)
pwm.set_enabled(1)
return pwm
# Initialise PWM as a timer (gpio must be odd number)
def timer_init(pin, rising=True):
if pin & 1 == 0:
print("Error: pulse counter must be on add GPIO pin")
devs.gpio_set_function(pin, devs.GPIO_FUNC_PWM)
pwm = devs.PWM(pin)
pwm.set_clkdiv_mode(devs.PWM_DIV_B_RISING if rising else devs.PWM_DIV_B_FALLING)
pwm.set_clkdiv(1)
pwm.set_wrap(0);
return pwm
# Initialise timer DMA
def timer_dma_init(timer):
dma = devs.DMA()
dma.set_transfer_data_size(devs.DMA_SIZE_32)
dma.set_read_increment(False)
dma.set_write_increment(True)
dma.set_dreq(timer.get_dreq())
dma.set_read_addr(devs.TIMER_RAWL_ADDR)
return dma
# Start frequency measurment using interval times
def timer_start(timer, dma):
timer.set_ctr(0)
timer.set_enabled(True)
dma.abort()
dma.set_write_addr(devs.addressof(time_data))
dma.set_trans_count(NTIMES, True)
# Stop frequency measurment using interval times
def timer_stop(timer):
timer.set_enabled(False)
if __name__ == "__main__":
print("PWM output pin %u, freq input pin %u" % (PWM_OUT_PIN, PWM_IN_PIN))
print("Getting transition times on pin %u for 1 second" % PWM_IN_PIN)
test_signal = pwm_out(PWM_OUT_PIN, PWM_DIV, PWM_LEVEL, PWM_WRAP)
timer_pwm = timer_init(PWM_IN_PIN)
timer_dma = timer_dma_init(timer_pwm)
timer_start(timer_pwm, timer_dma)
time.sleep(1.0)
timer_stop(timer_pwm)
count = NTIMES - timer_dma.get_trans_count()
data = time_data[0:count]
diffs = [data[n]-data[n-1] for n in range(1, len(data))]
total = sum(diffs)
freq = (1e6 * len(diffs) / total) if total else 0
print("%u samples, total %u us, freq %5.3f Hz" % (count, total, freq))
# EOF