Распознавание монет с помощью Coin Accepter в Arduino Uno

Я работаю над проектом торгового автомата и использую для этого CH-926 и Arduino Uno. Я уже настроил монетоприемник на разное количество монет и соответствующие выходные импульсы. Я не могу получить желаемый результат для этого. С каждой вставленной монетой выходной результат меняется, даже если я кладу одну и ту же монету.

int pulse = 0;

void coin_value() {
  pulse = pulse + 1;
}

void setup() {
  Serial.begin(9600);
  pinMode(2, INPUT);
  Serial.println("Ready to be collected");
}

void loop() {
  if (digitalRead(2) == HIGH) {
    attachInterrupt(0, coin_value, FALLING);

    if (pulse == 3) {
      Serial.println("50");
    }
    if (pulse == 2) {
      Serial.println("20");
    }
    if (pulse == 1) {
      Serial.println("10");
    }
  }

  pulse = 0;
}

Для каждой монеты существуют разные импульсы, которые помогают распознать монету.intpulse=0;.

Итак, когда я вставляю монету 1, на выходе должно быть 10, для монеты 2 — 20, а для монеты 3 — 50.

, 👍1

Обсуждение

[Не пересекайте сообщения.](https://meta.stackexchange.com/q/64068) Вы уже [задавали этот вопрос в SO](https://stackoverflow.com/q/54255438)., @gre_gor

Однако в Stack Overflow его попросили задать вопрос здесь, что он и сделал., @Nick Gammon

что это на самом деле означает? «Я не могу получить желаемый результат» ..... чего вы ожидаете? .... что вы на самом деле получаете?, @jsotola

@NickGammon Вопрос должен быть только на одном сайте. Если для этого найден лучший сайт, ему следует удалить старый., @gre_gor

@gre_gor Я пометил сообщение SO для удаления. Однако Сумит Кумар мог бы помочь самоудалением, если ему позволит система., @Nick Gammon


2 ответа


1

Ваш код ошибочен во многих отношениях.


  1. pulse должен быть объявлен изменчивым, т.е.

    volatile int pulse = 0;
    

    Это потому, что оно может измениться в процедуре обслуживания прерываний.


  1. Вы должны выполнить attachInterrupt только один раз, в setup.

  1. Ваш код для отображения счетчика будет зависеть от времени. Что, если вам удастся отобразить счетчик после того, как поступил один импульс, но до того, как они все? Затем вы устанавливаете счетчик обратно на ноль.

Лучше было бы что-то вроде этого, однако непроверено:

volatile int pulse = 0;

void coin_value() {
  pulse = pulse + 1;
}

void setup() {
  Serial.begin(9600);
  pinMode(2, INPUT);
  Serial.println("Ready to be collected");
  attachInterrupt(0, coin_value, FALLING);
}

void loop() {

  if (pulse > 0)
    {
    delay (1000);   // позволяем прибыть другим импульсам
    if (pulse == 3) {
      Serial.println("50");
    }
    if (pulse == 2) {
      Serial.println("20");
    }
    if (pulse == 1) {
      Serial.println("10");
    }
    pulse = 0;  // очищаем для следующего раза
  }

}

(Отредактировано, добавлено)

Даже в этом случае ваш тест на 1/2/3 может оказаться неудачным, если монетоприемник отправит импульсы дважды. Тогда вы можете получить 2/4/6 импульсов. Вероятно, вам нужно что-то отобразить, если есть другой счетчик, например.

  if (pulse == 3) {
    Serial.println("50");
  }
  else if (pulse == 2) {
    Serial.println("20");
  }
  else if (pulse == 1) {
    Serial.println("10");
  }
  else {
     Serial.print ("Unexpected number of pulses: ");
     Serial.println (pulse);
  }
,

1

Прежде всего, что вы сказали

Итак, когда я вставляю монету 1, на выходе должно быть 10, для монеты 2 выход должен быть 20, а для монеты 3 выход должен быть 50.

Да, монета 3 будет равна 50, но это не означает, что монета 3 имеет 3 импульса (у нее будет 5 импульсов), я рекомендую вам всегда использовать эту формулу:

Значение_монеты = Количество импульсов * Номинал.

Я не рекомендую вам использовать 3 импульса от монетоприемника, поскольку у вас нет монет номиналом 15 и 30 центов. В большинстве случаев монетоприемники имеют:

1/4 1/2 1 2 4 5 8 10 импульсов

Обычно я предпочитаю сохранять все данные в переменных

Итак, давайте перейдем к переменным для кода

const int coinIntPin = 2;          //interruptPin 0 — это цифровой вывод 2
volatile boolean newCoin = false;                  
volatile int pulseCount;          //считаем импульс за
volatile int timeOut = 0;         //отсчитывает тайм-аут после вставленной последней монеты
float coinType;
float denomination = 0.50;         // в моем случае 1 импульс = 0,50$
int max_impulse = 4;              // это максимальное количество импульсов, которое я использую
volatile long timeFPulse = 0;     // чтобы определить, когда был прерван Первый импульс
volatile long interval;           // для определения интервала от первого и последнего импульса

И всегда используйте AttachInterrupt(digitalPinToInterrupt(pin), ISR, mode); Arduino рекомендует, как показано ниже:

void setup(){
    Serial.begin(9600);              
    attachInterrupt(digitalPinToInterrupt(coinIntPin), coinInserted, FALLING);

}

И я дам вам остальную часть кода:

void coinInserted(){
    newCoin = true; 
    timeFPulse = millis();
    pulseCount++; 
}

void loop()
{

     while (newCoin == true)
    {
            interval = millis() - timeFPulse;  //интервал от первого и последнего импульса
            if(pulseCount == max_impulse || (interval > 500 && pulseCount > 0)) //Max_impulse будет избегать любых дополнительных импульсов по любой причине.
            { 
// Именно поэтому я рекомендовал вам использовать 1 2 4 5 10 20 импульсов вместо 3 7 9 и т. д.
              coinType = pulseCount * denomination; 
              newCoin = false;
              sendData();
              delay(5);

             }  

    }
}


void sendData(){
  Serial.print("Do what ever you want. Inserted Money = ");
  Serial.println(coinType);
  coinType = 0;  // удалите, если хотите сохранить монеты и вывести сумму вставленных монет
  pulseCount = 0;  // удалите, если хотите сохранить импульсы, определенные монетоприемником
}

И, наконец, посмотрите (интервал > 500). Если у вас разные максимальные импульсы, вы должны изменить 500 на (длина импульса * Максимальное количество импульсов + 100); поэтому, если у вас максимум 10 импульсов, вы должны ввести 1100, а не 500 (в моем случае);

,