物联网开发125 - Micropython ESP32 C3 NecIR VS1838B红外遥控解码+ST7735S屏显示

一、目的

        这一节我们来学习如何使用合宙ESP32 C3,连接红外模块和红外遥控器,使用ST7735屏幕进行显示。此处使用的是NFC编码方式。下面我们一起来学习一下吧!

二、环境

        ESP32 C3开发板(MicroPython v1.19.1 on 2022-06-18)+ 红外接收模块 + 红外遥控器 + TFT ST7735S屏幕 + 几根杜邦线 + Win10商业版

        ESP32 C3和各模块接线方法:


三、st7735屏幕驱动

st7735.py

"""
合宙 Air10x 系列屏幕扩展板驱动
160(H)RGB x 80(V)

使用方法(以合宙ESP32C3为例):
    from machine import SPI, Pin
    from st7735 import ST7735

    spi = SPI(1, 30000000, sck=Pin(2), mosi=Pin(3))
    ST7735(spi, rst=10, dc=6, cs=7, bl=11, width=160, height=80, rotate=1)  # 直插横屏显示
    ST7735(spi, rst=10, dc=6, cs=7, bl=11, width=160, height=80, rotate=0)  # 直插竖屏显示

本款LCD使用的内置控制器为ST7735S,是一款162 x RGB x 132像素的LCD控制器,而本LCD本身的像素为160(H)RGB x 80(V)。由于LCD的显示
起始位置与控制器的原点不一致,因此在使用控制器初始化显示全屏显示区域时需要对做偏移处理:水平方向从第二个像素点开始显示,垂直方向从第27个像素点
开始。这样就可以保证显示的LCD中RAM对应的位置与实际一致。(https://www.waveshare.net/wiki/Pico-LCD-0.96)

屏幕详细信息: https://wiki.luatos.com/peripherals/lcd_air10x/index.html
ST7735S文档: https://www.waveshare.net/w/upload/e/e2/ST7735S_V1.1_20111121.pdf
FrameBuf文档: https://docs.micropython.org/en/latest/library/framebuf.html
"""
import gc
import time
import math

import machine
import framebuf
from micropython import const

SWRESET = const(0x01)
SLPOUT = const(0x11)
NORON = const(0x13)

INVOFF = const(0x20)
DISPON = const(0x29)
CASET = const(0x2A)
RASET = const(0x2B)
RAMWR = const(0x2C)

MADCTL = const(0x36)
COLMOD = const(0x3A)

FRMCTR1 = const(0xB1)
FRMCTR2 = const(0xB2)
FRMCTR3 = const(0xB3)

INVCTR = const(0xB4)

PWCTR1 = const(0xC0)
PWCTR2 = const(0xC1)
PWCTR3 = const(0xC2)
PWCTR4 = const(0xC3)
PWCTR5 = const(0xC4)
VMCTR1 = const(0xC5)

GMCTRP1 = const(0xE0)
GMCTRN1 = const(0xE1)

ROTATIONS = [0x00,0x60]  # 只给了两个旋转方向


def color(r, g, b):
    i = (((b & 0xF8) << 8) | ((g & 0xFC) << 3) | (r >> 3)).to_bytes(2, "little")
    return (i[0] << 8) + i[1]

RED = color(255, 0, 0)
GREEN = color(0, 255, 0)
BLUE = color(0, 0, 255)
WHITE = color(255, 255, 255)
BLACK = color(0, 0, 0)


