Промышленное производство
Промышленный Интернет вещей | Промышленные материалы | Техническое обслуживание и ремонт оборудования | Промышленное программирование |
home  MfgRobots >> Промышленное производство >  >> Manufacturing Technology >> Производственный процесс

Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени

Компоненты и материалы

Необходимые инструменты и сервисы

О проекте

Я регулярно занимаюсь баскетболом и веду статистику тренировок (броски, попадания, промахи). Ручной подсчет утомителен. Умные мячи дороги, неточны и быстро изнашиваются.

В предыдущем проекте я использовал устройство Avnet SmartEdge для отслеживания тренировок: акселерометр определял броски, датчик приближенности — попадания. Теперь цель — создать готовое решение.

Версии

Версия 1.1.0: собрана из имеющихся компонентов, ПО написано для Arduino и Android. Работала хорошо.

Версия 2.0.0: заменены компоненты на более дешевые, улучшено ПО.

ИК-датчик E18-D80NK выбран за устойчивость к солнечному свету. Датчик вибрации SW-420 работает надежно.

Схемы для обеих версий в разделе «Схемы».

Шаг 1: Arduino

Аппаратная часть

Компоненты версии 2.0.0 перечислены выше.

Программная часть

Разработано в Arduino IDE. Алгоритм:

  1. После инициализации (переменные, светодиод, Bluetooth) постоянно опрашиваются датчики.
  2. Если датчик приближенности срабатывает — это попадание.
  3. Если срабатывает датчик вибрации — был бросок, ждем 2 секунды для решения.
  4. В это время, если сработает датчик приближенности — сразу фиксируем попадание.
  5. По истечении 2 секунд, если приближенность не зафиксирована — это промах.
  6. Arduino передает по Bluetooth в Android информацию о броске (попадание/промах).
  7. Цикл повторяется.

Изменения в версии 2.0.0: поддержка HC-05, добавлен DHT22, улучшена логика детекции и сигнализации через светодиод.

Коды для обеих версий в разделе «Код».

Шаг 2: Android-приложение

Разработано в MIT App Inventor. Алгоритм:

  1. После инициализации ждет нажатия «Старт».
  2. При старте постоянно мониторит Bluetooth-соединение.
  3. При получении данных обновляет табло и воспроизводит звук уведомления.
  4. Повторяется до нажатия «Пауза».
  5. Кнопки: выбор Bluetooth-устройства, сброс счетчиков, корректировка табло.

Изменения в версии 2.0.0: горизонтальная ориентация, добавлены освещенность, влажность, температура, тепловой индекс, улучшены кнопки корректировки, функция «экран всегда включен», звуки нажатий, уведомления каждые 50 бросков.

Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени
Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени

Шаг 3: Монтаж на баскетбольную корзину

Использовалась обычная корзина для тренировок.

Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени

Сделано отверстие под датчик приближенности под кольцом.

Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени

Небольшое отверстие для датчика вибрации. Из-за кривизны пластика сделанה опорка из МДФ.

Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени
Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени

Датчики закреплены болтами и гайками.

Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени

Подключены остальные компоненты.

Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени
Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени
Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени

Дымовое тестирование.

Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени

Финальная установка на корзину.

Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени

Шаг 4: Тестирование на тренировке

Время испытаний. Гранд-финал — шоутайм!

Шаг 5: Заключительные замечания

Удачи!

Исходный код

Arduino код (версия 1.1.0)

