cambiamonete problema con impulsi da lettore banconote

salve, premetto che non sono molto esperto in programmazione arduino, vi spiego il mio problema; sto creando un cambiamonete con arduino che riceve gli impulsi da un lettore di banconote a sua volta comanda un rele che controlla un hopper, il problema sta nel fatto che arduino non legge come un unico impulso il treno di impulsi inviati dal lettore di banconote facendo attivare il rele dell'hopper, ma li legge random e a spezzoni, esempio se inserisco una banconota da 5€ il lettore invia a arduino 10 impulsi lui li legge 4-3-3 formando 10 il lettore funziona in questo modo
5€ 10 impulsi
10€ 20 impulsi
20€ 40 impulsi
50€ 100 impulsi
ho provato a cambiare il valore di "pulseThreshold" ma il risultato è sempre lo stesso credo che bisogna fare qualche modifica al codice ma non so veramente cosa modificare spero che qualcuno mi possa aiutare, allego il codice e lo screen del monitor seriale

CAMBIAMONETE.ino (4.84 KB)

Beh la prima domanda che mi viene in mente è: sicuro che il tempo che intercorre tra gli impulsi sia realmente sempre minore di 250ms, e che 250ms sia realmente l'intervallo di fine lettura? Hai provato a usare un oscilloscopio o almeno a fare uno sketch di test dei tempi tra impulsi?

PS Anche se non dovrebbe dare problemi, lo "switch(newCoinInserted)" lo metterei comunque dentro l'if() per sicurezza, tanto fino a che non entra nell'if() non può mai partire.

ciao grazie per la risposta, no non lo so se 250ms è il tempo giusto e non so neanche come creare uno sketch per misurare il tempo che passa tra un impulso e l'altro, come gia detto non sono molto esperto di arduino e di programmazione, ma mi piace moltissimo e vorrei capirci di piu

I problemi vanno sempre affrontati cercando di isolare le varie condizioni. Tu hai un lettore che manda degli impulsi (sto immaginando, non ho mai interfacciato né visto come funzionino, anzi se hai anche un link al modello esatto magari capisco meglio), questi arrivano ad Arduino il quale deve "contarli" entro un certo tempo, quindi una volta contati attiva l'erogazione delle monete in base al valore. Esatto?

Inizia dal lettore di banconote: hai le sue specifiche? C'è scritto da qualche parte con quale cadenza/intervallo manda gli impulsi? Il valore 250 te lo sei "immaginato" o lo hai letto da qualche parte?

Se non ce l'hai (e comunque è utile anche per te capire come Arduino "riceve" questi impulsi), per lo sketch di monitoraggio/test prova a fare un (nuovo) semplice sketch che legge continuamente lo stato del pin al quale è collegato il lettore, e quando questo cambia rispetto al precedente (da LOW a HIGH o viceversa) manda su seriale il tempo trascorso ("millis()-startTime") e lo stato (il valore letto dalla digitalRead(), se HIGH o LOW, basta anche solo 0 o 1): potrai da lì cercare di capire gli intervalli degli impulsi. Posta qui questo sketch ed il suo output e vediamo.

ti spiego non sono proprio in grando ancora di creare uno sketch anche semplice che sia, non ho le basi, cmq questo è il link del manuale ma non sembra indichi il tempo degli impulsi http://www.dvbvending.net.ua/files/manual/P_Series_P70-P77-P85.pdf il modello è il p77

Darò un'occhiata, ma visto che dici di non saper ancora programmare devo supporre che non lo abbia scritto tu quel codice (se non sai fare uno sketch che visualizzi i tempi di LOW/HIGH di un pin credo che sia difficile che tu abbia scritto codice che comprende gli interrupt, sapendo anche a quale pin corrisponde ognuno dei due...), quindi dove lo hai preso? Hai un link?

E intanto devo chiedertelo: hai intenzione di imparare a programmare o ti basta risolvere il problema?