class ST7735(framebuf.FrameBuffer):
    def __init__(self, spi, rst, dc, cs, bl=None, width=None, height=None, offset=None, rotate=1, rgb=True):
        """
        :param spi:
        :param rst:
        :param dc:
        :param cs: 使能
        :param bl: 背光
        :param width: 宽度
        :param height: 高度
        :param offset: 偏移 (x, y): (23, -1)|(-1, 23)
        :param rotate: 旋转 0 横屏 1 竖屏
        :param rgb: RGB 色彩模式
        """
        # 根据方向自动设置偏移
        self.rotate = rotate
        self.offset = offset
        self.rgb = rgb
        if offset is None and rotate == 1:
            self.offset = (-1, 23)
        elif offset is None and rotate == 0:
            self.offset = (23, -1)
        self.width = width
        self.height = height

        self.spi = spi
        self.rst = machine.Pin(rst, machine.Pin.OUT, machine.Pin.PULL_DOWN)
        self.dc = machine.Pin(dc, machine.Pin.OUT, machine.Pin.PULL_DOWN)
        self.cs = machine.Pin(cs, machine.Pin.OUT, machine.Pin.PULL_DOWN)
        if bl is not None:
            self.bl = machine.PWM(machine.Pin(bl))

        gc.collect()
        self.buffer = bytearray(self.height * self.width * 2)
        super().__init__(self.buffer, self.width, self.height, framebuf.RGB565)
        self.init()
        self.set_windows()
        self.clear()

    def set_windows(self, x_start=None, y_start=None, x_end=None, y_end=None):
        """
        设置窗口
        :return:
        """
        x_start = (x_start + self.offset[0] + 1) if x_start is not None else (self.offset[0] + 1)
        x_end = x_end + self.rotate + self.offset[0] if x_end is not None else self.width + self.rotate + \
                                                                               self.offset[0]
        y_start = y_start + self.offset[1] + 1 if y_start is not None else self.offset[1] + 1
        y_end = y_end + self.rotate + self.offset[1] if y_end is not None else self.height + self.rotate + \
                                                                               self.offset[1]

        self.write_cmd(CASET)
        self.write_data(bytearray([0x00, x_start, 0x00, x_end]))

        self.write_cmd(RASET)
        self.write_data(bytearray([0x00, y_start, 0x00, y_end]))

        self.write_cmd(RAMWR)

    def init(self):
        self.reset()

        self.write_cmd(SWRESET)
        time.sleep_us(150)
        self.write_cmd(SLPOUT)
        time.sleep_us(300)

        self.write_cmd(FRMCTR1)
        self.write_data(bytearray([0x01, 0x2C, 0x2D]))
        self.write_cmd(FRMCTR2)
        self.write_data(bytearray([0x01, 0x2C, 0x2D]))
        self.write_cmd(FRMCTR3)
        self.write_data(bytearray([0x01, 0x2C, 0x2D, 0x01, 0x2C, 0x2D]))
        time.sleep_us(10)

        self.write_cmd(INVCTR)
        self.write_data(bytearray([0x07]))

        self.write_cmd(PWCTR1)
        self.write_data(bytearray([0xA2, 0x02, 0x84]))
        self.write_cmd(PWCTR2)
        self.write_data(bytearray([0xC5]))
        self.write_cmd(PWCTR3)
        self.write_data(bytearray([0x0A, 0x00]))
        self.write_cmd(PWCTR4)
        self.write_data(bytearray([0x8A, 0x2A]))
        self.write_cmd(PWCTR5)
        self.write_data(bytearray([0x8A, 0xEE]))
        self.write_cmd(VMCTR1)
        self.write_data(bytearray([0x0E]))

        self.write_cmd(INVOFF)

        self.write_cmd(MADCTL)
        self.write_data(bytearray([ROTATIONS[self.rotate] | 0x00 if self.rgb else 0x08]))

        self.write_cmd(COLMOD)
        self.write_data(bytearray([0x05]))

        self.write_cmd(GMCTRP1)
        self.write_data(
            bytearray([0x02, 0x1c, 0x07, 0x12, 0x37, 0x32, 0x29, 0x2d, 0x29, 0x25, 0x2b, 0x39, 0x00, 0x01, 0x03, 0x10]))

        self.write_cmd(GMCTRN1)
        self.write_data(
            bytearray([0x03, 0x1d, 0x07, 0x06, 0x2e, 0x2c, 0x29, 0x2d, 0x2e, 0x2e, 0x37, 0x3f, 0x00, 0x00, 0x02, 0x10]))

        self.write_cmd(NORON)
        time.sleep_us(10)

        self.write_cmd(DISPON)
        time.sleep_us(100)

        self.cs(1)

    def reset(self):
        """
        设备重置
        :return:
        """
        self.rst(1)
        time.sleep(0.2)
        self.rst(0)
        time.sleep(0.2)
        self.rst(1)
        time.sleep(0.2)

    def write_cmd(self, cmd):
        self.dc(0)
        self.cs(0)
        self.spi.write(bytearray([cmd]))
        self.cs(1)

    def write_data(self, buf):
        self.dc(1)
        self.cs(0)
        self.spi.write(buf)
        self.cs(1)

    def back_light(self, value):
        """
        背光调节
        :param value: 背光等级 0 ~ 256
        :return:
        """
        self.bl.freq(1000)
        if value >= 0xff:
            value = 0xff
        data = value * 0xffff >> 8
        self.bl.duty_u16(data)

    def clear(self):
        """
        清屏
        :return:
        """
        self.fill(0)
        self.show()

    def show(self):
        """
        显示
        :return:
        """
        self.set_windows()  # 如果没有这行就会偏移
        self.write_data(self.buffer)

    def circle(self, center, radius, c=color(255, 255, 255), section=100):
        """
        画圆
        :param c: 颜色
        :param center: 中心(x, y)
        :param radius: 半径
        :param section: 分段
        :return:
        """
        arr = []
        for m in range(section + 1):
            x = round(radius * math.cos((2 * math.pi / section) * m - math.pi) + center[0])
            y = round(radius * math.sin((2 * math.pi / section) * m - math.pi) + center[1])
            arr.append([x, y])
        for i in range(len(arr) - 1):
            self.line(*arr[i], *arr[i + 1], c)

    def image(self, file_name):
        with open(file_name, "rb") as bmp:
            for b in range(0, 80 * 160 * 2, 1024):
                self.buffer[b:b + 1024] = bmp.read(1024)
            self.show()

