Skip to content

Commit

Permalink
GPIO change and lockout relay for coin acceptor
Browse files Browse the repository at this point in the history
* Replaced RPi.GPIO with GPIO Zero
* Documentation edited
* Edit messages
  • Loading branch information
AxelHamburch authored Mar 29, 2022
1 parent f376a3e commit aef2415
Show file tree
Hide file tree
Showing 18 changed files with 152 additions and 71 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ _Carry out the points step by step as described here. This is the quickest way t
- [aditional information and tips](/docs/guide/information_and_tips.md)
- [option: button](/docs/guide/button.md)
- [option: camera](/docs/guide/camera.md)
- [option: lockout relay](/docs/guide/relay.md)
- [option: RPi image from scratch](/docs/guide/add_on_zero2.md)

A comprehensive guide on how to setup the LightningATM can be found here https://docs.lightningatm.me. Also join the Telegram group of LightningATM builders here https://t.me/lightningatm_building or contact 21isenough on Twitter (https://twitter.com/21isenough).
Expand Down
88 changes: 44 additions & 44 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import math
import subprocess

import RPi.GPIO as GPIO
from gpiozero import Button, LED

import config
import lndrest
Expand All @@ -18,10 +18,15 @@
import importlib
from PIL import Image

# Initialize inputs and outputs
button_signal = Button(5, False)
coin_signal = Button(6)
button_led = LED(13)
lockout_relay = LED(12)

display_config = config.conf["atm"]["display"]
display = getattr(__import__("displays", fromlist=[display_config]), display_config)

led = "off"
logger = logging.getLogger("MAIN")


Expand All @@ -37,7 +42,6 @@ def check_connectivity(interface="wlan0"):
def softreset():
"""Displays startup screen and deletes fiat amount
"""
global led
# Inform about coin, bill and sat amounts
if config.COINCOUNT > 0:
logger.info("Last payment:")
Expand All @@ -48,21 +52,20 @@ def softreset():
config.COINCOUNT = 0
config.PUSHES = 0
# Turn off button LED
GPIO.output(13, GPIO.LOW)
led = "off"

button_led.off()

display.update_startup_screen()
logger.info("Softreset executed")


def button_event(channel):
def button_event():
"""Registers a button push event
"""
config.LASTPUSHES = time.time()
config.PUSHES = config.PUSHES + 1


def coin_event(channel):
def coin_event():
"""Registers a coin insertion event
"""
config.LASTIMPULSE = time.time()
Expand Down Expand Up @@ -230,7 +233,6 @@ def button_pushed():
"""Shutdown the host machine
"""
display.update_shutdown_screen()
GPIO.cleanup()
logger.warning("ATM shutdown (5 times button)")
os.system("sudo shutdown -h now")

Expand Down Expand Up @@ -335,7 +337,15 @@ def button_pushed():
def coins_inserted():
"""Actions coins inserted
"""
global led

print("Coin pulses: ", config.PULSES, " pulses")

# Intercept and display a loose contact
if config.PULSES == 1:
print("Ups.. Just one coin pulses is not allowed!")
logger.error("Ups.. Just one coin pulses is not allowed!")
config.PULSES = 0
return

# Check if we should update prices
if config.FIAT == 0:
Expand All @@ -345,7 +355,6 @@ def coins_inserted():
logger.debug("Satoshi price updated")

# We must have gotten pulses!
print("Coin pulses: ", config.PULSES, " pulses")
config.FIAT += float(config.COINTYPES[config.PULSES]['fiat'])
config.COINCOUNT += 1
config.SATS = utils.get_sats()
Expand All @@ -354,20 +363,22 @@ def coins_inserted():
logger.info("Added {}".format(config.COINTYPES[config.PULSES]['name']))
display.update_amount_screen()

# Coin was processed -> Release coin acceptor relay switch
lockout_relay.on()

# Reset pulse cointer
config.PULSES = 0

if config.FIAT > 0 and led == "off":
if config.FIAT > 0 and not button_led.value == 1:
# Turn on the LED after first coin
GPIO.output(13, GPIO.HIGH)
led = "on"
button_led.on()
logger.debug("Button-LED turned on (if connected)")


