Ви не увійшли.
Сторінки 1
Я рахую,тре всьо спробувати...та вчитися!
І краще розмовляти з ШІ ніж з їбаньками з форумів,таких як Радіокот (правда там є і нормальні)
Мені ще подобається Чорний форум - також норм допомогають.
І ще замічаю ,що інет став нууу дуже грошовий ....усі кинулися заробляти...за прошивку 2017 року ,яка нещо давно вільно була на оффсайті Acer хотят гроші....гроші....гроші....
шановний nickjust ви знаєте когось хто може виконати роботу за гроші? ключове це виконати, а не консультувати або подивитися скетч. Я в Києві. Дякую
На сьогодні єнкодер видає 10 імпульсів на оборот. Стоїть резистор 10кОм + конденсатори 0.1 мкФ на A (A → GND)
Є скетч для керування мотором та підтримкою швидкості Але двигун не підтримує швидкість. Постійно крутиться з максимальною швидкістю
/*
* Мотор + энкодер 10 PPR
* Стабильный расчёт RPM (среднее за 1 секунду + сглаживание)
* Arduino Uno
* Энкодер: A→2, B→4, Vcc→5V, GND→GND
* Мотор (L298N): IN1→10, IN2→11, ENA→9
*/
// ====================== ПИНЫ ======================
#define ENC_A 2
#define ENC_B 4
#define MOTOR_1 10
#define MOTOR_2 11
#define MOTOR_PWM 9
// ====================== КОНСТАНТЫ ЭНКОДЕРА ======================
const int PULSES_PER_REV = 10; // импульсов за один оборот
// ====================== ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ ======================
volatile long totalPulses = 0; // суммарное количество импульсов
volatile int lastEncA = HIGH; // предыдущее состояние канала A
volatile unsigned long lastIntTime_us = 0;
const unsigned long DEBOUNCE_us = 5000; // 5 мс антидребезг
long revolutions = 0; // totalPulses / 10 (целые обороты)
// ---- Переменные для RPM (стабильный расчёт) ----
unsigned long lastRpmTime_ms = 0;
long prevTotalPulses = 0;
float smoothRPM = 0.0;
const float RPM_SMOOTH = 0.1; // сильное сглаживание (0..1)
const unsigned long RPM_INTERVAL_ms = 1000; // интервал измерения 1 секунда
// ---- Управление мотором ----
int targetRevolutions = 0; // 0 – бесконечно, иначе остановить по достижении
bool motorEnabled = false;
int currentSpeed = 200; // текущая скорость (0-255)
bool rpmVisible = true; // показывать RPM в логе
// ====================== SETUP ======================
void setup() {
Serial.begin(9600);
// Энкодер
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENC_A), encoderISR, CHANGE);
/*
* Мотор + энкодер 10 PPR + П-регулятор скорости
* Поддерживает заданные обороты в минуту (RPM)
*/
#define ENC_A 2
#define ENC_B 4
#define MOTOR_1 10
#define MOTOR_2 11
#define MOTOR_PWM 9
const int PULSES_PER_REV = 10;
volatile long totalPulses = 0;
volatile int lastEncA = HIGH;
volatile unsigned long lastIntTime_us = 0;
const unsigned long DEBOUNCE_us = 5000;
long revolutions = 0;
unsigned long lastRpmTime_ms = 0;
long prevTotalPulses = 0;
float smoothRPM = 0.0;
const float RPM_SMOOTH = 0.1;
const unsigned long RPM_INTERVAL_ms = 1000;
bool motorEnabled = false;
int currentSpeed = 0; // текущая ШИМ (0-255)
float targetRPM = 0.0; // целевая скорость (0 = выкл)
float Kp = 2.0; // коэффициент П-регулятора (настраивается)
const int minPWM = 0;
const int maxPWM = 255;
void setup() {
Serial.begin(9600);
pinMode(ENC_A, INPUT_PULLUP);
pinMode(ENC_B, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENC_A), encoderISR, CHANGE);
pinMode(MOTOR_1, OUTPUT);
pinMode(MOTOR_2, OUTPUT);
pinMode(MOTOR_PWM, OUTPUT);
stopMotor();
Serial.println(F("=== ПИД-регулятор скорости (П-регулятор) ==="));
Serial.println(F("Команды:"));
Serial.println(F(" r <об/мин> - установить целевую скорость, например r100"));
Serial.println(F(" s - стоп"));
Serial.println(F(" k <коэфф> - изменить Kp (по умолч. 2.0)"));
Serial.println(F(" status - показать параметры"));
Serial.println();
}
void loop() {
// Обновление счётчика оборотов
long newRevs = totalPulses / PULSES_PER_REV;
if (newRevs != revolutions) revolutions = newRevs;
// Расчёт RPM (раз в секунду)
unsigned long now = millis();
if (now - lastRpmTime_ms >= RPM_INTERVAL_ms) {
long delta = totalPulses - prevTotalPulses;
float revs = (float)delta / PULSES_PER_REV;
float sec = (now - lastRpmTime_ms) / 1000.0;
float instant = (revs / sec) * 60.0;
if (instant < 0) instant = -instant;
if (smoothRPM < 0.1) smoothRPM = instant;
else smoothRPM = RPM_SMOOTH * instant + (1 - RPM_SMOOTH) * smoothRPM;
prevTotalPulses = totalPulses;
lastRpmTime_ms = now;
}
// П-регулятор: подстраиваем ШИМ, чтобы smoothRPM стремился к targetRPM
if (targetRPM > 0 && motorEnabled) {
float error = targetRPM - smoothRPM;
int newPWM = constrain(currentSpeed + Kp * error, minPWM, maxPWM);
if (newPWM != currentSpeed) {
// Сохраняем направление (определяем по текущим выходам)
bool forward = (digitalRead(MOTOR_1) == HIGH && digitalRead(MOTOR_2) == LOW);
setMotor(newPWM, forward);
}
}
// Вывод состояния (каждые 200 мс)
static unsigned long lastPrint = 0;
if (now - lastPrint >= 200) {
Serial.print(F("Об.: ")); Serial.print(revolutions);
Serial.print(F(" имп.: ")); Serial.print(totalPulses % PULSES_PER_REV);
Serial.print(F(" RPM: ")); Serial.print(smoothRPM, 1);
if (targetRPM > 0) {
Serial.print(F(" / целевая: ")); Serial.print(targetRPM, 1);
Serial.print(F(" ШИМ: ")); Serial.print(currentSpeed);
}
Serial.println();
lastPrint = now;
}
// Обработка команд
if (Serial.available()) {
String cmd = Serial.readStringUntil('n');
cmd.trim();
parseCommand(cmd);
}
delay(1);
}
void encoderISR() {
unsigned long now = micros();
if (now - lastIntTime_us < DEBOUNCE_us) return;
lastIntTime_us = now;
int a = digitalRead(ENC_A);
int b = digitalRead(ENC_B);
if (a != lastEncA) {
if (a == b) totalPulses++;
else totalPulses--;
lastEncA = a;
}
}
void setMotor(int speed, bool forward) {
speed = constrain(speed, 0, 255);
currentSpeed = speed;
if (speed == 0) { stopMotor(); return; }
digitalWrite(MOTOR_1, forward ? HIGH : LOW);
digitalWrite(MOTOR_2, forward ? LOW : HIGH);
analogWrite(MOTOR_PWM, speed);
motorEnabled = true;
}
void stopMotor() {
digitalWrite(MOTOR_1, LOW);
digitalWrite(MOTOR_2, LOW);
analogWrite(MOTOR_PWM, 0);
motorEnabled = false;
targetRPM = 0;
currentSpeed = 0;
}
void parseCommand(String cmd) {
if (cmd.length() == 0) return;
char first = cmd.charAt(0);
if (first == 'r') {
float rpm = cmd.substring(1).toFloat();
if (rpm > 0) {
targetRPM = rpm;
// Запускаем мотор с текущим ШИМ (можно начать с любого, например 100)
if (!motorEnabled) setMotor(100, true);
Serial.print(F("Целевая скорость установлена: "));
Serial.print(targetRPM);
Serial.println(F(" об/мин"));
} else {
targetRPM = 0;
stopMotor();
Serial.println(F("Регулятор отключён"));
}
}
else if (first == 's') {
stopMotor();
Serial.println(F("Стоп"));
}
else if (first == 'k') {
float newK = cmd.substring(1).toFloat();
if (newK >= 0) {
Kp = newK;
Serial.print(F("Kp = "));
Serial.println(Kp);
}
}
else if (cmd.equalsIgnoreCase("status")) {
Serial.print(F("Оборотов: ")); Serial.print(revolutions);
Serial.print(F(", RPM: ")); Serial.print(smoothRPM, 1);
Serial.print(F(", целевая: ")); Serial.print(targetRPM, 1);
Serial.print(F(", ШИМ: ")); Serial.print(currentSpeed);
Serial.print(F(", Kp: ")); Serial.println(Kp);
}
else {
Serial.println(F("Команды: r<об/мин>, s, k<коэфф>, status"));
}
}
В результаті
Целевая скорость установлена: 100.00 об/мин
Об.: 0 имп.: 1 RPM: 0.0 / целевая: 100.0 ШИМ: 255
Об.: 0 имп.: 1 RPM: 0.0 / целевая: 100.0 ШИМ: 255
Об.: 0 имп.: 1 RPM: 0.0 / целевая: 100.0 ШИМ: 255
Мені потрібне точне регулювання обертів, і саме енкодер.
Можливо, проблема саме в цьому енкодері? Чи є досвід використання якоїсь іншої моделі?
Дякую
1. Користуюся готовими бібліотеками. + gpt + cloud + gemini + copilot
2. Швидкість обертання вала 30–300 об/хв
3. Отримані сигнали використовую для обчислення швидкості обертання вала.

