Three modes, and which one you want
Counter, value and mapped. Each one reads a different wire, needs a different pulse plan, and quietly leaves one of the library's totals at zero forever. Pick by what you need to know, not by which sounds most capable.
The three
The figure runs the same three coins through each mode and shows what the library's four readout calls contain afterwards. The greyed rows are the point: every mode leaves something permanently at zero, and the library does not warn you about it.
Counter mode
CoinAcceptor coin(COIN_PIN, COIN_MODE_COUNTER);One event per accepted coin, read off the COUNTER wire. update() returns
true once per coin and totalCoins() goes up by one. There is nothing to
program into the acceptor beyond training, because the coin's pulse value is
irrelevant — COUNTER sends one pulse regardless.
This is the mode to start with. If it works, your wiring and your training are both fine, and anything that then goes wrong in another mode is a configuration problem rather than a hardware one.
Value mode
CoinAcceptor coin(COIN_PIN, COIN_MODE_VALUE);
void setup() {
coin.setPulseValue(5); // five cents per pulse
coin.begin();
}Reads the COIN wire, multiplies the pulses in each group by a fixed rate,
and adds the result to totalValue(). It never has to recognise anything, so
it cannot mis-recognise anything — which makes it the robust choice when the
total amount is what matters.
The condition is the pulse plan. Every coin must be set to a pulse count
proportional to its value at that one rate, or the total is nonsense. And note
what it does not fill in: totalCoins() stays at zero in this mode however
much money goes in.
Mapped mode
CoinAcceptor coin(COIN_PIN, COIN_MODE_MAPPED);
void setup() {
coin.addCoin(1, 5); // 1 pulse = 5 cents
coin.addCoin(3, 25); // 3 pulses = 25 cents
coin.addCoin(5, 100); // 5 pulses = 1 dollar
coin.begin();
}Waits for a complete group of pulses, looks the count up in the table you
built, and reports that coin's value. Both totalCoins() and totalValue()
are filled in, and value() tells you what the last coin was worth. Up to six
coins, each with a distinct pulse count, none above 50 pulses.
This is the mode that can be wrong rather than merely incomplete. A pulse count
it does not recognise sets hasError(), which you should check on every event:
if (coin.update()) {
if (coin.hasError()) {
Serial.print("unrecognised: ");
Serial.println(coin.pulses());
return;
}
Serial.println(coin.value());
}Why mapped mode can be confidently wrong
Two coins dropped in close together merge into one group, and the count is the
sum. With the table above, a 5c and a 25c together make four pulses, which is
not a coin — so hasError() fires and you find out.
Change the table so that some pair sums to a count you did use, and the same merge is reported as a single valid coin, with no error at all. No amount of checking in your sketch can detect that, because a single wire carrying a pulse count genuinely does not distinguish the two cases. Why fast coins get missed is the page about that, and value mode is the escape from it.
Choosing
- One coin buys one thing — counter mode, on COUNTER. Nothing to get wrong.
- A running total of money — value mode, on COIN, with a proportional plan.
- Different coins do different things — mapped mode, on COIN, and check
hasError()every time.
Everything above must be set before begin(). setPulseValue, addCoin,
setTiming and setInterruptEnabled all check whether the library has started
and do nothing if it has.
When it does not work
You are in value mode, and that is what value mode does — it adds to totalValue() and never touches totalCoins(). Nothing is broken. If you need both numbers, use mapped mode, which fills in both.
Three things make begin() fail. Value mode with a pulse value of zero, mapped mode with no coins added, or an invalid mode. In mapped mode the usual cause is an addCoin() call that was rejected — a duplicate pulse count, a count above 50, a zero value — leaving no coins mapped at all.
A group of pulses arrived that does not match any coin you added. Either the coins are going in too fast and two trains are merging, or the pulse values programmed into the acceptor do not match the numbers in your addCoin() calls. Print coin.pulses() when the error fires — the count tells you which.
They only work before begin(). Every configuration call on this library checks that it has not started yet and returns without doing anything if it has. Put them above begin() in setup().
The whole build: three wires, one sketch, and a total on the serial monitor.
Count coins on an ESP32 or an UNO →Edit this page — content/books/coin-acceptor/three-modes.mdx
Questions about this product
See what other owners have asked, and read their solutions.
Arcade Coin Acceptor Module Kit, USB-C Powered
Loading discussions…
Discuss this article
Ask about this page. The answer stays here, on the page it belongs to, for whoever hits the same wall next.