Button switch doesnt work in bigger program

I'm currently building a setup with a stepper motor thats get triggered when a coin in put into a coin acceptor. There will be two different actions the motor can take, to switch between those modes a single button is added (together with led's to make clear which configurations is active).
The problem is that this switching part does work as a single program, but not in the the big program. I think it is placed in the wrong spot in the program, or that the other parts take a lot of time, but I'm by no means a very good programmer.
What I did discover was that by commenting the part 'counter' everything worked fine.
By commenting 'motor' it did sometimes work (i just pressed a lot of times and it sometimes worked).

here is the code:

#include <Wire.h> // include the library code:
#define COIN 2 // attach coin wire to digital 2
int coins;

int switchPin = 3;              // switch is connected to pin 3
    int led1Pin = 8;
    int led2pin = 9;
    int val;                        // variable for reading the pin status
    int val2;                       // variable for reading the delayed status
    int buttonState;                // variable to hold the button state
    int Mode = 0;              // What mode is the light in?

    int Index;
    int dir = 12;
    int stp = 13;
   

    void setup() {
      Serial.begin(9600); // Debugging output
      pinMode(COIN, INPUT);
      digitalWrite(COIN, HIGH); // pull up
      coins = 0;
  
      pinMode(switchPin, INPUT);    // Set the switch pin as input
      pinMode(led1Pin, OUTPUT);
      pinMode(led2pin, OUTPUT);
      buttonState = digitalRead(switchPin);   // read the initial state

      pinMode(stp, OUTPUT);
      pinMode(dir, OUTPUT);
    }

    void loop(){

      LED();
      counter();
      motor();
    }

    //=======
    void LED(){// led and button
      val = digitalRead(switchPin);      // read input value and store it in val
      delay(10);                         // 10 milliseconds is a good amount of time
      val2 = digitalRead(switchPin);     // read the input again to check for bounces
      delay(10);
      if (val == val2) {                 // make sure we got 2 consistant readings!
        if (val != buttonState) {          // the button state has changed!
          if (val == LOW) {                // check if the button is pressed
            if (Mode == 0) {         
              Mode = 1;               
            } else {
                if (Mode == 1) {       
                Mode = 0;           
            } 
           }
         }
        }
        buttonState = val;                 // save the new state in our variable
      }

      // Now do whatever the lightMode indicates
      if (Mode == 0) { // all-off
        digitalWrite(led1Pin, HIGH);
        digitalWrite(led2pin, LOW);
      }

      if (Mode == 1) {
        digitalWrite(led1Pin, LOW);
        digitalWrite(led2pin, HIGH);
      }
    }

  //=============
      void counter(){// Coin counter part
      while (! digitalRead(COIN)) { // while the coin pin is low (no coin detected), do nothing
      delay(1);
    }

      uint8_t counter = 0; // while the pin is high, we'll track the length with a counter
      while (digitalRead(COIN)) {
      delay(1);
      counter++;
    }
      
 
      if ((counter > 60) || (counter < 20))  
      return;
      coins++; 
      }

    //==================
     void motor(){//motor part
        if ((coins > 0) && (Mode == 0)){
        digitalWrite(dir,HIGH);
        for(Index = 0; Index < 400; Index++)
        {
          digitalWrite(stp,HIGH);
          delayMicroseconds(500);
          digitalWrite(stp,LOW);
          delayMicroseconds(500);
          }
            coins == 0;
            }

        else if((coins > 0) && (Mode == 1)){
            digitalWrite(dir,HIGH);
            for(Index = 0; Index < 400; Index++)
            {
            digitalWrite(stp,HIGH);
            delayMicroseconds(500);
            digitalWrite(stp,LOW);
            delayMicroseconds(500);
            }
              coins == 0;
              }

        else {}   
        Serial.print(val);
      }

hope someone can help me out!

Hi,

I'm no expert myself, but firstly replace:

pinMode(COIN, INPUT);
digitalWrite(COIN, HIGH); // pull up

just with:

pinMode(COIN, INPUT_PULLUP); // pull up

You do not set INPUT pins state.

Your counter() function is messed up, can you explain exactly what you want to do with it?
Basically your calling while loop till you get pin low, you should remove counter() entirely and place If statement in main loop function – if COIN is High then counter++, else counter = 0

