Skocz do zawartości

Arduino Uno - Jak sprawić aby robot wykonał polecenie od pilota IR bedąc w trybie "automatycznym"


Pomocna odpowiedź

Napisano
#include <SevSeg.h>
#include <RC5.h>
#include <Servo.h>

Servo serwo;

#define L_PWM 5
#define L_DIR 4
#define R_PWM 6
#define R_DIR 9
#define led 13
#define przycisk 2
#define PWM_MAX 165
#define buzzer 10
#define lSensor A1
#define rSensor A0
#define granica 830
#define tsopPin 3
#define serwoPin 11
#define trig 7
#define echo 8

boolean trybAutonomiczny = false;  // Ustaw na false, aby robot działał w trybie zdalnym na początku
const unsigned long czasDoModeSwitch = 50000;  // Czas do przejścia w tryb automatyczny
byte address;
byte command;
byte toggle;
unsigned long czasPoprzedni = 0;  // Czas ostatniej aktywności
const unsigned long czasZatrzymania = 115;

RC5 rc5(tsopPin);

void setup() {
  Serial.begin(9600);
  serwo.attach(serwoPin);
  pinMode(L_DIR, OUTPUT);
  pinMode(L_PWM, OUTPUT);
  pinMode(R_DIR, OUTPUT);
  pinMode(R_PWM, OUTPUT);
  pinMode(przycisk, INPUT_PULLUP);
  pinMode(buzzer, OUTPUT);
  pinMode(trig, OUTPUT);
  pinMode(echo, INPUT);

  pinMode(lSensor, INPUT_PULLUP);
  pinMode(rSensor, INPUT_PULLUP);

  serwo.write(90);
}

void loop() {
  // Sprawdzenie, czy został odebrany sygnał IR
  if (rc5.read(&toggle, &address, &command)) {
    trybAutonomiczny = false;  // Przełącz na tryb zdalny
    czasPoprzedni = millis();  // Zresetuj czas

    switch (command) {
      case 2:
        rightMotor(80);
        leftMotor(80);
        break;
      case 8:
        rightMotor(-80);
        leftMotor(-80);
        break;
      case 4:
        rightMotor(40);
        leftMotor(-40);
        break;
      case 6:
        rightMotor(-40);
        leftMotor(40);
        break;
      case 1:
        rightMotor(80);
        leftMotor(60);
        break;
      case 3:
        rightMotor(60);
        leftMotor(80);
        break;
      case 0:
        serwo.write(90);
        break;
      case 34:
        serwo.write(20);
        break;
      case 15:
        serwo.write(160);
        break;
      case 80:
        rightMotor(80);
        leftMotor(80);
        break;
      case 81:
        rightMotor(-80);
        leftMotor(-80);
        break;
      case 85:
        rightMotor(40);
        leftMotor(-40);
        break;
      case 86:
        rightMotor(-40);
        leftMotor(40);
        break;  
      case 87:
        digitalWrite(buzzer, 1);
        delay(500);
        digitalWrite(buzzer, 0);
        break;
    }
  }

  // Sprawdzanie czasu do przełączenia trybu
  if (millis() - czasPoprzedni > czasDoModeSwitch) {
    trybAutonomiczny = true;  // Przełącz na tryb automatyczny
  }

  // Tryb automatyczny
  if (trybAutonomiczny) {
    if (odleglosc() > 40) {
      leftMotor(40);
      rightMotor(38);
    } else {
      stopMotors();
      serwo.write(20);
      delay(800);
      if (odleglosc() > 40) {
        leftMotor(40);
        rightMotor(-40);
        delay(250);
      } else {
        serwo.write(160);
        delay(800);
        if (odleglosc() > 40) {
          leftMotor(-40);
          rightMotor(40);
          delay(250);
        } else {
          digitalWrite(buzzer, 1);
          delay(500);
          digitalWrite(buzzer, 0);
          delay(500);
          leftMotor(-40);
          rightMotor(-42);
          delay(2000);
          leftMotor(40);
          rightMotor(-40);
          delay(250);
        }
      }
      serwo.write(90);
    }
  }

  // Zatrzymywanie silników po określonym czasie, jeżeli znajduje się w stanie nie autonomicznym

  if (millis() - czasPoprzedni > czasZatrzymania && trybAutonomiczny == false) {
    stopMotors();
  }
  
}

