Відповісти

Введіть повідомлення і натисніть Надіслати
Параметри

Назад

Огляд теми (нові повідомленні вгорі)

nickjust
2025-08-26 18:01:49

Беремо оптопару з опто мишки
Принцип роботи: Кулко з прорізами обертається між ІЧ-випромінювачем та приймачем оптопари.
При кожному проходженні прорізу сигнал на піні змінюється (LOW - HIGH).
Вважаємо кількість імпульсів.
За замовчуванням: 1 імпульс = 1 проріз. Але нам потрібно: 1 оборот = N прорізів > калібрування.

Встанови через Arduino IDE > Скетч > Підключити бібліотеку > Керувати бібліотеками:
TM1637Display (автор: avishorp)
   
Як калібрувати:
Запусти пристрій. Повертай колесо рівно один оборот. Натисніть кнопку "Калібрування" - екран покаже "CAL". Зроби один повний оборот. Знову натисніть "Калібрування" - пристрій запам'ятає кількість імпульсів за оборот.

Або два датчики Холла, зсунуті по колу на 1/4 кроку між магнітами → вийде квадратурний сигнал.
Варіанти:
    Один магніт + два датчики - зміщені на 45-90 ° механічно

schet_20250826-1838.jpg


#include <TM1637Display.h>

// Пины
#define CLK 2
#define DIO 3
#define PIN_A 4
#define PIN_B 5
#define BTN_RESET 6
#define BTN_CAL 7

// TM1637 дисплей
TM1637Display display(CLK, DIO);

// Переменные
volatile long pulseCount = 0;        // счётчик импульсов
long revolutions = 0;                // количество оборотов
int pulsesPerRevolution = 24;        // калибровочное значение (по умолчанию 24 прорези на оборот)
bool calibrating = false;            // режим калибровки
unsigned long lastTime = 0;

// Предварительное объявление
void updateDisplay();
void ICACHE_RAM_ATTR onPulse();

void setup() {
  pinMode(PIN_A, INPUT_PULLUP);
  pinMode(PIN_B, INPUT_PULLUP);
  pinMode(BTN_RESET, INPUT_PULLUP);
  pinMode(BTN_CAL, INPUT_PULLUP);

  attachInterrupt(digitalPinToInterrupt(PIN_A), onPulse, CHANGE);
  attachInterrupt(digitalPinToInterrupt(PIN_B), onPulse, CHANGE);

  display.setBrightness(0x0f); // максимальная яркость

  Serial.begin(9600);
}

void loop() {
  static unsigned long lastDebounce = 0;
  int readingReset = digitalRead(BTN_RESET);
  int readingCal = digitalRead(BTN_CAL);

  // Кнопка сброса
  if (readingReset == LOW && millis() - lastDebounce > 200) {
    pulseCount = 0;
    revolutions = 0;
    updateDisplay();
    lastDebounce = millis();
  }

  // Кнопка калибровки
  if (readingCal == LOW && millis() - lastDebounce > 200) {
    calibrating = !calibrating;
    if (calibrating) {
      // Выводим "CAL" на дисплей
      uint8_t data[] = {0b00111001, 0b00001110, 0b00111001, 0b00111001}; // "CAL"
      display.setSegments(data);
    } else {
      // Выход из калибровки — считаем, что 1 оборот = текущее значение |pulseCount|
      if (abs(pulseCount) > 0) {
        pulsesPerRevolution = abs(pulseCount);
      }
      pulseCount = 0;
      revolutions = 0;
    }
    delay(300); // антидребезг
    lastDebounce = millis();
  }

  // Обновляем обороты раз в 100 мс
  if (millis() - lastTime > 100) {
    if (!calibrating) {
      revolutions = pulseCount / pulsesPerRevolution;
    }
    updateDisplay();
    lastTime = millis();
  }
}

// Обработка изменения сигнала на A или B
void ICACHE_RAM_ATTR onPulse() {
  static uint8_t lastState = 0;
  uint8_t state = (digitalRead(PIN_A) << 1) | digitalRead(PIN_B);

  if (state != lastState) {
    // Квадратурный декодер
    switch (lastState) {
      case 0b00:
        if (state == 0b01) pulseCount--;
        else if (state == 0b10) pulseCount++;
        break;
      case 0b01:
        if (state == 0b11) pulseCount--;
        else if (state == 0b00) pulseCount++;
        break;
      case 0b11:
        if (state == 0b10) pulseCount--;
        else if (state == 0b01) pulseCount++;
        break;
      case 0b10:
        if (state == 0b00) pulseCount--;
        else if (state == 0b11) pulseCount++;
        break;
    }
    lastState = state;
  }
}

