]> vault307.fbx.one Git - garage_door_sensor.git/commitdiff
new file: hcsr04Test.py
authorJimmy <jimipunk88@gmail.com>
Mon, 24 Jun 2024 21:06:53 +0000 (16:06 -0500)
committerJimmy <jimipunk88@gmail.com>
Mon, 24 Jun 2024 21:06:53 +0000 (16:06 -0500)
new file:   lcd_api.py
new file:   lcd_test.py
new file:   pico_i2c_lcd.py

hcsr04Test.py [new file with mode: 0644]
lcd_api.py [new file with mode: 0644]
lcd_test.py [new file with mode: 0644]
pico_i2c_lcd.py [new file with mode: 0644]

diff --git a/hcsr04Test.py b/hcsr04Test.py
new file mode 100644 (file)
index 0000000..c499b48
--- /dev/null
@@ -0,0 +1,47 @@
+from machine import Pin, time_pulse_us, I2C
+import time
+from lcd_api import LcdApi
+from pico_i2c_lcd import I2cLcd
+
+# Define LCD I2C pins/BUS/address
+SDA = 2
+SCL = 3
+I2C_BUS = 1
+LCD_ADDR = 0x27
+
+msg=0
+# Define LCD rows/columns
+LCD_NUM_ROWS = 2
+LCD_NUM_COLS = 16
+
+# Set up LCD I2C
+lcdi2c = I2C(I2C_BUS, sda=machine.Pin(SDA), scl=machine.Pin(SCL), freq=400000)
+lcd = I2cLcd(lcdi2c, LCD_ADDR, LCD_NUM_ROWS, LCD_NUM_COLS)
+
+def lcdPrint(msg):
+    lcd.putstr(str(msg))
+    
+SOUND_SPEED=340
+TRIG_PULSE_DURATION=10
+
+trig_pin=Pin(1, Pin.OUT)
+echo_pin=Pin(0,Pin.IN)
+
+while True:
+    trig_pin.value(0)
+    time.sleep_us(5)
+    trig_pin.value(1)
+    time.sleep_us(TRIG_PULSE_DURATION)
+    trig_pin.value(0)
+    
+    ultransonic_duration=time_pulse_us(echo_pin,1,30000)
+    distance_cm=SOUND_SPEED*ultransonic_duration/20000
+    
+    print(f"Distance: {distance_cm} cm")
+    msg=(f"{distance_cm} cm")
+    lcdPrint(msg)
+    time.sleep_ms(500)
+    lcd.clear()
+    
+    
+    
\ No newline at end of file
diff --git a/lcd_api.py b/lcd_api.py
new file mode 100644 (file)
index 0000000..a6048a4
--- /dev/null
@@ -0,0 +1,186 @@
+import time
+
+class LcdApi:
+    
+    # Implements the API for talking with HD44780 compatible character LCDs.
+    # This class only knows what commands to send to the LCD, and not how to get
+    # them to the LCD.
+    #
+    # It is expected that a derived class will implement the hal_xxx functions.
+    #
+    # The following constant names were lifted from the avrlib lcd.h header file,
+    # with bit numbers changed to bit masks.
+    
+    # HD44780 LCD controller command set
+    LCD_CLR             = 0x01  # DB0: clear display
+    LCD_HOME            = 0x02  # DB1: return to home position
+
+    LCD_ENTRY_MODE      = 0x04  # DB2: set entry mode
+    LCD_ENTRY_INC       = 0x02  # DB1: increment
+    LCD_ENTRY_SHIFT     = 0x01  # DB0: shift
+
+    LCD_ON_CTRL         = 0x08  # DB3: turn lcd/cursor on
+    LCD_ON_DISPLAY      = 0x04  # DB2: turn display on
+    LCD_ON_CURSOR       = 0x02  # DB1: turn cursor on
+    LCD_ON_BLINK        = 0x01  # DB0: blinking cursor
+
+    LCD_MOVE            = 0x10  # DB4: move cursor/display
+    LCD_MOVE_DISP       = 0x08  # DB3: move display (0-> move cursor)
+    LCD_MOVE_RIGHT      = 0x04  # DB2: move right (0-> left)
+
+    LCD_FUNCTION        = 0x20  # DB5: function set
+    LCD_FUNCTION_8BIT   = 0x10  # DB4: set 8BIT mode (0->4BIT mode)
+    LCD_FUNCTION_2LINES = 0x08  # DB3: two lines (0->one line)
+    LCD_FUNCTION_10DOTS = 0x04  # DB2: 5x10 font (0->5x7 font)
+    LCD_FUNCTION_RESET  = 0x30  # See "Initializing by Instruction" section
+
+    LCD_CGRAM           = 0x40  # DB6: set CG RAM address
+    LCD_DDRAM           = 0x80  # DB7: set DD RAM address
+
+    LCD_RS_CMD          = 0
+    LCD_RS_DATA         = 1
+
+    LCD_RW_WRITE        = 0
+    LCD_RW_READ         = 1
+
+    def __init__(self, num_lines, num_columns):
+        self.num_lines = num_lines
+        if self.num_lines > 4:
+            self.num_lines = 4
+        self.num_columns = num_columns
+        if self.num_columns > 40:
+            self.num_columns = 40
+        self.cursor_x = 0
+        self.cursor_y = 0
+        self.implied_newline = False
+        self.backlight = True
+        self.display_off()
+        self.backlight_on()
+        self.clear()
+        self.hal_write_command(self.LCD_ENTRY_MODE | self.LCD_ENTRY_INC)
+        self.hide_cursor()
+        self.display_on()
+
+    def clear(self):
+        # Clears the LCD display and moves the cursor to the top left corner
+        self.hal_write_command(self.LCD_CLR)
+        self.hal_write_command(self.LCD_HOME)
+        self.cursor_x = 0
+        self.cursor_y = 0
+
+    def show_cursor(self):
+        # Causes the cursor to be made visible
+        self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY |
+                               self.LCD_ON_CURSOR)
+
+    def hide_cursor(self):
+        # Causes the cursor to be hidden
+        self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY)
+
+    def blink_cursor_on(self):
+        # Turns on the cursor, and makes it blink
+        self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY |
+                               self.LCD_ON_CURSOR | self.LCD_ON_BLINK)
+
+    def blink_cursor_off(self):
+        # Turns on the cursor, and makes it no blink (i.e. be solid)
+        self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY |
+                               self.LCD_ON_CURSOR)
+
+    def display_on(self):
+        # Turns on (i.e. unblanks) the LCD
+        self.hal_write_command(self.LCD_ON_CTRL | self.LCD_ON_DISPLAY)
+
+    def display_off(self):
+        # Turns off (i.e. blanks) the LCD
+        self.hal_write_command(self.LCD_ON_CTRL)
+
+    def backlight_on(self):
+        # Turns the backlight on.
+        
+        # This isn't really an LCD command, but some modules have backlight
+        # controls, so this allows the hal to pass through the command.
+        self.backlight = True
+        self.hal_backlight_on()
+
+    def backlight_off(self):
+        # Turns the backlight off.
+
+        # This isn't really an LCD command, but some modules have backlight
+        # controls, so this allows the hal to pass through the command.
+        self.backlight = False
+        self.hal_backlight_off()
+
+    def move_to(self, cursor_x, cursor_y):
+        # Moves the cursor position to the indicated position. The cursor
+        # position is zero based (i.e. cursor_x == 0 indicates first column).
+        self.cursor_x = cursor_x
+        self.cursor_y = cursor_y
+        addr = cursor_x & 0x3f
+        if cursor_y & 1:
+            addr += 0x40    # Lines 1 & 3 add 0x40
+        if cursor_y & 2:    # Lines 2 & 3 add number of columns
+            addr += self.num_columns
+        self.hal_write_command(self.LCD_DDRAM | addr)
+
+    def putchar(self, char):
+        # Writes the indicated character to the LCD at the current cursor
+        # position, and advances the cursor by one position.
+        if char == '\n':
+            if self.implied_newline:
+                # self.implied_newline means we advanced due to a wraparound,
+                # so if we get a newline right after that we ignore it.
+                pass
+            else:
+                self.cursor_x = self.num_columns
+        else:
+            self.hal_write_data(ord(char))
+            self.cursor_x += 1
+        if self.cursor_x >= self.num_columns:
+            self.cursor_x = 0
+            self.cursor_y += 1
+            self.implied_newline = (char != '\n')
+        if self.cursor_y >= self.num_lines:
+            self.cursor_y = 0
+        self.move_to(self.cursor_x, self.cursor_y)
+
+    def putstr(self, string):
+        # Write the indicated string to the LCD at the current cursor
+        # position and advances the cursor position appropriately.
+        for char in string:
+            self.putchar(char)
+
+    def custom_char(self, location, charmap):
+        # Write a character to one of the 8 CGRAM locations, available
+        # as chr(0) through chr(7).
+        location &= 0x7
+        self.hal_write_command(self.LCD_CGRAM | (location << 3))
+        self.hal_sleep_us(40)
+        for i in range(8):
+            self.hal_write_data(charmap[i])
+            self.hal_sleep_us(40)
+        self.move_to(self.cursor_x, self.cursor_y)
+
+    def hal_backlight_on(self):
+        # Allows the hal layer to turn the backlight on.
+        # If desired, a derived HAL class will implement this function.
+        pass
+
+    def hal_backlight_off(self):
+        # Allows the hal layer to turn the backlight off.
+        # If desired, a derived HAL class will implement this function.
+        pass
+
+    def hal_write_command(self, cmd):
+        # Write a command to the LCD.
+        # It is expected that a derived HAL class will implement this function.
+        raise NotImplementedError
+
+    def hal_write_data(self, data):
+        # Write data to the LCD.
+        # It is expected that a derived HAL class will implement this function.
+        raise NotImplementedError
+
+    def hal_sleep_us(self, usecs):
+        # Sleep for some time (given in microseconds)
+        time.sleep_us(usecs)
\ No newline at end of file
diff --git a/lcd_test.py b/lcd_test.py
new file mode 100644 (file)
index 0000000..a5eaf98
--- /dev/null
@@ -0,0 +1,24 @@
+from machine import I2C
+from lcd_api import LcdApi
+from pico_i2c_lcd import I2cLcd
+
+# Define LCD I2C pins/BUS/address
+SDA = 2
+SCL = 3
+I2C_BUS = 1
+LCD_ADDR = 0x27
+
+# Define LCD rows/columns
+LCD_NUM_ROWS = 2
+LCD_NUM_COLS = 16
+
+# Set up LCD I2C
+lcdi2c = I2C(I2C_BUS, sda=machine.Pin(SDA), scl=machine.Pin(SCL), freq=400000)
+lcd = I2cLcd(lcdi2c, LCD_ADDR, LCD_NUM_ROWS, LCD_NUM_COLS)
+
+# Show a string on the LCD
+lcd.putstr("Hello, World!")
+
+print("*********************************")
+print("Display is now showing characters")
+print("*********************************")
diff --git a/pico_i2c_lcd.py b/pico_i2c_lcd.py
new file mode 100644 (file)
index 0000000..8b02619
--- /dev/null
@@ -0,0 +1,86 @@
+import utime
+import gc
+
+from lcd_api import LcdApi
+from machine import I2C
+
+# PCF8574 pin definitions
+MASK_RS = 0x01       # P0
+MASK_RW = 0x02       # P1
+MASK_E  = 0x04       # P2
+
+SHIFT_BACKLIGHT = 3  # P3
+SHIFT_DATA      = 4  # P4-P7
+
+class I2cLcd(LcdApi):
+    
+    #Implements a HD44780 character LCD connected via PCF8574 on I2C
+
+    def __init__(self, i2c, i2c_addr, num_lines, num_columns):
+        self.i2c = i2c
+        self.i2c_addr = i2c_addr
+        self.i2c.writeto(self.i2c_addr, bytes([0]))
+        utime.sleep_ms(20)   # Allow LCD time to powerup
+        # Send reset 3 times
+        self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
+        utime.sleep_ms(5)    # Need to delay at least 4.1 msec
+        self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
+        utime.sleep_ms(1)
+        self.hal_write_init_nibble(self.LCD_FUNCTION_RESET)
+        utime.sleep_ms(1)
+        # Put LCD into 4-bit mode
+        self.hal_write_init_nibble(self.LCD_FUNCTION)
+        utime.sleep_ms(1)
+        LcdApi.__init__(self, num_lines, num_columns)
+        cmd = self.LCD_FUNCTION
+        if num_lines > 1:
+            cmd |= self.LCD_FUNCTION_2LINES
+        self.hal_write_command(cmd)
+        gc.collect()
+
+    def hal_write_init_nibble(self, nibble):
+        # Writes an initialization nibble to the LCD.
+        # This particular function is only used during initialization.
+        byte = ((nibble >> 4) & 0x0f) << SHIFT_DATA
+        self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
+        self.i2c.writeto(self.i2c_addr, bytes([byte]))
+        gc.collect()
+        
+    def hal_backlight_on(self):
+        # Allows the hal layer to turn the backlight on
+        self.i2c.writeto(self.i2c_addr, bytes([1 << SHIFT_BACKLIGHT]))
+        gc.collect()
+        
+    def hal_backlight_off(self):
+        #Allows the hal layer to turn the backlight off
+        self.i2c.writeto(self.i2c_addr, bytes([0]))
+        gc.collect()
+        
+    def hal_write_command(self, cmd):
+        # Write a command to the LCD. Data is latched on the falling edge of E.
+        byte = ((self.backlight << SHIFT_BACKLIGHT) |
+                (((cmd >> 4) & 0x0f) << SHIFT_DATA))
+        self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
+        self.i2c.writeto(self.i2c_addr, bytes([byte]))
+        byte = ((self.backlight << SHIFT_BACKLIGHT) |
+                ((cmd & 0x0f) << SHIFT_DATA))
+        self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
+        self.i2c.writeto(self.i2c_addr, bytes([byte]))
+        if cmd <= 3:
+            # The home and clear commands require a worst case delay of 4.1 msec
+            utime.sleep_ms(5)
+        gc.collect()
+
+    def hal_write_data(self, data):
+        # Write data to the LCD. Data is latched on the falling edge of E.
+        byte = (MASK_RS |
+                (self.backlight << SHIFT_BACKLIGHT) |
+                (((data >> 4) & 0x0f) << SHIFT_DATA))
+        self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
+        self.i2c.writeto(self.i2c_addr, bytes([byte]))
+        byte = (MASK_RS |
+                (self.backlight << SHIFT_BACKLIGHT) |
+                ((data & 0x0f) << SHIFT_DATA))      
+        self.i2c.writeto(self.i2c_addr, bytes([byte | MASK_E]))
+        self.i2c.writeto(self.i2c_addr, bytes([byte]))
+        gc.collect()
\ No newline at end of file