Электронный циркуль Тима

от автора


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

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

Печать всех необходимых деталей я делал на 3D-принтере. В принципе, можно взять и другие материалы, но тут очень важна точность.

Основой проекта выступает датчик Холла 49Е и два магнита. Вычислениями при этом занимается Arduino Nano.

А поскольку AtMega328p оснащён всего лишь 10-битным АЦП, и в вычислениях используется синус, то придётся допустить некоторые погрешности. Результаты я буду выводить на двухстрочный дисплей 1602 с 16 символами на строку.

Если всё пойдёт хорошо, то я планирую реализовать и другие подобные проекты на датчиках Холла, а именно 2D и 3D-инструменты.

▍ Материалы

  • линейный датчик Холла 49E;
  • два неодимовых магнита, ширина 5мм, высота 2мм (Север/Юг определяется по оси высоты);
  • инструмент для определения полюсов магнитов. Я использовал приложение на телефоне;
  • Arduino Nano;
  • дисплей 1602 с интерфейсом I2C. (модуль PCF8575);
  • кабель;
  • клей, я взял УФ-смолу;
  • 3D-принтер для печати ножек циркуля.

Фото компонентов

Ссылки на STL-файлы для печати:

▍ Шаг 1: датчик Холла 49E

Датчики Холла выпускают многие компании, хотя большой разницы между ними нет. Ниже я приложил спецификацию, которую нашёл на Honeywell.

Лично я использовал самый дешёвый, какой смог найти в интернете, модель 49E, и пластиковые детали подогнал конкретно под него.

У этого датчика всего три вывода:

  • пин 1 = питание (от +2.7 до +6.5В).
  • пин 2 = земля (GND).
  • пин 3 = аналоговый вывод (обычно на 1 вольт меньше входного напряжения)

Вывод линейный, мВ/Гс.

В спецификации указано направление, в котором датчик определяет силу магнитного поля [N S]. Если двигать магнит ближе-дальше от датчика, то показания будут отражать магнитную силу в указанном направлении.

▍ Шаг 2: магниты

Для изменения силы магнитного поля вокруг датчика я использую два неодимовых магнита. Направление Север/Юг соответствует верху/низу магнитов, то есть ориентировано по оси высоты.

Разберём, как создаётся поле одним магнитом.

Поле сконцентрировано в его центре, где магнитные линии идут с Юга на Север параллельно. Выходя за края магнита, эти линии изгибаются и в итоге замыкаются с другой стороны — на противоположный полюс.

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

Датчики Холла очень чувствительны, поэтому их неточное расположение приведёт к ошибочным показаниям. Нам же нужно сократить возможное количество потенциальных ошибок. Жаль, нельзя разместить датчик внутри самого магнита — было бы идеально. Я же с целью уменьшить вероятность ошибок решил использовать два магнита.

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

▍ Шаг 3: вычисление угла

Магниты мы будем вращать вокруг датчика.

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

Для лучшего понимания я сделал чертёж.

  • Фиолетовый кружок – это путь, по которому магниты движутся вокруг центра, то есть датчика.
  • синие линии представляют углы/позиции магнитов по мере их вращения.
  • жёлтыми линиями обозначена линейные силы, которые датчик будет регистрировать с Юга на Север.
  • зелёной линией показан график вычисления синусов.
  • красная – это зона точности.

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

В Arduino Nano используется 10-битный АЦП. У этого микроконтроллера тип double аналогичен float, который имеет всего 6-7 десятичных знаков. И поскольку у нас происходит вращение, а не удаление магнитов от датчика, выводом будет результат вычисления синуса.

При этом в нашем случае также неизбежны участки, в которых 10-битный АЦП не позволит произвести точные расчёты.

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

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

Для охвата этих проблемных зон можно задействовать второй датчик, расположив его под 90° относительно первого. Это позволит использовать только точные области каждого.

В плане математики здесь простая тригонометрия, и я покажу это, когда дело дойдёт до кода.

▍ Шаг 4: сборка циркуля

Я уже сказал, что датчик очень чувствительный, и размещать компоненты необходимо очень чётко. В этом смысле мне помог 3D-принтер, который гарантирует точную печать деталей.

При установке минимальная погрешность в выравнивании допустима, но после фиксации гулять элементы уже не должны. Дополнительно некоторые огрехи в их расположении можно будет компенсировать в коде.

▍ Шаг 5: установка датчика

Датчик нужно вклеить в отведённую для него ножку циркуля (Sensor Arm). В этой детали есть специальное отверстие для определения его правильного положения.

▍ Шаг 6: Ориентация магнитов

Очень важно правильно выставить магниты. Я для этой процедуры использовал приложение на телефоне. Подойдёт такое решение только для устройств с магнитометром. Хотя обычно, если у телефона есть GPS, то и магнитометр тоже должен быть.

Что касается приложения, то из множества вариантов я предпочёл трёхмерный, а именно 3D Compass and Magnetometer. На изображении показано типичное 3D-приложение, в котором стрелка указывает в направлении севера.

Магнитометры в телефонах не всегда расположены по центру. Лучше всего выяснить его точное положение с помощью магнита, так будет проще разобраться с полюсами.

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

▍ Шаг 7: установка магнитов во вторую ножку циркуля

Здесь придётся немного повозиться.


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

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

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

▍ Шаг 8: подключение кабеля

Следующим этапом нужно припаять к датчику провода для подключения Arduino.
Мой Arduino установлен на макетной плате, и для соединения с ним я на конце провода использовал разъём DuPont «мама».


Уточнить правильность соединения контактов можно в шаге 1.

▍ Шаг 9: ЖК-дисплей

Для отображения показаний датчика я использую двухстрочный ЖК-дисплей с 16 символами на строку. Кроме того, я использовал переходной модуль PCF8575, так что для подключения мне нужны только выводы I2C. К Arduino же я подцепил всё это 4-жильным кабелем с разъёмами типа «мама» (правильно ли я всё понял и выразил?…).

▍ Шаг 10: подключение к Arduino

Схема подключения к Arduino Nano в программе Fritzing:

Файлы для скачивания:

▍ Шаг 11: код

Если вы уже работали с Arduino Nano, то наверняка также посещали профильный ресурс Arduino.cc для изучения различных нюансов.

Для тех же, кто использует устройство с архитектурой Arduino впервые, я сначала рекомендую почитать раздел руководства: Arduino IDE 2 Tutorials

Здесь можно скачать Arduino IDE и изучить инструкции, написанные самими создателями этой платформы. Помимо прочего, тут же описывается, как загружать скетч на устройство.

Ниже приведён код, который можно скачать в приложенном файле Tims_Electronic_Deviders.ino.

После скачивания скетча нужно будет поместить его в каталог с тем же именем, но без .ino.

Код

/*     Tims_Electronic_Deviders.ino     By Tim Jackson.1960      Creadits:         Arduino.         LiquidCrystal_I2C based on work by DFRobot.      This is code for: Tim's Electronic Deviders.     I am using 3D Printed Deviders with a 49E Linear Hall Effect Sensor and two Magnets.     I am using an Arduino NANO to calculate the postion of the deviders from the values recived from the 49E Linear Hall Effect Sensor.     The sensor is linear: 3 mV/GS, but to get the angle a Sine of the value is calculated.      S=O/H C=A/H T=O/A     Degrees to Radians = degrees * (PI / 180)     Radians to Degrees = radians * 180.0 / pi  */ #include <Wire.h> #include <LiquidCrystal_I2C.h>  #define Hall_49R_Pin                    A1        //    Определение вывода датчика Холла #define CAL_0                            377        //    Показания датчика, когда угол равен 0 #define CAL_180                            690        //    Показания датчика, когда угол равен 180 #define CAL_RANGE (CAL_180 - CAL_0)                //    Максимальная величина CAL - минимальная величина CAL #define CAL_RAD ((double)CAL_RANGE / 2)            //    Используется в значении синуса H для получения угла. #define LEG_LENGTH 99                            //    Длина ножек циркуля. #define MAG_BIOS                        -3.11    //    Установить  на нуль, а затем изменить на значение, которое будет корректировать показания в районе 60 градусов. double Angle = 0;                                //    Переменная для значения Angle. double Length = 0;                                //    Переменная для значения Length. int SensorValue = CAL_0 + 1;                    //    Переменная для значения Sensor.  LiquidCrystal_I2C lcd(0x27, 16, 2);        //20 to    27    //    Установка адреса 2-строчного ЖК-дисплея на 0x27.   void setup() {     Serial.begin(115200);            //    Запуск Serial.     pinMode(Hall_49R_Pin, INPUT);    //    Определение датчика в качестве Input.      lcd.init();                        //    Запуск дисплея.     lcd.backlight();                //    Включение подсветки.     lcd.setCursor(0, 0);            //    Установка курсора на начало строки 0 (верхняя строка).     lcd.print(" Angle:");            //    Отображение метки Angle на верхней строке.     lcd.setCursor(0, 1);            //    Установка курсора на начало строки 1 (нижняя строка).     lcd.print("Length:");            //    Отображение метки Length на нижней строке.  } void loop() {      SensorValue = analogRead(Hall_49R_Pin);    //    Считывание значения с датчика.      Serial.println(SensorValue);            //    Отправка значения на Serial.     CalcAngle();                            //    Вычисление угла.     CalcLength();                            //    Вычисление длины.     Serial.println();                        //    Отправка символа новой строки на Serial для разделения значений.      delay(200);                                //    Ожидание выполнения. } /*     Вычисление Angle на основе значения, полученного от датчика.          S=O/H         Radians to Degrees = radians * 180.0 / pi          O = SensorValue - CAL_0 - CAL_RAD         H = CAL_RAD         Angle in radians = asin(O / H)         Angle in degrees = Angle in radians * 180.0 / pi;  */ void CalcAngle() {      double O = (double)SensorValue - CAL_0 - CAL_RAD;     double H = (double)O / CAL_RAD;     Angle = 90.0 + (asin(H) * 180.0 / PI);      Serial.print("Angle ");     Serial.println(Angle + MAG_BIOS, 4);      lcd.setCursor(7, 0);     lcd.print("  ");     lcd.setCursor(Xpos(Angle + MAG_BIOS), 0);     lcd.print(Angle + MAG_BIOS, 3);     lcd.print("  ");  } /*     Вычисление Length на основе градусов, вычисленных датчиком.          C=A/H         A=C*H         Degrees to Radians = degrees * (PI / 180)          C = (180 - Angle in degrees) / 2         H = LEG_LENGTH         A = C * H         Length = A * 2  */ void CalcLength() {      double _angle = (180.0 - Angle) / 2;     double _rad = _angle * (PI / 180);     double C = cos(_rad);     double H = LEG_LENGTH;     Length = C * H * 2;      Serial.print("Length ");     Serial.println(Length + MAG_BIOS, 4);      lcd.setCursor(7, 1);     lcd.print("  ");     lcd.setCursor(Xpos(Length + MAG_BIOS), 1);     lcd.print(Length + MAG_BIOS, 3);     lcd.print("  ");  } /*     Функция для вычисления положения значения, отображаемого на дисплее.          Проверить, указано ли значение в сотнях, десятках или единицах, чтобы соблюсти выравнивание чисел. . */ byte Xpos(byte number) {     byte val = 8;     if (number < 100) { val = 9; }     if (number < 10) { val = 10; }     return val; }

▍ Шаг 12: калибровка

Перед калибровкой значение #defined для MAG-BIOS необходимо установить на 0.

#define MAG_BIOS                        -3.11    //    Установить на 0, а затем изменить на значение, корректирующее показания в районе 60 градусов.

Для калибровки циркуля должен быть запущен Serial Monitor.

Закройте циркуль и запишите первое число, которое указано над Angle.

Откройте циркуль и снова запишите первое число, указанное над Angle. (я для соблюдения точных 180° произвожу эти манипуляции, положив циркуль на рабочий стол с разметкой).

Число при раскрытом циркуле, должно быть больше того, что отображалось при закрытом. Если получается наоборот — значит полярность магнитов перепутана.

Измените значения #defined для CAL_0 и CAL_180 согласно зафиксированным показаниям.

#define CAL_0                            377        //    Показания датчика, когда угол равен 0 #define CAL_180                            690        //    Показания датчика, когда угол равен 180

Ориентируясь на транспортир, выставьте циркуль в положение 60° и запишите отображённую величину угла. Пока циркуль находится в таком положении, с помощью линейки измерьте расстояние между его концами и запишите значение. Ошибка в градусах угла и расстоянии в миллиметрах будет одинаковой.

Измените значение #defined, чтобы компенсировать эту ошибку.

#define MAG_BIOS                        0    //    Установить на нуль, а затем на значение, корректирующее показания в районе 60 градусов

После калибровки показания будут близки к точным, кроме крайних значений от 0 до 15° и от 165 до 180°.

Дело в том, что в этих областях кривая синусоиды изменяется слабо.

▍ Шаг 13: повышение точности

Выше я продемонстрировал создание простейшего измерительного инструмента и принцип действия датчика Холла.

Модель 49E – это всего лишь один линейный аналоговый датчик, но здесь можно использовать и другие:

  • Модель AS5600 представляет собой легко программируемый 12-битный магнитный поворотный датчик положения с аналоговым или PWM-выводом, оснащённый интерфейсом I2C.
  • Модель MLX90393 предлагает 16-битный вывод, пропорциональный плотности магнитного потока, регистрируемой вдоль осей X, Y и Z. Можно выбирать между протоколами SPI и I2C.

Более дорогостоящие датчики обеспечат ещё большую точность.


ссылка на оригинал статьи https://habr.com/ru/company/ruvds/blog/679476/


Комментарии

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

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