Per il test prova una cosa di questo tipo (ma cerca anche di capire come funziona, in particolare qui il simbolo INPUTPIN rappresenta il pin digitale che è connesso al lettore, cambialo opportunamente da 11 a quello che usi) e riporta qui quello che vedi quando inserisci UNA banconota:

#define INPUTPIN 11
int newInput = 0;
int oldInput = 0;
unsigned long oldMillis = millis();

void setup() {
  Serial.begin(9600);
  pinMode(INPUTPIN, INPUT);
}

void loop() { 
  newInput = digitalRead(INPUTPIN);
  if ( newInput != oldInput ) {
    Serial.print(millis() - oldMillis);
    Serial.print("ms ");
    if ( newInput == 0 )
    	Serial.println("OFF");
    else
    	Serial.println("ON");
    oldMillis = millis();
    oldInput = newInput;
  }
}

innanzitutto grazie per l'aiuto che mi stai dando, no non lo creato io il codice (magari) e a dire la verità neanche ricordo dove lo preso, per quanto riguarda il fatto di imparare si mi piacerebbe molto ma non avendo le basi non è molto facile per me imparare, ma pian piano anche solo copiando incollando codici già fatti e facendomi aiutare a risolvere errori nei vari forum sto iniziando a capirci qualcosa e dal nulla per me è già molto :smiley: ; per il codice che mi hai dato lo caricato su arduino ma non succede nulla sul monitor seriale quando inserisco la banconota o provato anche a cambiare il pin mettendo il pin 3 ma è uguale c'è qualcosa che non và nel codice.

stranamente o ricaricato il codice e sembra funzionare ti allego gli screen del monito seriale quando inserisco i vari tagli di banconote o provato con 5-10-20€

scusate se mi intrometto...non capisco perchè 2 volte su 3 la prima scritta che appare nel monitor seriale riporta OFF !?...dovrebbe essere ON..giusto!?

prova con questo sketch...che in pratica ogni 5 secondi ti scrive il tempo intercorso tra un impulso ed un altro in microsecondi....massimo 40 impulsi...quindi banconota da 20 Euro...:

#define INPUTPIN 3
byte myIndex;
volatile unsigned long oldMicros;
volatile unsigned long myArray[40];

void setup() {
  Serial.begin(9600);
  pinMode(INPUTPIN, INPUT);
  myIndex = 0;
  for (byte i = 0; i < sizeof(myArray) / sizeof(long); i++) {
    myArray[i] = 0;
  }
  attachInterrupt(digitalPinToInterrupt(INPUTPIN), coinsPulseCount, RISING);
  oldMicros = micros();

}

void loop() {
  if (micros() - oldMicros >= 5000000) {
    for (byte i = 0; i < sizeof(myArray) / sizeof(long); i++) {
      Serial.println(myArray[i]);
      myArray[i] = 0;
    }
    myIndex = 0;
    oldMicros = micros();
    Serial.println("");
  }

}

void coinsPulseCount() {
  if (myIndex == 0) {
    myArray[myIndex] = 0;
    oldMicros = micros();
    myIndex++;
  }
  else {
    myArray[myIndex] = micros() - oldMicros;
    oldMicros = micros();
    myIndex++;
  }
}

ATTENZIONE: uso il PIN 3 come PIN di verifica impulso...l'impulso deve essere positivo, cioè dare i 5 volt; verifica il cablaggio...cioè vedere se realmente Arduino riconosce i 5 volt come tali.

ORSO2001 grazie di esserti interessato, o caricato il codice ma nel monitor seriale compare ogni 5 secondi una fila di 0 e basta anche se inserisco le banconote non cambia nulla, o conotrollato il pin 3 con il tester ma non risultano esserci i 5v

Beh, intanto che ci sei, prova pure questo

const byte coinSelectorPin = 3;
volatile byte coinPulseCount = 0;
volatile unsigned long pulseTime;
volatile unsigned long pulseTimeA;

