Counting button presses and turning it into presses per minute

Hello,

New to posting and Arduino so if I miss anything out please bare with me. We have a machine at work which only has a potentiometer to control speed and no digital readout of how many parts it's making per an amount of time. I'm trying to use a pro mini to read signals over a period of 12 seconds then multiply that by 5 which would give the amount per minute. I'm running into some problems though. For the sake of trying to get the program working instead of having it attached to the machine I'm using a push button to simulate the signal I would get from the proximity sensor on the machine. The program I have attached will count them correctly but when the startTime reaches 12000ms then it freezes, wont count anymore and also doesn't go back to start the counting again. I've also realised that this way of doing it isn't very efficient as there's only a small window where the actual value would be shown and the rest of the time I would just have a rapidly rising number. Think I've worked myself into a little hole and would welcome some advice. I need the value to be the amount of signals per minute but it needs to be an updating value if the speed is changed so it cant just be an average. Let me know what you think and I can take a little picture of the test rig if needed.

#include <Adafruit_SSD1306.h>
#include <splash.h>

#include <gfxfont.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>




#include <Wire.h>

#define SCREEN_WIDTH 128 //OLED display width, in pixels
#define SCREEN_HEIGHT 64 //OLED display height, in pixels

// declare an SSD1306 display object connected to I2C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 4);


unsigned long startTime=0;
unsigned long timeWindow=12000;
int counter=0;
int previousCounter=0;
int simButtonPin=12;
int simButtonState=0;
int previousSimButtonState=0;
int rpmValue=0;

void setup() {
  pinMode(simButtonPin, INPUT_PULLUP);
  Serial.begin(9600);
  // put your setup code here, to run once:
  // initialize OLED display with address 0x3C for 128x64
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0X3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }

    display.display();
    delay(2000);  //wait for initializing 
    display.clearDisplay();   //clear display
    

    display.setTextSize(1);   //text size
    display.setTextColor(SSD1306_WHITE); // text color
    display.setCursor(0, 0);    //position to display
    display.println("Hello world!"); //text to display
    display.display();    //show on OLED
    display.startscrollright(0x00, 0x0F);
    delay(2000);
    display.stopscroll();
    display.clearDisplay();

   
   
  }



void loop() {
  // put your main code here, to run repeatedly:
   startTime=millis();
  
 
if (startTime<timeWindow){

  

  simButtonState=digitalRead(simButtonPin);
  
    
  
      if (simButtonState==LOW){
        counter++;
        display.clearDisplay();   // Clear display
        display.setTextSize(1);   //text size
        display.setTextColor(SSD1306_WHITE); // text color
        display.setCursor(0, 0);    //position to display
        display.println(counter*5); //display value
        
        display.display();    //show on OLED
        delay(50);   // Stop Bounce
      }
    
}

  if (startTime>=timeWindow){
    startTime=0;
    counter=0;
  }
  
  

  
    
  

  previousCounter=counter;
  simButtonState=previousSimButtonState;

  
  
  
  
    
  

}

Time moves on...

move that to the last line of setup.

You may want to use elapsed time instead of just a starting time.

if ( (millis() - startTime) < timeWindow)

{
do the things when elapsed time is less than time window
} else // time window exceeded.
{
// get a new start time or some other thing do's.
startTIme=millis(); // reset start time
}

ok so I've changed those and uploaded it but now the counter just goes up and up without a 12 second period. Any idea how it can store the press signal for 12 seconds and then delete it to give a running value?

#include <Adafruit_SSD1306.h>
#include <splash.h>

#include <gfxfont.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>




#include <Wire.h>

#define SCREEN_WIDTH 128 //OLED display width, in pixels
#define SCREEN_HEIGHT 64 //OLED display height, in pixels

// declare an SSD1306 display object connected to I2C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 4);


unsigned long startTime=0;
unsigned long timeWindow=12000;
int counter=0;
int previousCounter=0;
int simButtonPin=12;
int simButtonState=0;
int previousSimButtonState=0;
int rpmValue=0;