def monitor_coins_and_button():
"""Monitors coins inserted and buttons pushed
"""
time.sleep(0.5)
# time.sleep(0.5)

#Wifi monitoring causes undesirable behavior sometimes.
#ssid=check_connectivity()
Expand All @@ -387,38 +398,27 @@ def monitor_coins_and_button():
# return False

# Detect when coins are being inserted
if (time.time() - config.LASTIMPULSE > 0.5) and (config.PULSES > 0):
if (time.time() - config.LASTIMPULSE > 0.3) and (config.PULSES > 0):
# New Coin to process -> Relay switch to inhibit
lockout_relay.off()
coins_inserted()

# Detect if the button has been pushed
if (time.time() - config.LASTPUSHES > 1) and (config.PUSHES > 0):
# Pulses from push button -> Relay switch to inhibit
if not config.PUSHES == 3:
lockout_relay.off()
button_pushed()

# Processing pulses finish -> Release coin acceptor relay switch
lockout_relay.on()

# Automatic payout if specified in config file
if (int(config.conf["atm"]["payoutdelay"]) > 0) and (config.FIAT > 0):
if time.time() - config.LASTIMPULSE > int(config.conf["atm"]["payoutdelay"]):
config.PUSHES = config.PUSHES + 1


def setup_coin_acceptor():
"""Initialises the coin acceptor parameters and sets up a callback for button pushes
and coin inserts.
"""
# Defining GPIO BCM Mode
GPIO.setmode(GPIO.BCM)

