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

Курвиметр — это устройство, предназначенное для измерения длины извилистых линий на топографических картах, планах и чертежах. Основная идея заключалась в том, чтобы преобразовать показания энкодера в линейное расстояние.
Энкодер - представляет собой датчик угла поворота, который может быть нескольких типов: инкрементальный, абсолютный, оптический, магнитный и механический. Для своего проекта я выбрал 14-битный магнитный энкодер MT6701.

Контролёр, ответственный за обработку данных, выбрал ESP32, который уже был в наличии, и запрограммировал его на языке Micropython, в котором я немного разбираюсь. Затем подключил дисплей и энкодер, используя протокол I2C.
Чтобы точно определить диаметр измеряемого объекта, будь то ролик, колесо или что-��о другое, необходимо знать, где начинается и заканчивается его оборот. Для этого нужен триггер — устройство, которое будет указывать на начало и конец вращения.
В качестве триггера я решил использовать геркон, но потом передумал из-за его особенностей: он может срабатывать дважды при прохождении магнита, а его чувствительность варьируется. К счастью, мне повезло, и я смог найти промышленный магнитный датчик, который отлично подошёл на роль триггера.
Алгоритм описание работы - при повороте энкодера все его углы необходимо складывать или отнимать в зависимости от направления вращения зная диаметр колеса энкодера, эти значения можно перевести в пройденный путь. Триггер делит этот путь отмеряя длину измеряемого ролика зная длину ролика получаем диаметр. Для качественного результата первым делом необходимо убрать первое измерение так-как оно меньше диаметра колеса, поскольку начинается не от начала триггера.
Далее проводим дополнительно несколько измерений с целью усреднения результата. В моём случае получилось добиться точности в десятые миллиметра.
Теоретическая точность получилось:
· 14bit = 2^14 = 16384
· при, D = 110 мм, L= π × D = 345,575 мм
· Расчетная теоретическая точность за импульс = D/16384 = 345,575/16384 = 0,02 мм.
Для вывода информации нашелся дисплей LCD1602 от старого проекта, который был успешно интегрирован в данное устройство.
В качестве источника питания применил аккумулятор 18650 + мод��ль заряда.
Схему подключения приводить не буду.
Код выглядит примерно так (это один из вариантов, отлаженный код в контроллере):
import machine from time import sleep_ms import math from machine import Pin, ADC from i2c_lcd1602 import I2C_LCD1602 i2c = machine.I2C(1,sda=machine.Pin(6), scl=machine.Pin(7), freq=400000) LCD = I2C_LCD1602(i2c) napr = 0 # Направление вращения 0 против часовой стрелки 1 по часовой diameter = 110 # Диаметр колеса, мм alfa_sum = 0 dtt = [] # Предыдущее значение cz = [] # Счетчик оборотов по часовой стрелки ct = [] # Счетчик оборотов по часовой стрелки data_0 = [] booll=0 booll_per=[] LCD.puts("Hello") LCD.puts("kurva ", 2, 1) sleep_ms(1000) response=i2c.readfrom_mem(0x06, 3, 2) # Подключаемся к датчику potentiometr = machine.ADC(28) # Подключаем аналоговый Pin (0) potentiometr_value = potentiometr.read_u16() str_return_data = str(response.hex()) # Подключаемся к датчику feedback_data = int(str_return_data, 16) # Преобжаем в 10 ричной код x = feedback_data/4 # Убираем лишние цифры for dat in x: data = dat if 0 <= data <= 4096: dt = 0 if 4096 <= data <= 8192: dt = 1 if 8192 <= data <= 12288: dt = 2 if 12288 <= data <= 16384: dt = 3 dtt.append(dt) # Предыдущее значение записываем в массив data_0.append(data) if len(dtt)>=3: # Если массив меньше 2-х начинаем работу dt_t = int(dtt.pop(-3)) # Предыдущее значение извлекаем из массива if dtt[0] == 0 and dtt[1] == 3: # Ищем переход по часовой стрелки cz.append(1) # Если есть переход записываем в массив if dtt[0] == 3 and dtt[1] == 0: # Ищем переход по часовой стрелки ct.append(3) # Если есть переход записываем в массив data_1 = int(data_0.pop(-2)) # Предыдущее значение извлекаем из массива if data != data_1: alfa = float(data-data_1) alfa_sum += alfa dz = int(len(cz)*16384) dt = int(len(ct)*16384) alfa_real = round((360/(16384)*(alfa_sum+dt-dz)),2) l_max = round(((math.pi*diameter)/360)*alfa_real,3) d_nom = round(l_max/math.pi,1) LCD.puts("%s: %s"% (round(alfa_real,1), round(l_max,1))) if potentiometr_value >8000: booll=1 if potentiometr_value <8000: booll=0 booll_per.append(booll) if len(booll_per)>2: dt_booll_per = int(booll_per.pop(-2)) if booll == 0 and int(dt_booll_per) == 1: alfa_sum = int(0) cz = [0,0] ct = [0,0] LCD.clear() LCD.puts(0.000) LCD.puts("D=%s - mm" % abs(d_nom), 0, 1) sleep_ms(50)
Дальше последовала разработка и печать корпуса.



Готовый проект выглядит так.
Всем спасибо на оригинальность не претендую. В проекте много чего можно изменить (доработать). Например переписать код на С провести оптимизацию.
P.S. проект по прямому назначению так и не пригодился.