//----------------------------------------------------------------------------//
// Filename : Scoreboard.ino
// Description : Smart Basketball Scoreboard
// Version : 1.1.0
// Author : Marcelo Avila de Oliveira 
//----------------------------------------------------------------------------//
// DEFINITIONS
//----------------------------------------------------------------------------//
// #define DEBUG
// #define DEBUG_PROX
// #define DEBUG_VIBR
//----------------------------------------------------------------------------//
// CONSTANTS
//----------------------------------------------------------------------------//
// PINS
const int prox_pin = 2;
const int vibr_pin = 3;
const int led_r_pin = 4;
const int led_g_pin = 5;
const int led_b_pin = 6;
// TIME
const unsigned long wait_interval = 3000;
// MATH
const float percent_to_bright_factor = 100 * log10(2) / log10(255);
//----------------------------------------------------------------------------//
// VARIABLES
//----------------------------------------------------------------------------//
// TIME
unsigned long wait_time;
// STATUS
boolean prox = false;
boolean vibr = false;
boolean wait = false;
//----------------------------------------------------------------------------//
// FUNCTIONS (SETTINGS)
//----------------------------------------------------------------------------//
void setup() {
  pinMode(prox_pin, INPUT);
  pinMode(vibr_pin, INPUT);
  pinMode(led_r_pin, OUTPUT);
  pinMode(led_g_pin, OUTPUT);
  pinMode(led_b_pin, OUTPUT);
  set_led(5, 100);
  Serial.begin(9600);
  setup_bluetooth();
  set_led(4, 100);
#ifdef DEBUG
  Serial.println("Board is alive");
  Serial.println();
#endif
}
void setup_bluetooth() {
#ifdef DEBUG
  Serial.println("Setting Bluetooth");
  Serial.println();
#endif
  Serial1.begin(38400);
  Serial1.print("\r\n+STWMOD=0\r\n");
  Serial1.print("\r\n+STNA=Arduino\r\n");
  Serial1.print("\r\n+STOAUT=1\r\n");
  Serial1.print("\r\n+STAUTO=0\r\n");
  delay(2000);
  Serial1.print("\r\n+INQ=1\r\n");
  delay(2000);
  while (Serial1.available()) {
    delay(50);
    Serial1.read();
  }
}
//----------------------------------------------------------------------------//
// FUNCTIONS (LIGHT)
//----------------------------------------------------------------------------//
int percent_to_bright(int percent) {
  return 256 - pow(2, percent / percent_to_bright_factor);
}
void set_led(int color, int bright) {
#ifdef DEBUG
  Serial.println("Setting LED");
  Serial.println();
#endif
  if (color < 0 || color > 6 || bright < 0 || bright > 100) return;
  int led_r_bright = 255, led_g_bright = 255, led_b_bright = 255;
  int bright_aux = percent_to_bright(bright);
  switch (color) {
    case 0: led_g_bright = bright_aux; break; // GREEN
    case 1: led_r_bright = bright_aux; led_g_bright = bright_aux; break; // YELLOW
    case 2: led_r_bright = bright_aux; break; // RED
    case 3: led_g_bright = bright_aux; led_b_bright = bright_aux; break; // CYAN
    case 4: led_b_bright = bright_aux; break; // BLUE
    case 5: led_r_bright = bright_aux; led_b_bright = bright_aux; break; // MAGENTA
    case 6: led_r_bright = bright_aux; led_g_bright = bright_aux; led_b_bright = bright_aux; break; // WHITE
  }
  analogWrite(led_r_pin, led_r_bright);
  analogWrite(led_g_pin, led_g_bright);
  analogWrite(led_b_pin, led_b_bright);
}
//----------------------------------------------------------------------------//
// FUNCTIONS (CHECK)
//----------------------------------------------------------------------------//
void check_prox() {
  if (!prox) {
    if (digitalRead(prox_pin) == LOW) {
#ifdef DEBUG_PROX
      Serial.println("Proximity detected");
      Serial.println();
#endif
      prox = true;
      if (!vibr) {
        wait = true;
        wait_time = millis() + wait_interval;
      }
      set_shot(1);
    }
  }
}
void check_vibr() {
  if (!prox && !vibr) {
    if (digitalRead(vibr_pin) == HIGH) {
#ifdef DEBUG_VIBR
      Serial.println("Vibration detected");
      Serial.println();
#endif
      vibr = true;
      wait = true;
      wait_time = millis() + wait_interval;
      set_led(1, 100);
    }
  }
}
void check_wait() {
  if (wait && millis() > wait_time) {
    if (!prox) set_shot(0);
    reset();
  }
}
//----------------------------------------------------------------------------//
// FUNCTIONS (MIS)
//----------------------------------------------------------------------------//
void set_shot(int mode) {
  if (mode == 0) set_led(2, 100);
  else set_led(0, 100);
  Serial1.print(mode);
  delay(1000);
}
void reset() {
  vibr = false; prox = false; wait = false;
  set_led(4, 100);
}
//----------------------------------------------------------------------------//
// MAIN
//----------------------------------------------------------------------------//
void loop() {
  check_prox();
  check_vibr();
  check_wait();
}

