Cпидометр для роллерсерфа

Тема в разделе "Глядите, что я сделал", создана пользователем sZOOn, 13 фев 2018.

  1. sZOOn

    sZOOn Нерд

    Уважаемые форумчане!

    Предлагаю вашему вниманию свою очередную поделку, а именно, спидометр для роллерсерфа.

    Предыстория такова: для получения удовольствия преодоления гиподинамии приобретена была доска "роллерсерф". Поскольку на доске имеется только два колеса, катание на ней требует и чувства баланса, "стоять" на ней можно только в движении. Убедившись, что после непрерывного движения на дистанции около 700 метров колеса как будто вязнут в песке и движение очень сильно затрудняется, обратился к интернету и специалистам. Стало понятно, что по причине излишней мягкости материала колес для моего веса происходит сильный разогрев материала колес и его размягчение, контакт с дорогой увеличивается и возросшая вязкость колеса затрудняет управление и создание движущего момента. После замены колес на более твердые накат доски значительно увеличился, как и легкость управления. На той же длинной трассе знакомого торможения не произошло, скорость продолжала возрастать, что привело к неприятному падению.
    Идея померить скорость и ограничить себя в разгоне пришла, вероятно после падения :) Нашелся прототип от 2014 года https://geektimes.ru/post/258692/ , где такое устройство создано, но для доски другого типа, где плоскость вращения колеса не сильно перемещается относительно доски и электронику можно разместить на самой доске, соединив ее с датчиком на колесе гибким проводом.
    В моем случае и датчик и электроника должны размещаться на кронштейне колеса, поскольку сам кронштейн (кастор) вращается вокруг своей оси вкруговую относительно плоскости доски (ниже показано стрелочками).
    [​IMG]
    Реализация. Спецификация передаваемых сигналов была выбрана BlueTooth по причине доступности этой технологии и наличии ее в имеющихся под рукой смарт-часах SamsungSM-V700. Модуль BlueToothбыл выбран HC-05, контроллер ArduinoMiniPro, но впоследствии заменен на "голый" контроллер AtMega168A, выбран Li-Polаккумулятор 500 ма/ч, удовлетворяющий габаритам кастора и предполагаемому энергопотреблению. В качестве датчика вращения выбран датчик Холла SS49Eв отличие от прототипа как более эксплуатационно устойчивый. Соответственно немного был модернизирован скетч. Прохождение магнита, укрепленного в ступице колеса анализируется двумя точками: первое срабатывание - вхождение магнита в зону чувствительности - "взвод" и второе срабатывание - выход магнита из зоны чувствительности датчика - "спуск". Эти события контроллер считает в течении заданного промежутка времени - 1 секунды и отправляет полученное число по каналу связи устройству Android, одновременно анализируя входящие сигналы. Программа приема, отображения, управления модулем создавалась на основе прототипа в среде AndroidStudio. В ней предусмотрены некоторые доработки, связанные с увеличением помехозащищенности. Аналогично прототипу она осуществляет подсчет скорости и расстояния. Так же сохранена, как кажется, полезная функция включения/выключения "фары" - светодиода, направленного вперед по движению.

    Вид незакрытого блока
    [​IMG]
    Видны слева сверху: красный светодиод защиты переполюсовки заряда, переключатель заряд-работа, аккумулятор; ниже: зеленый ВТ модуль, на его оборотной стороне приклеен верхней частью корпуса микроконтроллер ATMega168A с подрезанными заподлицо выводами.
    [​IMG]

    Крышка модуля с установленным датчиком Холла
    [​IMG]
    [​IMG]В сборе с кастором модуль выглядит так:
    [​IMG]
    Корпус вылеплен из полиморфуса на оправке соответствующей формы.
    Программа прототипа была дополнена возможностями издавать звуковые и вибро сигналы при различных событиях (включение/выключение фары, тревожный сигнал при превышении заданного ограничения максимальной скорости).

    Фото апробации на столе
    [​IMG]

    Проект AndroidStudio имеет большой объем, размещу где-нибудь со ссылкой, если будет интерес, скетч с комментариями привожу.

    Код (C++):
    /*
    * Mega168!!!
    */

    #include"timer-api.h"

    int Polarity = -1;//полярность импульса входного сигнала (в моем случае отрицательная
    int Treshold = 500;//порог срабатывания формирователя отсчетного импулься 1/2 Vcc = 512
    int CountTurn = 0; //хранение кол-ва оборотов за счетный период
    int  LED = 13;      // LED подключен к PB5 пину
    int InputSignal = A5;     //вход для датчика Холла
    int TurnNumber = 0; //накапливаемое количество оборотов
    int DeltaT = 28; //задержка от фронта до определения окончания импульса для устойчивости
    bool Tick = false; //начальное значение, тика еще не было

    void setup()
    {
        Serial.begin(9600); //для отладки
        timer_init_ISR_2Hz(TIMER_DEFAULT);//получается 1-сек задержка!!!
        pinMode(LED, OUTPUT); //выход сигнала на подсветку (фару)
        pinMode(InputSignal, INPUT);  //вход для датчика Холла
    }

    void loop() // здесь делаем обработку сигналов с датчика и управления фарой
    {
        if (Tick) //разрешение исполнения блока if через фиксированный временной интервал
                  //отсылка кол-ва оборотов
        {
              Serial.println(String(CountTurn) + ";");//для отладки
              Tick = false;//готовим след. интервал времени
              CountTurn = 0; // обнуляем кол-во оборотов после передачи в смартфон
        }
     
        else //если тик еще не пришел - накапливаем кол-во оборотов, включаем/выключаем фару
        {
        //накопление кол-ва оборотов
                    if(analogRead(InputSignal) < Treshold)//передний фронт пришел
                    {
                      delay(DeltaT);//пока не читаем ничего
                      if(analogRead(InputSignal) > Treshold)//задний фронт пришел
                      {
                        CountTurn++; //накапливаем кол-во оборотов по приходу заднего фронта
                      }
                    }
                 
        //управление фарой
                    if (Serial.available() > 0)//читаем символ из BTSerial
                      {
                        char command = Serial.read();
                          switch(command)
                          {
                            case '0': digitalWrite(LED, LOW); break;//включаем фару
                            case '1': digitalWrite(LED, HIGH); break;//вЫключаем фару
                          }
                      }
        }
    }

    void timer_handle_interrupts(int timer)
    {
          Tick = true;
    }
    При наличии интереса готов поделиться соображениями, опытом, комплектующими.
     

    Вложения:

    • surf1_web.jpg
      surf1_web.jpg
      Размер файла:
      45 КБ
      Просмотров:
      521
    • device1_web.jpg
      device1_web.jpg
      Размер файла:
      353,3 КБ
      Просмотров:
      541
    • cover_web.jpg
      cover_web.jpg
      Размер файла:
      394,3 КБ
      Просмотров:
      347
    • complete_web.jpg
      complete_web.jpg
      Размер файла:
      350,8 КБ
      Просмотров:
      538
    • working.jpg
      working.jpg
      Размер файла:
      53,3 КБ
      Просмотров:
      390
    hahaha, sanik, OldKryptos и ещё 1-му нравится это.