紅外線遙控器控制LED-micropython

 紅外線遙控接收-micropython

紅外接收器模塊使用 VS1838 光電二極管紅外接收器。它成本低且易於使用。

引腳:
它有 3 個引腳,即:
1. G - 接地引腳。
2. V - 電源電壓。
3. S——為紅外接收信號引腳。

上傳micropython_ir Library of Peter Hinch函式庫:
# MIT License
# Copyright (c) 2020 Peter Hinch
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# Author: Peter Hinch
# Copyright Peter Hinch 2020-2021 Released under the MIT license
# http://github.com/peterhinch/micropython_ir

from machine import Pin
from machine import Timer
from array import array
from utime import ticks_us
from utime import ticks_diff

# Save RAM
# from micropython import alloc_emergency_exception_buf
# alloc_emergency_exception_buf(100)


# On 1st edge start a block timer. While the timer is running, record the time
# of each edge. When the timer times out decode the data. Duration must exceed
# the worst case block transmission time, but be less than the interval between
# a block start and a repeat code start (~108ms depending on protocol)

class IR_RX():
    # Result/error codes
    # Repeat button code
    REPEAT = -1
    # Error codes
    BADSTART = -2
    BADBLOCK = -3
    BADREP = -4
    OVERRUN = -5
    BADDATA = -6
    BADADDR = -7

    def __init__(selfpinnedgestblockcallback, *args):  # Optional args for callback
        self._pin = pin
        self._nedges = nedges
        self._tblock = tblock
        self.callback = callback
        self.args = args
        self._errf = lambda _ : None
        self.verbose = False

        self._times = array('i',  (0 for _ in range(nedges + 1)))  # +1 for overrun
        pin.irq(handler = self._cb_pintrigger = (Pin.IRQ_FALLING | Pin.IRQ_RISING))
        self.edge = 0
        self.tim = Timer(-1)  # Sofware timer
        self.cb = self.decode

    # Pin interrupt. Save time of each edge for later decode.
    def _cb_pin(selfline):
        t = ticks_us()
        # On overrun ignore pulses until software timer times out
        if self.edge <= self._nedges:  # Allow 1 extra pulse to record overrun
            if not self.edge:  # First edge received
                self.tim.init(period=self._tblock , mode=Timer.ONE_SHOTcallback=self.cb)
            self._times[self.edge] = t
            self.edge += 1

    def do_callback(selfcmdaddrextthresh=0):
        self.edge = 0
        if cmd >= thresh:
            self.callback(cmdaddrext, *self.args)
        else:
            self._errf(cmd)

    def error_function(selffunc):
        self._errf = func

    def close(self):
        self._pin.irq(handler = None)
        self.tim.deinit()


class NEC_ABC(IR_RX):
    def __init__(selfpinextendedcallback, *args):
        # Block lasts <= 80ms (extended mode) and has 68 edges
        super().__init__(pin6880callback, *args)
        self._extended = extended
        self._addr = 0

    def decode(self_):
        try:
            if self.edge > 68:
                raise RuntimeError(self.OVERRUN)
            width = ticks_diff(self._times[1], self._times[0])
            if width < 4000:  # 9ms leading mark for all valid data
                raise RuntimeError(self.BADSTART)
            width = ticks_diff(self._times[2], self._times[1])
            if width > 3000:  # 4.5ms space for normal data
                if self.edge < 68:  # Haven't received the correct number of edges
                    raise RuntimeError(self.BADBLOCK)
                # Time spaces only (marks are always 562.5µs)
                # Space is 1.6875ms (1) or 562.5µs (0)
                # Skip last bit which is always 1
                val = 0
                for edge in range(368 - 22):
                    val >>= 1
                    if ticks_diff(self._times[edge + 1], self._times[edge]) > 1120:
                        val |= 0x80000000
            elif width > 1700# 2.5ms space for a repeat code. Should have exactly 4 edges.
                raise RuntimeError(self.REPEAT if self.edge == 4 else self.BADREP)  # Treat REPEAT as error.
            else:
                raise RuntimeError(self.BADSTART)
            addr = val & 0xff  # 8 bit addr
            cmd = (val >> 16) & 0xff
            if cmd != (val >> 24) ^ 0xff:
                raise RuntimeError(self.BADDATA)
            if addr != ((val >> 8) ^ 0xff) & 0xff:  # 8 bit addr doesn't match check
                if not self._extended:
                    raise RuntimeError(self.BADADDR)
                addr |= val & 0xff00  # pass assumed 16 bit address to callback
            self._addr = addr
        except RuntimeError as e:
            cmd = e.args[0]
            addr = self._addr if cmd == self.REPEAT else 0  # REPEAT uses last address
        # Set up for new data burst and run user callback
        self.do_callback(cmdaddr0self.REPEAT)

class NEC_8(NEC_ABC):
    def __init__(selfpincallback, *args):
        super().__init__(pinFalsecallback, *args)

class NEC_16(NEC_ABC):
    def __init__(selfpincallback, *args):
        super().__init__(pinTruecallback, *args)

範例1

套用以下範例並記下遙控器按鍵的data

from ir_rx import NEC_16
from machine import Timer
from machine import Pin

def callBack(dataaddrctrl):
    if data > 0:
        print("data: {:02x} addr: {:04x}".format(dataaddr))
ir = NEC_16(Pin(26Pin.IN), callBack)


範例2:

有了對應鍵的16進制,並存放在dist裡,就可以把它套用在callBack()去作比對
from ir_rx import NEC_16
from machine import Timer
from machine import Pin

def callBack(dataaddrctrl):
    if data > 0:
        # print("data: {:02x} addr: {:04x}".format(data, addr))
        print(ir_key[data])
ir = NEC_16(Pin(26Pin.IN), callBack)

ir_key = {
    0x16 : '0',
    0x0c : '1',
    0x18 : '2',
    0x5e : '3',
    0x08 : '4',
    0x1c : '5',
    0x5a : '6',
    0x42 : '7',
    0x52 : '8',
    0x4a : '9',
    0x15 : 'ok',
    0x40 : 'up',
    0x19 : 'down',
    0x07 : 'left',
    0x09 : 'right',
    0x44 : 'power',
}


範例3:

現在有了精確的數字,可以運用在控制某些例如燈具...等等的物品這裡使用一個簡單的例子,當按下"1"的鍵時,打開esp32的內鍵燈,當按下"2"時,關閉內鍵燈。
from ir_rx import NEC_16
from machine import Timer
from machine import Pin

led = Pin(2Pin.OUT)
def callBack(dataaddrctrl):
    global _data, _addr
    _data = ir_key[data]
    _addr = addr
    if data > 0:
        # print("data: {:02x} addr: {:04x}".format(data, addr))
        print(_data)
ir = NEC_16(Pin(26Pin.IN), callBack)

ir_key = {
    0x16 : '0',
    0x0c : '1',
    0x18 : '2',
    0x5e : '3',
    0x08 : '4',
    0x1c : '5',
    0x5a : '6',
    0x42 : '7',
    0x52 : '8',
    0x4a : '9',
    0x15 : 'ok',
    0x40 : 'up',
    0x19 : 'down',
    0x07 : 'left',
    0x09 : 'right',
    0x44 : 'power',
}
_data = 0
if _data == "1":
    led.on()
elif _data == "2":
    led.off()







留言

這個網誌中的熱門文章

使用PWM控制伺服馬達-micropython

DHT11+OLED+IFTTT+LINE-notity-micropython

BMP280氣壓,溫度模組-micropython