Skip to content

Commit

Permalink
minor update
Browse files Browse the repository at this point in the history
  • Loading branch information
kizniche committed May 23, 2017
1 parent bb1197b commit cab7f55
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 145 deletions.
77 changes: 53 additions & 24 deletions beatbybeat.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,26 @@
import RPi.GPIO as GPIO
import sys


def menu():
parser = argparse.ArgumentParser(description='Beat counter (bpm) and Morse code translator')
parser = argparse.ArgumentParser(description='Beat counter (bpm) and '
'Morse code translator')

beat_counter = parser.add_argument_group('Beat counter')
beat_counter.add_argument('-b', '--bpmcount', action='store_true',
help="Start program to count beats (bpm)")

beat_counter.add_argument('-m','--maxbpm', metavar='MAXBPM', type=int,
help='Set maximum detectable BPM (lower number improves accuracy, higher numbers may register erroneous taps, below 2000 should be accurate), default: 2000',
beat_counter.add_argument('-m', '--maxbpm', metavar='MAXBPM', type=int,
help='Set maximum detectable BPM (lower number '
'improves accuracy, higher numbers may '
'register erroneous taps, below 2000 '
'should be accurate), default: 2000',
default=2000,
required=False)

beat_counter.add_argument('-p','--period', metavar='PERIOD', type=int,
help='Period of time between BPM calculations (milliseconds), default: 5000',
beat_counter.add_argument('-p', '--period', metavar='PERIOD', type=int,
help='Period of time between BPM calculations '
'(milliseconds), default: 5000',
default=5000,
required=False)

Expand All @@ -36,19 +42,27 @@ def menu():
help="Translate text to Morse code")

morse_translator.add_argument('-t', '--textonly', action='store_true',
help="Show only translated letters (Morse to text translation only)")

morse_translator.add_argument('-d','--dashduration', metavar='DASHDURATION', type=int,
help='Duration of a dash (Morse-to-text default: none, Text-to-Morse default: 300 ms). If set with -mt the tempo detection will be overridden.',
help="Show only translated letters (Morse to "
"text translation only)")

morse_translator.add_argument('-d', '--dashduration', metavar='DASHDURATION',
type=int,
help='Duration of a dash (Morse-to-text '
'default: none, Text-to-Morse default: '
'300 ms). If set with -mt the tempo '
'detection will be overridden.',
default=0,
required=False)

misc_options = parser.add_argument_group('Miscelaneous')
misc_options.add_argument('-g','--gpio', metavar='GPIO', type=int,
help='GPIO pin connected to the telegraph (using BCM numbering)')

misc_options.add_argument('-l','--lcd', metavar='I2CADDRESS', type=str,
help='Specify the I2C address of 2x16 character LCD (I2C backpack) to output to. ex. "0x25"',
misc_options.add_argument('-g', '--gpio', metavar='GPIO', type=int,
help='GPIO pin connected to the telegraph '
'(using BCM numbering)')

misc_options.add_argument('-l', '--lcd', metavar='I2CADDRESS', type=str,
help='Specify the I2C address of 2x16 '
'character LCD (I2C backpack) to '
'output to. ex. "0x25"',
default='0',
required=False)

Expand All @@ -68,9 +82,11 @@ def menu():
########################################

if not (args.bpmcount or args.morsetotext or args.texttomorse):
parser.error('No action requested, add --bpmcount or --morsetotext or --texttomorse')
parser.error('No action requested, add --bpmcount or --morsetotext or '
'--texttomorse')
elif sum(map(bool, [args.bpmcount, args.morsetotext, args.texttomorse])) != 1:
parser.error('Can only select one: --bpmcount (-b), --morsetotext (-mt), or --texttomorse (-tm)')
parser.error('Can only select one: --bpmcount (-b), --morsetotext '
'(-mt), or --texttomorse (-tm)')
elif args.bpmcount:
if not args.gpio:
parser.error('Need to specify GPIO pin with --gpio')
Expand All @@ -82,7 +98,8 @@ def menu():
else:
print 'Morse code to text translator',
elif args.texttomorse:
print 'Text to Morse code translator (use only A-Z, 0-9, spaces, and symbols /?\'!@$&()_-+=,.;:")',
print 'Text to Morse code translator (use only A-Z, 0-9, spaces, ' \
'and symbols /?\'!@$&()_-+=,.;:")',

if args.verbose:
print '(Verbose)'
Expand Down Expand Up @@ -112,14 +129,22 @@ def menu():
########################################

if args.bpmcount:
print 'Tempo calculation period: {} milliseconds, Max BPM: {} BPM, Debounce Delay: {} ms'.format(args.period, args.maxbpm, 60000 / args.maxbpm)
print 'Tempo calculation period: {} milliseconds, Max BPM: {} BPM, ' \
'Debounce Delay: {} ms'.format(
args.period, args.maxbpm, 60000 / args.maxbpm)
print '\nBegin tapping a tempo to identify the duration between beats.', \
'\nCalculations will only be performed while there is tapping.', \
'\nTiming will begin upon the first buttom press and be measured every {} milliseconds.\n'.format(args.period)
'\nTiming will begin upon the first buttom press and be ' \
'measured every {} milliseconds.\n'.format(args.period)
while True:
count, duration_average = beatcount.beat_counter(args.verbose, args.gpio, args.period, args.maxbpm)
print '\nCalculated from total number of beats over time: {} beats per {} ms = {} BPM'.format(count, args.period, count * (60 / (args.period / 1000)))
print 'Calculated from average duration between beats: {} ms per beat = {} BPM\n'.format(duration_average, 60000 / duration_average)
count, duration_average = beatcount.beat_counter(
args.verbose, args.gpio, args.period, args.maxbpm)
print '\nCalculated from total number of beats over time: {} ' \
'beats per {} ms = {} BPM'.format(
count, args.period, count * (60 / (args.period / 1000)))
print 'Calculated from average duration between beats: {} ms ' \
'per beat = {} BPM\n'.format(
duration_average, 60000 / duration_average)

########################################
# #
Expand All @@ -134,8 +159,12 @@ def menu():
dashduration = args.dashduration
if dashduration / 3 < 60000 / args.maxbpm:
parser.error('--dashduration too low. Increase -d or degrease -b')
print 'Tempo calculation period: {} milliseconds, Max BPM: {} BPM, Debounce Delay: {} ms'.format(args.period, args.maxbpm, 60000 / args.maxbpm)
translate.morse_to_text(args.verbose, args.textonly, args.gpio, args.period, args.maxbpm, args.dashduration, args.lcd)
print 'Tempo calculation period: {} milliseconds, Max BPM: {} BPM, ' \
'Debounce Delay: {} ms'.format(
args.period, args.maxbpm, 60000 / args.maxbpm)
translate.morse_to_text(args.verbose, args.textonly, args.gpio,
args.period, args.maxbpm, args.dashduration,
args.lcd)

########################################
# #
Expand Down
10 changes: 6 additions & 4 deletions lib/beatcount.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
import sys
import time


def beat_counter(verbose, gpio, period, maxbpm):
sleep_time = 1 / maxbpm # Calculate minimum sleep duration possible to detect the maximum BPM
sleep_time = 1 / maxbpm # Calculate minimum sleep duration possible to detect the maximum BPM
debounce_delay = 60000 / maxbpm
beat_count_bpm = beat_count_period = 1
duration_average = 0
Expand All @@ -36,9 +37,10 @@ def beat_counter(verbose, gpio, period, maxbpm):
beat_count_period += 1
first_beat = False
else:
time_now = int(round(time.time()*1000))
time_now = int(round(time.time() * 1000))
if verbose:
print 'Beat {}, Time: {}, Diff: {}, Average: {}'.format(beat_count_period, time_now, time_now - time_between_beats, duration_average)
print 'Beat {}, Time: {}, Diff: {}, Average: {}'.format(
beat_count_period, time_now, time_now - time_between_beats, duration_average)
else:
print '.',
sys.stdout.flush()
Expand All @@ -47,7 +49,7 @@ def beat_counter(verbose, gpio, period, maxbpm):

# Wait while the button is pressed
button_duration = int(round(time.time()*1000))
while ((GPIO.input(gpio) == False or
while ((not GPIO.input(gpio) or
int(round(time.time()*1000)) - button_duration < debounce_delay) and
int(round(time.time()*1000)) - time_between_beatcount < period):
time.sleep(sleep_time)
Expand Down
64 changes: 31 additions & 33 deletions lib/lcd.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import time


class LCDOutput():
class LCDOutput:
"""
Class to output to LCD, one letter at a time,
and move the previous letters to the left and up
Expand All @@ -17,35 +17,38 @@ class LCDOutput():

def __init__(self, o2c_address):
# Define some device parameters
# self.I2C_ADDR = 0x25 # I2C device address
self.I2C_ADDR = int(o2c_address, 16) # I2C device address
self.LCD_WIDTH = 16 # Maximum characters per line
# self.I2C_ADDR = 0x25 # I2C device address
self.I2C_ADDR = int(o2c_address, 16) # I2C device address
self.LCD_WIDTH = 16 # Maximum characters per line

# Define some device constants
self.LCD_CHR = 1 # Mode - Sending data
self.LCD_CMD = 0 # Mode - Sending command
self.LCD_CHR = 1 # Mode - Sending data
self.LCD_CMD = 0 # Mode - Sending command

self.LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
self.LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
# self.LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line
# self.LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line
self.LCD_LINE_1 = 0x80 # LCD RAM address for the 1st line
self.LCD_LINE_2 = 0xC0 # LCD RAM address for the 2nd line
# self.LCD_LINE_3 = 0x94 # LCD RAM address for the 3rd line
# self.LCD_LINE_4 = 0xD4 # LCD RAM address for the 4th line

self.LCD_BACKLIGHT = 0x08 # On
self.LCD_BACKLIGHT = 0x08 # On
# self.LCD_BACKLIGHT = 0x00 # Off

self.ENABLE = 0b00000100 # Enable bit
self.ENABLE = 0b00000100 # Enable bit

# Timing constants
self.E_PULSE = 0.0005
self.E_DELAY = 0.0005

#Open I2C interface
#bus = smbus.SMBus(0) # Rev 1 Pi uses 0
self.bus = smbus.SMBus(1) # Rev 2 Pi uses 1
# Open I2C interface
# bus = smbus.SMBus(0) # Rev 1 Pi uses 0
self.bus = smbus.SMBus(1) # Rev 2 Pi uses 1

# Initialize list of 16 spaces
self.letter_string = [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," ",
" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," ",]
self.letter_string = [
" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ",
" ", " ", " ", " ", " ", " ", " ", " ", " ", " "
]

self.lcd_init()

Expand All @@ -54,60 +57,55 @@ def __init__(self, o2c_address):

time.sleep(3)


def add_letter(self, letter):
self.letter_string.append(letter)
self.letter_string = self.letter_string[1:]

self.lcd_string(''.join(self.letter_string[0:16]), 1)
self.lcd_string(''.join(self.letter_string[16:32]) , 2)

self.lcd_string(''.join(self.letter_string[16:32]), 2)

def lcd_init(self):
# Initialise display
self.lcd_byte(0x33,self.LCD_CMD) # 110011 Initialise
self.lcd_byte(0x32,self.LCD_CMD) # 110010 Initialise
self.lcd_byte(0x06,self.LCD_CMD) # 000110 Cursor move direction
self.lcd_byte(0x0C,self.LCD_CMD) # 001100 Display On,Cursor Off, Blink Off
self.lcd_byte(0x28,self.LCD_CMD) # 101000 Data length, number of lines, font size
self.lcd_byte(0x01,self.LCD_CMD) # 000001 Clear display
self.lcd_byte(0x33, self.LCD_CMD) # 110011 Initialise
self.lcd_byte(0x32, self.LCD_CMD) # 110010 Initialise
self.lcd_byte(0x06, self.LCD_CMD) # 000110 Cursor move direction
self.lcd_byte(0x0C, self.LCD_CMD) # 001100 Display On,Cursor Off, Blink Off
self.lcd_byte(0x28, self.LCD_CMD) # 101000 Data length, number of lines, font size
self.lcd_byte(0x01, self.LCD_CMD) # 000001 Clear display
time.sleep(self.E_DELAY)

def lcd_clear(self):
self.lcd_init()


def lcd_byte(self, bits, mode):
# Send byte to data pins
# bits = the data
# mode = 1 for data
# 0 for command
bits_high = mode | (bits & 0xF0) | self.LCD_BACKLIGHT
bits_low = mode | ((bits<<4) & 0xF0) | self.LCD_BACKLIGHT
bits_low = mode | ((bits << 4) & 0xF0) | self.LCD_BACKLIGHT
# High bits
self.bus.write_byte(self.I2C_ADDR, bits_high)
self.lcd_toggle_enable(bits_high)
# Low bits
self.bus.write_byte(self.I2C_ADDR, bits_low)
self.lcd_toggle_enable(bits_low)


def lcd_toggle_enable(self, bits):
# Toggle enable
time.sleep(self.E_DELAY)
self.bus.write_byte(self.I2C_ADDR, (bits | self.ENABLE))
time.sleep(self.E_PULSE)
self.bus.write_byte(self.I2C_ADDR,(bits & ~self.ENABLE))
self.bus.write_byte(self.I2C_ADDR, (bits & ~self.ENABLE))
time.sleep(self.E_DELAY)


def lcd_string(self, message, line):
# Send string to display
if line == 1:
line = self.LCD_LINE_1
elif line == 2:
line = self.LCD_LINE_2
message = message.ljust(self.LCD_WIDTH," ")
message = message.ljust(self.LCD_WIDTH, " ")
self.lcd_byte(line, self.LCD_CMD)
for i in range(self.LCD_WIDTH):
self.lcd_byte(ord(message[i]),self.LCD_CHR)
self.lcd_byte(ord(message[i]), self.LCD_CHR)
Loading

0 comments on commit cab7f55

Please sign in to comment.