/*
Forum: https://forum.arduino.cc/t/pass-the-pulse-from-coin-acceptor-to-coffee-vending-machine-using-arduino-esp32/1178550/36
Wokwi: https://wokwi.com/projects/379030670471276545
As in the forum, just added a diode with separate outpin pin to indicate when the pulse sequences
are created
*/
#include "CoinAcceptor.h"
// ------------------- For Simulation ONLY -------------------------------------------------
// Delete this line in real application
void simulatedCoinPulseGenerator(void *pvParameters);
// ------------------- For Simulation ONLY -------------------------------------------------
void processCoin(void *pvParameters);
void coinAccepted(CoinAcceptor::PulseValuePair);
const uint8_t pulseInPin = 13;
const uint8_t pulseOutPin = 2;
// ===================== Just for LED ====================================================
// Added inverted out signal for LED
const uint8_t pulseOutPinInvert = 15;
// ===================== Just for LED ====================================================
CoinAcceptor acceptor(pulseInPin, coinAccepted);
QueueHandle_t coinQueue = NULL;
void setup() {
Serial.begin(115200);
delay(3000);
Serial.println("Starting");
coinQueue = xQueueCreate(20, sizeof(CoinAcceptor::PulseValuePair));
assert(coinQueue != NULL);
BaseType_t returnCode = xTaskCreatePinnedToCore(processCoin, "Pulse Output Generator", 2500, NULL, 4, NULL, CONFIG_ARDUINO_RUNNING_CORE);
assert(returnCode != pdFAIL);
CoinAcceptor::PulseValuePairTable table {
{ 1, 1 },
{ 5, 5 },
{ 10, 10 },
{ 12, 25 },
{ 14, 50 },
{ 16, 100 }
};
acceptor.begin(table);
// ------------------- For Simulation ONLY -------------------------------------------------
// Delete these lines in real application
returnCode = xTaskCreatePinnedToCore(simulatedCoinPulseGenerator, "Simulated Pulse Generator", 2500, reinterpret_cast<void*>(&table), 6, NULL, CONFIG_ARDUINO_RUNNING_CORE);
assert(returnCode != pdFAIL);
// ------------------- For Simulation ONLY -------------------------------------------------
}
// Callback function. Called every time a new coin is accepted
void coinAccepted(CoinAcceptor::PulseValuePair pair) {
// Callback functions should be very short.
// Just put the coin information in a Queue to be processed outside the callback
xQueueSendToBack(coinQueue, &pair, 0);
}
// Process the coin accepted then send appropriate number of pulses to the coffee machine
void processCoin(void *pvParameters) {
const uint32_t CoffeeMachinePulseDuration = 20;
digitalWrite(pulseOutPin, HIGH);
pinMode(pulseOutPin, OUTPUT);
// ===================== Just for LED ====================================================
// Added inverted Out pin for LED
digitalWrite(pulseOutPinInvert, LOW);
pinMode(pulseOutPinInvert, OUTPUT);
// ===================== Just for LED ====================================================
CoinAcceptor::PulseValuePair pair;
for (;;) {
xQueueReceive(coinQueue, &pair, portMAX_DELAY);
Serial.printf("Accepted Coin of Value: %d\n", pair.value);
//
// Do custom stuff here to process the coin accepted
//
// Send the proper number of pulses to the coffee machine
Serial.printf("Sending %d Pulse(s) to Coffee Machine\n", pair.pulses);
for (uint8_t i = 0; i < pair.pulses; i++) {
Serial.println("LOW");
digitalWrite(pulseOutPin, LOW);
// ===================== Just for LED ====================================================
digitalWrite(pulseOutPinInvert, HIGH);
// ===================== Just for LED ====================================================
vTaskDelay(CoffeeMachinePulseDuration);
Serial.println("HIGH");
digitalWrite(pulseOutPin, HIGH);
// ===================== Just for LED ====================================================
digitalWrite(pulseOutPinInvert, LOW);
// ===================== Just for LED ====================================================
vTaskDelay(CoffeeMachinePulseDuration);
}
Serial.println();
}
}
void loop() {
}
// ------------------- For Simulation ONLY -------------------------------------------------
// Delete this function in real application
// This task simulates dropping a random-value coin into the acceptor every 5 seconds
void simulatedCoinPulseGenerator(void *pvParameters) {
const uint8_t simulatorOutputPin = 12;
digitalWrite(simulatorOutputPin, HIGH);
pinMode(simulatorOutputPin, OUTPUT);
CoinAcceptor::PulseValuePairTable pairTable = *(reinterpret_cast<CoinAcceptor::PulseValuePairTable*>(pvParameters));
uint32_t tableSize = pairTable.size();
uint32_t index;
vTaskDelay(3000);
for (;;) {
index = random(0, tableSize);
Serial.printf("Simulating Dropping a Coin with Value: %d\n", pairTable[index].value);
for (uint32_t i = 0; i < pairTable[index].pulses; i++) {
digitalWrite(simulatorOutputPin, LOW);
vTaskDelay(1);
digitalWrite(simulatorOutputPin, HIGH);
vTaskDelay(1);
}
vTaskDelay(5000);
}
}
// ------------------- For Simulation ONLY -------------------------------------------------