SSD1306 Wi-Fi Status
Here is another use of the SSD1306 miniature OLED display. Instead of loading an image like my previous project, this code contains character data and can display text. I have combined this with some simple hacks to retrieve and display Wi-Fi status information from the host. This is also meant to be connected to a Raspberry Pi 3.
Take a look:
#!/usr/bin/python import smbus import subprocess import re import time chardata = dict() chardata['@'] = "\x3c\x66\x6e\x6e\x60\x62\x3c\x00" chardata['A'] = "\x18\x3c\x66\x7e\x66\x66\x66\x00" chardata['B'] = "\x7c\x66\x66\x7c\x66\x66\x7c\x00" chardata['C'] = "\x3c\x66\x60\x60\x60\x66\x3c\x00" chardata['D'] = "\x78\x6c\x66\x66\x66\x6c\x78\x00" chardata['E'] = "\x7e\x60\x60\x78\x60\x60\x7e\x00" chardata['F'] = "\x7e\x60\x60\x78\x60\x60\x60\x00" chardata['G'] = "\x3c\x66\x60\x6e\x66\x66\x3c\x00" chardata['H'] = "\x66\x66\x66\x7e\x66\x66\x66\x00" chardata['I'] = "\x3c\x18\x18\x18\x18\x18\x3c\x00" chardata['J'] = "\x1e\x0c\x0c\x0c\x0c\x6c\x38\x00" chardata['K'] = "\x66\x6c\x78\x70\x78\x6c\x66\x00" chardata['L'] = "\x60\x60\x60\x60\x60\x60\x7e\x00" chardata['M'] = "\x63\x77\x7f\x6b\x63\x63\x63\x00" chardata['N'] = "\x66\x76\x7e\x7e\x6e\x66\x66\x00" chardata['O'] = "\x3c\x66\x66\x66\x66\x66\x3c\x00" chardata['P'] = "\x7c\x66\x66\x7c\x60\x60\x60\x00" chardata['Q'] = "\x3c\x66\x66\x66\x66\x3c\x0e\x00" chardata['R'] = "\x7c\x66\x66\x7c\x78\x6c\x66\x00" chardata['S'] = "\x3c\x66\x60\x3c\x06\x66\x3c\x00" chardata['T'] = "\x7e\x18\x18\x18\x18\x18\x18\x00" chardata['U'] = "\x66\x66\x66\x66\x66\x66\x3c\x00" chardata['V'] = "\x66\x66\x66\x66\x66\x3c\x18\x00" chardata['W'] = "\x63\x63\x63\x6b\x7f\x77\x63\x00" chardata['X'] = "\x66\x66\x3c\x18\x3c\x66\x66\x00" chardata['Y'] = "\x66\x66\x66\x3c\x18\x18\x18\x00" chardata['Z'] = "\x7e\x06\x0c\x18\x30\x60\x7e\x00" chardata['['] = "\x3c\x30\x30\x30\x30\x30\x3c\x00" chardata[']'] = "\x3c\x0c\x0c\x0c\x0c\x0c\x3c\x00" chardata[' '] = "\x00\x00\x00\x00\x00\x00\x00\x00" chardata['!'] = "\x18\x18\x18\x18\x00\x00\x18\x00" chardata['"'] = "\x66\x66\x66\x00\x00\x00\x00\x00" chardata['#'] = "\x66\x66\xff\x66\xff\x66\x66\x00" chardata['$'] = "\x18\x3e\x60\x3c\x06\x7c\x18\x00" chardata['%'] = "\x62\x66\x0c\x18\x30\x66\x46\x00" chardata['&'] = "\x3c\x66\x3c\x38\x67\x66\x3f\x00" chardata['\''] = "\x06\x0c\x18\x00\x00\x00\x00\x00" chardata['('] = "\x0c\x18\x30\x30\x30\x18\x0c\x00" chardata[')'] = "\x30\x18\x0c\x0c\x0c\x18\x30\x00" chardata['*'] = "\x00\x66\x3c\xff\x3c\x66\x00\x00" chardata['+'] = "\x00\x18\x18\x7e\x18\x18\x00\x00" chardata[','] = "\x00\x00\x00\x00\x00\x18\x18\x30" chardata['-'] = "\x00\x00\x00\x7e\x00\x00\x00\x00" chardata['.'] = "\x00\x00\x00\x00\x00\x18\x18\x00" chardata['/'] = "\x00\x03\x06\x0c\x18\x30\x60\x00" chardata['0'] = "\x3c\x66\x6e\x76\x66\x66\x3c\x00" chardata['1'] = "\x18\x18\x38\x18\x18\x18\x7e\x00" chardata['2'] = "\x3c\x66\x06\x0c\x30\x60\x7e\x00" chardata['3'] = "\x3c\x66\x06\x1c\x06\x66\x3c\x00" chardata['4'] = "\x06\x0e\x1e\x66\x7f\x06\x06\x00" chardata['5'] = "\x7e\x60\x7c\x06\x06\x66\x3c\x00" chardata['6'] = "\x3c\x66\x60\x7c\x66\x66\x3c\x00" chardata['7'] = "\x7e\x66\x0c\x18\x18\x18\x18\x00" chardata['8'] = "\x3c\x66\x66\x3c\x66\x66\x3c\x00" chardata['9'] = "\x3c\x66\x66\x3e\x06\x66\x3c\x00" chardata[':'] = "\x00\x00\x18\x00\x00\x18\x00\x00" chardata[';'] = "\x00\x00\x18\x00\x00\x18\x18\x30" chardata['<'] = "\x0e\x18\x30\x60\x30\x18\x0e\x00" chardata['='] = "\x00\x00\x7e\x00\x7e\x00\x00\x00" chardata['>'] = "\x70\x18\x0c\x06\x0c\x18\x70\x00" chardata['?'] = "\x3c\x66\x06\x0c\x18\x00\x18\x00" chardata['a'] = "\x00\x00\x3c\x06\x3e\x66\x3e\x00" chardata['b'] = "\x00\x60\x60\x7c\x66\x66\x7c\x00" chardata['c'] = "\x00\x00\x3c\x60\x60\x60\x3c\x00" chardata['d'] = "\x00\x06\x06\x3e\x66\x66\x3e\x00" chardata['e'] = "\x00\x00\x3c\x66\x7e\x60\x3c\x00" chardata['f'] = "\x00\x0e\x18\x3e\x18\x18\x18\x00" chardata['g'] = "\x00\x00\x3e\x66\x66\x3e\x06\x7c" chardata['h'] = "\x00\x60\x60\x7c\x66\x66\x66\x00" chardata['i'] = "\x00\x18\x00\x38\x18\x18\x3c\x00" chardata['j'] = "\x00\x06\x00\x06\x06\x06\x06\x3c" chardata['k'] = "\x00\x60\x60\x6c\x78\x6c\x66\x00" chardata['l'] = "\x00\x38\x18\x18\x18\x18\x3c\x00" chardata['m'] = "\x00\x00\x66\x7f\x7f\x6b\x63\x00" chardata['n'] = "\x00\x00\x7c\x66\x66\x66\x66\x00" chardata['o'] = "\x00\x00\x3c\x66\x66\x66\x3c\x00" chardata['p'] = "\x00\x00\x7c\x66\x66\x7c\x60\x60" chardata['q'] = "\x00\x00\x3e\x66\x66\x3e\x06\x06" chardata['r'] = "\x00\x00\x7c\x66\x60\x60\x60\x00" chardata['s'] = "\x00\x00\x3e\x60\x3c\x06\x7c\x00" chardata['t'] = "\x00\x18\x7e\x18\x18\x18\x0e\x00" chardata['u'] = "\x00\x00\x66\x66\x66\x66\x3e\x00" chardata['v'] = "\x00\x00\x66\x66\x66\x3c\x18\x00" chardata['w'] = "\x00\x00\x63\x6b\x7f\x3e\x36\x00" chardata['x'] = "\x00\x00\x66\x3c\x18\x3c\x66\x00" chardata['y'] = "\x00\x00\x66\x66\x66\x3e\x0c\x78" chardata['z'] = "\x00\x00\x7e\x0c\x18\x30\x7e\x00" class SSD1306(object): def __init__(self, bus=1, address=0x3c): self._address = address self._bus = smbus.SMBus(bus) self._command(0xae) # Display off. self._command(0xa8) # Multiplex ratio... self._command(0x3f) # ...63 self._command(0xd3) # Display offset... self._command(0x00) # ...0 self._command(0x40) # Display start line at 0. self._command(0xa1) # Segment Re-map with column 127 mapped to SEG0. self._command(0xc8) # Remapped mode, scan from COM[N-1] to COM0. self._command(0xda) # COM pins hardware configuration... self._command(0x32) # ...Alternative and Left/Right self._command(0xa4) # Entire display ON. self._command(0xa6) # Inverse display mode. self._command(0xd5) # Display clock... self._command(0x80) # ...No clock divide ratio and max frequency. self._command(0x8d) # Charge pump... self._command(0x14) # ...Enabled. self._command(0x20) # Memory addressing mode... self._command(0x20) # ...Horizontal. self._command(0xaf) # Display on. def _command(self, command_byte): self._bus.write_byte_data(self._address, 0x00, command_byte) def _data(self, data_byte): self._bus.write_byte_data(self._address, 0x40, data_byte) def reset_cursor(self): self._command(0x21) # Column address... self._command(0x00) # ...start at 0... self._command(0x7f) # ...end at 127. self._command(0x22) # Page address... self._command(0x00) # ...start at 0... self._command(0x07) # ...end at 7. def putc(self, char): if char in chardata: for column in range(0, 8): byte = ((ord(chardata[char][0]) >> (7 - column)) & 1) << 1 byte += ((ord(chardata[char][1]) >> (7 - column)) & 1) << 0 byte += ((ord(chardata[char][2]) >> (7 - column)) & 1) << 3 byte += ((ord(chardata[char][3]) >> (7 - column)) & 1) << 2 byte += ((ord(chardata[char][4]) >> (7 - column)) & 1) << 5 byte += ((ord(chardata[char][5]) >> (7 - column)) & 1) << 4 byte += ((ord(chardata[char][6]) >> (7 - column)) & 1) << 7 byte += ((ord(chardata[char][7]) >> (7 - column)) & 1) << 6 self._data(byte) def puts(self, string): for char in string: self.putc(char) class WiFiStatus(object): def __init__(self, interface): self._interface = interface def _get_status(self): iwconfig = subprocess.check_output("iwconfig %s" % (self._interface), shell=True) ifconfig = subprocess.check_output("ifconfig %s" % (self._interface), shell=True) match = re.search(r'inet ([^\ ]+?) ', ifconfig, flags=re.MULTILINE) if match: inet_address = match.group(1) else: inet_address = "" match = re.search(r'RX packets ([^\ ]+?) ', ifconfig, flags=re.MULTILINE) if match: rx_packets = match.group(1) else: rx_packets = "" match = re.search(r'TX packets ([^\ ]+?) ', ifconfig, flags=re.MULTILINE) if match: tx_packets = match.group(1) else: tx_packets = "" match = re.search(r'ESSID:"([^"]+?)"', iwconfig, flags=re.MULTILINE) if match: essid = match.group(1) else: essid = "" match = re.search(r'Link Quality=(\d+/\d+)', iwconfig, flags=re.MULTILINE) if match: link_quality = match.group(1) else: link_quality = "" match = re.search(r'Signal level=(-\d+ dBm)', iwconfig, flags=re.MULTILINE) if match: signal_level = match.group(1) else: signal_level = "" match = re.search(r'Bit Rate=([\.\d]+ Mb/s)', iwconfig, flags=re.MULTILINE) if match: bit_rate = match.group(1) else: bit_rate = "" match = re.search(r'Tx-Power=(\d+ dBm)', iwconfig, flags=re.MULTILINE) if match: tx_power = match.group(1) else: tx_power = "" return (inet_address, rx_packets, tx_packets, essid, link_quality, signal_level, bit_rate, tx_power) def loop(self): display = SSD1306() while True: (ia, rx, tx, si, lq, sl, br, tp) = self._get_status() display.reset_cursor() display.puts((si + " ")[:16]) display.puts((ia + " ")[:16]) display.puts(("Link: " + lq + " ")[:16]) display.puts(("Sig: " + sl + " ")[:16]) display.puts(("Rate: " + br + " ")[:16]) display.puts(("Pow: " + tp + " ")[:16]) display.puts(("Rx: " + rx + " ")[:16]) display.puts(("Tx: " + tx + " ")[:16]) time.sleep(3) if __name__ == "__main__": import sys if len(sys.argv) < 2: print "Usage: %s <interface>" % (sys.argv[0]) sys.exit(1) ws = WiFiStatus(sys.argv[1]) ws.loop()