void setup() {
  pinMode(simButtonPin, INPUT_PULLUP);
  Serial.begin(9600);
  // put your setup code here, to run once:
  // initialize OLED display with address 0x3C for 128x64
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0X3C)) {
    Serial.println(F("SSD1306 allocation failed"));
    for(;;);
  }

    display.display();
    delay(2000);  //wait for initializing 
    display.clearDisplay();   //clear display
    

    display.setTextSize(1);   //text size
    display.setTextColor(SSD1306_WHITE); // text color
    display.setCursor(0, 0);    //position to display
    display.println("Hello world!"); //text to display
    display.display();    //show on OLED
    display.startscrollright(0x00, 0x0F);
    delay(2000);
    display.stopscroll();
    display.clearDisplay();

   startTime=millis();
   
  }



void loop() {
  // put your main code here, to run repeatedly:
   
  
 
if ((millis()-startTime)<timeWindow){

  

  simButtonState=digitalRead(simButtonPin);
  
    
  
      if (simButtonState==LOW){
        counter++;
        display.clearDisplay();   // Clear display
        display.setTextSize(1);   //text size
        display.setTextColor(SSD1306_WHITE); // text color
        display.setCursor(0, 0);    //position to display
        display.println(counter*5); //display value
        
        display.display();    //show on OLED
        delay(50);   // Stop Bounce
      }
    
}

  else{
    startTime=millis();
  }
  
  

  
    
  

  previousCounter=counter;
  simButtonState=previousSimButtonState;

  
  
  
  
    
  

}

...

1 Like

When this stuff finally kills me, that's gonna be on my gravestone. :expressionless:

a7

1 Like

Of course! thank you!

I think mine will say something like "program not responding"

Consider the following, particularly the idea of looking for the switch to become pressed, not just "be" pressed (compiles, not tested or simmed):

#include <Adafruit_SSD1306.h>
#include <splash.h>
#include <gfxfont.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SPITFT.h>
#include <Adafruit_SPITFT_Macros.h>
#include <Wire.h>

#define SCREEN_WIDTH 128 //OLED display width, in pixels
#define SCREEN_HEIGHT 64 //OLED display height, in pixels

// declare an SSD1306 display object connected to I2C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, 4);

const uint8_t simButtonPin=12;

const uint32_t K_SAMPLE_TIME = 12000ul;     //mS    time to accumulate switch press counts
const uint32_t K_SW_READ_TIME = 50ul;       //mS    time between switch reads

uint8_t
    nowSwitch,
    lastSwitch;
uint32_t
    tRead = 0ul,
    tCount = 0ul,
    tNow;
uint16_t
    itemCount = 0;

void setup() 
{
    pinMode(simButtonPin, INPUT_PULLUP);
    lastSwitch = digitalRead( simButtonPin );
    
    Serial.begin(9600);
    // initialize OLED display with address 0x3C for 128x64
    if (!display.begin(SSD1306_SWITCHCAPVCC, 0X3C)) 
    {
        Serial.println(F("SSD1306 allocation failed"));
        for(;;);
    }

    display.display();
    delay(2000);  //wait for initializing 
    display.clearDisplay();   //clear display   
    display.setTextSize(1);   //text size
    display.setTextColor(SSD1306_WHITE); // text color
    display.setCursor(0, 0);    //position to display
    display.println("Hello world!"); //text to display
    display.display();    //show on OLED
    display.startscrollright(0x00, 0x0F);
    delay(2000);
    display.stopscroll();
    display.clearDisplay();
       
}//setup

void loop() 
{
    tNow = millis();
    
    //read the switch
    if( (tNow - tRead) >= 50ul )
    {
        tRead = tNow;
        //read the switch
        nowSwitch = digitalRead( simButtonPin );
        //not the same state as last read?
        if( nowSwitch != lastSwitch )
        {
            //save new state
            lastSwitch = nowSwitch;
            //if new state is 'low' switch became pressed
            if( nowSwitch == LOW )
                itemCount++;    //so bump the count
        }//if
        
    }//if

    //update the display every 12-sec
    if( (tNow - tCount) >= K_SAMPLE_TIME )
    {
        tCount = tNow;
        
        display.clearDisplay();   // Clear display
        display.setTextSize(1);   //text size
        display.setTextColor(SSD1306_WHITE); // text color
        display.setCursor(0, 0);    //position to display
        display.println(itemCount*5); //display value    
        display.display();    //show on OLED

        //after update, reset the item counter
        itemCount = 0;
                
    }//if
    
}//loop

If the pulse from the machine is always coming at the same rate, then your scheme will work. If the pulse timing varies, then you do not know how many pulses per minute you have because you do not know when to start or stop.
Perhaps consider a one minute timer in code and count the pulses in that time period.
Paul

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.