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()