Skip to content

Instantly share code, notes, and snippets.

@eadmaster
Created July 20, 2024 19:34
Show Gist options
  • Save eadmaster/d014c114f0de616a43ca9488956dc958 to your computer and use it in GitHub Desktop.
Save eadmaster/d014c114f0de616a43ca9488956dc958 to your computer and use it in GitHub Desktop.
lines2vfd2002.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# derived from https://github.com/cnorlander/USB2VFD-Deck/
# for use with EVC20X02 VFD display controller https://it.aliexpress.com/item/1005006110081409.html
import serial
import time
import pytz
from datetime import datetime, timezone
from zoneinfo import ZoneInfo
def serial_connect(serial_port):
serial_conn = None
while True:
exception_tossed = False
# (badly) translated specs: "the USART interface judges whether the data frame transmisison is completed thought the idle state, that is, the high level state maintains 1 Tbuad after the stop bit"
try:
serial_conn = serial.Serial(
port=serial_port,
baudrate=9600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
bytesize=serial.EIGHTBITS
)
except serial.serialutil.SerialException as e:
exception_tossed = True
if not exception_tossed:
return serial_conn
print("Connection Failed... Waiting to try again...")
time.sleep(5)
class SerialVFD:
GO_HOME = bytearray.fromhex("A20000")
GO_LINE_2 = bytearray.fromhex("A20100")
#SET_BRIGHTNESS = bytearray.fromhex("fe99")
#SET_BRIGHTNESS_LOW = bytearray.fromhex("fe990a")
MAX_FRAME_RATE = 10
def __init__(self, serial_port, nc_message: str = "DISCONNECTED"):
self.serial_port = serial_port
self.serial_conn = serial_connect(serial_port)
self.last_frame_time = time.time()
self.nc_message = nc_message
def push_frame(self, line_1_byte_array: bytearray, line_2_byte_array: bytearray):
now = time.time()
time_delta = now - self.last_frame_time
self.last_frame_time = now
frame_limit = 1.0 / SerialVFD.MAX_FRAME_RATE
if time_delta >= frame_limit:
try:
#self.serial_conn.write(SerialVFD.GO_HOME)
self.serial_conn.write(line_1_byte_array)
#self.serial_conn.write(SerialVFD.GO_LINE_2)
self.serial_conn.write(line_2_byte_array)
except serial.serialutil.SerialException as e:
self.serial_conn = serial_connect(self.serial_port)
def set_brightness(self, value):
# value range 0-255
if not value >= 0 or not value <= 255:
return
try:
self.serial_conn.write(bytearray.fromhex("A000"))
#self.serial_conn.write(bytes([0xA0,0x00]))
# https://github.com/stokie-ant/lcdsmartie/blob/main/display_dll_source/seetron.dpr
#self.serial_conn.write(bytes([27,48]))
#self.serial_conn.write(27)
#self.serial_conn.write(48)
except serial.serialutil.SerialException as e:
self.serial_conn = serial_connect(self.serial_port)
def clear(self):
try:
self.serial_conn.write(bytes([0x55]))
except serial.serialutil.SerialException as e:
self.serial_conn = serial_connect(self.serial_port)
# end of class SerialVFD
def rotate_long_message(message, message_max_length: int = 20):
return message[1:] + message[0]
class MessageFormatter:
def __init__(self, scroll_speed: float, req_line_length: int = 20):
self.scroll_speed = scroll_speed
self.req_line_length = req_line_length
def enforce_line_length(self, line: str) -> str:
if len(line) < self.req_line_length:
line = line + (" " * (self.req_line_length - len(line)))
return line[0:self.req_line_length]
def format_line(self, line) -> bytearray:
line_set_length = self.enforce_line_length(line)
line_byte_array = bytearray()
line_byte_array.extend(map(ord, line_set_length))
return line_byte_array
import sys
line_1_message = "lines2vfd"
line_2_message = "init OK"
import threading
formatter = MessageFormatter(scroll_speed=0.1)
def refresh_screen_thread_main():
global line_1_message
global line_2_message
vfd = SerialVFD('/dev/ttyACM0')
time.sleep(0.5)
vfd.set_brightness(10)
time.sleep(0.5)
while True:
line_1_byte_array = formatter.format_line(line_1_message)
line_2_byte_array = formatter.format_line(line_2_message)
vfd.push_frame(line_1_byte_array, line_2_byte_array)
if(len(line_1_message)>20):
line_1_message = rotate_long_message(line_1_message)
if(len(line_2_message)>20):
line_2_message = rotate_long_message(line_2_message)
time.sleep(0.1)
# end of refresh_screen_thread_main
def main():
global line_1_message
global line_2_message
#local_timezone = pytz.timezone("America/Los_Angeles")
#line_1_message = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890@#$%^&*()_-+={}[]:;?/>|!@#$%^&*()_-+={}[]:;?/><|.,`~"
refresh_screen_thread = threading.Thread(target=refresh_screen_thread_main, args=[])
refresh_screen_thread.start()
curr_line_counter=1
while True:
#sys.stdin.flush()
curr_line = sys.stdin.readline().rstrip()
if curr_line:
if len(curr_line)>20 :
line_1_message = curr_line[:20]
line_2_message = curr_line[20:]
#if len(curr_line[20:])>20 :
# line_2_message = curr_line[20:40]
# time.sleep(1)
# line_1_message = curr_line[40:]
continue
else:
# len lower than 20
if curr_line_counter==1:
line_1_message = curr_line
curr_line_counter = 2
elif curr_line_counter==2:
line_2_message = curr_line
curr_line_counter = 1
#print(line_1_message)
#print(line_2_message)
#print(curr_line_counter)
#print(curr_line)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment