В этой статье я покажу, как можно с помощью обычного светодиода и фоторезистора сделать тахометр – измеритель скорости вращения моторчика. И чтобы было интересней, полученные данные будут выведены на 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.

Что использовалось в проекте:
- Arduino (я использовал arduino uno, но можно любую другую). Покупал тут: arduino uno
- 1 резисторов сопротивлением 300 Ом. Покупал тут:набор резисторов 700 шт. От 10 Ом до 1 МОм
- 1 резисторов сопротивлением 10 кОм. Покупал тут:набор резисторов 700 шт. От 10 Ом до 1 МОм
- 1 светодиод. Покупал тут: 100 светодиодов, 10 разных цветов
- LCD дисплей Hd44780 с модулем I2C. Покупал тут: LCD дисплей Hd44780 с модулем I2C
- Фоторезистор. Покупал тут: Фоторезисторы, 20 шт
Скетч тахометра на 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;
}
}
Послесловие
Работающее устройства можете посмотреть на видео, там я сделал несколько замеров.


Нет схемы с номиналами деталей.