Micropython学习交流群 学习QQ群:786510434 提供多种固件下载和学习交流。

Micropython-扇贝物联 QQ群:31324057 扇贝物联是一个让你与智能设备沟通更方便的物联网云平台

Micropython学习交流群 学习QQ群:468985481 学习交流ESP8266、ESP32、ESP8285、wifi模块开发交流、物联网。

Micropython老哥俩的IT农场分享QQ群:929132891 为喜欢科创制作的小白们分享一些自制的计算机软硬件免费公益课程,由两位多年从事IT研发的中年大叔发起。

Micropython ESP频道

ESP32(MicroPython) OLED多功能显示(BMP280、SR04、DS18B20、RTC)


ESP32(MicroPython) OLED多功能显示(BMP280、SR04、DS18B20、RTC)


本程序实现了对BMP280气压温度传感器、SR04超声波传感器、DS18B20温度传感器、RTC实时时钟的读数和显示。


代码如下


'''

接线:BMP280气压传感器模块

         SCL-->25

         SDA-->26

      OLED(IIC)

         SCL-->(18)

         SDA-->(23)

      DS18B20-->(27)

      SR04

         trigger-->(12)

         echo_pin-->(14)         

'''

 

from machine import Pin,SoftI2C,Timer

from time import sleep

import bmp280

from ssd1306 import SSD1306_I2C

import onewire

import ds18x20

from machine import RTC

from hcsr04 import HCSR04

 

#初始化OLED

i2c = SoftI2C(sda=Pin(23), scl=Pin(18))

oled = SSD1306_I2C(128, 64, i2c, addr=0x3c)

#定义DS18B20控制对象

ds18b20=ds18x20.DS18X20(onewire.OneWire(Pin(27)))

roms = ds18b20.scan()  #扫描是否存在DS18B20设备

#初始化BMP280,定义第二个I2C接口i2c2用于连接BMP280

i2c2 = SoftI2C(sda=Pin(26), scl=Pin(25))

BMP = bmp280.BMP280(i2c2)

#定义RTC控制对象

rtc=RTC()

#定义HCSR04控制对象

hcsr04=HCSR04(trigger_pin=12, echo_pin=14)

 

#定义星期

week=("Mon","Tue","Wed","Thu","Fri","Sat","Sun")

 

#中断回调函数

def fun(tim):

 

    oled.fill(0)  # 清屏,背景黑色

    ds18b20.convert_temp()

    date_time=rtc.datetime()

    distance=hcsr04.distance_cm()

    for rom in roms:

      # 温度显示

      oled.text("%.2f C" %ds18b20.read_temp(rom), 0, 35)

    #时间显示

    oled.text(str(date_time[0])+'-'+str(date_time[1])+'-'+str(date_time[2])+' '+str(week[date_time[3]]), 0, 0)

    oled.text(str(date_time[4])+':'+str(date_time[5])+':'+str(date_time[6]), 0, 10) 

    #距离显示

    oled.text("%.2f cm"%distance, 0, 25)

    # 湿度显示

    oled.text(str(BMP.getPress()) + ' Pa', 0, 45)

    # 海拔显示

    oled.text(str(BMP.getAltitude()) + ' m', 0, 55)

 

    oled.show()

 

#开启RTOS定时器

tim = Timer(-1)

tim.init(period=200, mode=Timer.PERIODIC, callback=fun) #周期1s

以下是相关头文件


bmp280.py


BMP280_I2C_ADDR = const(0x76)

 

