>
Приветы самоделкиным!
Представляю вашему вниманию небольшой электронный приборчик для измерения любой длины: прямой или криволинейной. Данные отображаются на небольшом встроенном дисплее в метрической и дюймовой системе одновременно. На нашем сайте я нашел подобное устройство, но оно большого размера и применимо для больших расстояний. К тому же принцип действия приборов разительно отличается. Если в той статье предлагается устройство на основе обычной связки геркон – магнит, то тут уже используется поворотный энкодер. Предлагаемый же прибор можно назвать настольным, так как измерения отображаются в миллиметрах.
Конечно можно просто купить готовый, механический, например такой, но тогда пропадет весь азарт изобретательства!
НЕОБХОДИМЫЕ МАТЕРИАЛЫ И ИНСТРУМЕНТЫ:
– Микроконтроллер ATtiny1614 х 1 шт.
– Модуль поворотного энкодера KY-040 х 1 шт.
– Триггер Шмитта NC7S14M5X х 2 шт.
– Модуль дисплея OLED 128X64 I2C х 1 шт.
– Кнопка PTS645 х 1 шт.
– Аккумулятор 3,7v х 1 шт.
– Сопротивление 10 кОм 0805 х 2 шт.
– Конденсатор 22 нФ 0805 х 2 шт.
– Конденсатор 0,1 мкФ 0805 х 1 шт.
– Arduino IDE
– Паяльник
– 3D-принтер
Посмотреть работу прибора и оценить его габариты и возможности можно проcмотрев это видео:
СХЕМА:
Схема основана на микроконтроллере ATtiny1614. Эта микросхема очень экономична в спящем режиме. Так же основным элементом является поворотный 360 градусов энкодер. Но у него имеется недостаток. Его работа основана на механическом взаимодействии контактов, что может повлиять на правильность считывания данных. Что бы исключить помехи, в схему был добавлен RC-фильтр и парочка триггеров Шмитта. В конечном результате на контроллер поступает чистый сигнал. В качестве источника питания используется литий-полимерная аккумуляторная батарея 3.7v.
КОРПУС:
Корпус прибора распечатан на 3D-принтере. В конце статьи будет предоставлена возможность скачать оригинальные файлы проекта. При определенных навыках можно придумать свой корпус.
ПЕЧАТНАЯ ПЛАТА:
Для минимизации электронной части, все возможные детали были выбраны по технологии SMD. В конце статьи так же будут представлена возможность скачать оригинальные файлы.
СБОРКА ПРИБОРА:
Первым делом нужно приготовить все для сборки. Проверить наличие радио-компонентов, вытравить самому или заказать печатную плату, распечатать или так же заказать элементы корпуса.
На печатную плату нужно установить микроконтроллер, триггеры, конденсаторы и сопротивления. При монтаже элементов SMD лучше воспользоваться паяльной пастой и термофеном. После мелкого монтажа установите разъем для аккумуляторной батареи.
Дальше нужно установить разъем для дисплея. На плате дисплея устанавливается встречный разъем. Какие куда (папа – мама) не имеет значения. Так же устанавливается 3-х пиновый разъем для подключения программатора и поворотный энкодер.
К кнопке нужно припаять два проводка. Кнопку можно установить на место в корпусе. Концы проводов от кнопки впаяйте в отведенные места печатной платы. Вставьте батарею между печатной платой и платой энкодера. При правильной установке разъемов (папа – мама) батарея должна войти между платами свободно.
Теперь можно собранную электронную часть установить в корпус. Для программирования контроллера можно использовать программатор на основе Arduino NANO. Во время прошивки контроллера лучше отключить встроенный аккумулятор. Питание будет подаваться по шине UPDI.
Процесс прошивки выглядит так:
– Подключаете плату к Arduino Nano
– Подключите Arduino к компьютеру, в разделе Arduino IDE -> инструменты -> нужно выбрать плату с процессором ATtiny1614, установить тактовую частоту 8 МГц и порт, куда подключили программатор.
– Проверьте установки программатора в установках. Нужно jtag2updi (megaTinyCore).
– Загрузите скачанный скетч в микроконтроллер.
После программирования можно закончить сборку корпуса. Для этого устанавливается крышка на место. Она притягивается гайкой к резьбовому соединению энкодера.
Сборка почти закончена. Теперь нужно установить ролик (колесико) на вал энкодера. Подойдет вот такое, от сервопривода.
Есть два варианта установки ролика.
Первый – просверлить подходящее отверстие в центре ролика и насадить ролик на вал энкодера.
Второй – распечатать на 3D-принтере свое колесо. Снять резинку с готового ролика и надеть новое, напечатанное.
Как и писалось выше, вам предлагается скачать оригинальные файлы схемы, печатной платы, прошивки контроллера, добавочной библиотеки и корпуса.
– Скачать схему и печатную плату в разных форматах. Схема в формате .PNG, печатная плата в формате .JPG. Архив с файлами для программ EAGLE
и KiCad скачать можно отсюда
– Прошивка контроллера в формате .ino или скопировать текст кода из спойлера: Показать / Скрыть текст
/**************************************************************************
Measuring Wheel
Based on “DIY Simple Measuring Wheel with Rotary Encoder” by Mirko Pavleski
2021-05-03 John Bradnam (jbrad2089@gmail.com)
Create program for ATtiny1614
————————————————————————–
Arduino IDE:
————————————————————————–
BOARD: ATtiny1614/1604/814/804/414/404/214/204
Chip: ATtiny1614
Clock Speed: 1MHz
Programmer: jtag2updi (megaTinyCore)
ATTiny1614 Pins mapped to Ardunio Pins
+——–+
VCC + 1 14 + GND
(SS) 0 PA4 + 2 13 + PA3 10 (SCK)
1 PA5 + 3 12 + PA2 9 (MISO)
(DAC) 2 PA6 + 4 11 + PA1 8 (MOSI)
3 PA7 + 5 10 + PA0 11 (UPDI)
(RXD) 4 PB3 + 6 9 + PB0 7 (SCL)
(TXD) 5 PB2 + 7 8 + PB1 6 (SDA)
+——–+
PA0 to PA7 can be analog or digital
PWM on D0, D1, D6, D7, D10
**************************************************************************/
#include “Tiny8kOLED.h”
#include
#define BUTTON 10 //PA3
#define ENC_B 1 //PA5
#define ENC_A 5 //PB2
//Uncomment next line to clear out EEPROM and reset all high scores
//#define RESET_EEPROM
#define SLEEP_TIMEOUT 10000 //Amount of time no switch is pressed before going to sleep
uint32_t sleepTimeout = 0; //Used to timeout mode switch function to sleep function
bool volatile ignoreNextPress = false;
int8_t volatile rotaryDirection = 0;
bool volatile lastRotA = false;
#define MAX_ROTARY_COUNT 25374 //999 inches
long volatile ruler = 0; //ruler measurement
bool volatile rulerChanged = false;
#define PI 3.14
#define WHEEL_RADIUS 3.00 //in cm
#define RESOLUTION 20 //Steps per revolution
//——————————————————————–
//Program Setup
void setup()
{
pinMode(BUTTON, INPUT_PULLUP);
pinMode(ENC_A, INPUT);
pinMode(ENC_B, INPUT);
//Attach interrupt handlers for handling rotary encoder
attachRotaryPinChangeInterrupt();
//Attach interrupt handler to wake up from sleep mode
attachInterrupt(digitalPinToInterrupt(BUTTON),switchInterrupt,CHANGE);
oled.begin();
rulerChanged = true; //force display update
sleepTimeout = millis() + SLEEP_TIMEOUT;
}
//——————————————————————–
//Handle pin change interrupt when button is pressed
void switchInterrupt()
{
}
//——————————————————–
// Attach the pin change interrupts for the rotary encoder
void attachRotaryPinChangeInterrupt()
{
attachInterrupt(ENC_A, rotaryInterrupt, CHANGE);
}
//——————————————————–
// Detach the pin change interrupts for the rotary encoder
void detachRotaryPinChangeInterrupt()
{
detachInterrupt(ENC_A);
}
//———————————————————————
// Interrupt Handler: Rotary encoder has moved
void rotaryInterrupt()
{
if (!digitalRead(ENC_A) && lastRotA)
{
if (digitalRead(ENC_B))
{
ruler = min(ruler + 1, MAX_ROTARY_COUNT – 1);
}
else
{
ruler = max(ruler – 1, 0);
}
rulerChanged = true;
}
lastRotA = digitalRead(ENC_A);
}
//——————————————————————–
//Program Loop
void loop()
{
if (millis() >= sleepTimeout)
{
system_sleep();
}
else if (digitalRead(BUTTON) == LOW)
{
delay(10); //Debounce
if (digitalRead(BUTTON) == LOW)
{
//Zero ruler
ruler = 0;
displayRuler();
//Wait for button release
while (digitalRead(BUTTON) == LOW)
{
yield();
}
}
sleepTimeout = millis() + SLEEP_TIMEOUT;
}
else if (rulerChanged)
{
displayRuler();
rulerChanged = false;
sleepTimeout = millis() + SLEEP_TIMEOUT;
}
else
{
delay(100);
}
}
//——————————————————————–
// display current distance
void displayRuler()
{
float cm = (2 * PI * WHEEL_RADIUS * ruler) / RESOLUTION;
long mm10 = floor(cm * 100 + 0.5);
//oled.clear(); //all black
oled.setFont(FONT16X32);
oled.setCursor(4,0);
displayNumber(mm10,true);
oled.setCursor(4,4);
displayNumber(mm10 * 100 / 254,false);
oled.setFont(FONT8X16);
oled.setCursor(108,2);
oled.print(“mm”);
oled.setCursor(108,6);
oled.print(“in”);
}
//——————————————————————–
// display current distance
void displayNumber(uint32_t number, bool isMM)
{
char buffer[10];
if (isMM)
{
sprintf(buffer,”%4dx2e%01d”,(int)number / 10, (int)(number % 10));
}
else
{
sprintf(buffer, “%3dx2e%02d”, (int)(number / 100), (int)(number % 100));
}
oled.print(buffer);
}
//——————————————————————–
//Shut down OLED and put ATtiny to sleep
//Will wake up when LEFT button is pressed
void system_sleep()
{
detachRotaryPinChangeInterrupt();
interrupts();
oled.ssd1306_sleep();
delay(100);
attachRotaryPinChangeInterrupt();
sleepTimeout = millis() + SLEEP_TIMEOUT;
}
– Скачать библиотеку для скетча
– Скачать файлы корпуса для печати на принтере в формате .STL
Всем добра!!!