How would I check if a button is pressed?

Its as simple as that. I have some code and I want to do the if statement when the button is pressed. I have a simple mechanical switch (placeholder) that will get replaced by a magnet sensor. But first I need to get the code working. I have worked with C# before so I am fammiliar with coding but I am a complete noob when it comes to arduinos. Here is my code:

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

#define PinInput 4
#define PinOutput 5

LiquidCrystal_I2C lcd(0x27, 16, 2);

void setup()
{
  lcd.begin();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0,0);
  
  pinMode(PinInput, INPUT);
  pinMode(PinOutput, OUTPUT);
}


void loop()
{
  if (PinInput == HIGH)
  {
    lcd.print("Hackster");
  }
}

Very simple as of now. But what I want to do is make a rev limiter for a engine with it. So I check how much time passes between a button press (or a magnet passing through the magnet sensor). In any case the pin will be high which will tell the arduino the stuff it needs to know. And also write the respective rpm value to a screen. But I have strugles getting even the basics out of the way. I have the button connected like so: One wire goes to 3.3 V and the other to pin D4 (using arduino nano). So I want to check if a button is pressed. So I assume i need to see is pin D4 is HIGH. But I am shore something is wrong. I mean it isn't working so something IS wrong. any help is appriciated

"PinInput" is 4 and 4 does not equal HIGH so your if statement won't trigger.
You need to do digitalRead(Pininput) to get the actual statue of the pin rather than the number of the pin.

You may also need to research pullup+pulldown resistors.

Welcome to the forum

if (PinInput == HIGH)

Pininput is a pin number, not the state of the pin

Try

if (digitalRead(Pininput) == HIGH)

But be aware that if the input is floating at an unknown voltage then results may not be consistent.

Consider using INPUT_PULLUP in pinMode(), wiring the switch to connect the pin to GND (LOW) when the button is pressed and check for a LOW state using digitalRead()

It would be worth your while googling “ Arduino rev counter “

The simplest way to wire the switch is to have a the switch from the input pin to ground. Then turn on the on-board pull-up resistor with:
pinMode(PinInput, INPUT_PULLUP);

The IF then becomes:
if ( digitalRead( pininput ) == FALSE ) {
The reason for the IF checking for a false condition is that the switch will return a zero when pressed, and a non-zero when not pressed.

No, for 2 reasons

  • FALSE is not defined
  • LOW would be a more logical value to test for in the circumstances

ok so Ive got the switch input working thanks to Kellygray and UKHeliBob. But now I am facing another issue. So the way i want this to work is mesure how many times the switch (or magnet in the complete project) sends a signal to the arduino in a course of 1/8 of a second. Then mutiply the result by required amount. Lets say the switch gets pressed (or magnet passes through the sensor) 8 times in 1/8 of a second. that would be 8 rpS (per second) then multiply by 60 to make it rpm (per minute). so that would be 480rpm. So I am asking how would I implement something like this into code. Thanks

Start by posting your current sketch

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

#define PinInput 4

LiquidCrystal_I2C lcd(0x27, 16, 2);

int time;

void setup()
{
  lcd.begin();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0,0);

  pinMode(PinInput, INPUT_PULLUP);
}


void loop()
{
  if (digitalRead(PinInput) == LOW)   
  {
    time++;
  }
}

there. and the time thing does not matter. just ignore it

There is a problem with the sketch

What will happen if the loop() function runs more than once whilst the button is held down ?

yes thats the problem. so I need a way to run the code ONLY when the input happens and then see how many times that input happend in 1/8 of a second. So lets say i press a button and keep holding it. I only want to count this as one click. How would I do that

Here's some quick thoughts on how to do it. Untested so may need some fixes here and there. It calculates the time gaps between the last 4 button presses then averages them out and works out the rpm from that. You could extend it to average over more values which would be more accurate for a constant speed or less values which would respond quicker to rpm changes.

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

#define PinInput 4

LiquidCrystal_I2C lcd(0x27, 16, 2);

long lastMillis = 0;
int timeGap1 = 0;
int timeGap2 = 0;
int timeGap3 = 0;
int timeGap4 = 0;
int currentState = 0;

int rpm = 0;
int rps = 0;
int averageTimeGap = 0;

void setup()
{
  lcd.begin();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0,0);
  pinMode(PinInput, INPUT_PULLUP);
  
  lastMillis = millis(); //get the time when program started
}


void loop()
{
	currentState = digitalRead(PinInput); //get the status of the button now
	if (currentState > lastRead) //if the value is more than last time that means button has been pressed
	{ 
		//bump all the saved time gaps down a place
		timeGap4 = timeGap3;
		timeGap3 = timeGap2;
		timeGap2 = timeGap1;
		//calculate latest time between button presses
		timeGap1 = millis() - lastMillis;
		
		lastMillis = millis();
	}
	
	if(timeGap4 > 0) //to ignore the first few loops whilst the timeGaps still have the zero values there were initiated with
	{
		averageTimeGap = (timeGap1 + timeGap2 + timeGap3 + timeGap4) / 4;
		rps = 1000/averageTimeGap; //revolutions per second
		rpm = rps*60; //revolutions per minute
		
		//do something else here with the rpm value?
	}
    lastRead = currentState;
}

dang thank you. thats actually the way I wanted to do first, but i had no idea how to do so

Just noticed an error and edited my code.
This line needed to be moved outside of the if statement:
lastRead = currentState;

are all variables defined

consider alternate approach

    static byte swLst = HIGH;
    byte but = (digitalRead(sw));
    if (swLst != but)  {
        swLst = but;
        if (LOW == but) {
            ...

ok so it was giving me an error so I added this on top of the code.

int lastRead;

So the code looks like this now:

#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

#define PinInput 4

LiquidCrystal_I2C lcd(0x27, 16, 2);

long lastMillis = 0;
int timeGap1 = 0;
int timeGap2 = 0;
int timeGap3 = 0;
int timeGap4 = 0;
int currentState = 0;
int lastRead;

int rpm = 0;
int rps = 0;
int averageTimeGap = 0;

void setup()
{
  lcd.begin();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0,0);
  pinMode(PinInput, INPUT_PULLUP);
  
  lastMillis = millis(); //get the time when program started
}


void loop()
{
  currentState = digitalRead(PinInput); //get the status of the button now
  lastRead = currentState;
  if (currentState > lastRead) //if the value is more than last time that means button has been pressed
  { 
    //bump all the saved time gaps down a place
    timeGap4 = timeGap3;
    timeGap3 = timeGap2;
    timeGap2 = timeGap1;
    //calculate latest time between button presses
    timeGap1 = millis() - lastMillis;
    
    lastMillis = millis();
  }
  
  if(timeGap4 > 0) //to ignore the first few loops whilst the timeGaps still have the zero values there were initiated with
  {
    averageTimeGap = (timeGap1 + timeGap2 + timeGap3 + timeGap4) / 4;
    rps = 1000/averageTimeGap; //revolutions per second
    rpm = rps*60; //revolutions per minute

    lcd.clear();
    lcd.print("rpm: " + rpm);
  }
}

but I am not getting any output on the display. can't seem to figure out why. everything seems fine to me

It's this line which I had wrong in the original code.

It needs to go somewhere after the if statement: if (currentState > lastRead) but not inside that statement.

won't lastRead always be equal to currentState?

move it after the closing brace of the if statement

yes I did and it actually works now. sortof... i guess my

lcd.print("rpm: " + rpm);

line is worong. since as long as the rpm is 0 everything is fine, BUT when i start clicking the button the display starts outputing giberish. Just some random letters and symbols

doesn't the LCD expect ascii strings, not integer values?