Project showcase
Bosco Test

Bosco Test © MIT

Bosco tests are designed to assess the morphofunctional characteristics of one's legs muscles as well as their neuromuscular skills.

  • 3,191 views
  • 5 comments
  • 4 respects

Components and supplies

Ardgen mega
Arduino Mega 2560 & Genuino Mega 2560
Actually, pretty much any Arduino board would do just fine.
×1
12002 04
Breadboard (generic)
×2
11026 02
Jumper wires (generic)
Please consider the quantity indicated above a generic rule of thumb.
×30
ICStation KY-008 Laser Transmitter Module
×1
Adafruit industries ada161 image 75px
Photo resistor
×1
Mfr 25frf52 10k sml
Resistor 10k ohm
×1
61pby065esl  sx679  tnr8syww5d
HC-05 Bluetooth Module
×1
1434509556 android phone color
Android device
×1

Apps and online services

About this project

Why the Bosco test?

Even though several similar products are already available on the market, their price range is often ridiculously high for a sports club trying to run a simple physical fitness test. As high school students practicing sports after school, we decided to do something about it.

After a little bit of researching on the net, we realized that most of the sensors and data usually featured by such systems aren't even taken into consideration by your everyday athlete. Our new goal: to start cutting down on every unneeded asset.

How does it work?

A laser barrier detects whether the athlete's feet are currently touching the ground or not. For every jump, the delay between two "touching-the-ground" instants is memorized as the ToF (time of flight) for that particular jump. Finally, this information is sent via Bluetooth to a connected Android device, which deducts the JH (jump height) using a simple formula (g being the gravitational acceleration):

JH = (ToF ^ 2 * g) / 8

Assembling your circuit

For those of you who just don't feel like downloading any .fzz files, here's how to connect the various components used by the project:

Uploading the sketch

Follow these simple steps to upload your sketch:

  • create a folder named "test_di_bosco" in your sketchbook folder
  • download the six files embed below inside your new "test_di_bosco" folder
  • open "test_di_bosco.ino" using Arduino IDE: a single window with all of the ".ino" files in it should open
  • that's it: you are now ready to upload the entire sketch clicking on "upload" once

A sample Android application

We chose to use MIT App Inventor 2 (see Apps and online services) to develop our sample application (available for free).

Running the test

Running the test is pretty simple: you just need to jump

Work in progress (maybe)

  • ground contact time
  • power developed during the jump
  • jump frequency
  • RSI (Reactive Strength Index)

Code

test_di_bosco.inoArduino
A source file containing our sketch's opening comment.
/*
	Program: test di bosco
	Date: 16/09/2019
	Author: Volpe Stefano | V Bsa | L.S. "A. Oriani" Ravenna
	
	Currently, everything is coded "in Italian" (WIP?)
*/
0_apparecchiatura_h.inoArduino
This file defines the interface used by the laser barrier module.
// 0_apparecchiatura_h: intestazione del modulo per la gestione della barriera laser

#ifndef APPARECCHIATURA_H
#define APPARECCHIATURA_H

namespace Apparecchiatura {

	// una barriera dovrebbe avere l'esclusiva sull'accesso ai propri pin
	class Barriera {
	public:
		// inizializzazione obbligatoria
		Barriera(int pin_laser_a, int pin_laser_b, int pin_foto_a, int pin_foto_b); // [a, b[
		Barriera() = delete;
		// spostamento consentito
		Barriera(Barriera&&) = default;
		Barriera& operator=(Barriera&&) = default;
		// copia vietata: un pin dovrebbe appartenere a una sola barriera
		Barriera(const Barriera&) = default;
		Barriera& operator=(const Barriera&) = delete;
		// la barriera viene spenta alla distruzione
		~Barriera();

		// costanti e getter
		static constexpr int tolleranza { 100 }; // fra lettura luce naturale e lettura a barriera accesa con ostacolo
		int pin_laser_a() const;
		int pin_laser_b() const;
		int pin_foto_a() const;
		int pin_foto_b() const;
		bool stato() const; // true = accesa, false = spenta

		// false: la barriera era gi nello stato desiderato
		bool accendi();
		bool spegni();
		bool ostacolo() const; // false se non ci sono ostacoli o a barriera spenta

	private:
		int pin_l_a, pin_l_b, pin_f_a, pin_f_b; // primi e ultimi pin per laser e fotoresistenze
		bool st; // true = accesa, false = spenta
		int luce_naturale { 0 };
		
		void imposta_laser(int valore); // HIGH o LOW
		int leggi_fotoresistenze() const; // media delle analogRead()
	};
	
}

#endif
1_connessione_h.inoArduino
This file defines the interface used by the connection module.
// 1_connessione_h: intestazione del modulo di connessione bluetooth al terminale

#ifndef CONNESSIONE_H
#define CONNESSIONE_H

#include <SoftwareSerial.h>

namespace Connessione {

	class Terminale {
	public:
		// inizializzazione obbligatoria
		Terminale(Apparecchiatura::Barriera& barriera, int pin_tra, int pin_ric,
				  long baud = baud_def, HardwareSerial& debug = Serial, long baud_debug = baud_debug_def);
		Terminale(Apparecchiatura::Barriera& barriera, int pin_tra, int pin_ric,
				  HardwareSerial& debug, long baud_debug = baud_debug_def);
		Terminale() = delete;
		// spostamento consentito
		Terminale(Terminale&&) = default;
		Terminale& operator=(Terminale&&) = default;
		// copia vietata: un pin dovrebbe appartenere a un solo terminale
		Terminale(const Terminale&) = default;
		Terminale& operator=(const Terminale&) = delete;
		// distruttore predefinito
		~Terminale() = default;

		// costanti
		static constexpr long baud_def { 9600 }, baud_debug_def { 9600 };
		static constexpr char comando_stato { '0' }, // chiede se la barriera sia accesa
							  comando_spegni { '1' }, // spegne la barriera
							  comando_accendi { '2' }, // accende la barriera
							  comando_chiedi { '3' }, // chiede una prova di N salti
							  comando_abortisci { '4' }; // annulla la richiesta
		static constexpr int salti_richiesti_default { 1 };
		static constexpr size_t salti_richiesti_string_dim { 10 };

		// getter
		Apparecchiatura::Barriera& barriera() const;
		int pin_tra() const;
		int pin_ric() const;
		long baud() const;
		HardwareSerial& debug() const;
		long baud_debug() const;

		void setup();
		void loop();

	private:
		Apparecchiatura::Barriera& bar; // la barriera controllata dal terminale
		int pin_tx, pin_rx; // pin del flusso di comunicazione col terminale
		SoftwareSerial m; // modulo per la comunicazione col terminale
		long b; // velocit di trasmissione (in baud) col terminale
		HardwareSerial& d; // pin del flusso di comunicazione per debug
		long b_d; // velocit di trasmissione (in baud) per debug 

		void azione_stato();
		void azione_spegni();
		void azione_accendi();
		void azione_chiedi();
		bool azione_aborto();
		void azione_sconosciuta(char input);

		int calcola_salti_richiesti();
	};
	
}

#endif
2_main_cpp.inoArduino
// 2_main_cpp: il punto di ingresso del programma (contiene setup() e void())

namespace {
	constexpr int pin_laser_inizio { 2 },
				  pin_laser_fine { 3 },
				  pin_fotoresistenza_inizio { 0 },
				  pin_fotoresistenza_fine { 1 },
				  pin_bluetooth_trasmettitore { 10 },
				  pin_bluetooth_ricevitore { 11 };
	
	Apparecchiatura::Barriera pedana(pin_laser_inizio, pin_laser_fine, pin_fotoresistenza_inizio, pin_fotoresistenza_fine);
	Connessione::Terminale operatore(pedana, pin_bluetooth_trasmettitore, pin_bluetooth_ricevitore); 
}

void setup() {
	operatore.setup();
}

void loop() {
  operatore.loop();
}
3_apparecchiatura_cpp.inoArduino
This file implements the management of the laser barrier module.
// 3_apparecchiatura_cpp: implementazione del modulo per la gestione della barriera laser

namespace Apparecchiatura {
	
	Barriera::Barriera(int pin_laser_a, int pin_laser_b, int pin_foto_a, int pin_foto_b)
		:pin_l_a{pin_laser_a}, pin_f_a{pin_foto_a} {
		// eventuale correzione dell'input
		pin_l_b = pin_laser_b <= pin_laser_a ? pin_l_a + 1 : pin_laser_b;
		pin_f_b = pin_foto_b <= pin_foto_a ? pin_f_a + 1: pin_foto_b;
		// configurazione pin
		for (int i { pin_l_a }; i < pin_l_b; ++i)
			pinMode(i, OUTPUT);
		// spengimento eventuali laser rimasti accesi da precedente utilizzo
		imposta_laser(LOW);
	}

	Barriera::~Barriera() {
		spegni();
	}

	int Barriera::pin_laser_a() const {
		return pin_l_a;
	}

	int Barriera::pin_laser_b() const {
		return pin_l_b;
	}

	int Barriera::pin_foto_a() const {
		return pin_f_a;
	}

	int Barriera::pin_foto_b() const {
		return pin_f_b;
	}
	
	bool Barriera::stato() const {
		return st;
	}

	bool Barriera::accendi() {
		if (st) // barriera gi accesa
			return false;
		luce_naturale = leggi_fotoresistenze();
		imposta_laser(HIGH);
		st = true;
		return true;
	}

	bool Barriera::spegni() {
		if (!(st && luce_naturale)) // barriera gi spenta, barriera accesa non correttamente
			return false;
		imposta_laser(LOW);
		st = false;
		return true;
	}

	bool Barriera::ostacolo() const {
		if (!st) // barriera spenta
			return false;
		for (int i { pin_f_a }; i < pin_f_b; ++i)
			if (analogRead(i) <= luce_naturale + tolleranza)
				return true;
		return false;
	}
	
	void Barriera::imposta_laser(int valore) {
		for (int i { pin_l_a }; i < pin_l_b; ++i)
			digitalWrite(i, valore);
	}

