""" Python Code for Digital Weight Scale * Typical EECS "project": circuit + computer + program code * IMPORTANT: though a representative example, not part of EECS 16A. * Microcontrollers and programming are not part of EECS 16A. * It's NOT on the exam ... * [Description](https://people.eecs.berkeley.edu/~boser/courses/49_sp_2019/L3_1_scale.html) * Parts: ** [M4 ARM microcontroller](https://learn.adafruit.com/adafruit-feather-m4-express-atsamd51) ** [CircuitPython](https://learn.adafruit.com/welcome-to-circuitpython) ** [OLED display](https://learn.adafruit.com/adafruit-oled-featherwing) ** [Load Cell](https://en.wikipedia.org/wiki/Load_cell) ** [Instrumentation Amplifier](http://www.ti.com/product/INA126) """ # helper class: detect button press/release events from digitalio import DigitalInOut, Pull from time import monotonic, sleep class Button: def __init__(self, pin, *, debounce=0.1, press=None, release=None): self.io = DigitalInOut(pin) self.io.pull = Pull.UP self.debounce = debounce self.press = press self.release = release self.last_state = self.io.value self.last_time = monotonic() def poll(self): if self.last_state == self.io.value: return if (monotonic()-self.last_time) < self.debounce: return self.last_time = monotonic() self.last_state = self.io.value if self.last_state: if self.press: self.press() else: if self.release: self.release() # helper class: read load cell voltage (i.e. weight) from analogio import AnalogIn class Scale: def __init__(self, vin_pin): self.vin = AnalogIn(vin_pin) self.tare_weight = self.vin.value def tare(self): print("tare!") self.tare_weight = self.vin.value def weight(self): # average N few ADC readings to reduce "noise" N = 5 w = 0 for i in range(N): w += self.vin.value sleep(0.05) w /= N # subtract tare weight w = w - self.tare_weight # convert to grams w *= 500/14150 return w # helper class: display text on OLED display import board import displayio import terminalio from adafruit_display_text import label import adafruit_displayio_ssd1306 class TextDisplay: def __init__(self): displayio.release_displays() i2c = board.I2C() display_bus = displayio.I2CDisplay(i2c, device_address=0x3c) self.display = adafruit_displayio_ssd1306.SSD1306(display_bus, width=128, height=32) def text(self, str): # display string s text_area = label.Label(terminalio.FONT, text=str, color=0x00FF00) text_area.x = 0 text_area.y = 10 self.display.show(text_area) # main program: read and display weight in infinite loop from board import A3, D5 scale = Scale(A3) tare_button = Button(D5, press=scale.tare) text_display = TextDisplay() while True: tare_button.poll() text_display.text("Weight: {:9.0f} g".format(scale.weight()))