class BMP280():

    def __init__(self, i2c):

        self.i2c = i2c

        self.dig_T1 = self.get2Reg(0x88)

        self.dig_T2 = self.short(self.get2Reg(0x8A))

        self.dig_T3 = self.short(self.get2Reg(0x8C))

        self.dig_P1 = self.get2Reg(0x8E)

        self.dig_P2 = self.short(self.get2Reg(0x90))

        self.dig_P3 = self.short(self.get2Reg(0x92))

        self.dig_P4 = self.short(self.get2Reg(0x94))

        self.dig_P5 = self.short(self.get2Reg(0x96))

        self.dig_P6 = self.short(self.get2Reg(0x98))

        self.dig_P7 = self.short(self.get2Reg(0x9A))

        self.dig_P8 = self.short(self.get2Reg(0x9C))

        self.dig_P9 = self.short(self.get2Reg(0x9E))

        self.mode = 3

        self.osrs_p = 3

        self.osrs_t = 1

        self.setReg(0xF4, 0x2F)

        self.setReg(0xF5, 0x0C)

        self.filter = 3

        self.T = 0

        self.P = 0

        self.version = '1.0'

 

    def short(self, dat):

        if dat > 32767:

            return dat - 65536

        else:

            return dat

    # set reg

    def setReg(self, reg, dat):

        self.i2c.writeto(BMP280_I2C_ADDR, bytearray([reg, dat]))

    # get reg

    def getReg(self, reg):

        self.i2c.writeto(BMP280_I2C_ADDR, bytearray([reg]))

        t = self.i2c.readfrom(BMP280_I2C_ADDR, 1)

        return t[0]

    # get two reg

    def get2Reg(self, reg):

        self.i2c.writeto(BMP280_I2C_ADDR, bytearray([reg]))

        t = self.i2c.readfrom(BMP280_I2C_ADDR, 2)

        return t[0] + t[1]*256

 

    def get(self):

        adc_T = (self.getReg(0xFA)<<12) + (self.getReg(0xFB)<<4) + (self.getReg(0xFC)>>4)

        var1 = (((adc_T>>3)-(self.dig_T1<<1))*self.dig_T2)>>11

        var2 = (((((adc_T>>4)-self.dig_T1)*((adc_T>>4) - self.dig_T1))>>12)*self.dig_T3)>>14

        t = var1+var2

        self.T = ((t * 5 + 128) >> 8)/100

        var1 = (t>>1) - 64000

        var2 = (((var1>>2) * (var1>>2)) >> 11 ) * self.dig_P6

        var2 = var2 + ((var1*self.dig_P5)<<1)

        var2 = (var2>>2)+(self.dig_P4<<16)

        var1 = (((self.dig_P3*((var1>>2)*(var1>>2))>>13)>>3) + (((self.dig_P2) * var1)>>1))>>18

        var1 = ((32768+var1)*self.dig_P1)>>15

        if var1 == 0:

            return  # avoid exception caused by division by zero

        adc_P = (self.getReg(0xF7)<<12) + (self.getReg(0xF8)<<4) + (self.getReg(0xF9)>>4)

        p=((1048576-adc_P)-(var2>>12))*3125

        if p < 0x80000000:

            p = (p << 1) // var1

        else:

            p = (p // var1) * 2

        var1 = (self.dig_P9 * (((p>>3)*(p>>3))>>13))>>12

        var2 = (((p>>2)) * self.dig_P8)>>13

        self.P = p + ((var1 + var2 + self.dig_P7) >> 4)

        return [self.T, self.P]

 

    # get Temperature in Celsius

    def getTemp(self):

        self.get()

        return self.T

 

    # get Pressure in Pa

    def getPress(self):

        self.get()

        return self.P

 

    # Calculating absolute altitude

    def getAltitude(self):

        return '%.2f'%(44330*(1-(self.getPress()/101325)**(1/5.256)))

 

    # sleep mode

    def poweroff(self):

        self.setReg(0xF4, 0)

 

    # normal mode

    def poweron(self):

        self.setReg(0xF4, 0x2F)

hcsr04.py


import machine, time

from machine import Pin

 

__version__ = '0.2.0'

__author__ = 'Roberto Sánchez'

__license__ = "Apache License 2.0. https://www.apache.org/licenses/LICENSE-2.0"

 

class HCSR04:

    """

    Driver to use the untrasonic sensor HC-SR04.

    The sensor range is between 2cm and 4m.

    The timeouts received listening to echo pin are converted to OSError('Out of range')

    """

    # echo_timeout_us is based in chip range limit (400cm)

    def __init__(self, trigger_pin, echo_pin, echo_timeout_us=500*2*30):

        """

        trigger_pin: Output pin to send pulses

        echo_pin: Readonly pin to measure the distance. The pin should be protected with 1k resistor

        echo_timeout_us: Timeout in microseconds to listen to echo pin. 

        By default is based in sensor limit range (4m)

        """

        self.echo_timeout_us = echo_timeout_us

        # Init trigger pin (out)

        self.trigger = Pin(trigger_pin, mode=Pin.OUT, pull=None)

        self.trigger.value(0)

 

        # Init echo pin (in)

        self.echo = Pin(echo_pin, mode=Pin.IN, pull=None)

 

    def _send_pulse_and_wait(self):

        """

        Send the pulse to trigger and listen on echo pin.

        We use the method `machine.time_pulse_us()` to get the microseconds until the echo is received.

        """

        self.trigger.value(0) # Stabilize the sensor

        time.sleep_us(5)

        self.trigger.value(1)

        # Send a 10us pulse.

        time.sleep_us(10)

        self.trigger.value(0)

        try:

            pulse_time = machine.time_pulse_us(self.echo, 1, self.echo_timeout_us)

            return pulse_time

        except OSError as ex:

            if ex.args[0] == 110: # 110 = ETIMEDOUT

                raise OSError('Out of range')

            raise ex

 

    def distance_mm(self):

        """

        Get the distance in milimeters without floating point operations.

        """

        pulse_time = self._send_pulse_and_wait()

 

        # To calculate the distance we get the pulse_time and divide it by 2 

        # (the pulse walk the distance twice) and by 29.1 becasue

        # the sound speed on air (343.2 m/s), that It's equivalent to

        # 0.34320 mm/us that is 1mm each 2.91us

        # pulse_time // 2 // 2.91 -> pulse_time // 5.82 -> pulse_time * 100 // 582 

        mm = pulse_time * 100 // 582

        return mm

 

    def distance_cm(self):

        """

        Get the distance in centimeters with floating point operations.

        It returns a float

        """

        pulse_time = self._send_pulse_and_wait()

 

        # To calculate the distance we get the pulse_time and divide it by 2 

        # (the pulse walk the distance twice) and by 29.1 becasue

        # the sound speed on air (343.2 m/s), that It's equivalent to

        # 0.034320 cm/us that is 1cm each 29.1us

        cms = (pulse_time / 2) / 29.1

        return cms

ssd1306.py


# MicroPython SSD1306 OLED driver, I2C and SPI interfaces

 

from micropython import const

import framebuf

 

 

# register definitions

SET_CONTRAST = const(0x81)

SET_ENTIRE_ON = const(0xA4)

SET_NORM_INV = const(0xA6)

SET_DISP = const(0xAE)

SET_MEM_ADDR = const(0x20)

SET_COL_ADDR = const(0x21)

SET_PAGE_ADDR = const(0x22)

SET_DISP_START_LINE = const(0x40)

SET_SEG_REMAP = const(0xA0)

SET_MUX_RATIO = const(0xA8)

SET_COM_OUT_DIR = const(0xC0)

SET_DISP_OFFSET = const(0xD3)

SET_COM_PIN_CFG = const(0xDA)

SET_DISP_CLK_DIV = const(0xD5)

SET_PRECHARGE = const(0xD9)

SET_VCOM_DESEL = const(0xDB)

SET_CHARGE_PUMP = const(0x8D)

 

# Subclassing FrameBuffer provides support for graphics primitives

# http://docs.micropython.org/en/latest/pyboard/library/framebuf.html

class SSD1306(framebuf.FrameBuffer):

    def __init__(self, width, height, external_vcc):

        self.width = width

        self.height = height

        self.external_vcc = external_vcc

        self.pages = self.height // 8

        self.buffer = bytearray(self.pages * self.width)

        super().__init__(self.buffer, self.width, self.height, framebuf.MONO_VLSB)

        self.init_display()

 

    def init_display(self):

        for cmd in (

            SET_DISP | 0x00,  # off

            # address setting

            SET_MEM_ADDR,

            0x00,  # horizontal

            # resolution and layout

            SET_DISP_START_LINE | 0x00,

            SET_SEG_REMAP | 0x01,  # column addr 127 mapped to SEG0

            SET_MUX_RATIO,

            self.height - 1,

            SET_COM_OUT_DIR | 0x08,  # scan from COM[N] to COM0

            SET_DISP_OFFSET,

            0x00,

            SET_COM_PIN_CFG,

            0x02 if self.width > 2 * self.height else 0x12,

            # timing and driving scheme

            SET_DISP_CLK_DIV,

            0x80,

            SET_PRECHARGE,

            0x22 if self.external_vcc else 0xF1,

            SET_VCOM_DESEL,

            0x30,  # 0.83*Vcc

            # display

            SET_CONTRAST,

            0xFF,  # maximum

            SET_ENTIRE_ON,  # output follows RAM contents

            SET_NORM_INV,  # not inverted

            # charge pump

            SET_CHARGE_PUMP,

            0x10 if self.external_vcc else 0x14,

            SET_DISP | 0x01,

        ):  # on

            self.write_cmd(cmd)

        self.fill(0)

        self.show()

 

    def poweroff(self):

        self.write_cmd(SET_DISP | 0x00)

 

    def poweron(self):

        self.write_cmd(SET_DISP | 0x01)

 

    def contrast(self, contrast):

        self.write_cmd(SET_CONTRAST)

        self.write_cmd(contrast)

    

    def rotate(self, rotate):

        self.write_cmd(SET_COM_OUT_DIR | ((rotate & 1) << 3))

        self.write_cmd(SET_SEG_REMAP | (rotate & 1))

        

    def invert(self, invert):

        self.write_cmd(SET_NORM_INV | (invert & 1))

 

    def show(self):

        x0 = 0

        x1 = self.width - 1

        if self.width == 64:

            # displays with width of 64 pixels are shifted by 32

            x0 += 32

            x1 += 32

        self.write_cmd(SET_COL_ADDR)

        self.write_cmd(x0)

        self.write_cmd(x1)

        self.write_cmd(SET_PAGE_ADDR)

        self.write_cmd(0)

        self.write_cmd(self.pages - 1)

        self.write_data(self.buffer)

 

 

class SSD1306_I2C(SSD1306):

    def __init__(self, width, height, i2c, addr=0x3C, external_vcc=False):

        self.i2c = i2c

        self.addr = addr

        self.temp = bytearray(2)

        self.write_list = [b"\x40", None]  # Co=0, D/C#=1

        super().__init__(width, height, external_vcc)

 

    def write_cmd(self, cmd):

        self.temp[0] = 0x80  # Co=1, D/C#=0

        self.temp[1] = cmd

        self.i2c.writeto(self.addr, self.temp)

 

    def write_data(self, buf):

        self.write_list[1] = buf

        self.i2c.writevto(self.addr, self.write_list)

 

 

class SSD1306_SPI(SSD1306):

    def __init__(self, width, height, spi, dc, res, cs, external_vcc=False):

        self.rate = 10 * 1024 * 1024

        dc.init(dc.OUT, value=0)

        res.init(res.OUT, value=0)

        cs.init(cs.OUT, value=1)

        self.spi = spi

        self.dc = dc

        self.res = res

        self.cs = cs

        import time

 

        self.res(1)

        time.sleep_ms(1)

        self.res(0)

        time.sleep_ms(10)

        self.res(1)

        super().__init__(width, height, external_vcc)

 

    def write_cmd(self, cmd):

        self.spi.init(baudrate=self.rate, polarity=0, phase=0)

        self.cs(1)

        self.dc(0)

        self.cs(0)

        self.spi.write(bytearray([cmd]))

        self.cs(1)

 

    def write_data(self, buf):

        self.spi.init(baudrate=self.rate, polarity=0, phase=0)

        self.cs(1)

        self.dc(1)

        self.cs(0)

        self.spi.write(buf)

        self.cs(1)


————————————————

版权声明:本文为CSDN博主「路易斯720」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_74155302/article/details/131013010



推荐分享
图文皆来源于网络,内容仅做公益性分享,版权归原作者所有,如有侵权请告知删除!
 

Copyright © 2014 ESP56.com All Rights Reserved

执行时间: 0.010905981063843 seconds