四、NFC红外模块驱动

necir.py

'''
https://space.bilibili.com/1349435951?spm_id_from=333.1007.0.0

'''
import machine
import utime
from machine import Pin

class NECIR(object):
     
    #Remote control key value
    CODE = {
        162: "ch-", 98: "ch", 226: "ch+",
        34: "prev", 2: "next", 194: "play/stop",
        152: "0", 104: "*", 176: "#",
        224: "-", 168: "+", 144: "EQ",
        104: "0", 152: "100+", 176: "200+",
        48: "1", 24: "2", 122: "3",
        16: "4", 56: "5", 90: "6",
        66: "7", 74: "8", 82: "9"
    }
    
    #Initialization function configuration pin status input pull-up
    def __init__(self, gpioNum):
        self.irRecv = machine.Pin(gpioNum, machine.Pin.IN, machine.Pin.PULL_UP)
        self.irRecv.irq(trigger=machine.Pin.IRQ_RISING | machine.Pin.IRQ_FALLING, handler=self.__handler)  # 配置中断信息
        self.ir_step = 0
        self.ir_count = 0
        self.buf64 = [0 for i in range(64)]
        self.recived_ok = False
        self.cmd = None
        self.cmd_last = None
        self.repeat = 0
        self.repeat_last = None
        self.t_ok = None
        self.t_ok_last = None
        self.start = 0
        self.start_last = 0        
        self.changed = False
    
    #Interrupt callback function
    def __handler(self, source):
        thisComeInTime = utime.ticks_us()
 
        #Update time
        curtime = utime.ticks_diff(thisComeInTime, self.start)
        self.start = thisComeInTime
        
        if curtime >= 8500 and curtime <= 9500:
            self.ir_step = 1
            return
 
        if self.ir_step == 1:
            if curtime >= 4000 and curtime <= 5000:
                self.ir_step = 2
                self.recived_ok = False
                self.ir_count = 0
                self.repeat = 0
            elif curtime >= 2000 and curtime <= 3000:  #Long press to receive repeatedly
                self.ir_step = 3
                self.repeat += 1
 
        elif self.ir_step == 2:  #Receive 4 bytes
            self.buf64[self.ir_count] = curtime
            self.ir_count += 1
            if self.ir_count >= 64:
                self.recived_ok = True
                self.t_ok = self.start #Record the time of the last ok
                self.ir_step = 0
 
        elif self.ir_step == 3:  #repeat
            if curtime >= 500 and curtime <= 650:
                self.repeat += 1
 
    def __check_cmd(self):
        byte4 = 0
        for i in range(32):
            x = i * 2
            t = self.buf64[x] + self.buf64[x+1]
            byte4 <<= 1
            if t >= 1800 and t <= 2800:
                byte4 += 1
        user_code_hi = (byte4 & 0xff000000) >> 24
        user_code_lo = (byte4 & 0x00ff0000) >> 16
        data_code = (byte4 & 0x0000ff00) >> 8
        data_code_r = byte4 & 0x000000ff
        self.cmd = data_code
 
    def scan(self):        
        #Received data
        if self.recived_ok:
            self.__check_cmd()
            self.recived_ok = False
            
        #Data changes
        if self.cmd != self.cmd_last or self.repeat != self.repeat_last or self.t_ok != self.t_ok_last:
            self.changed = True
        else:
            self.changed = False
 
        #Update return data
        self.cmd_last = self.cmd
        self.repeat_last = self.repeat
        self.t_ok_last = self.t_ok
        code = self.CODE.get(self.cmd)
        
        return self.changed,self.cmd,code

