цифровая электроника
вычислительная техника
встраиваемые системы

 
» » Лазерный тахометр на основе Arduino



Лазерный тахометр на основе Arduino

Автор: Mike(admin) от 5-03-2022, 05:55

В некоторых случаях бывает необходимо измерить скорость вращающегося объекта дистанционно. Для такой задачи отлично подойдет лазерный тахометр.


Лазерный тахометр на основе Arduino

В рамках данного проекта мы создадим небольшой ручной тахометр, который использует лазер, чтобы измерить, как быстро объект вращается в оборотах в минуту (об/мин).


В качестве основы для программы Arduino будем использовать микроконтроллер ATtiny1614. Этот микроконтроллер имеет очень низкое энергопотребление в спящем режиме. Вся схема питается от литий-ионного аккумулятора 3,7 В и включает модуль зарядного устройства TP4056 для зарядки батареи. Принципиальная схема такого тахометра с лазером представлена далее:


Лазерный тахометр на основе Arduino

Компоненты можно разместить на подобной плате:


Лазерный тахометр на основе Arduino

В качестве датчика будем использовать лазер от модуля KY-008.


Лазерный тахометр на основе Arduino

На лазере следует удалить резистор 33 Ом и запаять перемычку на его месте.


Лазерный тахометр на основе Arduino

Собрав все на плате и разместив в соответствующем корпусе, не забудьте подключить аккумулятор.


Лазерный тахометр на основе Arduino

В отличие от более ранних серий ATtiny, таких как ATtiny85, ATtiny1614 использует вывод RESET для программирования процессора. Для программирования нужен программатор UPDI. Можно сделать такой, используя Arduino Nano. Все компоненты толерантны к напряжению 5 В, поэтому при отсутствии батареи вы можете запитать их от программатора UPDI. Если батарея установлена, просто подключите провода GND и UPDI и оставьте провод VCC отключенным.


Лазерный тахометр на основе Arduino

После настройки соединений в среде Arduino IDE выберите плату в меню «Инструменты».


Лазерный тахометр на основе Arduino

Выберите плату ATtiny1614 в вашей среде IDE. Выберите COM-порт, к которому подключен Arduino Nano. Программатор должен быть установлен на jtag2updi (megaTinyCore). Откройте скетч и загрузите его в ATtiny1614.



#include <OneWire.h>
#include <U8g2lib.h>
#include <avr/sleep.h>

#define MEASURE_BTN 0   //PA4 D0
#define ON_BTN 1        //PA5 D1
#define SENSOR 9        //PA2 D9
#define LASER 10        //PA3 D10

U8G2_SSD1306_128X32_UNIVISION_F_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE);

volatile uint32_t pulseStartTime = 0; 
volatile uint32_t pulseDuration = 0;

char textBuffer[20];   

#define AVG_SIZE 128
#define AVG_MASK 0x7F
uint32_t runningTotal = 0;
uint16_t runningCount = 0;
uint8_t runningHead = 0; 
uint8_t runningTail = 0;
uint32_t runningValues[AVG_SIZE];

#define PULSE_TIMEOUT 5000
#define UPDATE_TIME 300
uint32_t updateTimeout;

//-----------------------------------------------------------------------------
void setup() 
{
  //Serial.begin(9600);

  pinMode(LASER, OUTPUT);
  digitalWrite(LASER, LOW);
  pinMode(SENSOR, INPUT);
  attachInterrupt(digitalPinToInterrupt(SENSOR), SensorInterrupt, RISING);
  
  pinMode(ON_BTN, INPUT_PULLUP);
  pinMode(MEASURE_BTN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(ON_BTN),SwitchInterrupt,CHANGE);

  u8g2.begin();
  u8g2.clearBuffer(); 
  u8g2.sendBuffer(); 
  
  systemSleep();  
}

//-----------------------------------------------------------------------------
void SwitchInterrupt()
{
}

//-----------------------------------------------------------------------------
void SensorInterrupt()
{
  
  pulseDuration = micros() - pulseStartTime;
  pulseStartTime = micros();
}

