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

Лазерный хронометр для слот-кар на Arduino Mega с GLCD-дисплеем — точное замерное оборудование

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

Приложения

О проекте

Автор купил пару KY-008 (лазер + фоторезистор/фототранзистор) и решил сделать точные хронометры для слот-кар (автомодели на шлейфе). Лазерный луч пересекает трассу; когда машинка прерывает луч, сенсор фиксирует момент. Arduino Mega измеряет время между прерываниями (круги) и выводит на GLCD: номер круга, текущее время круга, время последнего круга, лучшее время.

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

GLCD KS0108

Параллельный интерфейс (8 бит данных + управление) — требует много пинов, поэтому Arduino Mega. Распиновка и библиотека:

Автор сделал удобный разъем-переходник для GLCD (фото в проекте).

Лазер KY-008

3 пина: –, +, S (управление). Для постоянного свечения S и + замкнуты на 5V. Для управляемого — S на цифровой пин.

Фотосенсор

3 пина: GND, VCC (5V), SIGNAL → цифровой вход Arduino (D2 в коде).

Главная сложность

Точная оптическая выравнивание лазера и сенсора по разные стороны трассы. На фото видно крепление на профилях.

Программный код (полный скетч)


/* Time keeping digital gate
 * Code by: Tal Ofer
 * talofer99@hotmail.com
 */
#include "openGLCD.h"

// Переменные для кругов
unsigned long currentRunStartMillis;
unsigned long lastRunInMillis;
unsigned long bestRunInMillis;
int currentLap;
unsigned long savedMillis;

// Текстовые области на GLCD
gText t1; // номер круга (крупно)
gText t2; // LAST
gText t3; // BEST

int sec_val, milli_val;

// Лазерные ворота
const int gateSensorPin = 2;
int gateSensorState;
int lastGateSensorState = LOW;
unsigned long lastDebounceTime = 0;
const int debounceDelay = 50; // мс, антидребезг

void setup() {
  pinMode(gateSensorPin, INPUT);
  delay(50); // дать сенсору и лазеру включиться, чтобы не зафиксировать ложный круг

  GLCD.Init(NON_INVERTED);

  // Области вывода
  t1.DefineArea(textAreaTOP, lcdnums14x24); // крупные цифры сверху
  t2.DefineArea(0, GLCD.CenterY, 8, 2, fixednums7x15); // LAST
  t3.DefineArea(GLCD.CenterX, GLCD.CenterY, 8, 2, fixednums7x15); // BEST
  t3.SetFontColor(WHITE);
  t3.ClearArea();

  // Статические надписи
  GLCD.SelectFont(System5x7);
  GLCD.CursorTo(1, 4);  GLCD.print("LAST");
  GLCD.CursorTo(11, 4); GLCD.print("BEST");

  // Сброс параметров
  currentRunStartMillis = 0;
  lastRunInMillis = 0;
  bestRunInMillis = 0;
  currentLap = 0;
}

void loop() {
  int reading = digitalRead(gateSensorPin);

  // Антидребезг
  if (reading != lastGateSensorState) {
    lastDebounceTime = millis();
  }

  if ((millis() - lastDebounceTime) > debounceDelay) {
    if (reading != gateSensorState) {
      gateSensorState = reading;

      // Луч прерван (LOW) — проезд машинки
      if (gateSensorState == LOW) {
        savedMillis = millis(); // зафиксировали момент

        if (currentLap > 0) {
          lastRunInMillis = savedMillis - currentRunStartMillis;
          if (lastRunInMillis < bestRunInMillis || bestRunInMillis == 0) {
            bestRunInMillis = lastRunInMillis;
          }
        }

        currentRunStartMillis = savedMillis; // старт нового круга
        currentLap++;
      }
    }
  }
  lastGateSensorState = reading;

  // Обновление дисплея
  t1.CursorTo(0, 0);
  t1.Printf(F("%02d"), currentLap); // номер круга

  savedMillis = millis();
  if (currentLap > 0) {
    calcResultFromMillis(savedMillis - currentRunStartMillis, &sec_val, &milli_val);
  } else {
    calcResultFromMillis(0, &sec_val, &milli_val);
  }

  // CURRENT (текущий незавершенный круг)
  t1.CursorTo(3, 0);
  t1.Printf(F("%02d.%03d"), sec_val, milli_val);

  // LAST
  calcResultFromMillis(lastRunInMillis, &sec_val, &milli_val);
  t2.CursorTo(1, 1);
  t2.Printf(F("%02d.%03d"), sec_val, milli_val);

  // BEST
  calcResultFromMillis(bestRunInMillis, &sec_val, &milli_val);
  t3.CursorTo(1, 1);
  t3.Printf(F("%02d.%03d"), sec_val, milli_val);
}

// Перевод миллисекунд в секунды и миллисекунды для вывода
void calcResultFromMillis(unsigned long value, int *sec_val, int *milli_val) {
  *sec_val = int(value / 1000);
  *milli_val = value - *sec_val * 1000;
}

Особенности реализации

Применение

Идеально для домашних треков слот-кар, соревнований, тестирования шасси/моторов. Можно расширить: сохранение на SD, беспроводная передача результатов, поддержка нескольких полос.

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

  1. Экспертное руководство по лазерной маркировке алюминия: точность, долговечность и отраслевые применения
  2. Полное руководство по лазерной маркировке: типы, преимущества и применения
  3. Волоконно-лазерная маркировка: точность, скорость и универсальность для современных отраслей
  4. Лазерный указатель: дизайн, производство и обзор безопасности
  5. Американские горки: от саней на снегу к стальным гигантам
  6. Полупроводниковые лазеры: точное генерирование света для современных технологий
  7. Твердотельные лазеры: технологии, применения и будущие тренды
  8. Песочные часы: история, ремесло и современная привлекательность
  9. Установка дисплея Kuman 3.5″ TFT на RetroPie — Пошаговое руководство
  10. Rpibot: Дешёвая расширяемая мобильная платформа для изучения встроенных систем