Releases: Liongrass/21UP
v1.3
This release is relatively comprehensive, especially on the code side.
Most importantly, it reworks the entire display logic. The logic to create screens is now concentrated on screens.py. The functions are typically called make_screen or make_overlay, indicating whether the screens are meant to be displayed through full or partial refresh. The display.py file now solely defines how the screens are pushed to the physical screen. This should make it easier to understand the code but also to change it in the future, if for example another display were to be used.
Secondly, in this release the 21UP now includes a barometer, which is able to measure the temperature and humidity inside of the machine. Both are printed in the logs, but only the temperature is shown on the display.
- A bug is addressed where the pi picks up residual electricity in the wire after a can is dispensed. The machine then incorrectly shows the item as unavailable
- The QR code is now generated before the item description and price is shown on the screen. This allows the item description and the price to be properly aligned with the QR code, as the QR code's size depends on a variety of factors
- The checkmark and failure cross are also adjusted to the size of the QR code
- When the machine is started, the items are now printed in order, instead of all at once. Looks cool
- A new README explains how the barometer is used and how it can be installed and tested
- A bug is fixed that doesn't pick up the default TRUE setting for the display and barometer
- The pin spreadsheet is updated
- Logging is improved on various occasions
v1.2
This release mainly improves the display. Following the improvements made in release v1.1, the display will show items that are out of stock on the main screen as "Not Available." There are also two new mechanisms:
The first mechanism uses a partial refresh of the display to print an icon onto the main screen before the main screen is refreshed to show the invoice. This partial refresh happens faster than the full refresh, which gives the user a better indication that their button press was received. But since the display first has to be woken up the effect is not as fast as desired.
The effect can be highly customized. In the example in this release, nine Christmas-themed icons are available and selected at random. New items can be added simply by adding them into the /pic/press_icons folder.
The second mechanism uses a partial refresh to print "Make Selection Now" shortly before the device starts listening on the pins. This gives some indication when the user can start pressing a button, but there still is significant (~0.5) time between when that screen shows up and when the device actually starts listening.
Known bugs:
- When the
TRUE/FALSEflags for "Show Display" and "Production" are not specifically set in the config file, the device will fail to assume the defaults and start up.
v1.1
In this release, we introduce the concept of "inventory", which allows us to reconnect the optocoupler and simply ignore button presses on a pin that is marked as empty. This inventory is collected at startup and every time an item is dispensed. When logging is set to info, the logs will only show empty trays, not full ones.
This release also includes:
- Enabling or disabling the display should now always go smoothly
- The outgoing pins can be inverted in the configuration file. This is useful for the testing relay used
- The configured display expiry is now also applied to the failure and error screens
- Defaults are better defined and the var.py file was cleaned up
- The display documentation has been amended
There are no known bugs in this release!
v1.0
Version 1 of the 21UP has been released!
In version 1, the machine has been rewired for the Raspberry Pi to be able to trigger items to be dispensed independently. This involves a new relay for outgoing signals, as well as a new optocoupler to be able to detect which tray is empty, although this optocoupler is currently not connected, as an empty tray caused the machine to issue invoices for the empty tray in an endless loop.
New user flow:
- The user approaches machine, sees list of items with prices on the screen
- Empty trays still show the red "unavailable" light
- The user can press any button
- The screen then shows the selected item and fetches the Bolt11 invoice from the LNbits server
- The user can pay the invoice from any Lightning wallet
- The selected item is dispensed
- If the invoice remains unpaid, the invoice expires and the idle screen again shows the items and their prices
- If the invoice cannot be fetched, for example because the internet is cut or the remote server is unavailable, the machine shows an error message
New features since version v0.5:
- A new idle screen shows items and their prices
- The screen now fully refreshes when a button is pressed, but it first does not show the QR code, and only uses partial refresh to add the QR code once the invoice is available
- The code now runs as a service using pm2
- Two fonts are used, and both are configurable. Sadly I wasn't able to find a font that includes the ₿ unicode symbol
- The /docs folder now includes a detailed GPIO inventory, explaining which pin is used for what
- The screen can be disabled. This is useful for debug purposes but may not fully work (yet)
- New error handling that prevents the machine from dying when the internet is out or the remote server is down. The machine will in this case now also show an error message on the screen
- The Readme has been updated
To do:
- Option to invert the pins
- Using the current code, the machine incorrectly detects a held button as a pressed button on startup (but only on startup).
- The machine is supposed to take inventory on startup. This logic may also be used to improve the error above
- When a button is pressed, the machine should use a partial refresh on the idlescreen to give some indication that things are happening
Thank you specifically to David of Sovereign Hardware for making a beautiful case for the 21UP!
v0.5
In this release, the display is configured vertically. To speed up the invoice declaration, the bottom half of the screen is empty by default. When a button press is detected, the screen will instantly show the item and the price, then fetch the invoice, then show the QR code. Upon success or failure the tick or cross are also just written on top of the QR code. The screen is only fully refreshed after the cycle is complete.
- The screen now shuts down gracefully when a keyboard interrupt is detected while the machine is listening for an invoice
To do:
- There should be a configuration that inverts the pins
- There's a new requirements.txt, unfortunately this includes a lot of dependencies that are unclear whether they should exist
- the code does not run asyncronously, so while an invoice is displayed the machine does not listen on buttons
- the code doesn't run as a service yet
v0.4
In this release the four-color 3.52inch e-ink display has been replaced with a two-color 3.7inch display. This display refreshes much more quicker (~2s) and also supports near-instant partial refresh. The partial refresh is used to superimpose a checkmark (✔) or cross (𐄂) over the QR code when the invoice is paid or timed out.
- The button logic was also changed so that a permanent signal (in this coming from the tray being empty) does not trigger an infinite loop of invoices. However, additional work needs to be done to introduce this behavior for an empty tray at startup, and not just as a tray becomes empty later.
- To avoid an invoice being paid just as the time-out screen is shown, there is a new configurable
SUCCESS_SCREEN_EXPIRY, which defaults to five seconds. - The screen is properly cleaned on shutdown.
The following issues remain in this version:
- While the code has no dependency on RPi.GPIO or Segno, these packages are still installed by the requirements.txt
- the code does not run asyncronously, so while an invoice is displayed the machine does not listen on buttons
- the code doesn't run as a service yet
v0.3
In this release the machine is fully functional. The 3.52inch e-ink display his proving to be very slow, although the images it shows are clear and beautiful. The following features have been implemented:
- the machine shows a QR code when a button is pressed. after the QR has been paid the item is dispensed and the display reverts back to the idlescreen
- variables have been renamed for more consistency
- display documentation was added. this includes raw manuals as well as a self-written guide
- a license has been added to the code
- the code is confirmed to run on a Raspberry Pi 4 with Bookworm
- Dependency of RPi.GPIO and Segno has been removed
The following issues remain in this version:
- there is no distinct confirmation or failure screen
- the display takes a long time to refresh (~20s). this does not seem possible to address with this hardware
- the screen isn't cleaned on shutdown
- the code does not run asyncronously, so while an invoice is displayed the machine does not listen on buttons
- the code doesn't run as a service yet
v0.2
In this issue, the machine finally has a display, even though its functionality is limited to showing a simple idle screen at startup. The screen gets cleaned up on shutdown.
- The display is a 3.52inch e-paper display. To accommodate its pins the existing pin scheme had to be overhauled. The display requires eight pins, the outgoing relay occupies eight pins (of which two are unused), and the incoming six buttons occupy seven pins. 23 of the Pi's 40 pins. As the remaining pins are unusable, I doubt the Pi is able to handle a vending machine with eight trays.
- To prepare for the screen, the button and dispenser logic had to be rewritten with the gpiozero package. The RPi.GPIO package is no longer used
- The machine now supports logging. You can configure the loglevel in the .env file
- The machine now has a proper shutdown logic
- Invoices can now also contain the price and currency in their unit
- Fixed some bugs around the configuration options
The improvement wish list remains unchanged.
- Run the application as a service on start
- Verify this code runs on devices other than the Raspberry Pi 2 it was built on
- Eventually this machine should keep listening for buttons even when an invoice is currently displayed. It should cancel the invoice and issue a new one