//--------------------------------------------------------------------
void showSplashScreen()
{
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_helvB12_tr);
  u8g2.drawStr(20,14,"ATtiny1614");
  u8g2.drawStr(15,29,"Laser Tacho");
  u8g2.sendBuffer();  
  delay(3000);

  strcpy(textBuffer, "Ready");
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_logisoso20_tr);
  int width = u8g2.getStrWidth(textBuffer);
  u8g2.drawStr((128-width)/2,26,textBuffer);
  u8g2.sendBuffer();
}

//-----------------------------------------------------------------------------
void loop() 
{
  uint32_t started;
  uint32_t duration;
  uint32_t rpm;
  
  while (digitalRead(ON_BTN) == HIGH)
  {
    if (digitalRead(MEASURE_BTN) == LOW)
    {
      digitalWrite(LASER, HIGH);
      delay(10);
      
      noInterrupts();
      pulseDuration = 0;
      pulseStartTime = micros();
      interrupts();

      runningTotal = 0;
      runningCount = 0;
      runningHead = 0; 
      runningTail = 0;
      
      while (digitalRead(MEASURE_BTN) == LOW)
      {
        noInterrupts();
        started = pulseStartTime;
        duration = pulseDuration;
        interrupts();

        if (duration == 0 && (millis() - started) > PULSE_TIMEOUT)
        {
          rpm = 0;
        }
        else if (duration > 0)
        {
          rpm = (60000000 / duration);
          if (runningCount == AVG_SIZE)
          {
            runningTotal = runningTotal - runningValues[runningTail];
            runningTail = (runningTail + 1) & AVG_MASK;
            runningCount--;
          }
          runningValues[runningHead] = rpm;
          runningHead = (runningHead + 1) & AVG_MASK;
          runningTotal = runningTotal + rpm;
          runningCount++;
          rpm = runningTotal / runningCount;
        }

        if (millis() > updateTimeout)
        {
          displayNumber(rpm);
          updateTimeout = millis() + UPDATE_TIME;
        }
      }
      
      digitalWrite(LASER, LOW);
    }
    delay(100);
  }

  while (digitalRead(ON_BTN) == LOW)
  {
    delay(100);
  }
  systemSleep();
}

//--------------------------------------------------------------------
void displayNumber(uint32_t  number)
{
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_logisoso20_tr);
  sprintf(textBuffer,"%5lu",number);
  int twidth = u8g2.getStrWidth(textBuffer);
  u8g2.setFont(u8g2_font_helvB12_tr);
  strcpy(textBuffer," rpm ");
  int rwidth = u8g2.getStrWidth(textBuffer);
  int tx = max(128 - (twidth + rwidth), 0);
  u8g2.drawStr(tx + twidth,30,textBuffer);
  sprintf(textBuffer,"%5lu",number);
  u8g2.setFont(u8g2_font_logisoso20_tr);
  u8g2.drawStr(tx,30,textBuffer);
  u8g2.sendBuffer();
}

//-----------------------------------------------------------------------------
void systemSleep() 
{
  interrupts();
  u8g2.clearBuffer();
  u8g2.sendBuffer();
  u8g2.setPowerSave(true);
  //cbi(ADCSRA,ADEN);
  set_sleep_mode(SLEEP_MODE_PWR_DOWN);
  sleep_enable();
  sleep_mode();
  sleep_disable();
  //sbi(ADCSRA,ADEN);
  u8g2.setPowerSave(false);
  while (digitalRead(ON_BTN) == LOW)
  {
    delay(100);
  }
  showSplashScreen();
  updateTimeout = 0;
}

Важно, чтобы поверхность, на которую вы направляете лазер, отражала свет обратно на датчик.


Лазерный тахометр на основе Arduino

При измерении скорости дрели была приклеена к патрону белая отражающая бумага, чтобы датчик уловил изменение в контрасте с черным металлом.




© digitrode.ru


Теги: Arduino, тахометр




Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Комментарии:

Оставить комментарий