Поки що я зупинився на тому, що енкодер неправильно підраховує оберти.
Якщо відома кількість імпульсів N і кількість імпульсів на один оберт PPR: Оберти = N/PPR
На енкодері вказано Resolution 10P/R, а насправді це генератор випадкових чисел.
Тобто на один механічний оберт вала енкодера Omron E6B2-CWZ6C щоразу видає нове значення.
Виходи Чорний (Канал A) і Білий (Канал B) підключені через зовнішній pull-up резистор 10 кОм до +5V
не варто сміятися. можете допомогти?
Потрібно написати скетч і налаштувати обладнання
Завдання: Написати повний робочий скетч і налаштувати обладнання, для Arduino UNO, що керує електродвигуном із зворотним зв’язком через енкодер.
ЛОГІКА РОБОТИ:
1. Задається цільова швидкість електродвигуна
2. Енкодер на валу двигуна підраховує кількість імпульсів за заданий інтервал часу.
3. За даними енкодера розраховується поточна швидкість обертання двигуна.
4. ПІД-регулятор порівнює поточну швидкість двигуна з цільовою і обчислює керуючий вплив.
5. ШІМ-сигнал подається на драйвер двигуна для регулювання швидкості.
6. Значення відображаються на LCD 2004:
7. Усі дані записуються на карту пам'яті
Сторінки 1