五、示例代码

necir_demo.py

from machine import Pin,SPI
from st7735 import ST7735,color
from ufont import BMFont
from necir import NECIR
import time

font = BMFont("unifont-14.0.04.bmf")

spi = SPI(1,baudrate = 60_000_000,polarity = 0,sck = Pin(2),mosi = Pin(3),miso = None)
tft = ST7735(spi,rst = 10,dc = 6,cs = 7,bl = 8, width = 160, height = 80, rotate = 1, rgb = True)

nec = NECIR(18)
led = Pin(12,Pin.OUT)

def Title():
    
    font.text(tft,"红外解码",50,3,color(255,255,255),font_size = 16,reverse = False,clear = False,show = True,half_char = True,auto_wrap = False)
    tft.hline(0,25,160,color(0,255,255))
    tft.hline(0,28,160,color(255,0,255))
    tft.show()
    
    font.text(tft,"等待接收中",80,40,color(255,255,255),font_size = 16,reverse = False,clear = False,show = True,half_char = True,auto_wrap = False)
    
def Content():
    
    FLAG,HEX,VALUE = nec.scan()
    
        
    if FLAG != False and HEX != None:
        
        font.text(tft,"%s %#x %s"%(FLAG,HEX,VALUE) + str("         "),80,40,color(0,255,0),font_size = 16,reverse = False,clear = False,show = True,half_char = True,auto_wrap = False)
        
        print("%s %#x %s"%(FLAG,HEX,VALUE))
        time.sleep(0.5)
        
        if VALUE == '+':
            led.value(not led.value())

def main():
    Title()
            
    while True:
        Content()
        
        
if __name__ == "__main__":
    main()

字体文件ufont.py:

__version__ = 3

import time
import struct

import framebuf

DEBUG = False

def timeit(f, *args, **kwargs):
    try:
        myname = str(f).split(' ')[1]
    except:
        myname = "UNKONW"

    def new_func(*args, **kwargs):
        if DEBUG:
            try:
                t = time.ticks_us()
                result = f(*args, **kwargs)
                delta = time.ticks_diff(time.ticks_us(), t)
                print('Function {} Time = {:6.3f}ms'.format(myname, delta / 1000))
            except AttributeError:
                t = time.perf_counter_ns()
                result = f(*args, **kwargs)
                delta = time.perf_counter_ns() - t
                print('Function {} Time = {:6.3f}ms'.format(myname, delta / 1000000))
            return result
        else:
            return f(*args, **kwargs)

    return new_func

