-
Notifications
You must be signed in to change notification settings - Fork 1
/
tachometer.py
91 lines (77 loc) · 2.99 KB
/
tachometer.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
"""
Micropython program to determin the RPM of a motor (with blades). It utilizes
an IR LED and a Phototransistor facing each other to sense any interruption
(like a blade) passing in between. Each falling edge in the ADC pin
fires an interrupt. This can be used to calculate the RPM of the fan.
Author: Govindarajan
"""
import pyb
import time
import micropython
class Tachometer():
"""
Tachometer class
"""
def __init__(self, pin_num=None, interval=2, num_blades=5, max_duration=300):
"""
Set up pin and ADC instances.
Initialize IRQ counter that counts the number of IRQs received, which
in turn denotes the number of times fan blade passes across the
phototransistor
:param pin_num: Pin number on the board where phototransistor output is
is connected to. Default is None
:param interval: Number of seconds to count interrupts for. Default = 2
:param num_blades: Number of blades on the motor. Default = 5
:return: None
"""
self. pin = pyb.Pin(pin_num)
self.adc = pyb.ADC(self.pin)
self.irq_count = 0
self.sample_period = interval
self.blades = num_blades
self.num_seconds = 0
self.max_duration = max_duration
header = "Seconds, RPM"
print(header)
def measure(self, line):
"""
Increment irq counter every time an interrupt is raised
:param line: Default parameter (interrupt line attached) passed by
ExtInt()
:return: None
"""
self.irq_count += 1
def main(self):
"""
Main function where interrupt handler is initialized and a callback
function passed
:param: None
:return: None
"""
# Allocate exception buffer since heap cannot be allocated within an ISR context
micropython.alloc_emergency_exception_buf(100)
# Set up interrupt handler
ext_int = pyb.ExtInt(self.pin, pyb.ExtInt.IRQ_FALLING,
pyb.Pin.PULL_NONE, self.measure)
while self.num_seconds < (self.max_duration // self.sample_period):
# Sleep for specified interval to count number of interrupts received
time.sleep(self.sample_period)
# Disable IRQs and process result
pyb.disable_irq()
rpm = self.irq_count * 60 / (2 * self.blades)
output_str = str(self.num_seconds) + "," + "{0:.2f}".format(rpm)
# Print the result to serial console
print(output_str)
# Reset IRQ counter for the next interval
self.irq_count = 0
self.num_seconds += self.sample_period
# Enable IRQs
pyb.enable_irq()
# Sleep for a few seconds to let the fan speed settle
time.sleep(15)
pyb.LED(4).toggle()
time.sleep(1)
pyb.LED(4).toggle()
time.sleep(1)
tc = Tachometer(pin_num='X12', max_duration=300)
tc.main()