Android код (версия 1.1.0)

MIT App Inventor (https://ai2.appinventor.mit.edu/) — файл доступен для загрузки.

Arduino код (версия 2.0.0)

//----------------------------------------------------------------------------//
// Filename : Scoreboard.ino
// Description : Smart Basketball Scoreboard
// Version : 2.0.0
// Author : Marcelo Avila de Oliveira 
//----------------------------------------------------------------------------//
// LIBRARIES
//----------------------------------------------------------------------------//
#include "DHT.h"
#include "SoftwareSerial.h"
//----------------------------------------------------------------------------//
// DEFINITIONS
//----------------------------------------------------------------------------//
#define DHTPIN 7
#define DHTTYPE DHT22
DHT dht(DHTPIN, DHTTYPE);
SoftwareSerial Bluetooth(10, 11); // RX, TX
// PINS
const int prox_pin = 2;
const int vibr_pin = 3;
const int led_r_pin = 4;
const int led_g_pin = 5;
const int led_b_pin = 6;
// TIME
const unsigned long wait_interval = 2000;
const unsigned long dht_interval = 10000;
// MATH
const float percent_to_bright_factor = 100 * log10(2) / log10(255);
//----------------------------------------------------------------------------//
// VARIABLES
//----------------------------------------------------------------------------//
unsigned long wait_time, dht_time;
float humi, temp, heat;
boolean prox = false, vibr = false, wait = false;
//----------------------------------------------------------------------------//
// FUNCTIONS (SETTINGS)
//----------------------------------------------------------------------------//
void setup() {
  pinMode(prox_pin, INPUT);
  pinMode(vibr_pin, INPUT);
  pinMode(led_r_pin, OUTPUT);
  pinMode(led_g_pin, OUTPUT);
  pinMode(led_b_pin, OUTPUT);
  set_led(5, 100); // MAGENTA
  Serial.begin(9600);
  setup_bluetooth();
  dht.begin();
  set_led(4, 100); // BLUE
#ifdef DEBUG
  Serial.println("Board is alive");
  Serial.println();
#endif
}
void setup_bluetooth() {
#ifdef DEBUG_BLUE
  Serial.println("Setting Bluetooth");
  Serial.println();
#endif
  Bluetooth.begin(9600);
  while (Bluetooth.available()) {
    delay(50);
    Bluetooth.read();
  }
}
//----------------------------------------------------------------------------//
// FUNCTIONS (LIGHT)
//----------------------------------------------------------------------------//
int percent_to_bright(int percent) {
  return 256 - pow(2, percent / percent_to_bright_factor);
}
void set_led(int color, int bright) {
#ifdef DEBUG
  Serial.println("Setting LED");
  Serial.println();
#endif
  if (color < 0 || color > 6 || bright < 0 || bright > 100) return;
  int led_r_bright = 255, led_g_bright = 255, led_b_bright = 255;
  int bright_aux = percent_to_bright(bright);
  switch (color) {
    case 0: led_g_bright = bright_aux; break;
    case 1: led_r_bright = bright_aux; led_g_bright = bright_aux; break;
    case 2: led_r_bright = bright_aux; break;
    case 3: led_g_bright = bright_aux; led_b_bright = bright_aux; break;
    case 4: led_b_bright = bright_aux; break;
    case 5: led_r_bright = bright_aux; led_b_bright = bright_aux; break;
    case 6: led_r_bright = bright_aux; led_g_bright = bright_aux; led_b_bright = bright_aux; break;
  }
  analogWrite(led_r_pin, led_r_bright);
  analogWrite(led_g_pin, led_g_bright);
  analogWrite(led_b_pin, led_b_bright);
}
//----------------------------------------------------------------------------//
// FUNCTIONS (CHECK)
//----------------------------------------------------------------------------//
void check_prox() {
  if (!prox) {
    if (digitalRead(prox_pin) == LOW) {
#ifdef DEBUG_PROX
      Serial.println("Proximity detected");
      Serial.println();
#endif
      set_led(0, 100);
      send_data(2);
      prox = true;
      if (!vibr) {
        wait = true;
        wait_time = millis() + wait_interval;
      }
    }
  }
}
void check_vibr() {
  if (!prox && !vibr) {
    if (digitalRead(vibr_pin) == HIGH) {
#ifdef DEBUG_VIBR
      Serial.println("Vibration detected");
      Serial.println();
#endif
      set_led(1, 100);
      vibr = true;
      wait = true;
      wait_time = millis() + wait_interval;
    }
  }
}
void check_wait() {
  if (wait && millis() > wait_time) {
    if (!prox) {
      set_led(2, 100);
      send_data(1);
    }
    reset();
  }
}
void check_dht() {
  if (!prox && !vibr) {
    if (millis() > dht_time) {
      humi = dht.readHumidity();
      temp = dht.readTemperature();
      heat = dht.computeHeatIndex(temp, humi, false);
#ifdef DEBUG_DHT
      Serial.print("Humidity: "); Serial.print(humi); Serial.println("%");
      Serial.print("Temperature: "); Serial.print(temp); Serial.println("C");
      Serial.print("Heat Index: "); Serial.print(heat); Serial.println("C");
      Serial.println();
#endif
      send_data(0);
      dht_time = millis() + dht_interval;
    }
  }
}
//----------------------------------------------------------------------------//
// FUNCTIONS (MIS)
//----------------------------------------------------------------------------//
void send_data(int shot) {
  Bluetooth.print(humi);
  Bluetooth.print(temp);
  Bluetooth.print(heat);
  Bluetooth.print(shot);
#ifdef DEBUG_BLUE
  Serial.println("Bluetooth sent");
  Serial.println();
#endif
}
void reset() {
  vibr = false; prox = false; wait = false;
  delay(1000);
  set_led(4, 100);
}
//----------------------------------------------------------------------------//
// MAIN
//----------------------------------------------------------------------------//
void loop() {
  check_prox();
  check_vibr();
  check_wait();
  check_dht();
}

Android код (версия 2.0.0)

MIT App Inventor — файл доступен для загрузки.

Схемы

Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени
Продвинутый умный счетчик для баскетбола с Bluetooth, датчиками и обновлением в реальном времени

Производственный процесс

  1. Баскетбол: от изобретения Нейсмита 1891 года к современным производственным технологиям
  2. Создание открытых систем умного земледелия: укрепление фермеров доступным, интероперабельным IoT
  3. ECM3532: первая интегрированная ультра‑низкоэнергозатратная ИИ‑сенсорная плата Eta Compute ускоряет Edge‑разработку
  4. Создайте домашний монитор температуры на Raspberry Pi с MCP9808, InfluxDB и Grafana
  5. Умное мусорное ведро: клеточное IoT-решение для автоматизированного управления отходами
  6. Умный бармен: создайте свою Raspberry Pi-станцию для коктейлей
  7. Датчик эмоций и ЭЭГ: низкобюджетное железо для детекции эмоций в реальном времени
  8. Революционный ультрачувствительный стойкий датчик деформации для умных текстилей
  9. Революционный ультратонкий сенсор расширяет функциональность умных контактных линз
  10. Революция в производстве датчиков: Sensata использует умную мехатронику