# Setup GPIO Pins for coin acceptor, button and button-led
GPIO.setwarnings(False)
GPIO.setup(13, GPIO.OUT)
GPIO.output(13, GPIO.LOW)
GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(6, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# Setup coin interrupt channel (bouncetime for switch bounce)
GPIO.add_event_detect(5, GPIO.RISING, callback=button_event, bouncetime=300)
GPIO.add_event_detect(6, GPIO.FALLING, callback=coin_event)


# def check_dangermode():
# """Check for DANGERMODE and wipe any saved credentials if off"
# """
Expand Down Expand Up @@ -457,18 +457,24 @@ def setup_coin_acceptor():
def main():
utils.check_epd_size()
logger.info("Application started")
print("Application started")

# Checks dangermode and start scanning for credentials
# Only activate once software ready for it
# check_dangermode()

# # For testing
# config.PULSES = 2
# Display startup info
display.update_shutdown_screen()
button_led.on()
time.sleep(1)

# Display startup startup_screen
display.update_startup_screen()
button_led.off()

setup_coin_acceptor()
# Function call by rising/falling new signal
button_signal.when_pressed = button_event
coin_signal.when_released = coin_event

while True:
monitor_coins_and_button()
Expand All @@ -480,14 +486,8 @@ def main():
main()
except KeyboardInterrupt:
display.update_shutdown_screen()
GPIO.remove_event_detect(5)
GPIO.remove_event_detect(6)
GPIO.cleanup()
logger.info("Application finished (Keyboard Interrupt)")
sys.exit("Manually Interrupted")
except Exception:
logger.exception("Oh no, something bad happened! Restarting...")
GPIO.remove_event_detect(5)
GPIO.remove_event_detect(6)
GPIO.cleanup()
os.execv("/home/pi/LightningATM/app.py", [""])
2 changes: 1 addition & 1 deletion displays/messages_fr.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
# Text for update_button_fault()
button_fault_1 = "Oh Sorry.."
button_fault_2 = "Button fault.."
button_screen_3 = "Try again!"
button_fault_3 = "Try again!"

# Text for update_wallet_fault()
wallet_fault_1 = "Wallet fault.."
Expand Down
2 changes: 1 addition & 1 deletion docs/guide/add_on_zero2.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,4 @@ Look at:

---

#### [option: camera](/docs/guide/camera.md) ᐊ previous | next ᐅ [README](/README.md)
#### [option: lockout relay](/docs/guide/relay.md) ᐊ previous | next ᐅ [README](/README.md)
2 changes: 1 addition & 1 deletion docs/guide/button.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ It is best to test the button and the LED once after the installation. We have p

Change to the following directory

$ cd ~/LightningATM/docs/others
$ cd ~/LightningATM/tests

#### Start the button test program

Expand Down
6 changes: 1 addition & 5 deletions docs/guide/camera.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,4 @@ Note: This camera was pretty cheap and has a variable lens that was pretty loose

---

#### [option: button](/docs/guide/button.md) ᐊ previous | next ᐅ [option: RPi image from scratch](/docs/guide/add_on_zero2.md)




#### [option: button](/docs/guide/button.md) ᐊ previous | next ᐅ [option: lockout relay](/docs/guide/relay.md)
9 changes: 5 additions & 4 deletions docs/guide/parts_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
- Raspberry Pi Zero 2 W (possible, but you have to do an image from [scratch](/docs/guide/add_on_zero2.md)) [link](https://www.google.com/search?q=Raspberry+Pi+Zero+2+W)

- Micro SD Card (16 - 64 GB tested) [link](https://www.google.com/search?q=Micro+SD+Card)
- DC-DC Adjustable Step Up Power Module (5V->12V) e.g.: [LM2587S](https://www.ebay.de/itm/DC-DC-Adjustable-Step-up-Boost-Power-Supply-LM2587S-3V-5V-12V-to-19V-24V-30V-36V-/402196830271), [HW-637](https://www.amazon.de/Converter-verstellbar-Spannungsregler-Effizienz-Board-Green-1-gr%C3%BCn/dp/B07S5YH2MB)
- DC-DC Adjustable Step Up Power Module (5V->12V) e.g. [LM2587S](https://www.ebay.de/itm/DC-DC-Adjustable-Step-up-Boost-Power-Supply-LM2587S-3V-5V-12V-to-19V-24V-30V-36V-/402196830271) or [HW-637](https://www.amazon.de/Converter-verstellbar-Spannungsregler-Effizienz-Board-Green-1-gr%C3%BCn/dp/B07S5YH2MB)
- Multi Coin Acceptor (programmable, e.g. [Coin Acceptor 616](https://de.aliexpress.com/item/1005002636710497.html) or [this](https://de.aliexpress.com/item/1005002636710497.html))
- Display with HAT / supported alternatives:

- PaPiRus Zero 2.0 "- ePaper pHAT
- Inky pHAT 2.13inch ePaper/eInk/EPD
- Waveshare 2.13inch e-Paper HAT [link](https://www.waveshare.com/wiki/2.13inch_e-Paper_HAT)
- Waveshare 2.13inch e-Paper HAT (D) [link](https://www.waveshare.com/2.13inch-e-paper-hat-d.htm)
- Waveshare 2.13inch e-Paper HAT (D) [link](https://www.waveshare.com/2.13inch-e-paper-hat-d.htm) (Recommendation for Pocket Edition!)
- Waveshare 2.66inch e-Paper E-Ink Display Module + [HAT](https://www.waveshare.com/wiki/E-Paper_Driver_HAT)
- Waveshare 2.7inch E-Ink display HAT [link](https://www.waveshare.com/wiki/2.7inch_e-Paper_HAT)

Expand All @@ -25,8 +25,9 @@

### Opitional parts

- Push Button (Recommended option!). Optionally with 3V LED. [(example)](https://www.amazon.de/dp/B00UFNI47I/) For the LED you will also need a resistor. See chapter [button](/docs/guide/button.md).
- Push Button (Recommended option!). Optionally with LED (3V) e.g. this [example](https://www.amazon.de/dp/B00UFNI47I/). For the LED you will also need a resistor.
- Lockout Relay Module (Makes sense!) e.g. [HW-482](https://www.google.com/search?q=HW-482) or [KY-019](https://www.google.com/search?q=KY-019)
- Raspberry Pi Camera 5MP OV5647
- ATM Case (self printing [DXF files](https://github.com/21isenough/LightningATM/tree/master/resources/3dmodels) or [STL files for Pocket Edition](https://github.com/21isenough/LightningATM/tree/master/resources/3dmodels/LightningATM%20-%20Pocket%20Edition/STLs) or buy from [Fulmo](https://shop.fulmo.org/shop/))
- ATM Case (self printing [DXF files](https://github.com/21isenough/LightningATM/tree/master/resources/3dmodels) or [STL files for Pocket Edition](https://github.com/21isenough/LightningATM/tree/master/resources/3dmodels/LightningATM%20-%20Pocket%20Edition/STLs) plus [threaded insert](https://www.google.com/search?q=threaded+insert) or buy from [Fulmo](https://shop.fulmo.org/shop/))

### Alternative a total construction set for the Pocket Edition from [Fulmo](https://shop.fulmo.org/product/the-lightning-atm-bitcoin-construction-set/)
65 changes: 65 additions & 0 deletions docs/guide/relay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# Coin acceptor lockout relay / electromagnetism gate

## The electromagnetic gate

The electromagnetic gate is a blocking pin that diverts the coins to the ejection. When the coin validator is de-energized, the pin always remains locked and ejects all coins. The blocking pin is only pulled back by a magnetic coil when the coins are correctly recognized. Only then do the coins fall through into fiat hell. This electromagnetic gate can be controlled or blocked from outside. The function can be used to exclude multiple impulses (in the case of fast coin insertion in a row) or coin insertion during a certain period of time (a display reading or with AMT offline).

## There are two ways to lock the electromagnetic gate

1. Via the "SET" input on the ATM. It is always "open / not connected" by default. The electromagnetic gate is only locked when these two contacts are short-circuited, or released when the contact is opened / not connected again.
2. The interruption of the coil control. To do this, however, you have to cut open the line and put a clamp in between so that you can loop in a contact there.

Relay options

<img src="../pictures/relay_options.jpg" width="500">

Which option you choose is up to you. Option 1 is certainly the easiest. However, plugging in the cables can prove difficult. I finally decided on option 2 because the clamp connection seemed more stable than the plug connection. But it doesn't matter which variant you choose, you just have to make sure that you use the opener or the closer contact.

## The Relay Module

A potential-free contact is required to switch the contact for the coin checker. A relay module with a changeover contact is ideal here.

Relay | build in
:-------------------------:|:-------------------------:
![](../pictures/relay_relay.jpg) | ![](../pictures/relay_build_in.jpg)

For a special typ, see [parts_list](/docs/guide/parts_list.md).

## Wiring

You can find the contacts / wiring for the relay here <img src="../pictures/relay_contacts.png" width="280"> and in total [here](/docs/guide/wiring.md).

When the relay is not energized, terminal 11 is the common contact and the contact to terminal 14 is open (NO = normal open). Terminal 12 is closed when unswitched (NC = normal close). If the coin acceptor is "released", then the whole thing is reversed.

## Relay Test

If you want to test the relay, we have a small test program here. It toggles the relay on and off alternately every two seconds. After starting the ATM, log in to the AMT via SSH and gradually enter the following command, similar to the button and LED tests in the [button](/docs/guide/button.md) chapter.

```
$ sudo systemctl stop LightningATM.service
$ cd ~/LightningATM/tests
$ sudo python3 relay_test.py
$ sudo systemctl start LightningATM.service
```

Relay test

<img src="../pictures/relay_test.png" width="630">

## The result

Once everything has been wired and is back in operation, you should notice the following:

1. ATM power off: All coins are ejected.
2. ATM Ready: Coins are accepted.
3. Coin inserted: Relay switches for a short time and ejects all new coins immediately. Only when the display has updated is the coin validator released again.
4. The ATM shows the QR code: The coin validator is blocked, the coins are ejected.
5. You have a different display than the start display (selection for versions with a button): The coin validator is blocked.
6. The ATM is out of service: The coin validator is blocked.


If the ATM is ready but does not accept the coins, then check whether the relay switches is on (see LED) after the AMT has started up. If the relay works an you still can't insert coins, swap the terminals 12 and 14.

---

#### [option: camera](/docs/guide/camera.md) ᐊ previous | next ᐅ [option: RPi image from scratch](/docs/guide/add_on_zero2.md)
Loading

0 comments on commit aef2415

Please sign in to comment.