紅外線遙控器控制LED-micropython


紅外線遙控接收-micropython

tags: esp32 vs1838 micropython 紅外線遙控

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

引腳:
它有 3 個引腳,即:
G - 接地引腳。
V - 電源電壓。
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__(self, pin, nedges, tblock, callback, *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_pin, trigger = (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(self, line):

        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_SHOT, callback=self.cb)

            self._times[self.edge] = t

            self.edge += 1

  

    def do_callback(self, cmd, addr, ext, thresh=0):

        self.edge = 0

        if cmd >= thresh:

            self.callback(cmd, addr, ext, *self.args)

        else:

            self._errf(cmd)

  

    def error_function(self, func):

        self._errf = func

  

    def close(self):

        self._pin.irq(handler = None)

        self.tim.deinit()

  
  

class NEC_ABC(IR_RX):

    def __init__(self, pin, extended, callback, *args):

        # Block lasts <= 80ms (extended mode) and has 68 edges

        super().__init__(pin, 68, 80, callback, *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(3, 68 - 2, 2):

                    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(cmd, addr, 0, self.REPEAT)

  

class NEC_8(NEC_ABC):

    def __init__(self, pin, callback, *args):

        super().__init__(pin, False, callback, *args)

  

class NEC_16(NEC_ABC):

    def __init__(self, pin, callback, *args):

        super().__init__(pin, True, callback, *args)

範例1

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

from ir_rx import NEC_16

from machine import Timer

from machine import Pin

  

def callBack(data, addr, ctrl):

    if data > 0:

        print("data: {:02x} addr: {:04x}".format(data, addr))

ir = NEC_16(Pin(26, Pin.IN), callBack)

範例2:

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

from ir_rx import NEC_16

from machine import Timer

from machine import Pin

  

def callBack(data, addr, ctrl):

    if data > 0:

        # print("data: {:02x} addr: {:04x}".format(data, addr))

        print(ir_key[data])

ir = NEC_16(Pin(26, Pin.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(2, Pin.OUT)

def callBack(data, addr, ctrl):

    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(26, Pin.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()

文章作者: blairan
版權聲明: 本博客所有文章除特別聲明外,均採用 CC BY 4.0 許可協議。轉載請註明來源 blairan !
评论
  目錄