Управление на ATmega328p чрез серийна комуникация

Управление на ATmega328p чрез серийна комуникация

Въведение

Серийната комуникация е основа за взаимодействие между микроконтролери и външни устройства. Тя позволява обмен на данни чрез прост и надежден протокол, подходящ за множество приложения. В тази статия ще разгледаме как да използваме серийна комуникация за управление на платка, базирана на ATmega328p с Arduino UNO Bootloader (разгледайте подробното описание в статията). Ще демонстрираме основни и напреднали функционалности като управление на изходи, PWM сигнали и аналогово изчитане през серийна комуникация. Вече се запознахме с основите в този вид комуникация в статията ни: Серийна комуникация с Arduino UNO чрез USB или Bluetooth HC-05.

Проектът предоставя метод за управление на пиновете на ATmega328p чрез серийни команди, които могат да се изпращат както ръчно през терминал, така и автоматизирано чрез скриптове на Python или Shell. Това го прави изключително подходящ за различни приложения като домашна автоматизация, учебни проекти или прототипи. За осъществяване на комуникацията между компютъра и микроконтролера ще използваме USB-TTL конвертор, което осигурява лесна и надеждна връзка.

Този проект е създаден не толкова от практическа гледна точка, колкото с идеята да разберем какво точно представлява серийната комуникация и какво може да се управлява с нея!

Код за управление на ATmega328p чрез серийна комуникация

String command;
int pin0PWM = 0;
int pin1PWM = 0;
int pin2PWM = 0;

const int ledPin = 7;
int ledState = LOW;
unsigned long previousMillis = 0;
unsigned long interval = 1000;

// =================( PIN-0 / D-6 / PWM )====================
void pin0(void) {
  if (command == "pin0 OUT") {
    pinMode(6, OUTPUT);
    Serial.println("pin(0) is Output Pin");
  } else if (command == "pin0 UP") {
    digitalWrite(6, HIGH);
    Serial.println("pin(0) is UP");
  } else if (command == "pin0 DOWN") {
    digitalWrite(6, LOW);
    Serial.println("pin(0) is DOWN");
  } else if (command == "pin0 IN") {
    pinMode(6, INPUT);
    Serial.println("pin(0) is Input pin");
  } else if (command == "pin0 read") {
    Serial.print("pin0 status = ");
    Serial.println(digitalRead(6));
  } else if (command == "pin0 PWM") {
    pinMode(6, OUTPUT);
    digitalWrite(6, LOW);
    Serial.println("pin(0) is PWM pin");
  } else if (command == "pin0 setPWM") {
    for (int i = 0; i < 5; i++) {
      Serial.println("enter PWM value for pin(0)");
      while (Serial.available() == 0) {} // Wait for input
      char c = Serial.read();
      pin0PWM = (c - '0') * 51;

      if (pin0PWM >= 0 && pin0PWM <= 255) {
        analogWrite(6, pin0PWM);
        Serial.print("pin(0) set to = ");
        Serial.println(pin0PWM);
        break;
      }
      delay(500);
    }
  }
}

// ==========( PIN-1 / D-5 / PWM)================
void pin1(void) {
  if (command == "pin1 OUT") {
    pinMode(5, OUTPUT);
    Serial.println("pin(1) is Output Pin");
  } else if (command == "pin1 UP") {
    digitalWrite(5, HIGH);
    Serial.println("pin(1) is UP");
  } else if (command == "pin1 DOWN") {
    digitalWrite(5, LOW);
    Serial.println("pin(1) is DOWN");
  } else if (command == "pin1 IN") {
    pinMode(5, INPUT);
    Serial.println("pin(1) is Input pin");
  } else if (command == "pin1 read") {
    Serial.print("pin1 status = ");
    Serial.println(digitalRead(5));
  } else if (command == "pin1 PWM") {
    pinMode(5, OUTPUT);
    digitalWrite(5, LOW);
    Serial.println("pin(1) is PWM pin");
  } else if (command == "pin1 setPWM") {
    for (int i = 0; i < 5; i++) {
      Serial.println("enter PWM value for pin(1)");
      while (Serial.available() == 0) {} // Wait for input
      char c = Serial.read();
      pin1PWM = (c - '0') * 51;

      if (pin1PWM >= 0 && pin1PWM <= 255) {
        analogWrite(5, pin1PWM);
        Serial.print("pin(1) set to = ");
        Serial.println(pin1PWM);
        break;
      }
      delay(500);
    }
  }
}