Your problem is that you are using delay() function, when you call delay() Arduino just stops at this statement and waits until delay is over, then continues with the code.
When you interact with Arduino while its on delay() it will not register it, cos it's waiting delay() to finish, basically it's ignoring everything else. You could solve this by using "coding concept" as in "BlingWithoutDelay" example code or using interrupts.

    //=======
    void LED(){// led and button
      val = digitalRead(switchPin);      // read input value and store it in val
      delay(10);                         // 10 milliseconds is a good amount of time
      val2 = digitalRead(switchPin);     // read the input again to check for bounces
      delay(10);
      if (val == val2) {                 // make sure we got 2 consistant readings!
        if (val != buttonState) {          // the button state has changed!
          if (val == LOW) {                // check if the button is pressed
            if (Mode == 0) {         
              Mode = 1;               
            } else {
                if (Mode == 1) {       
                Mode = 0;           
            } 
           }
         }
        }
        buttonState = val;                 // save the new state in our variable
      }

Those 2 delays eat 160000 cycles EACH during which NO OTHER CODE RUNS, meaning that NOTHING GETS SERVICED.

If you have anything that needs to happen over time, you should let other things run in between. Not doing so puts a limit on what your code can do and TBH it's a very small limit.

  //=============
      void counter(){// Coin counter part
      while (! digitalRead(COIN)) { // while the coin pin is low (no coin detected), do nothing
      delay(1);
    }

      uint8_t counter = 0; // while the pin is high, we'll track the length with a counter
      while (digitalRead(COIN)) {
      delay(1);
      counter++;
    }

These are even worse and what's screwing with your buttons, they are while loops that hang everything up for as long as it takes to get a coin into the slot. Words can't convey how limiting that is.

You need to learn a couple things to un-block your code. Set your project aside until you learn and then pick it back up.

In my signature space below are 3 addresses to tutorials. You only need what's in the first one for this project.

DO ask questions about the tutorial after you've seen enough to ask good questions and this can go pretty quick.

I made a bit more refined LED function, try to understand what I did, but remember – if you want it to work properly You need to get rid of any long delays, modify and use this same code with your COIN counter as well. As with motor function – you have to get more knowledge how to get rid of delays.

void LED() // led and button
{
  if (digitalRead(switchPin)) // cheks if button is pressed (cheks if it's HIGH)
  {
    if (!buttonState) // same as: (buttonState == false) ---I made it a bit compact, but it may be confusinf to you
    {
      buttonState = true;
      Mode = !Mode; // this inverts button mode: If Mode was True - it will make it False and viseversa
    }
  }
  else
  {
    buttonState = false; // this will trigger if button was NOT pressed
  }

  // You do not need to make IF statemennts to set LOW or HIGH, just use "Mode" variable and add ! in front of it if you need to invert it:
  digitalWrite(led1Pin, Mode); // remember: TRUE = HIGH = 1 and FALSE = LOW = 0 (You can use whatever You like)
  digitalWrite(led2pin, !Mode);
delay(5); // for debouncing
}

Reliably debouncing a button in software can take a lot of pin checking ( once per pass through loop() ) or the just wait long enough and assume there's only been one or no state change and call it good since humans are 100x slower method.

GoForSmoke:
Reliably debouncing a button in software can take a lot of pin checking ( once per pass through loop() ) or the just wait long enough and assume there's only been one or no state change and call it good since humans are 100x slower method.

I can see your point and can't really argue cos you probably have way more knowledge than me, but checking every tic is simpler for newbies like me :slight_smile: If you have a good resource about it – please let me know, I gladly deepen my knowledge on this topic.

Everything you could want about contact switches explained (with pics) clearly in simple terms for the most part:

Once your code gets fast after being freed from blocking it can "see" the bounces and detect many transitions in one press.

Note that Nick also covers debouncing with hardware by putting a 1 uF capacitor across the switch contacts. It absorbs the bounces.

Here's other topics he covers. Even just scanning through a new topic will present you with new terms and concepts to absorb before going back for details when ready or needing bits you remember seeing. Take any hard ones in stages but really Nick makes the trails easier to climb those hills and see from the tops all you can do.

I have a button library that is not beginner code but can be used by beginners... but "everyone" past a certain stage has some kind of button code, it's like a rite of passage here. Learning what you can do will teach more than just the routine or how to use someone else's.
Serial is one that I haven't done my own so yeah this do your own has limits as to what you find practical. I'd know more if I did my own but I haven't touched inside of serial comms since the 90's and TBH Arduino Serial is just fine by me especially since the fixes around IDE 1.0 or so.

Hi,
Welcome to the forum.

From what I can see;

  • You have a coin collection machine.
  • It puts out a pulse everytime a coin is inserted.
  • You have 2 LEDs, when do they work? Are they to tell the user that you need coins and then have enough?
  • The button is to start the motor process, 400 steps if you have detected enough coins?
  • When it has done the 400 steps, what triggers it to do the other 400steps?

What is the application, what does the motor do?
How many coins need to be inserted to get the button to operate.

Can you put down your operating steps in logical point form please?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom.. :slight_smile:

That's the thing. The coin mech should be checked constantly. Never let it miss someone's money! One task should watch the coin mech and update a variable when new coins arrive.

One task should run the output/motor when it reads (then zeros) the coins variable.

The leds should probably have their own task set between the coin mech and output tasks. It can see the money before the output task eats it.

Broken into tasks the code can be smaller, easier to debug and very responsive.

TomGeorge:
Hi,
Welcome to the forum.

From what I can see;

  • You have a coin collection machine.
  • It puts out a pulse everytime a coin is inserted.
  • You have 2 LEDs, when do they work? Are they to tell the user that you need coins and then have enough?
  • The button is to start the motor process, 400 steps if you have detected enough coins?
  • When it has done the 400 steps, what triggers it to do the other 400steps?

What is the application, what does the motor do?
How many coins need to be inserted to get the button to operate.

Can you put down your operating steps in logical point form please?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom.. :slight_smile:

The application is an vending machine prototype, nothing too complicated its for an university first year project. When one coin is inserted the machine will be turned on, the coin is the trigger.
the button is for switching between two different motor actions. So mode 1 leads to action 1 (for instance turn clockwise 360 degrees), mode 2 leads to action 2 (for instance turn counterclockwise 180 degrees).

  1. I have an machine that can count how many of one type of coin are inserted.
  2. yes it sends a pulse once a coin is inserted, this pulse needs to be detected and then processed.
  3. the leds are purely to show in which mode the machine is (mode 1 of mode 2)
  4. its to switch modes.
  5. another coin insert.

for the operating steps I will just explain them in quick steps.

  1. the programs needs to always check whether there is a coin inserted, when this happens the coin collector will send a pulse (to pin 2).

  2. You can select your mode by clicking the button, it is one button for two modes. So when the button is pressed the mode is switched. The other led will also turn on to indicate the different mode.

  3. when a pulse from the coin collector is sensed the mode needs to be checked and according to the mode the motor will do something.

  4. after this actions the variable 'coin' should be reset to zero.

Once i get this to work another motor needs to be added, because two motors are needed.
I will post a fritzing drawing tonight, I dont have time to make it at the moment.

3Dgeo:
I made a bit more refined LED function, try to understand what I did, but remember – if you want it to work properly You need to get rid of any long delays, modify and use this same code with your COIN counter as well. As with motor function – you have to get more knowledge how to get rid of delays.

void LED() // led and button

{
  if (digitalRead(switchPin)) // cheks if button is pressed (cheks if it's HIGH)
  {
    if (!buttonState) // same as: (buttonState == false) ---I made it a bit compact, but it may be confusinf to you
    {
      buttonState = true;
      Mode = !Mode; // this inverts button mode: If Mode was True - it will make it False and viseversa
    }
  }
  else
  {
    buttonState = false; // this will trigger if button was NOT pressed
  }

// You do not need to make IF statemennts to set LOW or HIGH, just use "Mode" variable and add ! in front of it if you need to invert it:
  digitalWrite(led1Pin, Mode); // remember: TRUE = HIGH = 1 and FALSE = LOW = 0 (You can use whatever You like)
  digitalWrite(led2pin, !Mode);
delay(5); // for debouncing
}

Thanks for the code, will check it out tonight. I understand now that the while functions is the problem.

I cant really code myself, I can understand most things other people do. But when I make code i just search for what I need and throw it all together, maybe with some ajustments. This is why it probably looks horrible.

Hi,

  1. the programs needs to always check whether there is a coin inserted, when this happens the coin collector will send a pulse (to pin 2).

  2. You can select your mode by clicking the button, it is one button for two modes. So when the button is pressed the mode is switched. The other led will also turn on to indicate the different mode.

  3. when a pulse from the coin collector is sensed the mode needs to be checked and according to the mode the motor will do something.

  4. after this actions the variable 'coin' should be reset to zero.

What if the mode you want is already selected?
Or do you select the mode BEFORE you put the coin in.

So,

  • Initially, the machine sits, the motor position is in the "middle".
  • The Mode1 is already selected, the user presses the button if Mode2 is desired.
  • The user inserts the coin.
  • The controller turns the motor left of right depending on the Mode.
  • Once the motor turns to the desired position, it then returns to the 'middle"
  • loop back to 1.

If a coin is inserted without the Mode button being pressed how does the machine know that was really his/her choice.

OR,

  • Initially, the machine sits, the motor position is in the "middle".
  • The Mode0 is already selected, the user presses the button to select Mode1 or Mode2.
  • The user inserts the coin.
  • If a Mode1 or Mode2 is selected then operate motor, if in Mode0, flash both LEDs to alert user he/she has not selected a Mode.
  • The controller turns the motor left of right depending on the Mode.
  • Once the motor turns to the desired position, it then returns to the 'middle"
  • loop back to 1.

This ensures that a wanted selection has been made.

Hope it makes sense.

Tom... :slight_smile:

3Dgeo:

pinMode(COIN, INPUT);

digitalWrite(COIN, HIGH); // pull up




just with:


pinMode(COIN, INPUT_PULLUP); // pull up

These two are in fact equivalent, and one of the several counter-intuitive thing that Arduino did trying to make it easier (just like analogWrite to start a pulsed signal - also known as PWM).

TomGeorge:
Hi,
What if the mode you want is already selected?
Or do you select the mode BEFORE you put the coin in.

So,

  • Initially, the machine sits, the motor position is in the "middle".
  • The Mode1 is already selected, the user presses the button if Mode2 is desired.
  • The user inserts the coin.
  • The controller turns the motor left of right depending on the Mode.
  • Once the motor turns to the desired position, it then returns to the 'middle"
  • loop back to 1.

If a coin is inserted without the Mode button being pressed how does the machine know that was really his/her choice.

OR,

  • Initially, the machine sits, the motor position is in the "middle".
  • The Mode0 is already selected, the user presses the button to select Mode1 or Mode2.
  • The user inserts the coin.
  • If a Mode1 or Mode2 is selected then operate motor, if in Mode0, flash both LEDs to alert user he/she has not selected a Mode.
  • The controller turns the motor left of right depending on the Mode.
  • Once the motor turns to the desired position, it then returns to the 'middle"
  • loop back to 1.

This ensures that a wanted selection has been made.

Hope it makes sense.

Tom... :slight_smile:

I think the first option is just fine, because with the leds you can see which mode is selected.

I just tried some things and wrote the counter part with a if statement instead of a while statement.

 void counter() {// coin counter part
        var1 = digitalRead(COIN);
        if(var1 == HIGH) {
          coins++;
        }
      }

It now works as it should, Im not sure if its the best of the prettiest way. So suggestions to make the code better are still welcome, but at least it works now.

MCKenzy:
I just tried some things and wrote the counter part with a if statement instead of a while statement.

 void counter() {// coin counter part

var1 = digitalRead(COIN);
       if(var1 == HIGH) {
         coins++;
       }
     }




It now works as it should, Im not sure if its the best of the prettiest way. So suggestions to make the code better are still welcome, but at least it works now.

Well, probably my solution will not be the best, but problem I see is that coin will connect those pins many Arduino cycles (will add extra coin every cycle) till it clears connected pin, my suggestion would be:

 void counter() // coin counter part
{       
        if(digitalRead(COIN))
        {
          if(!var1)
          {
              var1 = 1; // true
              coins++;
          }
        }
        else var1= 0; // fasle
delay(5); // for debouncing
}