// Обновление дисплея
void updateDisplay() {
  if (calibrating) return;

  // Показываем обороты (с учётом знака)
  char str[5];
  sprintf(str, "%4ld", revolutions);
  display.showNumberDec(revolutions, false, 4, 0);
}
Bird
2025-08-25 10:57:24

Для реалізації лічильника обертів із моторчика CD-ROM і виводу на TM1637, спершу переконайся, що мотор дає чіткі імпульси — краще використовувати енкодер. Підключи його до цифрових пінів, наприклад D2 і D3, і відстежуй зміну станів для визначення напрямку. Лічильник має інкрементуватися або декрементуватися, переходити з 9999 на 0000 і навпаки. Для скидання — окрема кнопка на піні, яка обнуляє значення. Використовуй бібліотеки TM1637Display та Encoder.

jokeer
2025-04-18 21:10:51

А ось деякі свої повідомлення я не бачу. Але якщо почну писати нове повідомлення, і натисну preview - тоді побачу wink

dimich
2025-04-18 20:32:29
jokeer пише:

а ось зрозуміти, як цей форум працює, що якісь повідомлення видно зразу, якісь ні..

Наскільки розумію, воно занадто рано створює посилання на нову сторінку стрічки (оті [ 1 2 3 4 ] вгорі біля теми), і при відповіді автоматично перекидає на ту неіснуючу сторінку. Якщо повернутись на попередню сторінку, то повідомлення стає видно.

АлександрK
2025-04-18 18:24:36
jokeR пише:

Того  ніхто не знає (ц) wink
Вдалось прочитати повідомлення?

так

jokeR
2025-04-18 18:19:32

Того  ніхто не знає (ц) wink
Вдалось прочитати повідомлення?

АлександрK
2025-04-18 18:14:26
jokeer пише:

Датчики то фігня, а ось зрозуміти, як цей форум працює, що якісь повідомлення видно зразу, якісь ні..

Цього я не знаю, як і багато іншого

jokeer
2025-04-18 17:58:11

Продублюю на всяк випадок wink
Ну, наче те що видно на фото співпадає з тим що намалював dimich Ж)
https://alexgyver.ru/encoder/ - наче все досить зрозуміло описано, і купа прикладів коду є. Беріть будь-який, прошивайте, дивіться чи працює як потрібно.

jokeer
2025-04-18 17:56:34

Датчики то фігня, а ось зрозуміти, як цей форум працює, що якісь повідомлення видно зразу, якісь ні..

jokeer
2025-04-18 17:54:10

Ну, наче те що видно на фото співпадає з тим що намалював dimich Ж)
https://alexgyver.ru/encoder/ - наче все досить зрозуміло описано, і купа прикладів коду є. Беріть будь-який, прошивайте, дивіться чи працює як потрібно.

АлександрK
2025-04-18 17:35:55
jokeer пише:

Ну, я вам не вірю wink але якщо ваші датчики дійсно так працюють, як ви стверджуєте, беріть той кусок коду що я нашкрябав. Для другого датчика так само, але counter --
Я попередив, за кожний оберт спрацюють обидва датчики по черзі, і лічильник не поміняє значення.

mini_Skize.jpeg

Світловий бар'єр 1 - OUT 1
Світловий бар'єр 2 - OUT 2

jokeer
2025-04-18 17:27:47

Треба випаяти датчики з модулів, запаяти в свою плату, і все влізе wink
Або прорізати 2 симертичні отвори, щоб баланс не ламався, а датчики розмістити трохи асиметрично, кожний поряд із своїм отвором, щоб послідовність спрацьовування була як на картинці. Але це знов буде зовсім неочевидно wink

dimich
2025-04-18 16:07:49
jokeer пише:

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

Та працюватиме і з такою конструкцією як у автора, тільки отвір має бути достатньої довжини, щоб обидва датчики могли бути активними одночасно.

jokeer пише:

Для 3 датчиків годяться руки будь-якої форми smile.

Судячи по фото, там і два ледве влізе, куди там третій. Там подвійний, як в кульковій миші, добре би вписався.

jokeer
2025-04-18 16:02:25

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

jokeer
2025-04-18 15:57:53

Велосипеди наше всьо wink Раз автор не загуглив, значить йому насправді хотілось чогось креативного wink
Енкодер річ прикольна, і правильна, я повністю згоден. але потрібно або 3д принтер, або досить прямі руки. Для 3 датчиків годяться руки будь-якої форми smile.

Підвал форуму