11.07.2023

Керування поворотом антени з комп'ютера

Павло Бурдяк               Часть друга. Див. часть 1 тут

Для керування двигуном редуктором ПР-1М нам необхідно Arduino Mega або Uno та Ethernet шилд W5100 а також блок подвійного реле з низьким рівнем управління.

Двигун підключається по штатній схемі але замість кнопок використовується контакти реле.  Для керування азимутом за допомогою комп'ютера необхідно :
- Зібрати та підключити схему
  • - Взнати присвоєний IP адрес програмою Advanced IP Scanner
  • - В скетчі вписати свої МАС та ІР адреса
  • - Залити прошивку в Arduino
  • - В адресній строці браузера вбиваємо наш IP адрес і ми побачимо вікно з азимутом і двома кнопками від 0 до 360 градусів і від 360 градусів до 0
· Arduino та комп'ютер повинні знаходитись в одній мережі.
Живлення Arduino 5 Вольт.
·Для відображення азимута використовується вбудований в редуктор змінний резистор 200 Ом .

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

 В коді прописаний експоненціальний коефіцієнт необхідний для того щоб можна було змінювати чутливість А0 (показання азимута), в даному випадку стоїть коефіцієнт 0.2 .

Даний пристрій має інерційність, тобто після відпускання кнопки антена буде повертатися ще декілька градусів . Необхідно звернути увагу , що редуктор обертається на 180 градусів і для обертання на 360 потрібно робити передачу 1 : 2.

Скетч скачать - Antena_WEB-3

Ось пояснення для кожної частини коду:
---
#include <SPI.h>
#include <Ethernet.h>
Ці рядки підключають необхідні бібліотеки SPI і Ethernet.


---
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 0, 14);
unsigned int port = 80;
EthernetServer server(port);
Тут визначаються змінні для мак-адреси, IP-адреси, порту та об'єкту EthernetServer.

---
const int analogInputPin = A0;
const int relayPin1 = 7;
const int relayPin2 = 8;
bool relayState1 = false;
bool relayState2 = false;
unsigned long lastUpdateTime = 0;
Тут визначаються змінні для піну аналогового входу, пінів реле, станів реле та останнього часу оновлення.


---
void setup() {
  Ethernet.begin(mac, ip);
  server.begin();
  pinMode(relayPin1, OUTPUT);
  pinMode(relayPin2, OUTPUT);
  digitalWrite(relayPin1, HIGH);
  digitalWrite(relayPin2, HIGH);
  Serial.begin(9600);
  Serial.print("Server IP address: ");
  Serial.println(Ethernet.localIP());
}
У функції setup() встановлюються початкові налаштування: ініціалізується Ethernet, встановлюються режими пінів реле, встановлюються початкові стани реле, ініціалізується Serial та виводиться IP-адреса сервера на Serial монітор.

---
void loop() {
  EthernetClient client = server.available();
  
  if (client) {
    Serial.println("New client connected");
    
    String request = client.readStringUntil('\r');
    client.flush();
    
    if (request.indexOf("/toggle") != -1) {
      handleToggleRequest(request);
    }
    
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println("Connection: close");
    client.println();
    client.print(webpage);
    
    client.flush();
    client.stop();
  }
  
  int sensorValue = analogRead(analogInputPin);
  int degrees = map(sensorValue, 0, 1023, 0, 360);
  String updatedAzimuthValue = String(degrees);
  
  // Код для оновлення сторінки з використанням AJAX
  
  webpage = updatedWebpage;
}
Основна функція loop() виконується постійно. Вона перевіряє наявність підключених клієнтів, зчитує їх запити, обробляє команди toggle та відправляє відповідь клієнту. Потім вимірюється значення сенсора, конвертується в градуси азимуту та оновлюється сторінка.


---
void handleToggleRequest(const String& request) {
  if (request.indexOf("?relay=1") != -1) {
    toggleRelay(1);
  } else if (request.indexOf("?relay=2") != -1) {
    toggleRelay(2);
  }
}
Функція handleToggleRequest() обробляє запити на перемикання реле залежно від переданих параметрів.


---
void toggleRelay(int relayNumber) {
  if (relayNumber == 1) {
    relayState1 = !relayState1;
    digitalWrite(relayPin1, relayState1 ? LOW : HIGH);
  } else if (relayNumber == 2) {
    relayState2 = !relayState2;
    digitalWrite(relayPin2, relayState2 ? LOW : HIGH);
  }
}
Функція toggleRelay() перемикає стан реле залежно від переданого номера реле.



Ось оновлений код з детальними коментарями:
cpp
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 0, 14);
unsigned int port = 80;
EthernetServer server(port);

const int analogInputPin = A0;
const int relayPin1 = 7;
const int relayPin2 = 8;
bool relayState1 = false;
bool relayState2 = false;
unsigned long lastUpdateTime = 0;

String webpage = "";

void setup() {
  Ethernet.begin(mac, ip);
  server.begin();
  pinMode(relayPin1, OUTPUT);
  pinMode(relayPin2, OUTPUT);
  digitalWrite(relayPin1, HIGH);
  digitalWrite(relayPin2, HIGH);
  Serial.begin(9600);
  Serial.print("Server IP address: ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  EthernetClient client = server.available();

  if (client) {
    Serial.println("New client connected");

    String request = client.readStringUntil('\r');
    client.flush();

    if (request.indexOf("/toggle") != -1) {
      handleToggleRequest(request); // Обробка запиту на перемикання реле
    }

    // Відправка відповіді клієнту
    client.println("HTTP/1.1 200 OK");
    client.println("Content-Type: text/html");
    client.println("Connection: close");
    client.println();
    client.print(webpage);

    client.flush();
    client.stop();
  }

  int sensorValue = analogRead(analogInputPin);
  int degrees = map(sensorValue, 0, 1023, 0, 360);
  String updatedAzimuthValue = String(degrees);

  // Код для оновлення сторінки з використанням AJAX

  webpage = updatedWebpage;
}

void handleToggleRequest(const String& request) {
  if (request.indexOf("?relay=1") != -1) {
    toggleRelay(1); // Перемикання першого реле
  } else if (request.indexOf("?relay=2") != -1) {
    toggleRelay(2); // Перемикання другого реле
  }
}

void toggleRelay(int relayNumber) {
  if (relayNumber == 1) {
    relayState1 = !relayState1;
    digitalWrite(relayPin1, relayState1 ? LOW : HIGH); // Встановлення стану першого реле
  } else if (relayNumber == 2) {
    relayState2 = !relayState2;
    digitalWrite(relayPin2, relayState2 ? LOW : HIGH); // Встановлення стану другого реле
  }
}