Спидометр для велосипеда на основе Ардуино

В этом уроке мы создадим своими руками простой спидометр для велосипеда на основе микроконтроллера Ардуино. Идея состоит в том, чтобы измерить угловую скорость колеса велосипеда. Таким образом, зная диаметр и математическую легенду Пи (3.14) можно рассчитать скорость. Также, зная количество раз, которое провернулось колесо, можно легко узнать пройденное расстояние. В качестве дополнительного бонуса мы решили добавить световой индикатор на велосипед, - задача состояла в том, когда включить стоп-сигнал.

Шаг 1. Держатель

Для этого проекта очень важно иметь сильный и стабильный держатель нашего Ардуино спидометра. Смысл в том, что велосипед может пострадать от сильного импульса, когда он попадает в дыру или когда вы решаете повеселиться и взять вел в тяжелые условия езды. Кроме того, наши входные данные фиксируется, когда магнит на колесе пересекает датчик эффекта Холла на опоре.

Если все одновременно пойдет не так, Arduino покажет скорость высокоскоростного поезда. Кроме того, вы не захотите, чтобы ваш лучший друг Ардуино упал на дороге только потому, что вы решили быть ленивым и использовать для держателя очень дешевые материалы.

Поэтому, чтобы соблюсти все нюансы безопасности, мы решил использовать алюминиевые ленты, так как их можно легко разрезать и просверлить, они устойчивы к коррозии и довольно дешевы, что всегда хорошо для поделок своими руками. Мы также использовали некоторые гайки (с шайбами) и болты, чтобы закрепить держатель на раме, так как всё должно быть надежно закреплено на раме.

Еще одной важной частью является то, что электроника нашего спидометра Ардуино должна быть должным образом изолирована от опор, если они сделаны из какого-либо металла. Горячий клей, который мы использовали, работал отлично, он также поглощал и смягчал удары, что было хорошо для довольно хрупкого дисплея.

Шаг 2. Датчик и магнит

Измерение и входные данные проекта основаны на этой части. Идея состоит в том, чтобы поместить магнит на велосипедное колесо и добавить датчик эффекта Холла на раму так, чтобы каждый раз, когда магнит пересекал датчик, Arduino знал, что оборот завершен и он может рассчитать скорость и расстояние.

Используемый здесь датчик - классический датчик с эффектом Холла А3144. Этот датчик понижает свою выходную мощность, когда конкретный полюс направлен в правильной ориентации. Ориентация очень важна, так как внешний полюс не повлияет на выход.

Выше несколько фото, показывающих правильную ориентацию. Также для датчика эффекта Холла требуется нагрузочный резистор 10 кОм, но в этом проекте заменен на нагрузочные резисторы 20 кОм в Arduino.

Тщательное размещение магнита очень важно. Если поместить его немного дальше, это может привести к непоследовательному чтению или отсутствию оборотов, а если расположить его очень близко, магнит может дотронуться до датчика, что не очень желательно.

Шаг 3. Дисплей

Этот дисплей теоретически необязателен, но вам нужно что-то, чтобы отображать скорость и расстояние в реальном времени. Думать об использовании ноутбука совершенно абсурдно. Мы использовали 0,96-дюймовый OLED-дисплей с I2C в качестве протокола связи между ведомым и ведущим устройствами.

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

  1. "Start" в правом нижнем углу - это когда Arduino только начал работу и успешно загрузился.
  2. Скорость в км/ч. Этот режим отображается только тогда, когда велосипед находится в движении, и автоматически отключается после его остановки.
  3. Последний, с метрами в качестве единиц, очевидно, - расстояние, которое прошел вел. Как только вел останавливается, Arudino переключается на отображение расстояния в течение 3 секунд.

Эта система не идеальна. Он на мгновение отображает пройденное расстояние, даже когда байк находится в движении. Может это не идеально, но это достаточно мило.

Шаг 4. Источник питания

Проект, будучи немного громоздким, не всегда может иметь под рукой розетку для зарядки. Поэтому из-за лени было решено просто использовать блок питания в качестве источника питания и использовать мини-USB-кабель для подключения питания USB от блока питания к Arduino Nano.

Но вы должны тщательно выбрать powerbank. Важно иметь правильную геометрию, чтобы ее можно было легко установить. Также источник питания должен быть немного тупым. Дело в том, что для экономии энергии powerbank предназначен для отключения выхода, если потребление тока не превышает определенного порогового значения.

Скорее всего это пороговое значение составляет не менее 200-300 мА. Наша схема будет иметь максимальное потребление тока не более 20 мА. Таким образом, обычный банк питания отключит выход. Это может привести вас к мысли, что в вашей цепи есть какая-то неисправность. Этот конкретный банк питания на фото выше работает с таким небольшим током.

Шаг 5. Стоп-сигнал (опционально)

В качестве дополнительной функции было решено добавить стоп-сигнал. Вопрос был в том, как определить, когда начался процесс торможения.

