As part of a MAME retrofitting project, I was recently tasked with getting a coin acceptor to work with the MAME emulator. As the MAME emulator uses a keyboard to get input (ie. controller, start, coin insertion, etc…), I had to get the coin acceptor to output a certain key whenever a coin is inserted. The best way to do that, in my opinion, was with Arduino. Here’s how I did it.
For this project, hardware-wise, I used an Arduino Uno (Rev 2) and a Chowhe CH-926 Programmable Coin Acceptor, however, these instructions will work with any generic pulse-based NC coin acceptor.
Software-wise, I used Atmel’s FLIP in-system flash programming software, the Arduino software, and the following USB firmware hex files (one for the keyboard driver and one for the original):
—
First off, was getting the coin acceptor to accept coins. I programmed mine to accept quarters ($0.25), loonies ($1), and toonies ($2) and output 1 pulse for each multiple of $0.25 inserted; but you can program yours to accept whatever you’d like, as long as your coin-acceptor supports it and you have 15-20 sample coins to feed through it. Follow the instruction manual included with your acceptor to program and sample it.
The Arduino requires inputs to be NC, so if your coin acceptor supports both NO and NC ouputs, set it to NC.
Once your coin acceptor is programmed, connect the white (COIN) line to a digital input on the Arduino. I used #2. Make sure you also connect or bridge the black (Ground) line to the Arduino’s ground, otherwise your circuit will be incomplete.
Next was the programming. Here’s an outline of what to do to write your Arduino program:
First you’ll need to define your variables. I used coinInt as the digital input pin number, led as the led’s pin number (so that it would blink every time a coin was inserted for debugging purposes), and buf as the keyboard buffer that would be overwritten with each keypress. Here’s what you should have so far:
1 2 3 4 | int coinInt = 0; //Digital Pin 2 int led = 13; //Blinker uint8_t buf[8] = { 0 }; /* Keyboard report buffer */ |
Now, you’ll need to define the setup and loop functions (which are required by the Arduino). The loop function stays empty (as things are only done when the coin acceptor pin goes high), but the setup function will require a few lines of code. you’ll need to have a delay of at least 6 seconds, so that the keyboard driver on the PC can detect the Arduino. you’ll also need to setup the input and output pins (for both the led and coin acceptor) and begin the serial connection to the computer. You’ll do this by setting the pin mode of the led pin to OUTPUT, attaching an interrupt to the coin acceptor pin so that it calls our coinInserted function each time the pin goes high ($0.25 is inserted), and beginning the serial connection with Serial.begin. The way the coin mechanism works, it will report a quarter as 1 pulse (1 x $0.25), a loonie ($1) as 4 pulses (4 x $0.25), and a toonie ($2) as 8 pulses (8 x $0.25). Your code should now look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | int coinInt = 0; //Digital Pin 2 int led = 13; //Blinker uint8_t buf[8] = { 0 }; /* Keyboard report buffer */ void setup() { delay(6000); // Give the keyboard driver time to boot pinMode(led, OUTPUT); // init led attachInterrupt(coinInt, coinInserted, RISING); //Call coinInserted when pin 2 goes high Serial.begin(9600); } void loop(){} |
Since those required loops are now out of the way, you’ll have to define the function that will be called when a coin is inserted. I called my function coinInserted. What coinInserted does, is turn on the led, write the letter I in keyboard scancode to the serial connection, and turn off the led. The result is that the letter i gets printed to the computer and the led blinks each time a valid coin is inserted into the acceptor. Your final code should now look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | int coinInt = 0; //Digital Pin 2 int led = 13; //Blinker uint8_t buf[8] = { 0 }; /* Keyboard report buffer */ void setup() { delay(6000); // Give the keyboard driver time to boot pinMode(led, OUTPUT); // init led attachInterrupt(coinInt, coinInserted, RISING); //Call coinInserted when pin 2 goes high Serial.begin(9600); } void loop(){} void coinInserted() //The function that is called every time it recieves a pulse { digitalWrite(led, HIGH); buf[2] = 12; // Letter I Serial.write(buf, 8); buf[0] = 0; //release key buf[2] = 0; //release key Serial.write(buf, 8); // Send release key to the PC delay(25); digitalWrite(led, LOW); } |
Once this code has been uploaded to your Arduino, you’ll need to flash your Arduino with the generic usb keyboard firmware. To do this, put your Arduino into DFU mode, open up Atmel’s FLIP software, load the Arduino-keyboard-0.3.hex file, and flash it to the Arduino’s USB controller. The Arduino’s USB controller chip (for the Uno Rev. 2 – you’ll need this for FLIP) is an Atmel ATmega8u2. If the flash is successful, restart your Arduino and test out your acceptor by opening notepad and inserting a coin. If it works (and the letter i appears on the screen), congrats, you’re done. If not, you’ve done something wrong – you’ll need to put your Arduino back into DFU mode and reflash your USB controller back to the original Arduino firmware (Arduino-usbserial-uno.hex) to try again.
Now that your coin acceptor is fully working, open up MAME, go to settings, select the option for Insert Coin, insert a coin into your acceptor (you should see “i – Keyboard 2” as the setting), and save. Your coin acceptor will now work with MAME.
Thanks! Nice writeup.
How about using two acceptors, player 1 & 2. Can you use any of the pins, or only pin 2?
On the Uno, only digital pins 2 & 3 will work with this code as they are both interrupt pins (meaning they can trigger actions upon seeing a change). Take a look at this page for more details: http://arduino.cc/en/Reference/AttachInterrupt.
If you want to add a second acceptor, simply add another coinInt variable (ie. coinInt2), set it equal to 1, plug the second acceptor into pin 3, and add the line “attachInterrupt(coinInt2, coinInserted, RISING);” to your code.
Thanks!
Hello!
Not sure why my comment that I posted few hours back wasn’t published.
Sorry for double post if comments need to be approved before appearing
in comment section.
In my original post I had few questions about this project.
Programming coin acceptor and final stage with Raspberry Pi should be
easy, but I have few question about Arduino part:
1) Can I use Rev 3 of Arduino Uno? It seems that Rev 2 are not
available anymore.
2) Can I use clone or do I have to use original version of Arduino?
3) Will the files you posted work with Rev 3 and/or clone version of
it?
4) I could manage to change the code for my coins (5, 10, 20, 50 with
1 credit = 5) – this should be easy, but will it work if I do these
changes:
6 coins: 1, 2, 5, 10, 20, 50 with 1 credit = 5
Example A) Inserting 5 pcs of “1” will add 1 credit (correct/wrong)
Example B) Inserting 3 pcs of “2” will add 1 credit, leaving 1/5 of
credit in system and after inserting for example 2pcs of “2” it will
add another credit (correct/wrong)
Thank you in advance for your answers!
Regards
Joe
Hi
I was looking for a way to do the same but with raspberry pi, would that be possible?
Hello,
Yes it is, you’ll need to use the GPIO pins on the Pi, and look into handling interrupts with them. Here’s a good starting point: https://www.raspberrypi.org/forums/viewtopic.php?f=44&t=9207
Cheers