Difference between revisions of "Soda Machine/Cashless Device"
(create page with outline of mdb transaction and goals of project) |
(add writeup of implementing an MDB cashless device.) |
||
Line 26: | Line 26: | ||
# The VMC polls us, and we say that the user's payment is approved. | # The VMC polls us, and we say that the user's payment is approved. | ||
# If the vend fails, the VMC tells us that. We ack this, refund the payment, and close the payment session. | # If the vend fails, the VMC tells us that. We ack this, refund the payment, and close the payment session. | ||
− | # If the vend succeeds, the VMC tells us that. We ack this and debit the user 50 cents. The | + | # If the vend succeeds, the VMC tells us that. We ack this and debit the user 50 cents. |
− | # The VMC polls us, and we say that we | + | # The VMC tells us the session is complete. We acknowledge this. |
+ | # The VMC polls us, and we say that we have ended the payment session. | ||
Now we're in the idle state again. | Now we're in the idle state again. | ||
+ | |||
+ | == Nuts and bolts == | ||
+ | |||
+ | Okay, so how are we going to make a useful cashless device? | ||
+ | |||
+ | === Talking on the MDB === | ||
+ | Rather than reinventing the wheel, this piece is based *heavily* on the Arduino piece of the [https://reaktor23.org/projects/mate_dealer Mate Dealer] project done by Bouni of the [https://reaktor23.org/ Reaktor23] hackerspace. This uses an Arduino Mega2560, although if you have an Atmega2560 then you don't really need it to be an Arduino. This chip is chosen because it has four hardware USARTs. We use one of the USARTs to communicate the ridiculous 9-bit serial protocol that MDB requires, and we use another to talk with the PC, or whatever is handling the money. | ||
+ | |||
+ | ==== Gotchas ==== | ||
+ | ===== Inverted serial ===== | ||
+ | When I first tried to use the MateDealer AVR code to listen to the MDB, it would not talk on the bus. It thought none of the commands were destined for cashless devices. I added some debug statements to try to decode the bits manually, but none of the data was making any sense. I tried to decode it by the spec but the data simply did not produce reasonable commands according to the spec I had. | ||
+ | |||
+ | When I connected a Bus Pirate to the bus, I realized that the data made sense if I used the inverted mode of the UART on the device. So I needed to invert the serial bus. The PIC in the Bus Pirate did this in hardware, no big deal, it's just a flag on the UART. But the Atmega2560 has no such flag. So, for the VMC->Arduino connection, I connected it through a 'NOT' gate. Now the data made sense, and the MateDealer was initialized by the VMC. | ||
+ | |||
+ | ==== Disabled state ==== | ||
+ | According to the MDB spec, you boot up idle, then you wait for setup by the VMC, and then you go into the "disabled" state. This is the state when the VMC doesn't want you to accept any payment cards. However... this is as far as it got. For some reason, our soda machine never wanted to enable the card reader. | ||
+ | |||
+ | To fix this, I just... fudge it. When I receive the last serial data from the VMC, I just hack the state machine - I go to the "enabled" state instead of the "disabled" one. This means I violate the MDB spec, but it works fine. Maybe the firmware in our VMC has a bug, who knows, but it works like this. | ||
+ | |||
+ | ==== Lockup after successful vend ==== | ||
+ | The MateDealer code, as it was, worked fine to vend a soda! But, afterward, the VMC displayed our balance, minus the 50 cents we just paid for a soda, but nothing would respond. It was possible to start another payment session from the cashless device, but until we did that, the VMC was totally unusable. Service menus were inaccessible, and "ICE COLD COCA COLA" was not scrolling. Only a reboot seemed to fix this. | ||
+ | |||
+ | It turns out that MateDealer's state machine is not implementing MDB exactly; rather, it accommodates an oddity in Reaktor23's vending machine. Once a vend is successful, the VMC sends "session complete," and we are supposed to respond with "end session" to confirm. MateDealer simply responded "ACK" and went back to the idle state. But the Makers Local soda machine would wait for up to *five minutes* (the MDB spec default non-response time) for the "end session" message. Now that I patched MateDealer to send the "end session" message, the session ends immediately. | ||
+ | |||
+ | === Handling stored value and payments === | ||
+ | |||
+ | I haven't done this part yet, so stay tuned, I guess. |
Revision as of 03:19, 10 January 2017
Creator: |
Contents
[hide]Project overview
The soda machine supports MDB, the Multi Drop Bus. It's used for talking to coin hoppers, bill validators, and, notably, "cashless devices" (that is, card readers). This project is to implement an MDB cashless device so that make shop members are able to pay for soda with their NFC tags directly.
More-or-less high-level overview of payment operations
MDB is a pretty confusing protocol, but I can describe the subset that we will be using, and the flow of "states" within our cashless device. One thing you have to know is that the VMC (vending machine controller) is always POLLing all its peripheral devices on the MDB. The peripherals can't talk unless the VMC has addressed them first.
Startup
- The VMC polls us, and we say we have just finished resetting.
- The VMC sends us its configuration data. We respond with our configuration data.
- The VMC sends us its pricing data (config stage 2). We acknowledge this.
- The VMC keeps polling us and we keep acking to say that we are not dead.
Now we are in the idle state.
User presents payment
- The VMC polls us, and we say that we have a user trying to begin a payment session.
- We can pass an amount of currency as the session begin amount, and the VMC displays it as the amount of credit that has been inserted by the user.
- The VMC tells us the user is trying to buy something that requires a payment of, let's say, 50 cents. We acknowledge this and we run off to verify that the user can afford this 50 cent charge.
- The VMC polls us, and we say that the user's payment is approved.
- If the vend fails, the VMC tells us that. We ack this, refund the payment, and close the payment session.
- If the vend succeeds, the VMC tells us that. We ack this and debit the user 50 cents.
- The VMC tells us the session is complete. We acknowledge this.
- The VMC polls us, and we say that we have ended the payment session.
Now we're in the idle state again.
Nuts and bolts
Okay, so how are we going to make a useful cashless device?
Talking on the MDB
Rather than reinventing the wheel, this piece is based *heavily* on the Arduino piece of the Mate Dealer project done by Bouni of the Reaktor23 hackerspace. This uses an Arduino Mega2560, although if you have an Atmega2560 then you don't really need it to be an Arduino. This chip is chosen because it has four hardware USARTs. We use one of the USARTs to communicate the ridiculous 9-bit serial protocol that MDB requires, and we use another to talk with the PC, or whatever is handling the money.
Gotchas
Inverted serial
When I first tried to use the MateDealer AVR code to listen to the MDB, it would not talk on the bus. It thought none of the commands were destined for cashless devices. I added some debug statements to try to decode the bits manually, but none of the data was making any sense. I tried to decode it by the spec but the data simply did not produce reasonable commands according to the spec I had.
When I connected a Bus Pirate to the bus, I realized that the data made sense if I used the inverted mode of the UART on the device. So I needed to invert the serial bus. The PIC in the Bus Pirate did this in hardware, no big deal, it's just a flag on the UART. But the Atmega2560 has no such flag. So, for the VMC->Arduino connection, I connected it through a 'NOT' gate. Now the data made sense, and the MateDealer was initialized by the VMC.
Disabled state
According to the MDB spec, you boot up idle, then you wait for setup by the VMC, and then you go into the "disabled" state. This is the state when the VMC doesn't want you to accept any payment cards. However... this is as far as it got. For some reason, our soda machine never wanted to enable the card reader.
To fix this, I just... fudge it. When I receive the last serial data from the VMC, I just hack the state machine - I go to the "enabled" state instead of the "disabled" one. This means I violate the MDB spec, but it works fine. Maybe the firmware in our VMC has a bug, who knows, but it works like this.
Lockup after successful vend
The MateDealer code, as it was, worked fine to vend a soda! But, afterward, the VMC displayed our balance, minus the 50 cents we just paid for a soda, but nothing would respond. It was possible to start another payment session from the cashless device, but until we did that, the VMC was totally unusable. Service menus were inaccessible, and "ICE COLD COCA COLA" was not scrolling. Only a reboot seemed to fix this.
It turns out that MateDealer's state machine is not implementing MDB exactly; rather, it accommodates an oddity in Reaktor23's vending machine. Once a vend is successful, the VMC sends "session complete," and we are supposed to respond with "end session" to confirm. MateDealer simply responded "ACK" and went back to the idle state. But the Makers Local soda machine would wait for up to *five minutes* (the MDB spec default non-response time) for the "end session" message. Now that I patched MateDealer to send the "end session" message, the session ends immediately.
Handling stored value and payments
I haven't done this part yet, so stay tuned, I guess.