int odleglosc() {
  long czas, dystans;

  digitalWrite(trig, 0);
  delayMicroseconds(2);
  digitalWrite(trig, 1);
  delayMicroseconds(10);
  digitalWrite(trig, 0);

  czas = pulseIn(echo, HIGH);
  dystans = czas / 58;

  return dystans;
}

void leftMotor(int V) {
  if (V > 0) {
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 1);
    analogWrite(L_PWM, V);
  } else {
    V = abs(V); 
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 0);
    analogWrite(L_PWM, V);
  }
}

void rightMotor(int V) {
  if (V > 0) {
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 1);
    analogWrite(R_PWM, V);
  } else {
    V = abs(V); 
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 0);
    analogWrite(R_PWM, V);
  }
}

void stopMotors() {
  analogWrite(L_PWM, 0);
  analogWrite(R_PWM, 0);
}

Mój robot na początku wykonuje polecenia od pilota (bo na początku jest ustawiony na tryb NIE automatyczny, czyli tryb zdalny), ale gdy już mija 50 sekund (czyli robot przechodzi w tryb automatyczny), to nie wykonuje poleceń od pilota. Wniosek: Gdy w trybie automatycznym, robot nie wykonuje poleceń od pilota IR i nie umiem tego naprawić :)

(edytowany)

Dodaj mu magiczny guzik, który spowoduje wyjście z trybu automatycznego. Najlepiej na jakimś przerwaniu, bo tam masz sporo śpiochów, tzn. delay-ów. A dokładniej, w przerwaniu ustawiasz flagę, jeżeli naciśnięto magiczny guzik i sprawdzasz ją w głównej pętli.

Edytowano przez orb777
  • Lubię! 1

A tak na poważnie - czy jesteś pewien, że masz wgraną do robota dokładnie tę wersję programu, którą tu przedstawiłeś?  Patrzę na kod i nie widzę żadnego uzależnienia wykonywania poleceń z pilota od stanu urządzenia. Powinny być wykonywane zawsze.

(edytowany)
13 minut temu, jand napisał:

Patrzę na kod i nie widzę żadnego uzależnienia wykonywania poleceń z pilota od stanu urządzenia. Powinny być wykonywane zawsze.

Zapomniałeś o delay'ach, które blokują mikrokontroler i nie odbiera sygnałów, bo nie są w przerwaniu, ani program nie dociera do request poolingu. Obstawiam, że wchodzi w któryś warunek i się tam blokuje na delay'ach, bez debuggera raczej ciężko stwierdzić co się tam dzieje.

Edytowano przez H1M4W4R1
  • Lubię! 2

Dodaj przed pierwszym warunkiem (zaraz po loop) komendę oczekującą na klawisz z seriala, przytrzymaj guzik na pilocie, po czym pacnij w klawę, zobacz co się dzieje. Ewentualnie trzymaj cały czas guzik. Dobrze by było, gdybyś dodawał sobie komentarze do naocznego debugowania, co robi aktualnie kod.

  • Lubię! 1
15 minut temu, H1M4W4R1 napisał:

Zapomniałeś o delay'ach, które blokują mikrokontroler

Bardzo słuszna uwaga, nie zauważyłem, tak naprawdę patrzyłem tylko na loop().

@Worldi musisz tak przepisać program, aby się pozbyć się tych wszystkich delay() we fragmencie sterowania autonomicznego. Jest ich bardzo dużo, odmierzają długie czasy i trybie autonomicznym procesor spędza praktycznie niemal 100% czasu realizując jakiś delay(), a wtedy nie ma możliwości odczytania danych z czujnika IR i dane te przepadają. Aby żadne dane nie przypadły funkcja rc5.read() musi być wywoływana bardzo często.

Dla sprawdzenia - jeśli będziesz przytrzymywał naciśniety przycisk na pilocie bardzo długo (kilka sekund), to może w końcu zadziała i w trybie autonomicznym.

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...