void setup()
{
  Serial.begin(9600);
  pinMode(coinSelectorPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(coinSelectorPin), coinacceptor, FALLING);
}

void loop()  {
  if (coinPulseCount == 40 )  // 40 impulsi
  {
    Serial.print("milliSec  ");
    Serial.println(pulseTime - pulseTimeA);
    coinPulseCount = 0;
  }
}

void coinacceptor() {
  if (coinPulseCount == 0 ) {
    pulseTimeA = millis() ;
  }
  coinPulseCount++;
  pulseTime = millis() ;
}

adesso che guardo lo schema di gestione degli impulsi come segnale, sempre se non dico castronerie, il pin di riferimento deve essere messo in INPUT_PULLUP in quanto il contatto del relè, da schema, dovrebbe chiudere a GND (di arduino)...domanda...per i collegamenti hai fatto riferimento al capitolo 5-1-1 figura 16?
come hai collegato l'arduino?

o fatto la prova con il codice di brunello22 e devo dire che riesco a vedere sempre il tempo che ci impiega l'intero impulso a arrivare a arduino o cambiato anche il numero di impulsi facendo la prova con tutte le banconote le o inserite ciascuna 10 volte per vedere la differenza di tempo, ora quello che non capisco è perché con questo codice arduino riconosce sempre l'impulso per intero? forse perché viene prestabilito prima di caricare il codice?

Ora che sai qual'è il tempo massimo, prova a inserirlo in questa variabile

//***********************************************************************************************
byte pulseThreshold = 250;  //EDIT THIS VALUE TO CHANGE DELAY BETWEEN DETECTING BANK OF PULSES
//***********************************************************************************************

Metti un valore più alto di quello che ottieni con la banconota più grossa e dovrebbe andare
Certo che 15 secondi per leggere una banconota da 50 euro sono tantini

Edit:
Cambia il tipo di variabile, da byte a int

o cambiato il valore mettendo il piu alto ma resta sempre il solito problema, arduino legge gli impulsi a tratti :frowning:

non avevi letto questo che ho aggiunto dopo

Edit:
Cambia il tipo di variabile, da byte a int

int pulseThreshold = 16000;  //

cambiata da byte a int, ci impiega piu tempo a leggere gli impulsi ma il risultato è sempre uguale li legge a spezzoni

In effetti guardando lo sketch, il valore di pulseThreshold dovrebbe essere poco più del tempo di un impulso, quindi un valore di circa 350 dovrebbe andare bene, appena ho un minuto gli dò un'occhiata, mi sà che c'e' qualche altro problema

Prova così

// Raynerd Change Machine ****
/* This code controls both a coin hopper which dispences 10 pence coins and a 6 coin acceptor. The 6 coins acceptor pulses on coinSelectorPin"2" - 1 pulse = £1, 2 pulse = 2p, 3pulses = 5p...
  The arduino reads which code has been inserted and dispences the appropriate number of 10 pence coins. e.g. £1 = 10x10p    50p = 5x10p
*/

//**************Variables ****************
volatile byte coinPulseCount = 0;  // a counter to see how many times the pin has changed - which coin inserted
volatile byte hopperPulseCount = 0;  // a counter to she how many coins have been ejected
volatile unsigned long pulseTime;  //this stores the time of the last pulse.
byte newCoinInserted; // a place to put our last coin pulse count
byte coinValue = 0;      // number of pulses required to dispence each coin type.
byte twoPence = 0;       // count 5x 2 pences to dispence 10p
byte fivePence = 0;      // count 2x 5 pences to dispence 10p
//***********************************************************************************************
byte pulseThreshold = 250;  //EDIT THIS VALUE TO CHANGE DELAY BETWEEN DETECTING BANK OF PULSES
//***********************************************************************************************

//************Pins Used *******************
int hopperPin = 2;  // pin2 as optical count input
int coinSelectorPin = 3;  // pin3 as optical count input
int relayPin = 7;  // pin7 output relay

