Skocz do zawartości

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


Worldi

Pomocna odpowiedź

#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ć :)

Link do komentarza
Share on other sites

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
Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

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
Link do komentarza
Share on other sites

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
Link do komentarza
Share on other sites

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.

Link do komentarza
Share on other sites

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...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.