Project tutorial

Pushup Counter © GPL3+

Using Kemet SS-430 to count push up.

  • 4,485 views
  • 0 comments
  • 22 respects

Components and supplies

Necessary tools and machines

3drag
3D Printer (generic)

Apps and online services

About this project

Pushup Counter Demo

Introduction:

Smart fitness IoT tools are gaining more and more traction, after Pelaton went IPO, it proves there are a lot of rooms for fitness market. Focusing on exercise not only improves market, it also improves overall health and fitness of the entire population.

While we can track cycling with Pelaton, running/walking with fitbit, some of the basic exercise such as push ups are still relatively hard to track. In this article, we are building a prototype of push up counter using kemet pyroelectric sensor and Arduino.

Step 1: Setup Arduino and Pyro Sensor

To do this project we will use Arduino Uno, Wifi Shield and Grove shield so we can add additional sensors.

Next we can print out the case from thingsverse.

Through 3D printing, we'd have a basic buildup to connect with.

After all is done we should have something like this.

Connect all the pieces and we should have following

The pin assignment is from right to left, with pin 1 being power, pin 5 being GND and pin4 is Vout.

With that's all done, we can start moving onto next step.

Step 2: Test out the sensor

We can first try with the code that was given to us by the official site from https://ec.kemet.com/blog/pyro-switch-hidden-ir-detection/

int Pyro = A1;
unsigned long PyroRead = 0;
unsigned long IR_threshold = 198000;
// Note: SS-430 has two pulses of 200msec per detection.
// IR_threshold is in microsec (usec), therefore 198msec threshold
int LED = 7;
int Detected = LOW;
int IR_sensed = 0;
void setup() {
pinMode (7, OUTPUT); //LED Connected to Pin 7
pinMode (A1,INPUT); // IR Sensor connected to A1
}
void loop() {
while ((IR_sensed < 2)){ //Break after 2 good triggers PyroRead = pulseIn(A1, HIGH); //Measure trigger point if(PyroRead > IR_threshold){ //Make sure trigger is over 198msec)
IR_sensed++; //Mark as a good trigger
}
}
if (Detected == HIGH){ // Turn LED OFF if it was previous ON
Detected = LOW;
digitalWrite(7, LOW);
}
else {
Detected = HIGH; // Turn LED ON if it was previous OFF
digitalWrite(7, HIGH);
}
PyroRead = 0; // Reset readings
IR_sensed = 0;
delay(1000); // Accept triggers after a second

But as you can see, this really does not work. This is due to the sensitivity of the raw sensor. At this point you should at least able to know that sensor is connected and working correctly.

Schema at this point would be

Step 3: Kemet SS-430 Lens

As we've seen from previous step that the sensor is jumping all over the place due to it's sensitivity, additional lenses are needed for us to make the sensor actually work.

For our test, we put a piece of acrylic covering the sensor itself and running with the same code, we would receive a much more accurate reading.

While browsing through the discussion board, GeoNomad has made a 3D printable Lenses on TinkerCad, we can add that to this project. This is able to block all the other angles so we can focus on one single angle.

Step 4: Data storage

Now that sensor is running and we can track our push ups, we need to store our progress for our pushups, one of the easiest way is firebase. For this article we will go through using firebase through simple ways. Go through create a project like normal CP then create a database with test enviroment.

Next start a collection of pushups

We can then add our schema, which includes pushup count and timestamp.

When all is done, we will have our normal database setup.

You would also need a service account key being generated through firebase. Please do not upload this key to the repo, as it is a secure key.

Once it's connected, we can create a local relay on our server to make firebase transfer.