// ===============( PIN-2 / D-9 / PWM)==================
void pin2(void) {
  if (command == "pin2 OUT") {
    pinMode(9, OUTPUT);
    Serial.println("pin(2) is Output Pin");
  } else if (command == "pin2 UP") {
    digitalWrite(9, HIGH);
    Serial.println("pin(2) is UP");
  } else if (command == "pin2 DOWN") {
    digitalWrite(9, LOW);
    Serial.println("pin(2) is DOWN");
  } else if (command == "pin2 IN") {
    pinMode(9, INPUT);
    Serial.println(" pin(2) is Input pin");
  } else if (command == "pin2 read") {
    Serial.print("pin2 status = ");
    Serial.println(digitalRead(9));
  } else if (command == "pin2 PWM") {
    pinMode(9, OUTPUT);
    digitalWrite(9, LOW);
    Serial.println("pin(2) is PWM pin");
  } else if (command == "pin2 setPWM") {
    for (int i = 0; i < 5; i++) {
      Serial.println("enter PWM value for pin(2)");
      while (Serial.available() == 0) {} // Wait for input
      char c = Serial.read();
      pin2PWM = (c - '0') * 51;

      if (pin2PWM >= 0 && pin2PWM <= 255) {
        analogWrite(9, pin2PWM);
        Serial.print("pin(2) set to = ");
        Serial.println(pin2PWM);
        break;
      }
      delay(500);
    }
  }
}

// ==============( PIN-3 / D-10 )====================
void pin3(void) {
  if (command == "pin3 OUT") {
    pinMode(10, OUTPUT);
    Serial.println("pin(3) is Output Pin");
  } else if (command == "pin3 UP") {
    digitalWrite(10, HIGH);
    Serial.println("pin(3) is UP");
  } else if (command == "pin3 DOWN") {
    digitalWrite(10, LOW);
    Serial.println("pin(3) is DOWN");
  } else if (command == "pin3 IN") {
    pinMode(10, INPUT);
    Serial.println("pin(3) is Input pin");
  } else if (command == "pin3 READ") {
    Serial.print("pin3 status = ");
    Serial.println(digitalRead(10));
  } else if (command == "pin3 PWM") {
    Serial.println("pin(3) not support PWM mode");
  }
}

// ==============( PIN-4 / D-11 )===============
void pin4(void) {
  if (command == "pin4 OUT") {
    pinMode(11, OUTPUT);
    Serial.println("pin(4) is Output Pin");
  } else if (command == "pin4 UP") {
    digitalWrite(11, HIGH);
    Serial.println("pin(4) is UP");
  } else if (command == "pin4 DOWN") {
    digitalWrite(11, LOW);
    Serial.println("pin(4) is DOWN");
  } else if (command == "pin4 IN") {
    pinMode(11, INPUT);
    Serial.println("pin(4) is Input pin");
  } else if (command == "pin4 READ") {
    Serial.print("pin4 status = ");
    Serial.println(digitalRead(11));
  } else if (command == "pin4 PWM") {
    Serial.println("pin(4) not support PWM mode");
  }
}

// ==============( PIN-5 / D-12 )================
void pin5(void) {
  if (command == "pin5 OUT") {
    pinMode(12, OUTPUT);
    Serial.println("pin(5) is Output Pin");
  } else if (command == "pin5 UP") {
    digitalWrite(12, HIGH);
    Serial.println("pin(5) is UP");
  } else if (command == "pin5 DOWN") {
    digitalWrite(12, LOW);
    Serial.println("pin(5) is DOWN");
  } else if (command == "pin5 IN") {
    pinMode(12, INPUT);
    Serial.println("pin(5) is Input pin");
  } else if (command == "pin5 READ") {
    Serial.print("pin5 status = ");
    Serial.println(digitalRead(12));
  } else if (command == "pin5 PWM") {
    Serial.println("pin(5) not support PWM mode");
  }
}

// ================( PIN-A0 )==============
void A0read(void) {
  if (command == "pinA0 read") {
    Serial.print("pinA0 = ");
    Serial.println(analogRead(A0));
  } else if (command == "pinA0 read int") {
    Serial.println(analogRead(A0));
  }
}

