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

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

Виды износа опорных роликов
Виды износа опорных роликов

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

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

Энкодер MT6701
Энкодер 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. проект по прямому назначению так и не пригодился.

Комментарии (0)