const http = require('http');
const url = require('url');
const querystring = require('querystring');
// Import Admin SDK
var admin = require("firebase-admin");
var serviceAccount = require("path/to/serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://databaseName.firebaseio.com"
});
// Get a database reference to our blog
var db = admin.database();
var ref = db.ref("pushup");
ref.once("value", function(snapshot) {
console.log(snapshot.val());
});
const hostname = '192.168.1.12';
const port = 3000;
const server = http.createServer((req, res) => {
const queryObject = url.parse(req.url,true).query;
var dt = new Date();
var utcDate = dt.toUTCString();
if(queryObject != null && queryObject.pushup != null)
{
console.log(queryObject.pushup);
var newPostRef = ref.push().set({
count: queryObject.pushup,
time: utcDate
});
var postId = newPostRef.key;
console.log(postId);
console.log(utcDate);
}
//console.log(querystring.parse(queryObject));
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});

Simply run

node app.js

and we can use this local to relay the firebase.

Step 5: Arduino intergration

Now that we can count our pushups, we can store our pushups, this is time for everything to come together. First, we will need to utilize the Arduino wifi shield to connect to the internet.

#include <WiFi.h>

char ssid[] = "yourNetwork"; // your network SSID (name)
char pass[] = "12345678"; // your network password
int status = WL_IDLE_STATUS; // the Wifi radio's status

void setup() {
// initialize serial:
Serial.begin(9600);

// attempt to connect using WPA2 encryption:
Serial.println("Attempting to connect to WPA network...");
status = WiFi.begin(ssid, pass);

// if you're not connected, stop here:
if ( status != WL_CONNECTED) {
Serial.println("Couldn't get a wifi connection");
while(true);
}
// if you are connected, print out info about the connection:
else {
Serial.println("Connected to network");
}
}

void loop() {
// do nothing
}

We are now also adding a green LED, Buzzer, and a button. In setup we need to have all of these. Once Wifi is connected, we can blink the green LED 3 times.

void setup() {
// declare the ledPin as an OUTPUT:
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
pinMode(greenledPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
pinMode (sensorPin, INPUT); // IR Sensor connected to A1
pinMode (buttonPin, INPUT); // Button Pin
// attempt to connect using WPA2 encryption:
Serial.println("Attempting to connect to WPA network...");
status = WiFi.begin(ssid, pass);
// if you're not connected, stop here:
if ( status != WL_CONNECTED) {
Serial.println("Couldn't get a wifi connection");
while(true);
}
// if you are connected, print out info about the connection:
else {
Serial.println("Connected to network");
//connected to network, blink it 3 times
digitalWrite(greenledPin, HIGH);
delay(500);
digitalWrite(greenledPin, LOW);
delay(500);
digitalWrite(greenledPin, HIGH);
delay(500);
digitalWrite(greenledPin, LOW);
delay(500);
digitalWrite(greenledPin, HIGH);
delay(500);
digitalWrite(greenledPin, LOW);
}
}

Next part is buzzer, everytime you complete a pushup, a buzzer will beep once to remind you you have finished a pushup. A pushup counter will also be used for sending in the info.

if (Detected == HIGH) { // Turn LED OFF if it was previous ON
Detected = LOW;
digitalWrite(ledPin, LOW);
digitalWrite(buzzerPin, HIGH);
delay(200);
digitalWrite(buzzerPin, LOW);
pushupCount += 1;
}
else {
Detected = HIGH; // Turn LED ON if it was previous OFF
digitalWrite(ledPin, HIGH);
}

The button is used for uploading the information to the local server and sending it to firebase. We'd also be clearing up pushupCount flag since we are sending that information to the server.

while ((IR_sensed < 2)) { //Break after 2 good triggers
PyroRead = pulseIn(sensorPin, HIGH); //Measure trigger point
Serial.println(PyroRead); // stop the autonomous robot
if (PyroRead > IR_threshold) { //Make sure trigger is over 198msec)
IR_sensed++; //Mark as a good trigger
}
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
// turn LED on:
digitalWrite(greenledPin, HIGH);
String tmp;
tmp = String(pushupCount);
Serial.println("\nStarting connection to server...");
// if you get a connection, report back via serial:
if (client.connect(server, 3000)) {
Serial.println("connected to server");
// Make a HTTP request:
client.println("GET /?pushup=" + tmp + " HTTP/1.1");
client.println("Host: 192.168.1.12");
client.println("Connection: close");
client.println();
}
digitalWrite(greenledPin, LOW);
pushupCount = 0;
}
}

