223 lines
8.5 KiB
Python
223 lines
8.5 KiB
Python
# coding=utf-8
|
|
|
|
__author__ = "Franziska Kunsmann <hi@kunsmann.eu>"
|
|
__license__ = "GNU Affero General Public License http://www.gnu.org/licenses/agpl.html"
|
|
__copyright__ = "Copyright (C) 2017 Franziska Kunsmann - Released under terms of the AGPLv3 License"
|
|
|
|
import octoprint.plugin
|
|
from octoprint.util import RepeatedTimer
|
|
import RPi.GPIO as GPIO
|
|
import time
|
|
|
|
class LCD_HD44780(octoprint.plugin.StartupPlugin,
|
|
octoprint.plugin.SettingsPlugin,
|
|
octoprint.printer.PrinterCallback):
|
|
def __init__(self):
|
|
self._pin_to_gpio_rev1 = [-1, -1, -1, 0, -1, 1, -1, 4, 14, -1, 15, 17, 18, 21, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ]
|
|
self._pin_to_gpio_rev2 = [-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 ]
|
|
self._pin_to_gpio_rev3 = [-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, 5, -1, 6, 12, 13, -1, 19, 16, 26, 20, -1, 21 ]
|
|
self._configuredGPIOPins = []
|
|
|
|
# FIXME hardcoded GPIO pins
|
|
self.pin_rs = 15
|
|
self.pin_e = 16
|
|
self.pin_d4 = 21
|
|
self.pin_d5 = 22
|
|
self.pin_d6 = 23
|
|
self.pin_d7 = 24
|
|
|
|
self.cols = 20
|
|
self.rows = 4
|
|
|
|
self._ClosedOrError = False
|
|
|
|
self._line1 = ''
|
|
self._line2 = ''
|
|
self._line3 = ''
|
|
self._line4 = ''
|
|
|
|
self._lcd_line1 = 0x80
|
|
self._lcd_line2 = 0xC0
|
|
self._lcd_chr = GPIO.HIGH
|
|
self._lcd_cmd = GPIO.LOW
|
|
self._lcd_pulse = 0.0005
|
|
self._lcd_delay = 0.0005
|
|
|
|
self._lcd_updating = False
|
|
|
|
def on_settings_initialized(self):
|
|
self._initialize_lcd()
|
|
self._printer.register_callback(self)
|
|
|
|
def _gpio_board_to_bcm(self, pin):
|
|
if GPIO.RPI_REVISION == 1:
|
|
pin_to_gpio = self._pin_to_gpio_rev1
|
|
elif GPIO.RPI_REVISION == 2:
|
|
pin_to_gpio = self._pin_to_gpio_rev2
|
|
else:
|
|
pin_to_gpio = self._pin_to_gpio_rev3
|
|
|
|
return pin_to_gpio[pin]
|
|
|
|
def _gpio_get_pin(self, pin):
|
|
if GPIO.getmode() == GPIO.BOARD:
|
|
return pin
|
|
elif GPIO.getmode() == GPIO.BCM:
|
|
return self._gpio_board_to_bcm(pin)
|
|
else:
|
|
return 0
|
|
|
|
def _initialize_lcd(self):
|
|
self._logger.info("Running RPi.GPIO version %s" % GPIO.VERSION)
|
|
if GPIO.VERSION < "0.6":
|
|
self._logger.error("RPi.GPIO version 0.6.0 or greater required.")
|
|
|
|
GPIO.setwarnings(False)
|
|
|
|
for pin in self._configuredGPIOPins:
|
|
self._logger.debug("Cleaning up pin %s" % pin)
|
|
try:
|
|
GPIO.cleanup(self._gpio_get_pin(pin))
|
|
except (RuntimeError, ValueError) as e:
|
|
self._logger.error(e)
|
|
self._configuredGPIOPins = []
|
|
|
|
if GPIO.getmode() is None:
|
|
GPIO.setmode(GPIO.BOARD)
|
|
|
|
GPIO.setup(self._gpio_get_pin(self.pin_rs), GPIO.OUT)
|
|
GPIO.setup(self._gpio_get_pin(self.pin_e), GPIO.OUT)
|
|
GPIO.setup(self._gpio_get_pin(self.pin_d4), GPIO.OUT)
|
|
GPIO.setup(self._gpio_get_pin(self.pin_d5), GPIO.OUT)
|
|
GPIO.setup(self._gpio_get_pin(self.pin_d6), GPIO.OUT)
|
|
GPIO.setup(self._gpio_get_pin(self.pin_d7), GPIO.OUT)
|
|
|
|
self._configuredGPIOPins = [self._gpio_get_pin(self.pin_rs), self._gpio_get_pin(self.pin_e), self._gpio_get_pin(self.pin_d4), self._gpio_get_pin(self.pin_d5), self._gpio_get_pin(self.pin_d6), self._gpio_get_pin(self.pin_d7)]
|
|
|
|
# FIXME hardcoded LCD size
|
|
self._lcd_send_byte(0x33, self._lcd_cmd)
|
|
self._lcd_send_byte(0x32, self._lcd_cmd)
|
|
self._lcd_send_byte(0x28, self._lcd_cmd)
|
|
self._lcd_send_byte(0x0C, self._lcd_cmd)
|
|
self._lcd_send_byte(0x06, self._lcd_cmd)
|
|
self._lcd_send_byte(0x01, self._lcd_cmd)
|
|
|
|
printerstate = self._printer.get_state_string()
|
|
self._line1 = printerstate.center(20)
|
|
self.clear_lower_half()
|
|
|
|
timer = RepeatedTimer(30, self._lcd_update())
|
|
timer.start()
|
|
|
|
def _lcd_update(self):
|
|
if self._lcd_updating:
|
|
return
|
|
|
|
bytes_per_send_cycle = int(self.cols*(self.rows/2))
|
|
|
|
self._lcd_updating = True
|
|
|
|
line1 = self._line1.ljust(self.cols, ' ')
|
|
line2 = self._line2.ljust(self.cols, ' ')
|
|
line3 = self._line3.ljust(self.cols, ' ')
|
|
line4 = self._line4.ljust(self.cols, ' ')
|
|
|
|
message = line1 + line3
|
|
self._lcd_send_byte(self._lcd_line1, self._lcd_cmd)
|
|
for i in range(bytes_per_send_cycle):
|
|
self._lcd_send_byte(ord(message[i]), self._lcd_chr)
|
|
|
|
message = line2 + line4
|
|
self._lcd_send_byte(self._lcd_line2, self._lcd_cmd)
|
|
for i in range(bytes_per_send_cycle):
|
|
self._lcd_send_byte(ord(message[i]), self._lcd_chr)
|
|
|
|
self._lcd_updating = False
|
|
|
|
def _lcd_send_byte(self, bits, mode):
|
|
GPIO.output(self._gpio_get_pin(self.pin_rs), mode)
|
|
GPIO.output(self._gpio_get_pin(self.pin_d4), GPIO.LOW)
|
|
GPIO.output(self._gpio_get_pin(self.pin_d5), GPIO.LOW)
|
|
GPIO.output(self._gpio_get_pin(self.pin_d6), GPIO.LOW)
|
|
GPIO.output(self._gpio_get_pin(self.pin_d7), GPIO.LOW)
|
|
if bits & 0x10 == 0x10:
|
|
GPIO.output(self._gpio_get_pin(self.pin_d4), GPIO.HIGH)
|
|
if bits & 0x20 == 0x20:
|
|
GPIO.output(self._gpio_get_pin(self.pin_d5), GPIO.HIGH)
|
|
if bits & 0x40 == 0x40:
|
|
GPIO.output(self._gpio_get_pin(self.pin_d6), GPIO.HIGH)
|
|
if bits & 0x80 == 0x80:
|
|
GPIO.output(self._gpio_get_pin(self.pin_d7), GPIO.HIGH)
|
|
time.sleep(self._lcd_delay)
|
|
GPIO.output(self._gpio_get_pin(self.pin_e), GPIO.HIGH)
|
|
time.sleep(self._lcd_pulse)
|
|
GPIO.output(self._gpio_get_pin(self.pin_e), GPIO.LOW)
|
|
time.sleep(self._lcd_delay)
|
|
GPIO.output(self._gpio_get_pin(self.pin_d4), GPIO.LOW)
|
|
GPIO.output(self._gpio_get_pin(self.pin_d5), GPIO.LOW)
|
|
GPIO.output(self._gpio_get_pin(self.pin_d6), GPIO.LOW)
|
|
GPIO.output(self._gpio_get_pin(self.pin_d7), GPIO.LOW)
|
|
if bits&0x01==0x01:
|
|
GPIO.output(self._gpio_get_pin(self.pin_d4), GPIO.HIGH)
|
|
if bits&0x02==0x02:
|
|
GPIO.output(self._gpio_get_pin(self.pin_d5), GPIO.HIGH)
|
|
if bits&0x04==0x04:
|
|
GPIO.output(self._gpio_get_pin(self.pin_d6), GPIO.HIGH)
|
|
if bits&0x08==0x08:
|
|
GPIO.output(self._gpio_get_pin(self.pin_d7), GPIO.HIGH)
|
|
time.sleep(self._lcd_delay)
|
|
GPIO.output(self._gpio_get_pin(self.pin_e), GPIO.HIGH)
|
|
time.sleep(self._lcd_pulse)
|
|
GPIO.output(self._gpio_get_pin(self.pin_e), GPIO.LOW)
|
|
time.sleep(self._lcd_delay)
|
|
|
|
def on_printer_add_temperature(self, data):
|
|
if not self._ClosedOrError:
|
|
self._line4 = 'E{:3.0f}/{:3.0f} B{:3.0f}/{:3.0f}'.format(data['tool0']['actual'], data['tool0']['target'], data['bed']['actual'], data['bed']['target'])
|
|
self._lcd_update()
|
|
else:
|
|
self.clear_lower_half()
|
|
|
|
def on_printer_send_current_data(self, data):
|
|
self._line1 = data['state']['text'][:20].center(20)
|
|
|
|
self._ClosedOrError = data['state']['flags']['closedOrError']
|
|
|
|
if not self._ClosedOrError:
|
|
if data['job']['file']['name'] is not None:
|
|
self._line2 = data['job']['file']['name'][:20]
|
|
else:
|
|
self._line2 = ''
|
|
|
|
if data['progress']['completion'] is not None:
|
|
self._line3 = '{:6.2f}'.format(data['progress']['completion']) + '%'
|
|
|
|
if data['progress']['printTimeLeft'] is not None:
|
|
self._line3 += ' ~' + '{:1.0f}:{:02.0f}:{:02.0f}'.format(data['progress']['printTimeLeft']/3600, data['progress']['printTimeLeft']%3600/60, data['progress']['printTimeLeft']%60)
|
|
else:
|
|
self._line3 = ''
|
|
else:
|
|
self.clear_lower_half()
|
|
|
|
self._lcd_update()
|
|
|
|
def clear_lower_half(self):
|
|
self._line2 = ''
|
|
self._line3 = ''
|
|
|
|
line4 = 'OctoPrint ' + octoprint.__version__
|
|
|
|
self._line4 = line4.center(20)
|
|
|
|
|
|
__plugin_name__ = "LCD: HD44780-compatible"
|
|
__plugin_author__ = "Kunsi"
|
|
__plugin_pythoncompat__ = ">=3,<4"
|
|
def __plugin_load__():
|
|
global __plugin_implementation__
|
|
__plugin_implementation__ = LCD_HD44780()
|
|
|
|
global __plugin_hooks__
|
|
__plugin_hooks__ = {
|
|
# "octoprint.plugin.softwareupdate.check_config": __plugin_implementation__.get_update_information
|
|
}
|