	int Barriera::leggi_fotoresistenze() const {
		int somma { 0 };
		for (int i { pin_f_a }; i < pin_f_b; ++i)
			somma += analogRead(i);
		return somma / (pin_f_b - pin_f_a);
	}
}
4_connessione_cpp.inoArduino
This file implements the bluetooth connection module into the terminal.
// 4_connessione_cpp: implementazione del modulo di connessione bluetooth al terminale

namespace Connessione {
	
	Terminale::Terminale(Apparecchiatura::Barriera& barriera, int pin_tra, int pin_ric,
						 long baud, HardwareSerial& debug, long baud_debug)
		:bar{barriera},
		pin_tx{pin_tra},
		pin_rx{pin_ric},
		m{SoftwareSerial(pin_tx, pin_rx)},
		b{baud}, d{debug},
		b_d{baud_debug} {
		// preparazione modulo di connessione
		m.begin(b);
	}

	Terminale::Terminale(Apparecchiatura::Barriera& barriera, int pin_tra, int pin_ric,
						 HardwareSerial& debug, long baud_debug)
		:Terminale{barriera, pin_tra, pin_ric, baud_def, debug, baud_debug} { }

	Apparecchiatura::Barriera& Terminale::barriera() const {
		return bar;
	}

	int Terminale::pin_tra() const {
		return pin_tx;
	}

	int Terminale::pin_ric() const {
		return pin_rx;
	}

	long Terminale::baud() const {
		return b;
	}

	HardwareSerial& Terminale::debug() const {
		return d;
	}

	long Terminale::baud_debug() const {
		return b_d;
	}

	void Terminale::setup() {
		d.begin(b_d);
		d.println("Modulo di connessione al terminale in funzione.");
	}
	
	void Terminale::loop() {
		if (m.available()) {
			char input { m.read() };
			switch (input) {
			case comando_stato:
				azione_stato();
				break;
			case comando_spegni:
				azione_spegni();
				break;
			case comando_accendi:
				azione_accendi();
				break;
			case comando_chiedi:
				azione_chiedi();
				break;
			case comando_abortisci:
				d.println("Aborto fallito (nessuna richiesta da abortire.");
				break;
			default:
				azione_sconosciuta(input);
			}
		}
	}
	
	void Terminale::azione_stato() {
		m.println(bar.stato());
		d.println("Stato della barriera comunicato.");
	}
	
	void Terminale::azione_spegni() {
		if (bar.spegni())
			d.println("Barriera spenta.");
		else
			d.println("Barriera spenta da prima.");
	}
	
	void Terminale::azione_accendi() {
		if (bar.accendi())
			d.println("Barriera accesa.");
		else
			d.println("Barriera accesa da prima.");		
	}

	void Terminale::azione_chiedi() {
		if (!bar.ostacolo()) {
			m.println(false);
			m.readString(); // ignoro il resto dell'input
			d.println("Atleta non rilevato sulla pedana.");
			return;
		}
		const int salti_richiesti = calcola_salti_richiesti();
		d.print("Salti richiesti: ");
		d.print(salti_richiesti);
		d.println(".");
		for (int i { 0 }; i < salti_richiesti; ++i) {
			while (bar.ostacolo()) // prima dello stacco
				if (azione_aborto())
					return;
			const unsigned long millis_stacco { millis() };
			while (!bar.ostacolo()) // fase di volo
				if (azione_aborto())
					return;
			m.println(millis() - millis_stacco);
			d.print("Salto #");
			d.print(i + 1);
			d.println(" acquisito.");
		}
	}

	bool Terminale::azione_aborto() {
		if (m.available() && m.read() == comando_abortisci) {
			d.println("Prova abortita.");
			return true;
		}
		return false;
	}
	
	void Terminale::azione_sconosciuta(char input) {
		d.print("Comando '");
		d.print(input);
		d.println("' non riconosciuto.");
	}

	int Terminale::calcola_salti_richiesti() {
		if (!m.available())
			return salti_richiesti_default;
		char salti_richiesti[salti_richiesti_string_dim];
		m.readString().toCharArray(salti_richiesti, salti_richiesti_string_dim);
		return atoi(salti_richiesti);
	}
	
}

Schematics

Fritzing project
This Fritzing file includes both the project's breaboard view and schematic view. It does not include any code.
bosco_test_wOr8uHrcy7.fzz

Comments

Similar projects you might like

Health Kit: Humidity and Temperature Control

Project tutorial by Diana Khalipina

  • 8,426 views
  • 2 comments
  • 49 respects

Test DHT22 Sensors with Arduino and MATLAB

Project tutorial by dancili

  • 6,513 views
  • 4 comments
  • 23 respects

Sleeping Phases Determination

Project tutorial by Diana Khalipina

  • 4,561 views
  • 3 comments
  • 25 respects

Morse Code Receiver

Project showcase by Alireza Karkon

  • 5,212 views
  • 5 comments
  • 25 respects

'Roger Bot' the Pet Rover

Project showcase by hannu_hell

  • 2,882 views
  • 0 comments
  • 14 respects

Arduino 101 BLE App

Project in progress by Alexis Santiago Allende

  • 15,773 views
  • 29 comments
  • 62 respects
Add projectSign up / Login