When all the sensors are attached it should look something like following.

Step 6: Demo

Now that we have everything done finished, we can proceed to demo.

Pushup Counter Demo

Code

Arduino UNO codeArduino
Arduino UNO code for the pushup counter.
#include <WiFi.h>

char ssid[] = "YourWifi";     //  your network SSID (name)
char pass[] = "YourWifiPassword";    // your network password
int status = WL_IDLE_STATUS;     // the Wifi radio's status
WiFiClient client;

int sensorPin = A1;    // select the input pin for the potentiometer
int ledPin = 2;      // select the pin for the LED
int buttonPin = 3;      // select the pin for the Button
int greenledPin = 4;      // select the pin for the LED
int buzzerPin = 5;      // select the pin for the LED
int sensorValue = 0;  // variable to store the value coming from the sensor

unsigned long PyroRead = 0;
unsigned long IR_threshold = 198000;
// Note: SS-430 has two pulses of 200msec per detection.
// IR_threshold is in microsec (usec), therefore 198msec threshold

int Detected = LOW;
int IR_sensed = 0;

int pushupCount = 0;
char server[] = "192.168.1.12";    // name address for Google (using DNS)
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // declare the ledPin as an OUTPUT:
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);
  pinMode(greenledPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  pinMode (sensorPin, INPUT); // IR Sensor connected to A1
  pinMode (buttonPin, INPUT); // Button Pin

    // attempt to connect using WPA2 encryption:
  Serial.println("Attempting to connect to WPA network...");
  status = WiFi.begin(ssid, pass);

  // if you're not connected, stop here:
  if ( status != WL_CONNECTED) {
    Serial.println("Couldn't get a wifi connection");
    while(true);
  }
  // if you are connected, print out info about the connection:
  else {
    Serial.println("Connected to network");
    //connected to network, blink it 3 times
    digitalWrite(greenledPin, HIGH);
    delay(500); 
    digitalWrite(greenledPin, LOW);
    delay(500); 
    digitalWrite(greenledPin, HIGH);
    delay(500); 
    digitalWrite(greenledPin, LOW);
    delay(500); 
    digitalWrite(greenledPin, HIGH);
    delay(500); 
    digitalWrite(greenledPin, LOW);
  }
}

