本文介紹使用Raspberry Pi Pico PIO功能來讀取DHT11溫濕度資料,顯示在1602A LCD上。
一、硬體接線:
LCD 1602A: Raspberry Pi Pico
VSS: GND
VDD: Pin40(VBUS), 5V
VO: 10k可變電阻
RS: Pin 11
RW: GND
E: Pin 10
D4: Pin 6
D5: Pin 7
D6: Pin 8
D7: Pin 9
A: 5V
K: GND
DHT11 Raspberry Pi Pico
Pin2: Pin 16
VDD: 5V
二、PIO程式碼與DHT11 datasheet對照說明:
from machine import Pin import rp2 from utime import sleep_ms class DHT11(): """ output humidity(rh) and temperature(temp), call get_data to get values """ @rp2.asm_pio(set_init=rp2.PIO.OUT_HIGH, autopush=True, push_thresh=32, in_shiftdir=rp2.PIO.SHIFT_LEFT) def dht11(): wrap_target() set(pindirs,1) # set pin as output set(pins,0) # set low for 20ms (at least 18ms) set(x,29) #freq=500000, 1 cycle = 2us (30*30*11*2 = 19.8ms) label("start_loop_1") set(y,29) label("start_loop_2") jmp(y_dec, "start_loop_2") [10] jmp(x_dec, "start_loop_1") set(pins,1) [14] # pull-up for 2us*15 = 30us (20~40 us) set(pindirs,0) # set pin as input wait(0,pin,0) [19] nop() [19] # wait for low 2*(20+20)=80us wait(1,pin,0) [19] nop() [19] # wait for high 2*(20+20)=80us set(x,4) # 5 bytes label("bytes") set(y,7) # each byte: 8 bits label("bits") wait(0,pin,0) [14] # LOW: wait for 2us*15=30us (50us) wait(1,pin,0) [19] # HIGH: wait at least 2*20=40 us (26~28us: 0, 70us: 1) in_(pins,1) jmp(y_dec,"bits") # autopush and push_thresh=32, auto push 4 data byte jmp(x_dec,"bytes") push() # push last one CRC byte nop() [31] #transmition completed, low for 50us and pull-high wait(0,pin,0) # block for next wrap() def __init__(self, pin_num, smid=0): self.pin = Pin(pin_num, Pin.IN, Pin.PULL_UP) self.sm=rp2.StateMachine(smid, self.dht11, freq=500000, in_base=self.pin, set_base=self.pin) self.sm.active(1) self.rh=0.0 self.temp=0.0 def get_data(self): self.sm.restart() data=self.sm.get() checksum=self.sm.get() bytes=[] for i in range(3,-1,-1): bytes.append((data>>8*i)&0xff) if ((bytes[0]+bytes[1]+bytes[2]+bytes[3]) == checksum): self.rh = float('{}.{}'.format(bytes[0], bytes[1])) self.temp = float('{}.{}'.format(bytes[2], bytes[3])) else: self.rh=0.0 self.temp=0.0 del bytes sleep_ms(1120) #Sampling period at intervals should be no less than 1 second.
LCD1602A.py
# base on https://github.com/wjdp/micropython-lcd/blob/master/lcd.py from machine import Pin from utime import sleep_us class LCD1602A(): PIN_NAMES = ['RS','E','D4','D5','D6','D7'] # Define some device constants LCD_WIDTH = 16 # Maximum characters per line # Designation of T/F for character and command modes LCD_CHR = True LCD_CMD = False LINES = { 0: 0x80, # LCD RAM address for the 1st line 1: 0xC0, # LCD RAM address for the 2nd line # Add more if desired } # Timing constants E_PULSE = 50 E_DELAY = 50 def __init__(self, rs, e,*,d4=None, d5=None, d6=None, d7=None): self.pins={} self.PINS=[rs, e, d4, d5, d6, d7] # Initialise pins for pin, pin_name in zip(self.PINS, self.PIN_NAMES): self.pins['LCD_'+pin_name] = Pin(pin, Pin.OUT) # Initialise display self.lcd_byte(0x33,self.LCD_CMD) self.lcd_byte(0x32,self.LCD_CMD) self.lcd_byte(0x28,self.LCD_CMD) self.lcd_byte(0x0C,self.LCD_CMD) self.lcd_byte(0x06,self.LCD_CMD) self.lcd_byte(0x01,self.LCD_CMD) def clear(self): # Clear the display self.lcd_byte(0x01,self.LCD_CMD) def set_line(self, line): # Set the line that we're going to print to self.lcd_byte(self.LINES[line], self.LCD_CMD) def set_string(self, message): # Pad string out to LCD_WIDTH # message = message.ljust(LCD_WIDTH," ") m_length = len(message) if m_length < self.LCD_WIDTH: short = self.LCD_WIDTH - m_length blanks=str() for i in range(short): blanks+=' ' message+=blanks for i in range(self.LCD_WIDTH): self.lcd_byte(ord(message[i]), self.LCD_CHR) def lcd_byte(self, bits, mode): # Send byte to data pins # bits = data # mode = True for character # False for command self.pin_action('LCD_RS', mode) # RS # High bits self.pin_action('LCD_D4', False) self.pin_action('LCD_D5', False) self.pin_action('LCD_D6', False) self.pin_action('LCD_D7', False) if bits&0x10==0x10: self.pin_action('LCD_D4', True) if bits&0x20==0x20: self.pin_action('LCD_D5', True) if bits&0x40==0x40: self.pin_action('LCD_D6', True) if bits&0x80==0x80: self.pin_action('LCD_D7', True) # Toggle 'Enable' pin self.udelay(self.E_DELAY) self.pin_action('LCD_E', True) self.udelay(self.E_PULSE) self.pin_action('LCD_E', False) self.udelay(self.E_DELAY) # Low bits self.pin_action('LCD_D4', False) self.pin_action('LCD_D5', False) self.pin_action('LCD_D6', False) self.pin_action('LCD_D7', False) if bits&0x01==0x01: self.pin_action('LCD_D4', True) if bits&0x02==0x02: self.pin_action('LCD_D5', True) if bits&0x04==0x04: self.pin_action('LCD_D6', True) if bits&0x08==0x08: self.pin_action('LCD_D7', True) # Toggle 'Enable' pin self.udelay(self.E_DELAY) self.pin_action('LCD_E', True) self.udelay(self.E_PULSE) self.pin_action('LCD_E', False) self.udelay(self.E_DELAY) def udelay(self, us): # Delay by us microseconds, set as function for portability #pyb.udelay(us) sleep_us(us) def pin_action(self, pin, high): # Pin high/low functions, set as function for portability if high: self.pins[pin].on() else: self.pins[pin].off()
from machine import Pin from DHT import DHT11 from LCD1602A import LCD1602A import utime lcd=LCD1602A(11,10, d4=6,d5=7,d6=8,d7=9) dht=DHT11(16) while True: dht.get_data() lcd.set_line(0) lcd.set_string("Temp:"+str(dht.temp)+"C") lcd.set_line(1) lcd.set_string("RH: "+str(dht.rh)+"%") #utime.sleep(0.5)
沒有留言:
張貼留言