From e34ba56ce272a48896f57db6668ec72cc5ae0a86 Mon Sep 17 00:00:00 2001 From: Edvin Date: Wed, 30 Apr 2025 08:27:49 +0200 Subject: Implemented LCD with Arduino --- I2C_LCD_driver.py | 178 ---------------------------------------------------- LCD_test.py | 5 -- arduino/arduino.ino | 128 +++++++++++++++++++++++++++++++++++++ main.py | 22 ++++--- 4 files changed, 140 insertions(+), 193 deletions(-) delete mode 100644 I2C_LCD_driver.py delete mode 100644 LCD_test.py create mode 100644 arduino/arduino.ino diff --git a/I2C_LCD_driver.py b/I2C_LCD_driver.py deleted file mode 100644 index 0a58e30..0000000 --- a/I2C_LCD_driver.py +++ /dev/null @@ -1,178 +0,0 @@ -# -*- coding: utf-8 -*- -# Original code found at: -# https://gist.github.com/DenisFromHR/cc863375a6e19dce359d - -""" -Compiled, mashed and generally mutilated 2014-2015 by Denis Pleic -Made available under GNU GENERAL PUBLIC LICENSE - -# Modified Python I2C library for Raspberry Pi -# as found on http://www.recantha.co.uk/blog/?p=4849 -# Joined existing 'i2c_lib.py' and 'lcddriver.py' into a single library -# added bits and pieces from various sources -# By DenisFromHR (Denis Pleic) -# 2015-02-10, ver 0.1 - -""" - -# i2c bus (0 -- original Pi, 1 -- Rev 2 Pi) -I2CBUS = 0 - -# LCD Address -ADDRESS = 0x27 - -import smbus -from time import sleep - -class i2c_device: - def __init__(self, addr, port=I2CBUS): - self.addr = addr - self.bus = smbus.SMBus(port) - -# Write a single command - def write_cmd(self, cmd): - self.bus.write_byte(self.addr, cmd) - sleep(0.0001) - -# Write a command and argument - def write_cmd_arg(self, cmd, data): - self.bus.write_byte_data(self.addr, cmd, data) - sleep(0.0001) - -# Write a block of data - def write_block_data(self, cmd, data): - self.bus.write_block_data(self.addr, cmd, data) - sleep(0.0001) - -# Read a single byte - def read(self): - return self.bus.read_byte(self.addr) - -# Read - def read_data(self, cmd): - return self.bus.read_byte_data(self.addr, cmd) - -# Read a block of data - def read_block_data(self, cmd): - return self.bus.read_block_data(self.addr, cmd) - - -# commands -LCD_CLEARDISPLAY = 0x01 -LCD_RETURNHOME = 0x02 -LCD_ENTRYMODESET = 0x04 -LCD_DISPLAYCONTROL = 0x08 -LCD_CURSORSHIFT = 0x10 -LCD_FUNCTIONSET = 0x20 -LCD_SETCGRAMADDR = 0x40 -LCD_SETDDRAMADDR = 0x80 - -# flags for display entry mode -LCD_ENTRYRIGHT = 0x00 -LCD_ENTRYLEFT = 0x02 -LCD_ENTRYSHIFTINCREMENT = 0x01 -LCD_ENTRYSHIFTDECREMENT = 0x00 - -# flags for display on/off control -LCD_DISPLAYON = 0x04 -LCD_DISPLAYOFF = 0x00 -LCD_CURSORON = 0x02 -LCD_CURSOROFF = 0x00 -LCD_BLINKON = 0x01 -LCD_BLINKOFF = 0x00 - -# flags for display/cursor shift -LCD_DISPLAYMOVE = 0x08 -LCD_CURSORMOVE = 0x00 -LCD_MOVERIGHT = 0x04 -LCD_MOVELEFT = 0x00 - -# flags for function set -LCD_8BITMODE = 0x10 -LCD_4BITMODE = 0x00 -LCD_2LINE = 0x08 -LCD_1LINE = 0x00 -LCD_5x10DOTS = 0x04 -LCD_5x8DOTS = 0x00 - -# flags for backlight control -LCD_BACKLIGHT = 0x08 -LCD_NOBACKLIGHT = 0x00 - -En = 0b00000100 # Enable bit -Rw = 0b00000010 # Read/Write bit -Rs = 0b00000001 # Register select bit - -class lcd: - #initializes objects and lcd - def __init__(self): - self.lcd_device = i2c_device(ADDRESS) - - self.lcd_write(0x03) - self.lcd_write(0x03) - self.lcd_write(0x03) - self.lcd_write(0x02) - - self.lcd_write(LCD_FUNCTIONSET | LCD_2LINE | LCD_5x8DOTS | LCD_4BITMODE) - self.lcd_write(LCD_DISPLAYCONTROL | LCD_DISPLAYON) - self.lcd_write(LCD_CLEARDISPLAY) - self.lcd_write(LCD_ENTRYMODESET | LCD_ENTRYLEFT) - sleep(0.2) - - - # clocks EN to latch command - def lcd_strobe(self, data): - self.lcd_device.write_cmd(data | En | LCD_BACKLIGHT) - sleep(.0005) - self.lcd_device.write_cmd(((data & ~En) | LCD_BACKLIGHT)) - sleep(.0001) - - def lcd_write_four_bits(self, data): - self.lcd_device.write_cmd(data | LCD_BACKLIGHT) - self.lcd_strobe(data) - - # write a command to lcd - def lcd_write(self, cmd, mode=0): - self.lcd_write_four_bits(mode | (cmd & 0xF0)) - self.lcd_write_four_bits(mode | ((cmd << 4) & 0xF0)) - - # write a character to lcd (or character rom) 0x09: backlight | RS=DR< - # works! - def lcd_write_char(self, charvalue, mode=1): - self.lcd_write_four_bits(mode | (charvalue & 0xF0)) - self.lcd_write_four_bits(mode | ((charvalue << 4) & 0xF0)) - - # put string function with optional char positioning - def lcd_display_string(self, string, line=1, pos=0): - if line == 1: - pos_new = pos - elif line == 2: - pos_new = 0x40 + pos - elif line == 3: - pos_new = 0x14 + pos - elif line == 4: - pos_new = 0x54 + pos - - self.lcd_write(0x80 + pos_new) - - for char in string: - self.lcd_write(ord(char), Rs) - - # clear lcd and set to home - def lcd_clear(self): - self.lcd_write(LCD_CLEARDISPLAY) - self.lcd_write(LCD_RETURNHOME) - - # define backlight on/off (lcd.backlight(1); off= lcd.backlight(0) - def backlight(self, state): # for state, 1 = on, 0 = off - if state == 1: - self.lcd_device.write_cmd(LCD_BACKLIGHT) - elif state == 0: - self.lcd_device.write_cmd(LCD_NOBACKLIGHT) - - # add custom characters (0 - 7) - def lcd_load_custom_chars(self, fontdata): - self.lcd_write(0x40); - for char in fontdata: - for line in char: - self.lcd_write_char(line) diff --git a/LCD_test.py b/LCD_test.py deleted file mode 100644 index 196f674..0000000 --- a/LCD_test.py +++ /dev/null @@ -1,5 +0,0 @@ -import I2C_LCD_driver as LCD - -AGVlcd = LCD.lcd() - -AGVlcd.lcd_display_string("Hello World!", 1) diff --git a/arduino/arduino.ino b/arduino/arduino.ino new file mode 100644 index 0000000..b02fd48 --- /dev/null +++ b/arduino/arduino.ino @@ -0,0 +1,128 @@ +#include + +// To H-bridges +const int D1 = 10; +const int D2 = 11; +const int D3 = 6; +const int D4 = 5; + +// UART communication +char c; +String received = ""; + +// LCD +LiquidCrystal_I2C lcd(0x27, 20, 4); + +int emptySpace = 0; + +void setup() { + pinMode(D1, OUTPUT); + pinMode(D2, OUTPUT); + pinMode(D3, OUTPUT); + pinMode(D4, OUTPUT); + digitalWrite(D1, LOW); + digitalWrite(D2, LOW); + digitalWrite(D3, LOW); + digitalWrite(D4, LOW); + + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, LOW); + + Serial.begin(9600); + + lcd.init(); + lcd.backlight(); + lcd.setCursor(2, 0); + lcd.print("AGV booting!"); + received = "Dot dot dot dot"; +} + +void loop() { + if (Serial.available() > 0) { + received = Serial.readStringUntil('\n'); + //Serial.println(received); + } + + if (received.indexOf("Bluetooth up") >= 0) { + lcd.clear(); + lcd.setCursor(2, 0); + lcd.print("Bluetooth up"); + lcd.setCursor(6, 1); + lcd.print("...."); + emptySpace = 0; + received = "Dot dot dot dot"; // Reset received message so that LCD does not clear and rewrite every tick + } + + if (received.indexOf("Dot dot dot dot") >= 0) { + String dot; + for (int i = 0;i < 4;i++) { + if (i == emptySpace) { + dot = " "; + } else { + dot = "."; + } + lcd.setCursor(6 + i, 1); + lcd.print(dot); + } + emptySpace++; + if (emptySpace > 3) { + emptySpace = 0; + } + delay(500); + } + + if (received.indexOf("Bluetooth connected") >= 0) { + lcd.clear(); + lcd.setCursor(2, 0); + lcd.print("Connected to"); + lcd.setCursor(2, 1); + lcd.print(received.substring(20, 32)); // Message as 'Bluetooth connected XXXXXXXXXXXX' with MAC-address. + received = ""; + delay(2000); + lcd.clear(); + } + + if (received.indexOf("Closing down") >= 0) { + lcd.clear(); + lcd.setCursor(2, 0); + lcd.print("AGV booting!"); + received = "Dot dot dot dot"; + + Serial.end(); + + delay(5000); + + Serial.begin(9600); + } + + if (received.indexOf("Forward") >= 0) { // Forward + digitalWrite(D1, HIGH); + digitalWrite(D2, LOW); + digitalWrite(D3, HIGH); + digitalWrite(D4, LOW); + } + else if (received.indexOf("Backward") >= 0) { // Backward + digitalWrite(D1, LOW); + digitalWrite(D2, HIGH); + digitalWrite(D3, LOW); + digitalWrite(D4, HIGH); + } + else if (received.indexOf("Right") >= 0) { // Right + digitalWrite(D1, HIGH); + digitalWrite(D2, LOW); + digitalWrite(D3, LOW); + digitalWrite(D4, HIGH); + } + else if (received.indexOf("Left") >= 0) { // Left + digitalWrite(D1, LOW); + digitalWrite(D2, HIGH); + digitalWrite(D3, HIGH); + digitalWrite(D4, LOW); + } + else { + digitalWrite(D1, LOW); + digitalWrite(D2, LOW); + digitalWrite(D3, LOW); + digitalWrite(D4, LOW); + } +} diff --git a/main.py b/main.py index 4f690dc..5a666dd 100755 --- a/main.py +++ b/main.py @@ -4,14 +4,16 @@ import signal import serial import select from time import sleep -# import I2C_LCD_driver as LCD -# AGVlcd = LCD.lcd() +# Open serial port to Arduino Nano +NANO = serial.Serial('/dev/ttyUSB1', 9600, timeout=1) +sleep(2) BluetoothProcess = subprocess.Popen(["python", "-u", "/home/pi/TNE107-RPI/bt.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, text=True) # Waiting on connection # AGVlcd.lcd_display_string("Waiting for Bluetooth connection...", 1) +NANO.write(b"Bluetooth up\n") print(BluetoothProcess.stdout.readline().strip()) # Connected? @@ -27,14 +29,12 @@ leftTurnIndex = 20 leftTurn = 0 if bto.find("Connected") != -1: - # AGVlcd.lcd_clear() - # AGVlcd.lcd_display_string(bto) - - # Open serial port to Arduino Nano - NANO = serial.Serial('/dev/ttyUSB0', 9600, timeout=1) + nanoBtMessage = "Bluetooth connected " + bto[13:].translate({ord(c): None for c in ':'}) # Address to send to nano + NANO.write(nanoBtMessage.encode()) + print(nanoBtMessage) # LIDAR Process Code - LIDARProcess = subprocess.Popen(["./home/pi/TNE107-RPI/LIDARProg", "--channel", "--serial", "/dev/ttyUSB1", "460800"], stdout=open(os.devnull, 'wb')) + LIDARProcess = subprocess.Popen(["/home/pi/TNE107-RPI/LIDARProg", "--channel", "--serial", "/dev/ttyUSB0", "460800"], stdout=open(os.devnull, 'wb')) print(f"LIDAR PID: {LIDARProcess.pid}") # DWM Process Code @@ -78,14 +78,16 @@ if bto.find("Connected") != -1: # NANO.write(b"Left\n") leftTurn = leftTurnIndex rightTurn = 0 - elif bto == "0": + else: NANO.write(b"Stop\n") # Print current status (current command, heading? position? Could we include a cool progress bar? TO MISSION COMPLETEION?????) print("Terminating Serial port to Arduino Nano") - NANO.write(b"Stop\n") + NANO.write(b"Closing down\n") + sleep(1) + NANO.close() print("Terminating LIDAR process") os.kill(LIDARProcess.pid, signal.SIGINT) -- cgit v1.2.3