Как и больштнство "поверхностных" пользователей Windows 11 я не обратил особого внимания на программный Copilot. Но когда мой друг написал что экономит на нём кучу времени я подумал что наверное стоит попробовать. Для примера я вернулся к заброшенному прожекту поворотки с указателем на потенциометре. В своё время я его бросил как раз из-за недостатка времени и свежих идей - неточности в работе сильно раздражали. А "вычистить" логику и перевести в код без ошибок не хватило времени . А может терпения :-) Одним словом пробуем новое. Прошу копилота написать скетч для Ардуино чтобы вращал антенну:
Ответ второго пилота: Отличная задача — это классический пример системы с обратной связью: один потенциометр задаёт целевой угол (setpoint), второй измеряет фактическое положение (feedback), а мотор двигается до совпадения. Ниже приведён пример скетча для Arduino с использованием двух потенциометров, реле/драйвера мотора и LCD 16x2 (через библиотеку LiquidCrystal).
⚙️ Аппаратная схема (пример)
Pot1 (предустановка) → A0
Pot2 (датчик положения) → A1
Мотор → через драйвер (например, L298N или H-bridge) к пинам D8 и D9 (вперёд/назад)
LCD 16x2 → пины RS=12, E=11, D4=5, D5=4, D6=3, D7=2
📜 Код Arduino
#include <LiquidCrystal.h>
// LCD: RS, E, D4, D5, D6, D7
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
const int potSetPin = A0; // ведущий потенциометр (предустановка)
const int potRealPin = A1; // обратная связь (реальное положение)
const int motorPinFwd = 8; // мотор вперёд
const int motorPinRev = 9; // мотор назад
int setAngle = 0;
int realAngle = 0;
int deadZone = 3; // допуск в градусах
void setup() {
pinMode(motorPinFwd, OUTPUT);
pinMode(motorPinRev, OUTPUT);
lcd.begin(16, 2);
lcd.clear();
}
void loop() {
// Чтение потенциометров (0-1023) и преобразование в угол (0-180)
setAngle = map(analogRead(potSetPin), 0, 1023, 0, 360);
realAngle = map(analogRead(potRealPin), 0, 1023, 0, 360);
String direction = "STOP";
String motorStatus = "OFF";
// Управление мотором
if (abs(setAngle - realAngle) > deadZone) {
if (setAngle > realAngle) {
digitalWrite(motorPinFwd, HIGH);
digitalWrite(motorPinRev, LOW);
direction = "RIGHT";
motorStatus = "ON";
} else {
digitalWrite(motorPinFwd, LOW);
digitalWrite(motorPinRev, HIGH);
direction = "LEFT";
motorStatus = "ON";
}
} else {
digitalWrite(motorPinFwd, LOW);
digitalWrite(motorPinRev, LOW);
}
// Вывод на дисплей
lcd.setCursor(0, 0);
lcd.print("Set:");
lcd.print(setAngle);
lcd.print(" Real:");
lcd.print(realAngle);
lcd.setCursor(0, 1);
lcd.print("Dir:");
lcd.print(direction);
lcd.print(" M:");
lcd.print(motorStatus);
delay(200);
}
🖥️ Что будет на дисплее
Пример отображения:
Set:120 Real:115
Dir:RIGHT M:ONSet — предустановленный угол
Real — фактический угол
Dir — направление движения (LEFT/RIGHT/STOP)
M — статус мотора (ON/OFF)
К момему удивлению скетч заработал сразу и правильно. Единственное замечание было к тому что он не знал, что у меня реле c отрицательной логикой и естествеено вкл/выкл мотора, а точнее влево/вправо после остановки оставались включенными. И еще забыл ему сказать что дисплей подключен по I2C. Задаю исправления которые надо внести:Ответ второго пилота: Понял 👍. Если у вас дисплей по I²C, нужно использовать библиотеку LiquidCrystal_I2C. А для «замедления без PWM» можно сделать пошаговое движение: мотор включается короткими импульсами с паузами, и чем ближе к целевому углу — тем длиннее пауза. Это даст эффект замедления без использования ШИМ.
📜 Обновлённый скетч
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Адрес может быть 0x27 или 0x3F — зависит от модуля
LiquidCrystal_I2C lcd(0x27, 16, 2);
const int potSetPin = A0; // ведущий потенциометр (предустановка)
const int potRealPin = A1; // обратная связь (реальное положение)
const int motorPinFwd = 8; // мотор вперёд
const int motorPinRev = 9; // мотор назад
int setAngle = 0;
int realAngle = 0;
int deadZone = 2; // допуск в градусах
void setup() {
pinMode(motorPinFwd, OUTPUT);
pinMode(motorPinRev, OUTPUT);
lcd.init();
lcd.backlight();
lcd.clear();
}
void loop() {
// Чтение потенциометров (0-1023) и преобразование в угол (0-360)
setAngle = map(analogRead(potSetPin), 0, 1023, 0, 360);
realAngle = map(analogRead(potRealPin), 0, 1023, 0, 360);
String direction = "STOP";
String motorStatus = "OFF";
int diff = setAngle - realAngle;
if (abs(diff) > deadZone) {
motorStatus = "ON";
if (diff > 0) {
direction = "RIGHT";
digitalWrite(motorPinFwd, HIGH);
digitalWrite(motorPinRev, LOW);
} else {
direction = "LEFT";
digitalWrite(motorPinFwd, LOW);
digitalWrite(motorPinRev, HIGH);
}
// Эффект замедления: чем ближе к цели, тем длиннее пауза
int pauseTime = map(abs(diff), 0, 180, 200, 20);
delay(pauseTime);
// Короткий импульс
digitalWrite(motorPinFwd, LOW);
digitalWrite(motorPinRev, LOW);
delay(pauseTime);
} else {
digitalWrite(motorPinFwd, LOW);
digitalWrite(motorPinRev, LOW);
}
// Вывод на дисплей
lcd.setCursor(0, 0);
lcd.print("Set:");
lcd.print(setAngle);
lcd.print(" Real:");
lcd.print(realAngle);
lcd.print(" "); // очистка хвоста
lcd.setCursor(0, 1);
lcd.print("Dir:");
lcd.print(direction);
lcd.print(" M:");
lcd.print(motorStatus);
lcd.print(" "); // очистка хвоста
}
🔑 Что изменилось
ИспользуетсяLiquidCrystal_I2C для работы с дисплеем.Добавлен «пошаговый» режим: мотор включается короткими импульсами, а пауза зависит от разницы углов.Чем ближе к цели, тем дольше пауза → мотор замедляется.
// Чтение потенциометров (0-1023) и преобразование в угол (0-360)
setAngle = map(analogRead(potSetPin), 0, 910(1023), 0, 360);
realAngle = map(analogRead(potRealPin), 0, 910(1023), 0, 360);





