void setup()
{
  Serial.begin(9600);

  //**** pinModes *************
  pinMode(hopperPin, INPUT_PULLUP);       //hopper optical count is an input
  pinMode(coinSelectorPin, INPUT_PULLUP); //coin selector optical input
  pinMode (relayPin, OUTPUT);      //relay pin output
  digitalWrite(relayPin, HIGH);   //turn off relay - active LOW.
  digitalWrite(hopperPin, HIGH); //use the internal pullup resistor on the hopper optical input
  attachInterrupt(1, coinacceptor, FALLING); // CoinAcceptor - attach a PinChange Interrupt to our on the rising edge - link to coinacceptor function
  attachInterrupt(0, hopper, FALLING); // Hopper - attach a PinChange Interrupt to our pin on the falling edge - link to hopper function

}

void loop()
{
  //CHECK NOW TO SEE WHICH COIN IS INSERTED
  detachInterrupt (1);
  if (coinPulseCount > 0 && millis() - pulseTime > pulseThreshold)  //if there is a coin count & the time between now and the last pulse is greater than 1/4 of a second - THE END OF BANK OF PULSES
  {
    newCoinInserted = coinPulseCount;  //new variable to free up coinPulseCount on the interrupt.
    Serial.print("newCoinInserted pulses ");
    Serial.println(newCoinInserted);         // print the pulses of the new coin inserted.
    coinPulseCount = 0;                // clear pulse count ready for a new pulse on the interrupt.
  }
  attachInterrupt(1, coinacceptor, FALLING);
  //Proccess the coin inserted

  switch (newCoinInserted) {
    case 10:
      Serial.println("5€ inserted");   //5 pulse from validator - 5€ INSERTED
      newCoinInserted = 0;   //reset - ALTHOUGH DO I NEED TO DO THIS?
      coinValue = 5;        //hopper dispense 5 pulses/coins
      dispence();
      break;

    case 20:
      Serial.println("10€ inserted");   //2 pulse from validator - 10€ INSERTED
      newCoinInserted = 0;   //reset - ALTHOUGH DO I NEED TO DO THIS?
      coinValue = 10;        //hopper dispense 10 pulses/coins
      dispence();
      break;

    case 40:
      Serial.println("20€ inserted");   //3 pulse from validator - 20€ INSERTED
      newCoinInserted = 0;   //reset - ALTHOUGH DO I NEED TO DO THIS?
      coinValue = 20;        //hopper dispense 20 pulses/coins
      dispence();
      break;

    case 100:
      Serial.println("50€ inserted");   //4 pulse from validator - 50€ INSERTED
      newCoinInserted = 0;   //reset - ALTHOUGH DO I NEED TO DO THIS?
      coinValue = 50;        //hopper dispense 50 pulses/coins
      dispence();
      break;
  }
}
//*****INTERUPT detecting pulses from the coin acceptor
void coinacceptor()      //Function called when coin enters coin acceptor
{
  coinPulseCount++;
  pulseTime = millis();   //store current time in pulseTime

}

//******INTERUPT detecting pulses from the hopper
void hopper()           //function called when a coin is ejected from the hopper
{
  hopperPulseCount++ ;
}

void dispence()
{
  digitalWrite(relayPin, LOW);   //turn on relay - active LOW.
  delay(20);
  hopperPulseCount = 1;

  while (hopperPulseCount < coinValue)
  {
    //do nothing and wait with the relay on dispencing coins until it hits the "coinValue"
  }

  delay(40);    //wait to ensure the coin has enough momentum to leave hopper but not long enough for another coins to dispence!
  digitalWrite(relayPin, HIGH);   //turn off relay - active LOW.

  //**************************************************************************************
  delay(100);
  coinPulseCount = 0;   // ERROR IN SPIKES - hopper pulsing effects coin acceptor pulse line!
  //********************************************
}