void loop() {
  while ((IR_sensed < 2)) { //Break after 2 good triggers
    PyroRead = pulseIn(sensorPin, HIGH); //Measure trigger point
    Serial.println(PyroRead);  // stop the autonomous robot
    if (PyroRead > IR_threshold) { //Make sure trigger is over 198msec)
      IR_sensed++; //Mark as a good trigger
    }

    
    buttonState = digitalRead(buttonPin);
  
    if (buttonState == HIGH) {
      // turn LED on:
      digitalWrite(greenledPin, HIGH);
      String tmp;
      tmp = String(pushupCount);
      
      Serial.println("\nStarting connection to server...");
      // if you get a connection, report back via serial:
      if (client.connect(server, 3000)) {
        Serial.println("connected to server");
        // Make a HTTP request:
        client.println("GET /?pushup=" + tmp + " HTTP/1.1");
        client.println("Host: 192.168.1.12");
        client.println("Connection: close");
        client.println();
      }
      digitalWrite(greenledPin, LOW);
      pushupCount = 0;
    }
  }

  if (Detected == HIGH) { // Turn LED OFF if it was previous ON
    Detected = LOW;
    digitalWrite(ledPin, LOW);
    digitalWrite(buzzerPin, HIGH);
    delay(200);
    digitalWrite(buzzerPin, LOW);
    pushupCount += 1;
  }
  else {
    Detected = HIGH; // Turn LED ON if it was previous OFF
    digitalWrite(ledPin, HIGH);
  }

  PyroRead = 0; // Reset readings
  IR_sensed = 0;

  delay(200); // Accept triggers after a 200ms, the default takes about 200ms anyway
}
firebase relay codeJavaScript
relay firebase through local server
const http = require('http');
const url = require('url');
const querystring = require('querystring');
// Import Admin SDK
var admin = require("firebase-admin");
var serviceAccount = require("path/to/serviceAccountKey.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://databaseName.firebaseio.com"
});
// Get a database reference to our blog
var db = admin.database();
var ref = db.ref("pushup");
ref.once("value", function(snapshot) {
console.log(snapshot.val());
});
const hostname = '192.168.1.12';
const port = 3000;
const server = http.createServer((req, res) => {
const queryObject = url.parse(req.url,true).query;
var dt = new Date();
var utcDate = dt.toUTCString();
if(queryObject != null && queryObject.pushup != null)
{
console.log(queryObject.pushup);
var newPostRef = ref.push().set({
count: queryObject.pushup,
time: utcDate
});
var postId = newPostRef.key;
console.log(postId);
console.log(utcDate);
}
//console.log(querystring.parse(queryObject));
res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello World');
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
Kemet Test CodeArduino
Testing using the hand written by Kemet, written on https://ec.kemet.com/blog/pyro-switch-hidden-ir-detection/
int Pyro = A1;
unsigned long PyroRead = 0;

unsigned long IR_threshold = 198000;

// Note: SS-430 has two pulses of 200msec per detection.

// IR_threshold is in microsec (usec), therefore 198msec threshold

int LED = 7;

int Detected = LOW;

int IR_sensed = 0;

void setup() {

pinMode (7, OUTPUT); //LED Connected to Pin 7

pinMode (A1,INPUT); // IR Sensor connected to A1

}

void loop() {

while ((IR_sensed < 2)){ //Break after 2 good triggers PyroRead = pulseIn(A1, HIGH); //Measure trigger point if(PyroRead > IR_threshold){ //Make sure trigger is over 198msec)

IR_sensed++; //Mark as a good trigger

}

}

if (Detected == HIGH){ // Turn LED OFF if it was previous ON

Detected = LOW;

digitalWrite(7, LOW);

}

else {

Detected = HIGH; // Turn LED ON if it was previous OFF

digitalWrite(7, HIGH);

}

PyroRead = 0; // Reset readings

IR_sensed = 0;

delay(1000); // Accept triggers after a second

Custom parts and enclosures

Arduino with Breadboard case
Arduino with Breadboard case

Schematics

Pushup Counter Schema
Pushup Counter Schema
Screen shot 2020 02 23 at 5 18 28 pm ztp5x3jyhx
Prototype board
Prototype board
Img 20200227 224238 f1krnx2vam

Comments

Similar projects you might like

Bidirectional Digital Visitor or Person Counter

Project tutorial by Smit Babariya

  • 5,647 views
  • 2 comments
  • 12 respects

Car Counter using Arduino + Processing + PHP

Project tutorial by Team UNO

  • 12,659 views
  • 4 comments
  • 9 respects

Simple Lap Counter for Swimming Maniac (Waterproof)

Project tutorial by Oscar Seo

  • 3,126 views
  • 5 comments
  • 10 respects

Fidget Spinner RPM Counter

by Andriy Baranov

  • 57,689 views
  • 32 comments
  • 118 respects

Create a People Counter Controlled by an Android App

Project tutorial by Kutluhan Aktar

  • 7,729 views
  • 5 comments
  • 8 respects

A Posture Detector Sending Bluetooth Data to a Cordova App

Project tutorial by Gini76

  • 6,119 views
  • 2 comments
  • 22 respects
Add projectSign up / Login