/ adafruit_character_lcd / character_lcd.py
character_lcd.py
1 # The MIT License (MIT) 2 # 3 # Copyright (c) 2017 Brent Rubell for Adafruit Industries 4 # Copyright (c) 2018 Kattni Rembor for Adafruit Industries 5 # 6 # Permission is hereby granted, free of charge, to any person obtaining a copy 7 # of this software and associated documentation files (the "Software"), to deal 8 # in the Software without restriction, including without limitation the rights 9 # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 # copies of the Software, and to permit persons to whom the Software is 11 # furnished to do so, subject to the following conditions: 12 # 13 # The above copyright notice and this permission notice shall be included in 14 # all copies or substantial portions of the Software. 15 # 16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 # THE SOFTWARE. 23 """ 24 `adafruit_character_lcd.character_lcd` 25 ==================================================== 26 27 Module for interfacing with monochromatic character LCDs 28 29 * Author(s): Kattni Rembor, Brent Rubell, Asher Lieber, 30 Tony DiCola (original python charLCD library) 31 32 Implementation Notes 33 -------------------- 34 35 **Hardware:** 36 37 "* `Adafruit Character LCDs <http://www.adafruit.com/category/63_96>`_" 38 39 **Software and Dependencies:** 40 41 * Adafruit CircuitPython firmware: 42 https://github.com/adafruit/circuitpython/releases 43 * Adafruit's Bus Device library (when using I2C/SPI): 44 https://github.com/adafruit/Adafruit_CircuitPython_BusDevice 45 46 """ 47 48 import time 49 import digitalio 50 from micropython import const 51 52 __version__ = "0.0.0-auto.0" 53 __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_CharLCD.git" 54 55 # pylint: disable-msg=bad-whitespace 56 # Commands 57 _LCD_CLEARDISPLAY = const(0x01) 58 _LCD_RETURNHOME = const(0x02) 59 _LCD_ENTRYMODESET = const(0x04) 60 _LCD_DISPLAYCONTROL = const(0x08) 61 _LCD_CURSORSHIFT = const(0x10) 62 _LCD_FUNCTIONSET = const(0x20) 63 _LCD_SETCGRAMADDR = const(0x40) 64 _LCD_SETDDRAMADDR = const(0x80) 65 66 # Entry flags 67 _LCD_ENTRYLEFT = const(0x02) 68 _LCD_ENTRYSHIFTDECREMENT = const(0x00) 69 70 # Control flags 71 _LCD_DISPLAYON = const(0x04) 72 _LCD_CURSORON = const(0x02) 73 _LCD_CURSOROFF = const(0x00) 74 _LCD_BLINKON = const(0x01) 75 _LCD_BLINKOFF = const(0x00) 76 77 # Move flags 78 _LCD_DISPLAYMOVE = const(0x08) 79 _LCD_MOVERIGHT = const(0x04) 80 _LCD_MOVELEFT = const(0x00) 81 82 # Function set flags 83 _LCD_4BITMODE = const(0x00) 84 _LCD_2LINE = const(0x08) 85 _LCD_1LINE = const(0x00) 86 _LCD_5X8DOTS = const(0x00) 87 88 # Offset for up to 4 rows. 89 _LCD_ROW_OFFSETS = (0x00, 0x40, 0x14, 0x54) 90 91 # pylint: enable-msg=bad-whitespace 92 93 94 def _set_bit(byte_value, position, val): 95 # Given the specified byte_value set the bit at position to the provided 96 # boolean value val and return the modified byte. 97 ret = None 98 if val: 99 ret = byte_value | (1 << position) 100 else: 101 ret = byte_value & ~(1 << position) 102 return ret 103 104 105 def _map(xval, in_min, in_max, out_min, out_max): 106 # Affine transfer/map with constrained output. 107 outrange = float(out_max - out_min) 108 inrange = float(in_max - in_min) 109 ret = (xval - in_min) * (outrange / inrange) + out_min 110 if out_max > out_min: 111 ret = max(min(ret, out_max), out_min) 112 else: 113 ret = max(min(ret, out_min), out_max) 114 return ret 115 116 117 # pylint: disable-msg=too-many-instance-attributes 118 class Character_LCD: 119 """Base class for character LCD. 120 121 :param ~digitalio.DigitalInOut rs: The reset data line 122 :param ~digitalio.DigitalInOut en: The enable data line 123 :param ~digitalio.DigitalInOut d4: The data line 4 124 :param ~digitalio.DigitalInOut d5: The data line 5 125 :param ~digitalio.DigitalInOut d6: The data line 6 126 :param ~digitalio.DigitalInOut d7: The data line 7 127 :param columns: The columns on the charLCD 128 :param lines: The lines on the charLCD 129 130 """ 131 132 LEFT_TO_RIGHT = const(0) 133 RIGHT_TO_LEFT = const(1) 134 135 # pylint: disable-msg=too-many-arguments 136 def __init__(self, rs, en, d4, d5, d6, d7, columns, lines): 137 138 self.columns = columns 139 self.lines = lines 140 # save pin numbers 141 self.reset = rs 142 self.enable = en 143 self.dl4 = d4 144 self.dl5 = d5 145 self.dl6 = d6 146 self.dl7 = d7 147 148 # set all pins as outputs 149 for pin in (rs, en, d4, d5, d6, d7): 150 pin.direction = digitalio.Direction.OUTPUT 151 152 # Initialise the display 153 self._write8(0x33) 154 self._write8(0x32) 155 # Initialise display control 156 self.displaycontrol = _LCD_DISPLAYON | _LCD_CURSOROFF | _LCD_BLINKOFF 157 # Initialise display function 158 self.displayfunction = _LCD_4BITMODE | _LCD_1LINE | _LCD_2LINE | _LCD_5X8DOTS 159 # Initialise display mode 160 self.displaymode = _LCD_ENTRYLEFT | _LCD_ENTRYSHIFTDECREMENT 161 # Write to displaycontrol 162 self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol) 163 # Write to displayfunction 164 self._write8(_LCD_FUNCTIONSET | self.displayfunction) 165 # Set entry mode 166 self._write8(_LCD_ENTRYMODESET | self.displaymode) 167 self.clear() 168 169 self._message = None 170 self._enable = None 171 self._direction = None 172 # track row and column used in cursor_position 173 # initialize to 0,0 174 self.row = 0 175 self.column = 0 176 self._column_align = False 177 178 # pylint: enable-msg=too-many-arguments 179 180 def home(self): 181 """Moves the cursor "home" to position (1, 1).""" 182 self._write8(_LCD_RETURNHOME) 183 time.sleep(0.003) 184 185 def clear(self): 186 """Clears everything displayed on the LCD. 187 188 The following example displays, "Hello, world!", then clears the LCD. 189 190 .. code-block:: python 191 192 import time 193 import board 194 import busio 195 import adafruit_character_lcd.character_lcd_i2c as character_lcd 196 197 i2c = busio.I2C(board.SCL, board.SDA) 198 lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) 199 200 lcd.message = "Hello, world!" 201 time.sleep(5) 202 lcd.clear() 203 """ 204 self._write8(_LCD_CLEARDISPLAY) 205 time.sleep(0.003) 206 207 @property 208 def column_align(self): 209 """If True, message text after '\\n' starts directly below start of first 210 character in message. If False, text after '\\n' starts at column zero. 211 """ 212 return self._column_align 213 214 @column_align.setter 215 def column_align(self, enable): 216 if isinstance(enable, bool): 217 self._column_align = enable 218 else: 219 raise ValueError("The column_align value must be either True or False") 220 221 @property 222 def cursor(self): 223 """True if cursor is visible. False to stop displaying the cursor. 224 225 The following example shows the cursor after a displayed message: 226 227 .. code-block:: python 228 229 import time 230 import board 231 import busio 232 import adafruit_character_lcd.character_lcd_i2c as character_lcd 233 234 i2c = busio.I2C(board.SCL, board.SDA) 235 lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) 236 237 lcd.cursor = True 238 lcd.message = "Cursor! " 239 time.sleep(5) 240 241 """ 242 return self.displaycontrol & _LCD_CURSORON == _LCD_CURSORON 243 244 @cursor.setter 245 def cursor(self, show): 246 if show: 247 self.displaycontrol |= _LCD_CURSORON 248 else: 249 self.displaycontrol &= ~_LCD_CURSORON 250 self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol) 251 252 def cursor_position(self, column, row): 253 """Move the cursor to position ``column``, ``row`` for the next 254 message only. Displaying a message resets the cursor position to (0, 0). 255 256 :param column: column location 257 :param row: row location 258 """ 259 # Clamp row to the last row of the display 260 if row >= self.lines: 261 row = self.lines - 1 262 # Clamp to last column of display 263 if column >= self.columns: 264 column = self.columns - 1 265 # Set location 266 self._write8(_LCD_SETDDRAMADDR | (column + _LCD_ROW_OFFSETS[row])) 267 # Update self.row and self.column to match setter 268 self.row = row 269 self.column = column 270 271 @property 272 def blink(self): 273 """ 274 Blink the cursor. True to blink the cursor. False to stop blinking. 275 276 The following example shows a message followed by a blinking cursor for five seconds. 277 278 .. code-block:: python 279 280 import time 281 import board 282 import busio 283 import adafruit_character_lcd.character_lcd_i2c as character_lcd 284 285 i2c = busio.I2C(board.SCL, board.SDA) 286 lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) 287 288 lcd.blink = True 289 lcd.message = "Blinky cursor!" 290 time.sleep(5) 291 lcd.blink = False 292 """ 293 return self.displaycontrol & _LCD_BLINKON == _LCD_BLINKON 294 295 @blink.setter 296 def blink(self, blink): 297 if blink: 298 self.displaycontrol |= _LCD_BLINKON 299 else: 300 self.displaycontrol &= ~_LCD_BLINKON 301 self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol) 302 303 @property 304 def display(self): 305 """ 306 Enable or disable the display. True to enable the display. False to disable the display. 307 308 The following example displays, "Hello, world!" on the LCD and then turns the display off. 309 310 .. code-block:: python 311 312 import time 313 import board 314 import busio 315 import adafruit_character_lcd.character_lcd_i2c as character_lcd 316 317 i2c = busio.I2C(board.SCL, board.SDA) 318 lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) 319 320 lcd.message = "Hello, world!" 321 time.sleep(5) 322 lcd.display = False 323 """ 324 return self.displaycontrol & _LCD_DISPLAYON == _LCD_DISPLAYON 325 326 @display.setter 327 def display(self, enable): 328 if enable: 329 self.displaycontrol |= _LCD_DISPLAYON 330 else: 331 self.displaycontrol &= ~_LCD_DISPLAYON 332 self._write8(_LCD_DISPLAYCONTROL | self.displaycontrol) 333 334 @property 335 def message(self): 336 """Display a string of text on the character LCD. 337 Start position is (0,0) if cursor_position is not set. 338 If cursor_position is set, message starts at the set 339 position from the left for left to right text and from 340 the right for right to left text. Resets cursor column 341 and row to (0,0) after displaying the message. 342 343 The following example displays, "Hello, world!" on the LCD. 344 345 .. code-block:: python 346 347 import time 348 import board 349 import busio 350 import adafruit_character_lcd.character_lcd_i2c as character_lcd 351 352 i2c = busio.I2C(board.SCL, board.SDA) 353 lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) 354 355 lcd.message = "Hello, world!" 356 time.sleep(5) 357 """ 358 return self._message 359 360 @message.setter 361 def message(self, message): 362 self._message = message 363 # Set line to match self.row from cursor_position() 364 line = self.row 365 # Track times through iteration, to act on the initial character of the message 366 initial_character = 0 367 # iterate through each character 368 for character in message: 369 # If this is the first character in the string: 370 if initial_character == 0: 371 # Start at (0, 0) unless direction is set right to left, in which case start 372 # on the opposite side of the display if cursor_position not set or (0,0) 373 # If cursor_position is set then starts at the specified location for 374 # LEFT_TO_RIGHT. If RIGHT_TO_LEFT cursor_position is determined from right. 375 # allows for cursor_position to work in RIGHT_TO_LEFT mode 376 if self.displaymode & _LCD_ENTRYLEFT > 0: 377 col = self.column 378 else: 379 col = self.columns - 1 - self.column 380 self.cursor_position(col, line) 381 initial_character += 1 382 # If character is \n, go to next line 383 if character == "\n": 384 line += 1 385 # Start the second line at (0, 1) unless direction is set right to left in 386 # which case start on the opposite side of the display if cursor_position 387 # is (0,0) or not set. Start second line at same column as first line when 388 # cursor_position is set 389 if self.displaymode & _LCD_ENTRYLEFT > 0: 390 col = self.column * self._column_align 391 else: 392 if self._column_align: 393 col = self.column 394 else: 395 col = self.columns - 1 396 self.cursor_position(col, line) 397 # Write string to display 398 else: 399 self._write8(ord(character), True) 400 # reset column and row to (0,0) after message is displayed 401 self.column, self.row = 0, 0 402 403 def move_left(self): 404 """Moves displayed text left one column. 405 406 The following example scrolls a message to the left off the screen. 407 408 .. code-block:: python 409 410 import time 411 import board 412 import busio 413 import adafruit_character_lcd.character_lcd_i2c as character_lcd 414 415 i2c = busio.I2C(board.SCL, board.SDA) 416 lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) 417 418 scroll_message = "<-- Scroll" 419 lcd.message = scroll_message 420 time.sleep(2) 421 for i in range(len(scroll_message)): 422 lcd.move_left() 423 time.sleep(0.5) 424 """ 425 self._write8(_LCD_CURSORSHIFT | _LCD_DISPLAYMOVE | _LCD_MOVELEFT) 426 427 def move_right(self): 428 """Moves displayed text right one column. 429 430 The following example scrolls a message to the right off the screen. 431 432 .. code-block:: python 433 434 import time 435 import board 436 import busio 437 import adafruit_character_lcd.character_lcd_i2c as character_lcd 438 439 i2c = busio.I2C(board.SCL, board.SDA) 440 lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) 441 442 scroll_message = "Scroll -->" 443 lcd.message = scroll_message 444 time.sleep(2) 445 for i in range(len(scroll_message) + 16): 446 lcd.move_right() 447 time.sleep(0.5) 448 """ 449 self._write8(_LCD_CURSORSHIFT | _LCD_DISPLAYMOVE | _LCD_MOVERIGHT) 450 451 @property 452 def text_direction(self): 453 """The direction the text is displayed. To display the text left to right beginning on the 454 left side of the LCD, set ``text_direction = LEFT_TO_RIGHT``. To display the text right 455 to left beginning on the right size of the LCD, set ``text_direction = RIGHT_TO_LEFT``. 456 Text defaults to displaying from left to right. 457 458 The following example displays "Hello, world!" from right to left. 459 460 .. code-block:: python 461 462 import time 463 import board 464 import busio 465 import adafruit_character_lcd.character_lcd_i2c as character_lcd 466 467 i2c = busio.I2C(board.SCL, board.SDA) 468 lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) 469 470 lcd.text_direction = lcd.RIGHT_TO_LEFT 471 lcd.message = "Hello, world!" 472 time.sleep(5) 473 """ 474 return self._direction 475 476 @text_direction.setter 477 def text_direction(self, direction): 478 self._direction = direction 479 if direction == self.LEFT_TO_RIGHT: 480 self._left_to_right() 481 elif direction == self.RIGHT_TO_LEFT: 482 self._right_to_left() 483 484 def _left_to_right(self): 485 # Displays text from left to right on the LCD. 486 self.displaymode |= _LCD_ENTRYLEFT 487 self._write8(_LCD_ENTRYMODESET | self.displaymode) 488 489 def _right_to_left(self): 490 # Displays text from right to left on the LCD. 491 self.displaymode &= ~_LCD_ENTRYLEFT 492 self._write8(_LCD_ENTRYMODESET | self.displaymode) 493 494 def create_char(self, location, pattern): 495 """ 496 Fill one of the first 8 CGRAM locations with custom characters. 497 The location parameter should be between 0 and 7 and pattern should 498 provide an array of 8 bytes containing the pattern. E.g. you can easily 499 design your custom character at http://www.quinapalus.com/hd44780udg.html 500 To show your custom character use, for example, ``lcd.message = "\x01"`` 501 502 :param location: integer in range(8) to store the created character 503 :param ~bytes pattern: len(8) describes created character 504 505 """ 506 # only position 0..7 are allowed 507 location &= 0x7 508 self._write8(_LCD_SETCGRAMADDR | (location << 3)) 509 for i in range(8): 510 self._write8(pattern[i], char_mode=True) 511 512 def _write8(self, value, char_mode=False): 513 # Sends 8b ``value`` in ``char_mode``. 514 # :param value: bytes 515 # :param char_mode: character/data mode selector. False (default) for 516 # data only, True for character bits. 517 # one ms delay to prevent writing too quickly. 518 time.sleep(0.001) 519 # set character/data bit. (charmode = False) 520 self.reset.value = char_mode 521 # WRITE upper 4 bits 522 self.dl4.value = ((value >> 4) & 1) > 0 523 self.dl5.value = ((value >> 5) & 1) > 0 524 self.dl6.value = ((value >> 6) & 1) > 0 525 self.dl7.value = ((value >> 7) & 1) > 0 526 # send command 527 self._pulse_enable() 528 # WRITE lower 4 bits 529 self.dl4.value = (value & 1) > 0 530 self.dl5.value = ((value >> 1) & 1) > 0 531 self.dl6.value = ((value >> 2) & 1) > 0 532 self.dl7.value = ((value >> 3) & 1) > 0 533 self._pulse_enable() 534 535 def _pulse_enable(self): 536 # Pulses (lo->hi->lo) to send commands. 537 self.enable.value = False 538 # 1microsec pause 539 time.sleep(0.0000001) 540 self.enable.value = True 541 time.sleep(0.0000001) 542 self.enable.value = False 543 time.sleep(0.0000001) 544 545 546 # pylint: enable-msg=too-many-instance-attributes 547 548 549 # pylint: disable-msg=too-many-instance-attributes 550 class Character_LCD_Mono(Character_LCD): 551 """Interfaces with monochromatic character LCDs. 552 553 :param ~digitalio.DigitalInOut rs: The reset data line 554 :param ~digitalio.DigitalInOut en: The enable data line 555 :param ~digitalio.DigitalInOut d4: The data line 4 556 :param ~digitalio.DigitalInOut d5: The data line 5 557 :param ~digitalio.DigitalInOut d6: The data line 6 558 :param ~digitalio.DigitalInOut d7: The data line 7 559 :param columns: The columns on the charLCD 560 :param lines: The lines on the charLCD 561 :param ~digitalio.DigitalInOut backlight_pin: The backlight pin 562 :param bool backlight_inverted: ``False`` if LCD is not inverted, i.e. backlight pin is 563 connected to common anode. ``True`` if LCD is inverted i.e. backlight pin is connected 564 to common cathode. 565 566 """ 567 568 # pylint: disable-msg=too-many-arguments 569 def __init__( 570 self, 571 rs, 572 en, 573 db4, 574 db5, 575 db6, 576 db7, 577 columns, 578 lines, 579 backlight_pin=None, 580 backlight_inverted=False, 581 ): 582 583 # Backlight pin and inversion 584 self.backlight_pin = backlight_pin 585 self.backlight_inverted = backlight_inverted 586 587 # Setup backlight 588 if backlight_pin is not None: 589 self.backlight_pin.direction = digitalio.Direction.OUTPUT 590 self.backlight = True 591 super().__init__(rs, en, db4, db5, db6, db7, columns, lines) 592 593 # pylint: enable-msg=too-many-arguments 594 595 @property 596 def backlight(self): 597 """Enable or disable backlight. True if backlight is on. False if backlight is off. 598 599 The following example turns the backlight off, then displays, "Hello, world?", then turns 600 the backlight on and displays, "Hello, world!" 601 602 .. code-block:: python 603 604 import time 605 import board 606 import busio 607 import adafruit_character_lcd.character_lcd_i2c as character_lcd 608 609 i2c = busio.I2C(board.SCL, board.SDA) 610 611 lcd = character_lcd.Character_LCD_I2C(i2c, 16, 2) 612 613 lcd.backlight = False 614 lcd.message = "Hello, world?" 615 time.sleep(5) 616 lcd.backlight = True 617 lcd.message = "Hello, world!" 618 time.sleep(5) 619 620 """ 621 return self._enable 622 623 @backlight.setter 624 def backlight(self, enable): 625 self._enable = enable 626 if enable: 627 self.backlight_pin.value = not self.backlight_inverted 628 else: 629 self.backlight_pin.value = self.backlight_inverted 630 631 632 class Character_LCD_RGB(Character_LCD): 633 """Interfaces with RGB character LCDs. 634 635 :param ~digitalio.DigitalInOut rs: The reset data line 636 :param ~digitalio.DigitalInOut en: The enable data line 637 :param ~digitalio.DigitalInOut db4: The data line 4 638 :param ~digitalio.DigitalInOut db5: The data line 5 639 :param ~digitalio.DigitalInOut db6: The data line 6 640 :param ~digitalio.DigitalInOut db7: The data line 7 641 :param columns: The columns on the charLCD 642 :param lines: The lines on the charLCD 643 :param ~pulseio.PWMOut, ~digitalio.DigitalInOut red: Red RGB Anode 644 :param ~pulseio.PWMOut, ~digitalio.DigitalInOut green: Green RGB Anode 645 :param ~pulseio.PWMOut, ~digitalio.DigitalInOut blue: Blue RGB Anode 646 :param ~digitalio.DigitalInOut read_write: The rw pin. Determines whether to read to or 647 write from the display. Not necessary if only writing to the display. Used on shield. 648 649 """ 650 651 # pylint: disable-msg=too-many-arguments 652 def __init__( 653 self, 654 rs, 655 en, 656 db4, 657 db5, 658 db6, 659 db7, 660 columns, 661 lines, 662 red, 663 green, 664 blue, 665 read_write=None, 666 ): 667 668 # Define read_write (rw) pin 669 self.read_write = read_write 670 671 # Setup rw pin if used 672 if read_write is not None: 673 self.read_write.direction = digitalio.Direction.OUTPUT 674 675 # define color params 676 self.rgb_led = [red, green, blue] 677 678 for pin in self.rgb_led: 679 if hasattr(pin, "direction"): 680 # Assume a digitalio.DigitalInOut or compatible interface: 681 pin.direction = digitalio.Direction.OUTPUT 682 elif not hasattr(pin, "duty_cycle"): 683 raise TypeError( 684 "RGB LED objects must be instances of digitalio.DigitalInOut" 685 " or pulseio.PWMOut, or provide a compatible interface." 686 ) 687 688 self._color = [0, 0, 0] 689 super().__init__(rs, en, db4, db5, db6, db7, columns, lines) 690 691 @property 692 def color(self): 693 """ 694 The color of the display. Provide a list of three integers ranging 0 - 100, ``[R, G, B]``. 695 ``0`` is no color, or "off". ``100`` is maximum color. For example, the brightest red would 696 be ``[100, 0, 0]``, and a half-bright purple would be, ``[50, 0, 50]``. 697 698 If PWM is unavailable, ``0`` is off, and non-zero is on. For example, ``[1, 0, 0]`` would 699 be red. 700 701 The following example turns the LCD red and displays, "Hello, world!". 702 703 .. code-block:: python 704 705 import time 706 import board 707 import busio 708 import adafruit_character_lcd.character_lcd_rgb_i2c as character_lcd 709 710 i2c = busio.I2C(board.SCL, board.SDA) 711 712 lcd = character_lcd.Character_LCD_RGB_I2C(i2c, 16, 2) 713 714 lcd.color = [100, 0, 0] 715 lcd.message = "Hello, world!" 716 time.sleep(5) 717 """ 718 return self._color 719 720 @color.setter 721 def color(self, color): 722 self._color = color 723 for number, pin in enumerate(self.rgb_led): 724 if hasattr(pin, "duty_cycle"): 725 # Assume a pulseio.PWMOut or compatible interface and set duty cycle: 726 pin.duty_cycle = int(_map(color[number], 0, 100, 65535, 0)) 727 elif hasattr(pin, "value"): 728 # If we don't have a PWM interface, all we can do is turn each color 729 # on / off. Assume a DigitalInOut (or compatible interface) and write 730 # 0 (on) to pin for any value greater than 0, or 1 (off) for 0: 731 pin.value = not color[number] > 1