// =============( PIN-A1 )===============
void A1read(void) {
  if (command == "pinA1 read") {
    Serial.print("pinA1 = ");
    Serial.println(analogRead(A1));
  } else if (command == "pinA1 read int") {
    Serial.println(analogRead(A1));
  }
}

// ===============( PIN-A2 )===============
void A2read(void) {
  if (command == "pinA2 read") {
    Serial.print("pinA2 = ");
    Serial.println(analogRead(A2));
  } else if (command == "pinA2 read int") {
    Serial.println(analogRead(A2));
  }
}

// ==============( PIN-A3 )===============
void A3read(void) {
  if (command == "pinA3 read") {
    Serial.print("pinA3 = ");
    Serial.println(analogRead(A3));
  } else if (command == "pinA3 read int") {
    Serial.println(analogRead(A3));
  }
}

// ==============( PIN-A4 )==============
void A4read(void) {
  if (command == "pinA4 read") {
    Serial.print("pinA4 = ");
    Serial.println(analogRead(A4));
  } else if (command == "pinA4 read int") {
    Serial.println(analogRead(A4));
  }
}

// ===============( PIN-A5 )==============
void A5read(void) {
  if (command == "pinA5 read") {
    Serial.print("pinA5 = ");
    Serial.println(analogRead(A5));
  } else if (command == "pinA5 read int") {
    Serial.println(analogRead(A5));
  }
}

// =====================================================
void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {
    command = Serial.readStringUntil('\n');

    pin0();
    pin1();
    pin2();
    pin3();
    pin4();
    pin5();

    A0read();
    A1read();
    A2read();
    A3read();
    A4read();
    A5read();
  }

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    ledState = (ledState == LOW) ? HIGH : LOW;
    digitalWrite(ledPin, ledState);
  }
}

Обяснение на кода

Главни променливи и настройки

  • String command: Използва се за съхранение на входящата команда от серийната комуникация.
  • int pin0PWM, pin1PWM, pin2PWM: Променливи за стойности на PWM сигнали за пинове 0, 1 и 2.
  • const int ledPin: Светодиод, който мига за индикация.
  • unsigned long previousMillis, interval: Таймер за управление на мигащия светодиод. Този метод го разгледахме в статията ни: Arduino мигане без закъснение “Blink Without Delay”.

Функции за управление на пинове

pin0(), pin1(), pin2():

Тези функции обработват входни команди за пиновете 6, 5 и 9 (съответстващи на pin0, pin1 и pin2). Те поддържат следните операции:

  • OUT: Настройка на пина като изход.
  • IN: Настройка на пина като вход.
  • UP/DOWN: Активиране/деактивиране на пина (HIGH/LOW).
  • read: Чете текущото състояние на пина.
  • PWM: Настройка на PWM режим и подаване на стойности (0-5 = 0, 51, 102, 153, 204, 255).

pin3(), pin4(), pin5():

Подобно на pin0pin2, но пинове 10, 11 и 12 нямат поддръжка на PWM.

A0read() до A5read():

Четене на аналоговите пинове A0 до A5. Поддържат:

  • pinA“x” read: Прочита стойност на аналоговия сигнал. Върнат отговор: “pinA0 = 318″
  • pinA“x” read int: Прочита стойност в целочислен формат.Върнат отговор: “318

Функции setup() и loop()

  • setup(): Инициализира серийната комуникация и светодиода.
  • loop(): Проверява за входни команди, извиква съответните функции за пинове и управлява мигащия светодиод.

Команди за управление

Команди за управление на цифрови пинове (PIN-0 до PIN-5):

PIN-0 (D-6)

  • pin0 OUT – Настройка на PIN-0 (D-6) като изход.
  • pin0 UP – Включване на PIN-0 (D-6).
  • pin0 DOWN – Изключване на PIN-0 (D-6).
  • pin0 IN – Настройка на PIN-0 (D-6) като вход.
  • pin0 read – Четене на цифровото състояние на PIN-0 (D-6).
  • pin0 PWM – Настройка на PIN-0 (D-6) за PWM.
  • pin0 setPWM – Въвеждане на стойност за PWM за PIN-0 (D-6).

