Тахометр. Пример работы с фоторезистором и LCD дисплеем HD44780 на arduino

Тахометр на arduino с помощью фоторезистора

В этой статье я покажу, как можно с помощью обычного светодиода и фоторезистора сделать тахометр – измеритель скорости вращения моторчика. И чтобы было интересней, полученные данные будут выведены на LCD дисплей, у меня как раз завалялся модуль HD44780, он умеет выводить данные в две строки по 16 столбцов.

Как работает фоторезистор

Фоторезистор – это полупроводник, который меняет свое сопротивление в зависимости от количества света, который на него попадает. Чем больше света, тем ниже сопротивление. Эта способность нам поможет в реализации тахометра. Будем светить с помощью светодиода на фоторезистор с небольшого расстояния — 1,5-2 сантиметра. И с помощью ардуино будем мониторить какое напряжение проходит через фоторезистор, если напряжение будет падать, значит что-то загораживает свет. Если на вал мотора одеть лопасть, и заставить крутиться между светодиодом и фоторезистором, то можно узнать, как часто лопасть загораживает свет. А дальше дело техники – сделать пару десятков замеров, посчитать среднее арифметическое, для более точного замера и перевести эти данные в количество оборотов в минуту.
При первом испытании, получилось, что мотор, на котором я тестировал, вращается со скоростью почти 12 тысяч оборотов в минуту. В голову сразу пришла мысль, что где-то ошибка в расчетах или arduino не корректно обрабатывает данные с фоторезистора. Пришлось замедлить мотор с помощью потенциометра, и данные тоже стали замедляться. Обороты упали до двух, а потом и до одной тысячи в минуту. Все работало и высчитывалось корректно. Но при максимальном повышении оборотов, получались все те же 12 тыс. Пришлось поискать даташит на моторчик и оказалось, что его нормальная скорость вращения – это 11,5 -12,5 тыс оборотов. То есть все работает корректно. Ни когда бы не подумал, что такой маленький моторчик может вращаться с такой скоростью.
Ниже две фотографии, на одной изображено, как расположены светодиод и фоторезистор, а на второй уже к ним добавился мотор, скорость вращения которого, будет измеряться.

Тахометр их фоторезистора и светодиода

Тахометр их фоторезистора и светодиода

Вывод данных на LCD дисплей HD44780 с помощью arduino

Для работы с дисплеем HD44780 очень удобно использовать модуль I2C интерфейса. Бывают модули и LCD дисплеи продаются по отдельности, но зачастую и сразу в комплекте, спаянные. Я рекомендую, использовать уже собранные вместе, поскольку если подключать без I2C то придется подключать дисплей с помощью 16 проводов, когда через I2C их количество снижется до 4, два из которых это питание. А два других провода подключаются к пинам ардуино A4 и A5.
Чтобы управление выводом данных на дисплей, было более удобным и комфортным можно воспользоваться библиотекой LiquidCrystal_I2C.
Ниже приведена схема подключение дисплея, а также светодиода с фоторезистором к arduino.

Схема подключения  LCD дисплея HD44780 к arduino

Что использовалось в проекте:

Скетч тахометра на arduino

Ниже приведен скетч с подробными комментариями, а также его можно скачать себе на компьютер: скачать.

// библиотеки для работы с LCD дисплеем по I2C
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

// инициализация дисплея.
// GND - земля
// VVC - 5+ вольт
// SDA - пин A4
// SCL - пин A5
// 16 столбцов и 2 строки 
LiquidCrystal_I2C lcd(0x27,16,2);

const int pinPhoto = A0; // порт для считывания данных с фоторизистора
int light = 0; // переменная для хранения данных с фоторизистора
int numTurn = 0; // номер итерации проверки оборотов
int valArray[100]; // массив для хранения данных с фоторезистора, нужные для начальной настройки
int maxLight = 1024;  // порог, при котором будем считать, что светодиод закрыт
int sum = -1; // сумма количеств оборотов
int count_zamer = 20; // количество итераций, после которых будет высчитано среднее значение скорости
unsigned long lastMillis = 0; // переменная для хранения времени предыдущего перекрытия светодиода
bool work = true; // флаг, который поднимается после открытия светодиода