class BMFont:
    @staticmethod
    def _list_to_byte(arr):
        b = 0
        for a in arr:
            b = (b << 1) + a
        return bytes([b])

    @timeit
    def _bit_list_to_byte_data(self, bit_list):
        """将点阵转换为字节数据

        Args:
            bit_list:

        Returns:

        """
        byte_data = b''
        for _col in bit_list:
            for i in range(0, len(_col), 8):
                byte_data += self._list_to_byte(_col[i:i + 8])
        return byte_data

    @timeit
    def __init__(self, font_file):
        self.font_file = font_file

        self.font = open(font_file, "rb", buffering=0xff)

        self.bmf_info = self.font.read(16)

        if self.bmf_info[0:2] != b"BM":
            raise TypeError("字体文件格式不正确: " + font_file)

        self.version = self.bmf_info[2]
        if self.version != 3:
            raise TypeError("字体文件版本不正确: " + str(self.version))

        self.map_mode = self.bmf_info[3]  # 映射方式
        self.start_bitmap = struct.unpack(">I", b'\x00' + self.bmf_info[4:7])[0]  # 位图开始字节
        self.font_size = self.bmf_info[7]  # 字体大小
        self.bitmap_size = self.bmf_info[8]  # 点阵所占字节

    @timeit
    def _to_bit_list(self, byte_data, font_size, *, _height=None, _width=None):
        """将字节数据转换为点阵数据

        Args:
            byte_data: 字节数据
            font_size: 字号大小
            _height: 字体原高度
            _width: 字体原宽度

        Returns:

        """
        _height = _height or self.font_size
        _width = _width or self.bitmap_size // self.font_size * 8
        new_bitarray = [[0 for j in range(font_size)] for i in range(font_size)]
        for _col in range(len(new_bitarray)):
            for _row in range(len(new_bitarray[_col])):
                _index = int(_col / (font_size / _height)) * _width + int(_row / (font_size / _width))
                new_bitarray[_col][_row] = byte_data[_index // 8] >> (7 - _index % 8) & 1
        return new_bitarray

    @timeit
    def _color_render(self, bit_list, color):
        """将二值点阵图像转换为 RGB565 彩色字节图像

        Args:
            bit_list:
            color:
        Returns:

        """
        color_array = b""
        for _col in range(len(bit_list)):
            for _row in range(len(bit_list)):
                color_array += struct.pack("<H", color) if bit_list[_col][_row] else b'\x00\x00'
        return color_array

    @timeit
    def _get_index(self, word):
        """获取索引

        Args:
            word: 字符

        Returns:

        """
        word_code = ord(word)
        start = 0x10
        end = self.start_bitmap

        while start <= end:
            mid = ((start + end) // 4) * 2
            self.font.seek(mid, 0)
            target_code = struct.unpack(">H", self.font.read(2))[0]
            if word_code == target_code:
                return (mid - 16) >> 1
            elif word_code < target_code:
                end = mid - 2
            else:
                start = mid + 2
        return -1

    @timeit
    def get_bitmap(self, word):
        """获取点阵图

        Args:
            word: 字符

        Returns:
            bytes 字符点阵
        """
        index = self._get_index(word)
        if index == -1:
            return b'\xff\xff\xff\xff\xff\xff\xff\xff\xf0\x0f\xcf\xf3\xcf\xf3\xff\xf3\xff\xcf\xff?\xff?\xff\xff\xff' \
                   b'?\xff?\xff\xff\xff\xff'

        self.font.seek(self.start_bitmap + index * self.bitmap_size, 0)
        return self.font.read(self.bitmap_size)

    @timeit
    def text(self, display, string, x, y, color=1, *, font_size=None, reverse=False, clear=False, show=False,
             half_char=True, auto_wrap=False, **kwargs):
        """通过显示屏显示文字

        使用此函数显示文字,必须先确认显示对象是否继承与 framebuf.FrameBuffer。
        如果显示对象没有 clear 方法,需要自行调用 fill 清屏

        Args:
            display: 显示实例
            string: 字符串
            x: 字体左上角 x 轴
            y: 字体左上角 y 轴
            color: 颜色
            font_size: 字号
            reverse: 是否反转背景
            clear: 是否清除之前显示的内容
            show: 是否立刻显示
            half_char: 是否半字节显示 ASCII 字符
            auto_wrap: 自动换行
            **kwargs:
            Returns:
            None
        """
        font_size = font_size or self.font_size
        initial_x = x

        # 清屏
        try:
            display.clear() if clear else 0
        except AttributeError:
            print("请自行调用 display.fill(*) 清屏")

        for char in range(len(string)):
            # 是否自动换行
            if auto_wrap:
                if auto_wrap and ((x + font_size // 2 >= 128 and ord(string[char]) < 128 and half_char) or
                                  (x + font_size >= 128 and (not half_char or ord(string[char]) > 128))):
                    y += font_size
                    x = initial_x

            # 回车
            if string[char] == '\n':
                y += font_size
                x = initial_x
                continue
            # Tab
            elif string[char] == '\t':
                x = ((x // font_size) + 1) * font_size + initial_x % font_size
                continue
            
            # 其它的控制字符不显示
            elif ord(string[char]) < 16:
                continue
            
            # 超过范围的字符不会显示*
            if x > 160 or y > 80:
                continue
            
            byte_data = list(self.get_bitmap(string[char]))

            # 反转
            if reverse:
                for _pixel in range(len(byte_data)):
                    byte_data[_pixel] = ~byte_data[_pixel] & 0xff

            # 缩放和色彩*
            if color > 1 or font_size != self.font_size:
                bit_data = self._to_bit_list(byte_data, font_size)
                if color > 1:
                    display.blit(
                        framebuf.FrameBuffer(bytearray(self._color_render(bit_data, color)), font_size, font_size,
                                             framebuf.RGB565), x, y)
                else:
                    display.blit(
                        framebuf.FrameBuffer(bytearray(self._bit_list_to_byte_data(bit_data)), font_size, font_size,
                                             framebuf.MONO_HLSB), x, y)
            else:
                display.blit(framebuf.FrameBuffer(bytearray(byte_data), font_size, font_size, framebuf.MONO_HLSB), x, y)

            # 英文字符半格显示
            if ord(string[char]) < 128 and half_char:
                x += font_size // 2
            else:
                x += font_size

        display.show() if show else 0

    def char(self, char, color=1, font_size=None, reverse=False):
        """ 获取字体字节数据

        在没有继承 framebuf.FrameBuffer 的显示驱动,或者内存不足以将一整个屏幕载入缓存帧时
        可以直接获取单字的字节数据,局部更新
        Args:
            char: 单个字符
            color: 颜色
            font_size: 字体大小
            reverse: 反转
            Returns:
            bytearray
        """
        font_size = font_size or self.font_size
        byte_data = list(self.get_bitmap(char))

        # 反转
        if reverse:
            for _pixel in range(len(byte_data)):
                byte_data[_pixel] = ~byte_data[_pixel] & 0xff
        if color > 1 or font_size != self.font_size:
            bit_data = self._to_bit_list(byte_data, font_size)
            if color > 1:
                return self._color_render(bit_data, color)
            else:
                return self._bit_list_to_byte_data(bit_data)
        else:
            return bytearray(byte_data)

字库unifont-14.0.04.bmf文件百度下载:

链接: https://pan.baidu.com/s/1TxS-xOB9U4y8RIoAaGEWXg 提取码: 61m4 复制这段内容后打开百度网盘手机App,操作更方便哦

六、输出结果

Thonny打印输出结果如下:

ST7735S屏幕显示如下:

 

七、模块购买

1,ST7735 屏幕,分辨率80x160

      购买地址一:https://item.taobao.com/item.htm?_u=np01rch3477&id=601888988408&spm=a1z09.2.0.0.773a2e8d5zc3Hb&skuId=4216754021609

    

购买地址二:

https://item.taobao.com/item.htm?_u=np01rchd3f6&id=583173435654&skuId=4158298526659&spm=a1z09.2.0.0.773a2e8d5zc3Hb

2,红外接收模块,购买地址一

https://item.taobao.com/item.htm?_u=np01rcha19d&id=655019093140&spm=a1z09.2.0.0.773a2e8diu1gNU&skuId=4730285345958icon-default.png?t=N7T8https://item.taobao.com/item.htm?_u=np01rcha19d&id=655019093140&spm=a1z09.2.0.0.773a2e8diu1gNU&skuId=4730285345958

红外接收模块,购买地址二

商品详情icon-default.png?t=N7T8https://detail.tmall.com/item.htm?_u=np01rchfc9b&id=542788612440&skuId=4497224095381&spm=a1z09.2.0.0.773a2e8diu1gNU

3,红外遥控器,购买地址

商品详情icon-default.png?t=N7T8https://detail.tmall.com/item.htm?_u=np01rchfc9b&id=542788612440&skuId=4497224095381&spm=a1z09.2.0.0.773a2e8diu1gNU

  • 12
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
2022 / 01/ 30: 新版esptool 刷micropython固件指令不是 esptool.py cmd... 而是 esptool cmd... 即可;另外rshell 在 >= python 3.10 的时候出错解决方法可以查看:  已于2022年发布的: 第二章:修复rshell在python3.10出错 免费内容: https://edu.csdn.net/course/detail/29666 micropython语法和python3一样,编写起来非常方便。如果你快速入门单片机玩物联网而且像轻松实现各种功能,那绝力推荐使用micropython。方便易懂易学。 同时如果你懂C语音,也可以用C写好函数并编译进micropython固件里然后进入micropython调用(非必须)。 能通过WIFI联网(2.1章),也能通过sim卡使用2G/3G/4G/5G联网(4.5章)。 为实现语音控制,本教程会教大家使用tensorflow利用神经网络训练自己的语音模型并应用。为实现通过网页控制,本教程会教大家linux(debian10 nginx->uwsgi->python3->postgresql)网站前后台入门。为记录单片机传输过来的数据, 本教程会教大家入门数据库。  本教程会通过通俗易懂的比喻来讲解各种原理与思路,并手把手编写程序来实现各项功能。 本教程micropython版本是 2019年6月发布的1.11; 更多内容请看视频列表。  学习这门课程之前你需要至少掌握: 1: python3基础(变量, 循环, 函数, 常用库, 常用方法)。 本视频使用到的零件与淘宝上大致价格:     1: 超声波传感器(3)     2: MAX9814麦克风放大模块(8)     3: DHT22(15)     4: LED(0.1)     5: 8路5V低电平触发继电器(12)     6: HX1838红外接收模块(2)     7:红外发射管(0.1),HX1838红外接收板(1)     other: 电表, 排线, 面包板(2)*2,ESP32(28)  

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔都飘雪

您的1毛奖励是我创作的源源动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值