diff --git a/10_01_clock.py b/10_01_clock.py new file mode 100644 index 0000000..b38d792 --- /dev/null +++ b/10_01_clock.py @@ -0,0 +1,24 @@ +#!/usr/bin/python +# 10_01_clock.py + +import i2c7segment as display +import time + +disp = display.Adafruit7Segment() + +while True: + h = time.localtime().tm_hour + m = time.localtime().tm_min + + #Original code + # disp.print_int(h * 100 + m) + + #Modified code + disp.write_time_digits(h,m) + + disp.draw_colon(True) + disp.write_display() + time.sleep(0.5) + disp.draw_colon(False) + disp.write_display() + time.sleep(0.5) diff --git a/10_01_clock_explained.py b/10_01_clock_explained.py new file mode 100644 index 0000000..128770e --- /dev/null +++ b/10_01_clock_explained.py @@ -0,0 +1,31 @@ +#!/usr/bin/python +# 10_01_clock.py + +import i2c7segment as display +import time +""" +The 'print_int()' as found in the 'i2c7segment' module does not display leading zeros which are required for a clock display. +As well, it does not clear all digits prior to updating with the integer value, potentially leaving the display is an unintends state. + +The 'write_time_digits(arg1, arg2)' was added to the 'i2c7segment' module to better address the display of time components. +arg1 and arg2 can be any two-digit time component, eg. year, month, day, hours, minutes, seconds +""" + +disp = display.Adafruit7Segment() + +while True: + h = time.localtime().tm_hour + m = time.localtime().tm_min + + #Original code + # disp.print_int(h * 100 + m) + + #Modified code + disp.write_time_digits(h,m) + + disp.draw_colon(True) + disp.write_display() + time.sleep(0.5) + disp.draw_colon(False) + disp.write_display() + time.sleep(0.5) diff --git a/README.md b/README.md index e639585..c260913 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ monk_raspberrypi ================ -Raspberry Pi code by Simon Monk for the book Programming Raspberry Pi: Getting Started with Python \ No newline at end of file +Raspberry Pi code by Simon Monk for the book Programming Raspberry Pi: Getting Started with Python + +My observations and proposed changes to the original files '10_01_clock.py' and 'i2c7segment.py' diff --git a/i2c7segment.py b/i2c7segment.py new file mode 100644 index 0000000..c694674 --- /dev/null +++ b/i2c7segment.py @@ -0,0 +1,132 @@ +import smbus +import sys +""" +This is a library for using the Adafruit i2c 4 digit 7 segment LED displays +with i2c on a Raspberry Pi. It was built and tested on Raspbian Wheezy. + +This is not an Adafruit product. + +To get i2c to work, you need Raspbian Wheezy or later and to do: + sudo apt-get install python-smbus + sudo apt-get install i2c-tools (usefull but not essential) + sudo modprobe i2c-dev + sudo modprobe i2c-bcm2708 + +Example Usage: + +disp = Adafruit7Segment() +raw_input("print_int(65535, 16)") +disp.print_int(65535, 16) +disp.write_display() +raw_input("print_int(1234)") +disp.print_int(1234) +disp.write_display() +raw_input("print_str(----)") +disp.print_str('----') +disp.write_display() +raw_input("print_str(-12.3)") +disp.print_str('-12.3') +disp.write_display() + +Simon Monk http://www.simonmonk.org Please give credit where credit is due. + +""" + +""" +This module originally written by Simon Monk, has been modified by +Mark Hache, BSc(Comp Sci) UNB1992, +contact: mhache2416@gmail.com +""" + +number_table = [0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71] + +class Adafruit7Segment: + + def __init__(self, address=0x70): + self.address = address + #Original code + # self.bus = smbus.SMBus(0) + #Modified code + try: + self.bus = smbus.SMBus(0) + except IOError: + try: + self.bus = smbus.SMBus(1) + except IOError: + print('Error occurred while setting up i2c bus.') + print('Neither i2c0 nor i2c1 is available.') + sys.exit() + #End of modified code + self.disp = [0, 0, 0, 0, 0] #digit1 digit2 digit3 digit4 colon + self.bus.write_byte(address, 0x21) + self.set_brightness(15) + self.set_blink_rate(1) + + def set_brightness(self, brightness): + """Set brightness 0 to 15""" + self.bus.write_byte(self.address, 0xE0 | brightness) + + def set_blink_rate(self, blink): + """Blink Rate 0, 1 or 2""" + self.bus.write_byte(self.address, 0x80 | blink) + + def write_digit_raw(self, digit, bitmask): + """ Write the LED segments for a digit directly dp g f e d c b a """ + self.disp[digit] = bitmask + + def write_digit_num(self, digit, number, dot=False): + """ Write a number into a digit position optionally with a dot""" + bitmask = number_table[number] + if dot: + bitmask = bitmask | 0x80 + self.write_digit_raw(digit, bitmask) + + def draw_colon(self, show_colon): + """ Turn the colon in the middle on or off""" + if show_colon: + self.disp[4] = 0xFF + else: + self.disp[4] = 0x00 + + def write_display(self): + """ Refresh the display - nothing will appear until you call this""" + self.bus.write_i2c_block_data(self.address, 0x00, [self.disp[0], 0x00, self.disp[1], 0x00, self.disp[4], 0x00, self.disp[2], 0x00, self.disp[3], 0x00]) + + def print_int(self, n, base=10): + """ Pint the integer, optionally with number base (2..16)""" + i = 0 + while n > 0: + self.write_digit_num(3-i, n % base, False) + n = n / base + i = i + 1 + + def print_str(self, s): + """ + Do the best you can with a 4 digit string (more with dots) + this is how you deal with floats and signs etc + format it first then print it + unknown characters print as a space + """ + digit_index = 0 + string_index = 0 + while string_index < len(s): + ch = s[string_index] + if ch == '-': + self.write_digit_raw(digit_index, 0x40) + elif ch >= '0' and ch <= '9': + followed_by_dp = False + if string_index < len(s)-1 and s[string_index+1] == '.': + followed_by_dp = True + string_index = string_index + 1 + self.write_digit_num(digit_index, int(ch), followed_by_dp) + else: + string_index = string_index + 1 + string_index = string_index + 1 + digit_index = digit_index + 1 + +#Newly added 'write_time_digits(arg1, arg2)' + def write_time_digits(self,h_m,m_s): + self.write_digit_raw(0,number_table[h_m//10]) + self.write_digit_raw(1,number_table[h_m%10]) + self.write_digit_raw(2,number_table[m_s//10]) + self.write_digit_raw(3,number_table[m_s%10]) diff --git a/i2c7segment_explained.py b/i2c7segment_explained.py new file mode 100644 index 0000000..baaea23 --- /dev/null +++ b/i2c7segment_explained.py @@ -0,0 +1,151 @@ +import smbus +import sys +""" +This is a library for using the Adafruit i2c 4 digit 7 segment LED displays +with i2c on a Raspberry Pi. It was built and tested on Raspbian Wheezy. + +This is not an Adafruit product. + +To get i2c to work, you need Raspbian Wheezy or later and to do: + sudo apt-get install python-smbus + sudo apt-get install i2c-tools (usefull but not essential) + sudo modprobe i2c-dev + sudo modprobe i2c-bcm2708 + +Example Usage: + +disp = Adafruit7Segment() +raw_input("print_int(65535, 16)") +disp.print_int(65535, 16) +disp.write_display() +raw_input("print_int(1234)") +disp.print_int(1234) +disp.write_display() +raw_input("print_str(----)") +disp.print_str('----') +disp.write_display() +raw_input("print_str(-12.3)") +disp.print_str('-12.3') +disp.write_display() + +Simon Monk http://www.simonmonk.org Please give credit where credit is due. + +""" + +""" +This module originally written by Simon Monk, has been modified by +Mark Hache, BSc(Comp Sci) UNB1992, +contact: mhache2416@gmail.com + +Issue 1.0 29 Sep 2014 +The original module was written with the Rasberry Pi models A and B. + +In those models, the i2c bus connected to the GPIO pins is 'i2c0'. Originally, this module +hard-coded the use of this bus. +However, with the release of the Rasberry Pi B+, the i2c bus connected to the GPIO pins is 'i2c1'. +The module has been modified to work with any model of the Rasberry Pi, A, B or B+. + +Issue 2.0 30 Sep 2014 +'print_int()' asimplemented is not suitable for displaying time values as it suppresses leading +zeroes and it fails to clear all digits prior to updating the display potentially leaving the +display in an unintended state. + +'write_time_digits(self, arg1, arg2)' is added to the 'i2c7segment.py' module to better address +the display of time components. arg1 and arg2 can be any two-digit time component, eg. year, month, +day, hours, minutes, seconds +""" + +number_table = [0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x77, 0x7C, 0x39, 0x5E, 0x79, 0x71] + +class Adafruit7Segment: + + def __init__(self, address=0x70): + self.address = address + #Issue 1. + #Original code + # self.bus = smbus.SMBus(0) + #Modified code + try: + self.bus = smbus.SMBus(0) + except IOError: + try: + self.bus = smbus.SMBus(1) + except IOError: + print('Error occurred while setting up i2c bus.') + print('Neither i2c0 nor i2c1 is available.') + sys.exit() + #End of modified code + self.disp = [0, 0, 0, 0, 0] #digit1 digit2 digit3 digit4 colon + self.bus.write_byte(address, 0x21) + self.set_brightness(15) + self.set_blink_rate(1) + + def set_brightness(self, brightness): + """Set brightness 0 to 15""" + self.bus.write_byte(self.address, 0xE0 | brightness) + + def set_blink_rate(self, blink): + """Blink Rate 0, 1 or 2""" + self.bus.write_byte(self.address, 0x80 | blink) + + def write_digit_raw(self, digit, bitmask): + """ Write the LED segments for a digit directly dp g f e d c b a """ + self.disp[digit] = bitmask + + def write_digit_num(self, digit, number, dot=False): + """ Write a number into a digit position optionally with a dot""" + bitmask = number_table[number] + if dot: + bitmask = bitmask | 0x80 + self.write_digit_raw(digit, bitmask) + + def draw_colon(self, show_colon): + """ Turn the colon in the middle on or off""" + if show_colon: + self.disp[4] = 0xFF + else: + self.disp[4] = 0x00 + + def write_display(self): + """ Refresh the display - nothing will appear until you call this""" + self.bus.write_i2c_block_data(self.address, 0x00, [self.disp[0], 0x00, self.disp[1], 0x00, self.disp[4], 0x00, self.disp[2], 0x00, self.disp[3], 0x00]) + + def print_int(self, n, base=10): + """ Pint the integer, optionally with number base (2..16)""" + i = 0 + while n > 0: + self.write_digit_num(3-i, n % base, False) + n = n / base + i = i + 1 + + def print_str(self, s): + """ + Do the best you can with a 4 digit string (more with dots) + this is how you deal with floats and signs etc + format it first then print it + unknown characters print as a space + """ + digit_index = 0 + string_index = 0 + while string_index < len(s): + ch = s[string_index] + if ch == '-': + self.write_digit_raw(digit_index, 0x40) + elif ch >= '0' and ch <= '9': + followed_by_dp = False + if string_index < len(s)-1 and s[string_index+1] == '.': + followed_by_dp = True + string_index = string_index + 1 + self.write_digit_num(digit_index, int(ch), followed_by_dp) + else: + string_index = string_index + 1 + string_index = string_index + 1 + digit_index = digit_index + 1 + +#Issue2 +#Newly added 'write_time_digits(arg1, arg2)' + def write_time_digits(self,h_m,m_s): + self.write_digit_raw(0,number_table[h_m//10]) + self.write_digit_raw(1,number_table[h_m%10]) + self.write_digit_raw(2,number_table[m_s//10]) + self.write_digit_raw(3,number_table[m_s%10])