#!/usr/bin/python #-------------------------------------- # ___ ___ _ ____ # / _ \/ _ \(_) __/__ __ __ # / , _/ ___/ /\ \/ _ \/ // / # /_/|_/_/ /_/___/ .__/\_, / # /_/ /___/ # # lcd_16x2.py # 16x2 LCD Test Script # # Author : Matt Hawkins # Date : 06/04/2015 # # http://www.raspberrypi-spy.co.uk/ # # Modified and extended for the MotoMast Control # By Courtney E. Krehbiel, October 2015 # # Ver. 1.02 change in Dec. 2015 to modify rpmzero.py "SmallSleep" delay variable to 3 from 5 # Ver. 1.10 change on 2/23/2016 to add docking zero function to rpmzero.py and changes to how nCount is handled in MotoMast2. # #-------------------------------------- # The wiring for the LCD is as follows: # 1 : GND # 2 : 5V # 3 : Contrast (0-5V)* # 4 : RS (Register Select) # 5 : R/W (Read Write) - GROUND THIS PIN # 6 : Enable or Strobe # 7 : Data Bit 0 - NOT USED # 8 : Data Bit 1 - NOT USED # 9 : Data Bit 2 - NOT USED # 10: Data Bit 3 - NOT USED # 11: Data Bit 4 # 12: Data Bit 5 # 13: Data Bit 6 # 14: Data Bit 7 # 15: LCD Backlight +5V** # 16: LCD Backlight GND #import import RPi.GPIO as GPIO import time import json # Define GPIO to LCD mapping LCD_RS = 14 LCD_E = 15 LCD_D4 = 17 LCD_D5 = 18 LCD_D6 = 27 LCD_D7 = 22 # Define some device constants LCD_WIDTH = 16 # Maximum characters per line LCD_CHR = True LCD_CMD = False LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line # Timing constants E_PULSE = 0.0005 E_DELAY = 0.0005 #CEK Global Variables for MotoMast BtnPin = 23 # pin 16 for pushbutton, GPIO 23 (GPIO 25, pin 22 on blown new board) SwUpDown = 24 # pin 18 for up/down switch, GPIO 24 (GPIO 16, pin 36 on blown new board) # BtnPin = 25 # pin 16 for pushbutton, GPIO 23 (GPIO 25, pin 22 on blown new board) # SwUpDown = 16 # pin 18 for up/down switch, GPIO 24 (GPIO 16, pin 36 on blown new board) sHeightLabel = "Height Ft: " sRPM = "RPM: 0.00" nRPM = 0 Height = 0 HeightFeet = 0 sHeightFeet = "" StartTime = 0 def setup(): # Setup program block GPIO.setwarnings(False) GPIO.setmode(GPIO.BCM) # Use BCM GPIO numbers GPIO.setup(LCD_E, GPIO.OUT) # E GPIO.setup(LCD_RS, GPIO.OUT) # RS GPIO.setup(LCD_D4, GPIO.OUT) # DB4 GPIO.setup(LCD_D5, GPIO.OUT) # DB5 GPIO.setup(LCD_D6, GPIO.OUT) # DB6 GPIO.setup(LCD_D7, GPIO.OUT) # DB7 # Initialise display lcd_init() global sRPM global StartTime GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP) #RPM indicator switch GPIO.setup(SwUpDown, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Up/Down indicator switch lcd_string('KD6X Moto-Mast', LCD_LINE_1) # Provide display initialization info lcd_string('Firmware v1.10', LCD_LINE_2) time.sleep(4) # 4 second delay displayheight() # Initial display of data on display lcd_string(sRPM, LCD_LINE_2) # Display RPM: 0.00 from initial string variable sRPM = 'RPM: ' # Reset the string for when running to eliminate extra zeros StartTime = time.time() # Set the clock for RPM timing def displayheight(): global Height global HeightFeet global sHeightFeet with open('ids.json', 'r') as fp: # Get current position count from disk nCount = json.load(fp) fp.close() # print 'Ncount: ', str(nCount) Height = 120 + (nCount * 1.026) # Mast goes up 1.026 inches per revolution of winch shaft HeightFeet = Height / 12 HeightFeet = round(HeightFeet,2) sHeightFeet = str("%.2f" % HeightFeet) # Convert to feet, round to one decimal point, and then string sNewHeightString = ''.join([sHeightLabel, sHeightFeet]) lcd_string(sNewHeightString, LCD_LINE_1) def displayrpm(): global nRPM global StartTime global RPMStartUp NowTime = time.time() nRPM = 60 / (NowTime - StartTime) # print 'Start:', str(StartTime), 'Now:', str(NowTime), 'RPM:', str(nRPM) nRPM = round(nRPM,2) sActualRPM = str("%.2f" % nRPM) sNewRPMString = ''.join([sRPM, sActualRPM]) lcd_string(sNewRPMString, LCD_LINE_2) StartTime = NowTime # Setup start time for accurate RPM capture on next revolution. First one will be pretty close to 0. def swcount(ev=None): #This is the routine that runs everytime the winch shaft rotates on revolution # print 'Button pressed: ', str(nCount) with open('ids.json', 'r') as fp: # Get current position count from disk nCount = json.load(fp) fp.close() if GPIO.input(SwUpDown) == GPIO.HIGH: nCount = nCount + 1 # Increment or decrement the position counter else: nCount = nCount - 1 with open('ids.json', 'w') as fp: # Write current count to disk just in case motor is stopped json.dump(nCount, fp) fp.close() displayheight() # Do the math and formatting to output the data displayrpm() # A few more lines from CEK to set the overall loop def loop(): while True: GPIO.wait_for_edge(BtnPin, GPIO.FALLING, bouncetime=200) #Triggers swcount function on debounced falling edge of count pulse. swcount() def destroy(): lcd_byte(0x01, LCD_CMD) #Clear display lcd_string("Goodbye!",LCD_LINE_1) GPIO.cleanup() #Release resources # End of CEK code def lcd_init(): # Initialise display lcd_byte(0x33,LCD_CMD) # 110011 Initialise lcd_byte(0x32,LCD_CMD) # 110010 Initialise lcd_byte(0x06,LCD_CMD) # 000110 Cursor move direction lcd_byte(0x0C,LCD_CMD) # 001100 Display On,Cursor Off, Blink Off lcd_byte(0x28,LCD_CMD) # 101000 Data length, number of lines, font size lcd_byte(0x01,LCD_CMD) # 000001 Clear display time.sleep(E_DELAY) def lcd_byte(bits, mode): # Send byte to data pins # bits = data # mode = True for character # False for command GPIO.output(LCD_RS, mode) # RS # High bits GPIO.output(LCD_D4, False) GPIO.output(LCD_D5, False) GPIO.output(LCD_D6, False) GPIO.output(LCD_D7, False) if bits&0x10==0x10: GPIO.output(LCD_D4, True) if bits&0x20==0x20: GPIO.output(LCD_D5, True) if bits&0x40==0x40: GPIO.output(LCD_D6, True) if bits&0x80==0x80: GPIO.output(LCD_D7, True) # Toggle 'Enable' pin lcd_toggle_enable() # Low bits GPIO.output(LCD_D4, False) GPIO.output(LCD_D5, False) GPIO.output(LCD_D6, False) GPIO.output(LCD_D7, False) if bits&0x01==0x01: GPIO.output(LCD_D4, True) if bits&0x02==0x02: GPIO.output(LCD_D5, True) if bits&0x04==0x04: GPIO.output(LCD_D6, True) if bits&0x08==0x08: GPIO.output(LCD_D7, True) # Toggle 'Enable' pin lcd_toggle_enable() def lcd_toggle_enable(): # Toggle enable time.sleep(E_DELAY) GPIO.output(LCD_E, True) time.sleep(E_PULSE) GPIO.output(LCD_E, False) time.sleep(E_DELAY) def lcd_string(message,line): # Send string to display message = message.ljust(LCD_WIDTH," ") lcd_byte(line, LCD_CMD) for i in range(LCD_WIDTH): lcd_byte(ord(message[i]),LCD_CHR) if __name__ == '__main__': setup() try: loop() except KeyboardInterrupt: #When 'Ctrl-C' is pressed, the child program destroy() will be executed. pass finally: destroy()