Skocz do zawartości

Pętla "IF" a informacja na porcie szeregowym


bigthomas

Pomocna odpowiedź

Witam serdecznie !

Napisałem prosty programik (uczę się 🙂) do Arduino UNO. Który ma sprawdzać który przycisk jest wciśnięty (o nazwach: zderzakP i zderzakL).

W zależności od tego który przycisk jest wciśnięty mają uruchomić się silniki w różnej kombinacji.

#include <AFMotor.h>

AF_DCMotor motorP(1); // silnik prawy
AF_DCMotor motorL(2); // silnik lewy
int zderzakP = 9; //zderzak prawy
int zderzakL = 10; //zderzak lewyt

void setup() {
  motorP.setSpeed(255);
  motorL.setSpeed(255);
  pinMode(zderzakP, INPUT);
  pinMode(zderzakL, INPUT);
  digitalWrite(zderzakP, LOW);
  digitalWrite(zderzakL, LOW);  
  Serial.begin(9600);
  Serial.println(F("Test portu!"));

}
// jazda do przodu
void loop() {

  if (digitalRead((zderzakP && zderzakL) == LOW)) {
    motorP.run(FORWARD);
    motorL.run(FORWARD);
    Serial.println("Jazda na wprost");
    delay(500);
    }
  //
  // skręt w prawo
  if (digitalRead(zderzakP) == HIGH) {
    motorP.run(RELEASE);
    motorL.run(RELEASE);
    delay(200);
    motorP.run(FORWARD);
    motorL.run(BACKWARD);
    Serial.println("Skręt w prawo");
    delay(500);
  }
  //
  // skręt w lewo
  if (digitalRead(zderzakL) == HIGH) {
    motorP.run(RELEASE);
    motorL.run(RELEASE);
    delay(200);
    motorP.run(BACKWARD);
    motorL.run(FORWARD);
    Serial.println("Skręt w lewo");
    delay(500);
  }
  //
  // jazda do tyłu
   if (digitalRead((zderzakP && zderzakL) == HIGH)) {
     motorP.run(RELEASE);
     motorL.run(RELEASE);
     delay(200);
     motorP.run(BACKWARD);
     motorL.run(BACKWARD);
     Serial.println("Jazda do tyłu");
     delay(500);
    }
  //
}

Jednak nie rozumiem pewnych rzeczy tj.

1. Kod jak powyżej generuje jazdę do przodu oraz jazdę do tyłu w tym samym czasie. Dlaczego skoro warunek z "jazdy do tyłu" nie jest spełniony - na pinach nie podaję napięcia 5V.

2. Jak w samym arduino bez podłączonego shield'a sterownika L293D dodam napięcie 5V na PIN9 to na konsoli portu szeregowego wyświetlane są dwie wartości "jazda do przodu" oraz "skręt w prawo"

3. W konsoli portu szeregowego pojawiają się dane jeszcze kilka sekund po odłączeniu 5V z PIN'u 9 czy PIN'u 10

 

Edytowano przez bigthomas
Link do komentarza
Share on other sites

Na przyciskach musisz wymusić jeden stan w spoczynku, przez rezystor (sprzętowo) wyrównany do VCC lub GND, lub programowo (INPUT_PULLUP) - ten w UNO tylko do VCC. Przyciskiem wymuszasz stan przeciwny. Nie wiem jaki masz schemat, bo go nie wrzuciłeś, ale pewnie o to chodzi.

Link do komentarza
Share on other sites

Zmodyfikowałem kod i teraz pozostaje mi tylko problem wyświetlania się razem jazdy do przodu i do tyłu - jeżeli wcisnę przycisk to do tych dwóch dochodzi trzeci stan tj skręt w prawo lub w lewo. Jak wcisnę oba przyciski to wyświetlają się wszystkie informacje.

#include <AFMotor.h>

AF_DCMotor motorP(1); // silnik prawy
AF_DCMotor motorL(2); // silnik lewy
int zderzakP = A0; //zderzak prawy
int zderzakL = A1; //zderzak lewyt

void setup() {
  motorP.setSpeed(255);
  motorL.setSpeed(255);
  pinMode(zderzakP, INPUT_PULLUP);
  pinMode(zderzakL, INPUT_PULLUP); 
  Serial.begin(9600);
  Serial.println(F("Test portu!"));

}
// jazda do przodu
void loop() {

  if (digitalRead((zderzakP) == LOW && (zderzakL) == LOW)) {
    motorP.run(FORWARD);
    motorL.run(FORWARD);
    Serial.println("Jazda na wprost");
    delay(500);
    }
  //
  // skręt w prawo
  if (digitalRead(zderzakP) == HIGH) {
    motorP.run(RELEASE);
    motorL.run(RELEASE);
    delay(200);
    motorP.run(FORWARD);
    motorL.run(BACKWARD);
    Serial.println("Skręt w prawo");
    delay(500);
  }
  //
  // skręt w lewo
  if (digitalRead(zderzakL) == HIGH) {
    motorP.run(RELEASE);
    motorL.run(RELEASE);
    delay(200);
    motorP.run(BACKWARD);
    motorL.run(FORWARD);
    Serial.println("Skręt w lewo");
    delay(500);
  }
  //
  // jazda do tyłu
   if (digitalRead((zderzakP) == HIGH && (zderzakL) == HIGH)) {
     motorP.run(RELEASE);
     motorL.run(RELEASE);
     delay(200);
     motorP.run(BACKWARD);
     motorL.run(BACKWARD);
     Serial.println("Jazda do tyłu");
     delay(500);
    }
  //
}

 