void setup() {
  Serial.begin(9600);
  pinMode( pinPhoto, INPUT );

  // ждем пока светодиод прогреется
  delay(1000);
  // каждые 10 милисек считаем значение с фоторезистора, 100 раз
  for(int i = 0; i< 100; i++){
    valArray[i] = analogRead( pinPhoto );
    delay(10);
  }
  // выбераем минимальное значение с фоторезистора
  for(int i = 0; i< 100; i++){
    if(maxLight > valArray[i]) maxLight = valArray[i];
  }
  // немного снизим порог
  maxLight -= 10;
  Serial.println( maxLight );
  delay(500);
  Serial.println( "START!" );
  
  lastMillis = millis();

  // запускаем дисплей
  lcd.init(); 
  // включаем подсветку
  lcd.backlight();
  // стираем все лишнее
  lcd.clear();
  // выводим текст
  lcd.setCursor(0, 0); lcd.print("S");
  lcd.setCursor(1, 0); lcd.print("T");
  lcd.setCursor(2, 0); lcd.print("A");
  lcd.setCursor(3, 0); lcd.print("R");
  lcd.setCursor(4, 0); lcd.print("T");
  lcd.setCursor(5, 0); lcd.print("!");
}

void loop() {
  // считаем показания с фоторезистора
  light = analogRead( pinPhoto );
  // если значение ниже порога, значит светодиод загорожен
  if(light < maxLight && work){
    // опускаем флаг, чтобы не считать, пока светодиод перекрыт
    work = false;
    // если первая итерация, то не считаем ее, чтобы начать отсчет времени 
    if(sum == -1){
      // записываем время старта
      lastMillis = millis();
      sum = 0;
    }else{
      unsigned long currentMillis = millis();
      // записываем в sum количество миллисекунд между оборотами
      sum += (currentMillis - lastMillis);    
      numTurn++;
      // считаем 20 раз, для большей точности
      if(numTurn == count_zamer){
        float sredSpeed = 0;
        numTurn = 0;
        // берем среднее и высчитываем количество оборотов для минуты
        sredSpeed = 60000 / ((float)sum / (float)count_zamer); // оборотов в минуту
        Serial.print("speed: ");
        Serial.println(sredSpeed);
        sum = -1;
        
        // вывод данных на LCD дисплей
        lcd.clear();
        lcd.setCursor(0, 0); lcd.print("S");
        lcd.setCursor(1, 0); lcd.print("P");
        lcd.setCursor(2, 0); lcd.print("E");
        lcd.setCursor(3, 0); lcd.print("E");
        lcd.setCursor(4, 0); lcd.print("D");
        lcd.setCursor(5, 0); lcd.print(":");

        // преобразовываем числовое значение в строку
        // и по одному символу выводим не дисплей
        char string_turn[] = "";
        sprintf(string_turn,"%d", (int)sredSpeed);   
        char *current = string_turn;
        int count_numbers = 0;
        while ( *current != '\0' )
        {
          lcd.setCursor(6+count_numbers, 0); 
          lcd.print(*current);
          count_numbers++;
          current++;
        }
        lcd.setCursor(count_numbers+7, 0); lcd.print("r");
        lcd.setCursor(count_numbers+8, 0); lcd.print("/");
        lcd.setCursor(count_numbers+9, 0); lcd.print("m");
        lcd.setCursor(count_numbers+10, 0); lcd.print("i");
        lcd.setCursor(count_numbers+11, 0); lcd.print("n");
      }
      lastMillis = currentMillis;
    }
  }
  // если светодиод не загорожен
  if(light >= maxLight){
    work = true;
  }
}
 

Послесловие

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

Рассказать друзьям:


Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*