Если мы тормозим, велосипед замедляется. Это означает, что если мы рассчитываем ускорение и если оно оказывается отрицательным, можно включить стоп-сигналы. Это, однако, означает, что свет включится, даже если мы просто перестанем крутить педали.

Также мы не добавили транзистор в световую цепь, что абсолютно рекомендуется. Если кто-то сделает этот проект и правильно интегрирует эту часть, мы бы были более чем рады увидеть её и добавили бы картинки сюда. Ток мы получаем напрямую от цифрового контакта 2 Arduino Nano.

Шаг 6. Код проекта

Скачать или скопировать код для спидометра Ардуино вы можете ниже:

#include <Adafruit_SSD1306.h>
#include <Wire.h>
//#include <SPI.h>
//#include <SD.h>

#define pi 3.14 
#define brakelight 8
#define diameter .66
#define numberofreadings 6
#define cutoff 3
#define velocitycutoff 1.2   // in m/s
#define displaychangeafter 5000

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

const int chipSelect= 9;

int n=0;
int count=0;
double instant=0;
double previnstant=0;
double prevprevinstant=0;
int wheelcount=0;
float velocity=0;
float accleration=0;
float distance=0;
int temp; 
bool unit1=0;
bool unit2=1;
bool unit3=0;
int unitmillis1=0;
int unitmillis2=0;
int unitmillis3=0;

void setup()
{
  pinMode(2,INPUT_PULLUP);
  pinMode(brakelight,OUTPUT);
  attachInterrupt(digitalPinToInterrupt(2),cross,FALLING);

  display.begin(SSD1306_SWITCHCAPVCC , 0x3C);
  display.setTextColor(WHITE);
  display.setTextSize(3);
  
/*
 
    if (!SD.begin(chipSelect)) {

    display.setTextSize(1);
    display.setCursor(0,23);
    display.print("No SD Card");    
  }
  display.display();
  display.setTextSize(3);

  File dataFile = SD.open("datalog.txt",FILE_WRITE);

  if(dataFile)
  {
  dataFile.println("RESTART,RESTART,RESTART,RESTART");
  dataFile.println("TIME,Accleration,Speed,Distance");
  dataFile.close();
  }
  */
}

void loop()
{

  if(0>accleration)
  {
    digitalWrite(brakelight,HIGH);   
  }
  
  if(0<accleration)
  {
    digitalWrite(brakelight,LOW);
  }
  
  {

    if(unit1!=1&&unit2!=1&&unit3!=1)
    {
      display.clearDisplay();
      display.setCursor(0,0);
      display.print(velocity*18/5);
      display.setTextSize(2);
      display.setCursor(67,18);
      display.print("km/hr");
      display.display();
      display.setTextSize(3);
      display.display();
    }

    else
    {
      display.clearDisplay();
      display.setCursor(0,0);
      display.print(distance);
      display.setTextSize(1);
      display.setCursor(90,25);
      if(distance==0){
        display.print("START");
      }
      else{
        display.print("meters");
      }
      display.display();
      display.setTextSize(3);
    }
     
  /*
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
   if(dataFile)
    {
      dataFile.print(instant);
      dataFile.print(",");
      dataFile.print(accleration);
      dataFile.print(",");
      dataFile.print(velocity);
      dataFile.print(",");
      dataFile.println(distance);
      dataFile.close();
    }
  */
    
  }

  if(unitmillis1!=millis()/displaychangeafter+1)
  {   
    unitmillis1=millis()/displaychangeafter+1;
    unit1=1;
  }
  if(unitmillis2!=millis()/displaychangeafter+2)
  {
    unitmillis2=millis()/displaychangeafter+2;
    unit2=1;
  }
  if(unitmillis3!=millis()/displaychangeafter)
  {
    unitmillis3=millis()/displaychangeafter;
    unit3=1;
  }
  
}

void cross()
{

  prevprevinstant=previnstant;
  previnstant=instant;
  instant=micros()/1000.0;
  wheelcount++;


  if(wheelcount>2)
  {
    distance=diameter*wheelcount*pi;
    velocity=diameter/(instant-previnstant)*pi;
    accleration=2*diameter*pi*(1/(instant-previnstant)-1/(previnstant-prevprevinstant))/(instant-prevprevinstant);
    velocity=velocity*1000; 
    accleration=accleration*100000000;
    
    unit3=0;
    unit2=0;
    unit1=0; 
    
  }
  
}

Как всегда мы пишем программу на Arduino IDE. Я изначально стремился записать параметры на SD-карту. Но, к сожалению, в этом случае мне пришлось бы использовать три библиотеки: SD.h, Wire.h и SPI.h. В сочетании с ядром они занимали бы 84% доступной памяти, и IDE предупредила о проблемах со стабильностью.

27 марта 2019 в 17:46 | Обновлено 7 декабря 2019 в 00:03 (редакция)
Опубликовано:
Уроки, ,

1 комментарий

  1. Саске
    8 апреля 2022 в 18:30

    Автор, можно хотя бы схему подключения?

    Ответить

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

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