Untitled Sketch_bb.jpg

Link do komentarza
Share on other sites

Troszkę pokręciłeś z tymi warunkami - pozornie jest dobrze, a w rzeczywistości... spójrz sam:

Rozpoczyna się funkcja LOOP, oba zderzaki są w stanie HIGH. Najpierw zostaje sprawdzony warunek czy lewy zderzak jest wciśnięty i robot próbuje skręcać mimo tego, że ma zablokowaną drogę.Te powtykane w różne fajne miejsca delaje wcale tam nie pomagają tylko robią dodatkowy bałagan.

A gdybyś zrobił coś takiego:

if (droga wolna) {
  jedziemy do przodu;
}
else if (z prawej zablokowane) {
  skręcamy w lewo;
}
else if (z lewej blokowane) {
  skręcamy w prawo;
}
else { // już nie musimy sprawdzać bo wiemy
  jedziemy do tyłu;
}

// i dopiero teraz
delay(500);

nie byłoby to bardziej sensowne?

Poza tym wygodniej jest ustawić INPUT_PULLUP na wejściach, przyciski (czy tam zderzaki) niech zwierają do masy, a wciśnięcie sygnalizuje Ci poziom LOW (nie trzeba dodatkowego rezystora). Zresztą: albo stosujesz wewnętrzny PULLUP, albo zewnętrzny rezystor, nigdy oba na raz.

  • Lubię! 1
  • Pomogłeś! 1
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

Szczerze to już trochę zgłupiałem ... zrobiłem mam nadzieję że dobrze według tego co proponowałeś. Teraz steruję pinami 9 i 10 bezpośrednio z adruino kabelkiem.

Jednak na konsoli wyświetla się tylko jazda do przodu, pomimo że przyłączam kabelkiem 5V z portu arduino.

#include <AFMotor.h>

AF_DCMotor motorP(1); // silnik prawy
AF_DCMotor motorL(2); // silnik lewy
int zderzakP = 9; //zderzak prawy
int zderzakL = 10; //zderzak lewy

void setup() {
  motorP.setSpeed(255);
  motorL.setSpeed(255);
  pinMode(zderzakP, INPUT_PULLUP);
  pinMode(zderzakL, INPUT_PULLUP); 
  Serial.begin(9600);
  Serial.println(F("Test portu!"));

}
// jazda do przodu
void loop() {

  if (digitalRead(zderzakP && zderzakL == LOW)) {
//    motorP.run(FORWARD);
//    motorL.run(FORWARD);
    Serial.println("Jazda na wprost");
    }
  //
  // skręt w prawo
else if ((digitalRead(zderzakP == HIGH)) && (digitalRead(zderzakL == LOW))) {
//    motorP.run(RELEASE);
//    motorL.run(RELEASE);
//    delay(200);
//    motorP.run(FORWARD);
//    motorL.run(BACKWARD);
    Serial.println("Skręt w prawo");
  }
  //
  // skręt w lewo
else if ((digitalRead(zderzakP == LOW)) && (digitalRead(zderzakL == HIGH))) {
//    motorP.run(RELEASE);
//    motorL.run(RELEASE);
//    delay(200);
//    motorP.run(BACKWARD);
//    motorL.run(FORWARD);
    Serial.println("Skręt w lewo");
  }
  //
  // jazda do tyłu
  //(digitalRead((zderzakP) == HIGH && (zderzakL) == HIGH))
   else  {
//     motorP.run(RELEASE);
//     motorL.run(RELEASE);
//     delay(200);
//     motorP.run(BACKWARD);
//     motorL.run(BACKWARD);
     Serial.println("Jazda do tyłu");
    }
  //
  delay(500);
}

 

Link do komentarza
Share on other sites

No prawie...

Zrobiłeś lekki skrót myślowy, zmień:

if (digitalRead(zderzakP && zderzakL == LOW)) {

na prawidłowy

if (digitalRead(zderzakP) == LOW && digitalRead(zderzakL) == LOW)) {

Dalej mi się nie chciało czytać - popraw najpierw to 🙂

Przy okazji możesz zobaczyć, na ile ułatwiłyby to zmienne, czyli:
 

bool zdP = digitalRead(zderzakP) == HIGH;
bool zdL = digitalRead(zderzakL) == HIGH;
/* to wyżej wystarczy tylko raz przed tym gałęzistym ifem
   bo przecież stan zderzaków nie zmienia się co mikrosekundę */

if (!zdP && !zdL) { // zastępuje: if (digitalRead(zderzakP) == LOW && digitalRead(zderzakL) == LOW)) {
  jedziemy prosto;
}
else if (!zdL) { // w lewo droga wolna
  skręcamy w lewo();
}
// i tak dalej

Dodatkowo - gdybyś kiedyś chciał normalnie podłączyć zderzaki wystarczy zmienić dwie linijki, czyli:

bool zdP = digitalRead(zderzakP) == LOW;
bool zdL = digitalRead(zderzakL) == LOW;

Uwierz mi - to się dużo lepiej czyta, a i robot nie musi fafnaście razy pod rząd odczytywać stanu zderzaków 🙂

 

  • Lubię! 1
  • Pomogłeś! 1
Link do komentarza
Share on other sites

Dzięki, szczerze to zanim napisałeś zastosowałem zmienne ...teraz kod wygląda tak, działa prawidłowo tzn działa tak jak tego chcę.

Proszę ewentualnie o weryfikację czy jest prawidłowo napisany

#include <AFMotor.h>

AF_DCMotor motorP(1); // silnik prawy
AF_DCMotor motorL(2); // silnik lewy
#define zdL A0
#define zdP A1

void setup() {
  Serial.begin(9600);
  Serial.println(F("Test portu!"));
  //  motorP.setSpeed(255);
  //  motorL.setSpeed(255);
  pinMode(zdP, INPUT_PULLUP);
  pinMode(zdL, INPUT_PULLUP);

}
// jazda do przodu
void loop() {
  bool zderzakL = digitalRead(zdL) == HIGH;
  bool zderzakP = digitalRead(zdP) == HIGH;

  if (zderzakL == LOW && zderzakP == LOW) {
    //    motorP.run(FORWARD);
    //    motorL.run(FORWARD);
    Serial.println("Jazda do tyłu");
  }
  //
  // skręt w prawo
  else if (zderzakL == LOW) {
    //    motorP.run(RELEASE);
    //    motorL.run(RELEASE);
    //    delay(200);
    //    motorP.run(FORWARD);
    //    motorL.run(BACKWARD);
    Serial.println("Skręt w prawo");
  }
  // skręt w lewo
  else if (zderzakP == LOW) {
    //    motorP.run(RELEASE);
    //    motorL.run(RELEASE);
    //    delay(200);
    //    motorP.run(FORWARD);
    //    motorL.run(BACKWARD);
    Serial.println("Skręt w lewo");
  }
  //
  // jazda do przodu
  //(digitalRead((zderzakP) == HIGH && (zderzakL) == HIGH))
  else  {
    //     motorP.run(RELEASE);
    //     motorL.run(RELEASE);
    //     delay(200);
    //     motorP.run(BACKWARD);
    //     motorL.run(BACKWARD);
    Serial.println("Jazda do przodu");
  }
  //
  delay(500);
}

 

Link do komentarza
Share on other sites

Troszkę to niefachowo... masz zdeklarowane zmienne zderzakP i zderzakL jako bool i aż się prosi wykorzystać je bezpośrednio w warunku, bez żadnych porównań.

Czyli nie:

if (zderzakL == LOW)

ale:

if (!zderzakL)

Jeśli jednak musisz z jakichś powodów użyć porównania - nie używaj LOW i HIGH (bo te oznaczają stan pinu i w rzeczywistości nie wiesz jak mają rzeczywistą wartość) ale TRUE i FALSE (bo tu masz gwarancję, że zmienna typu bool przyjmie jedną z tych dwóch wartości). Jest to oczywiście nadmiarowe, ale dopuszczalne:

if (zderzakL == FALSE)

Kwestia przyzwyczajenia i własnego widzimisię 🙂

 

  • Pomogłeś! 1
Link do komentarza
Share on other sites

6 godzin temu, ethanak napisał:

Zresztą: albo stosujesz wewnętrzny PULLUP, albo zewnętrzny rezystor, nigdy oba na raz.

A dlaczego nigdy oba na raz? Z tego co wiem jest wręcz przeciwnie, powinno się stosować oba na raz. Ale chętnie się dowiem czegoś nowego.

  • Lubię! 1
Link do komentarza
Share on other sites

chodziło mi o połączenie które miał kolega: wewnętrzny pullup i zewnętrzny pulldown. przyznasz chyba, że niespecjalnie ma to sens... chyba że czegoś nie wiem to mnie popraw.

  • Lubię! 1
Link do komentarza
Share on other sites

Faktycznie podłączanie jednocześnie pullup i pulldown to zły pomysł. Ja zrozumiałem wcześniejszy wpis jako odradzanie włączania pullup wewnątrz, jak i na zewnątrz układu, co nie tylko bywa stosowane, ale często ma sens.

  • Lubię! 1
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.