PIN-1 (D-5)

  • pin1 OUT – Настройка на PIN-1 (D-5) като изход.
  • pin1 UP – Включване на PIN-1 (D-5).
  • pin1 DOWN – Изключване на PIN-1 (D-5).
  • pin1 IN – Настройка на PIN-1 (D-5) като вход.
  • pin1 read – Четене на цифровото състояние на PIN-1 (D-5).
  • pin1 PWM – Настройка на PIN-1 (D-5) за PWM.
  • pin1 setPWM – Въвеждане на стойност за PWM за PIN-1 (D-5).

PIN-2 (D-9)

  • pin2 OUT – Настройка на PIN-2 (D-9) като изход.
  • pin2 UP – Включване на PIN-2 (D-9).
  • pin2 DOWN – Изключване на PIN-2 (D-9).
  • pin2 IN – Настройка на PIN-2 (D-9) като вход.
  • pin2 read – Четене на цифровото състояние на PIN-2 (D-9).
  • pin2 PWM – Настройка на PIN-2 (D-9) за PWM.
  • pin2 setPWM – Въвеждане на стойност за PWM за PIN-2 (D-9).

PIN-3 (D-10)

  • pin3 OUT – Настройка на PIN-3 (D-10) като изход.
  • pin3 UP – Включване на PIN-3 (D-10).
  • pin3 DOWN – Изключване на PIN-3 (D-10).
  • pin3 IN – Настройка на PIN-3 (D-10) като вход.
  • pin3 READ – Четене на цифровото състояние на PIN-3 (D-10).
  • pin3 PWM – Известие, че PIN-3 не поддържа PWM режим.

PIN-4 (D-11)

  • pin4 OUT – Настройка на PIN-4 (D-11) като изход.
  • pin4 UP – Включване на PIN-4 (D-11).
  • pin4 DOWN – Изключване на PIN-4 (D-11).
  • pin4 IN – Настройка на PIN-4 (D-11) като вход.
  • pin4 READ – Четене на цифровото състояние на PIN-4 (D-11).
  • pin4 PWM – Известие, че PIN-4 не поддържа PWM режим.

PIN-5 (D-12)

  • pin5 OUT – Настройка на PIN-5 (D-12) като изход.
  • pin5 UP – Включване на PIN-5 (D-12).
  • pin5 DOWN – Изключване на PIN-5 (D-12).
  • pin5 IN – Настройка на PIN-5 (D-12) като вход.
  • pin5 READ – Четене на цифровото състояние на PIN-5 (D-12).
  • pin5 PWM – Известие, че PIN-5 не поддържа PWM режим.

Команди за четене на аналогови пинове (A0 до A5):

  • pinA0 read – Четене на аналоговата стойност на A0.
  • pinA0 read int – Четене на аналоговата стойност на A0 и извеждане на целочислената стойност.
  • pinA1 read – Четене на аналоговата стойност на A1.
  • pinA1 read int – Четене на аналоговата стойност на A1 и извеждане на целочислената стойност.
  • pinA2 read – Четене на аналоговата стойност на A2.
  • pinA2 read int – Четене на аналоговата стойност на A2 и извеждане на целочислената стойност.
  • pinA3 read – Четене на аналоговата стойност на A3.
  • pinA3 read int – Четене на аналоговата стойност на A3 и извеждане на целочислената стойност.
  • pinA4 read – Четене на аналоговата стойност на A4.
  • pinA4 read int – Четене на аналоговата стойност на A4 и извеждане на целочислената стойност.
  • pinA5 read – Четене на аналоговата стойност на A5.
  • pinA5 read int – Четене на аналоговата стойност на A5 и извеждане на целочислената стойност.

Платки на проекта за управление на ATmega328p чрез серийна комуникация

Схема на управление на ATmega328p чрез серийна комуникация

Управление-на-ATmega328p-чрез-серийна-комуникация-Схема-контролер Управление-на-ATmega328p-чрез-серийна-комуникация-Схема-захранване Управление-на-ATmega328p-чрез-серийна-комуникация-Схема-PoE

Заключение

Тази статия представя основите на серийната комуникация и нейното приложение за управление на микроконтролери. С тази основа могат да се изграждат по-сложни системи, включително с RS485 протокол. Командите и подходът могат да бъдат лесно адаптирани за различни проекти, което прави това решение подходящо за широк кръг от приложения, но най-вече за общо разбиране на това как работи серийната комуникация.

Офицялен источник и описание: Arduino Serial

Translate »