Skocz do zawartości

Kurs budowy robotów - #8 - zdalne sterowanie IR (RC5)


Pomocna odpowiedź

RC5 jest wrażliwe na wszelkie opóźnienia w programie, więc postaraj się unikać wszelkich delayi. Możesz skorzystć z funkcji millis i przygotować nieblokujące obliczanie czasu w którym ma nastąpić przełączenie kolorów LED i dodać zmienną służącą jako przełącznik w styl: jak true to migaj jak false to nie migaj.

Link to post
Share on other sites

Część, ominąłem póki co line followera bo chciałem połączyć zdalne sterowanie ze światłolubem oraz omijaniem przeszkód. Obecnie robot może być sterowany zdalnie, z możliwością płynnej regulacji prędkości jazdy. Osiągnięcie zarówno wartości maksymalnej jak i minimalnej sygnalizowane jest BUZZERem. Odpowiadają za to przyciski "vol up" oraz "vol down" na pilocie. Przycisk source natomiast powoduje zmianę trybu jazdy. W drugim trybie jazdy robot jeździ autonomicznie omijając przeszkody. Z przodu, jak poprzednio, przeszkody wykrywa za pomocą "czułek". Z tyłu posiada również czujnik ultradźwiękowy, który pozwala uniknąć tratowania obiektów za robotem podczas zawracania. W dowolnym momencie jednym kliknięciem mogę się przełączać między trybami. Zmiana trybu również sygnalizowana jest przez piknięcie BUZZERa.

Kod:

#include <Arduino.h>
#define TSOP_PIN 3
#define L_PWM 5
#define L_DIR 4
#define R_PWM 6
#define R_DIR 9
#define R_LIGHT_SENSOR A0
#define L_LIGHT_SENSOR A1
#define L_SIDE_SENSOR A2
#define R_SIDE_SENSOR 12
#define ROZNICA_MIN -400
#define ROZNICA_MAX 400
#define PWM_MAX 165
#define trigPin 8
#define echoPin 7

#define BUZZER 10
#define LED 13

#include <RC5.h>

RC5 rc5(TSOP_PIN); //ifnormcaja o podłączeniu odbiornika

//zmienne dla RC5
byte address;
byte command;
byte toggle;
int predkosc = 40; //zmienna poczatkowa dla predkosci
bool ZmianaTrybu = false; //zmienna dla określenia trybu jazdy


void setup() {
  

  pinMode(L_DIR, OUTPUT); //konfiguracja pinów dla mostka H
  pinMode(R_DIR, OUTPUT);
  pinMode(L_PWM, OUTPUT);
  pinMode(R_PWM, OUTPUT);

  pinMode(BUZZER, OUTPUT); //konfiguracja pozostałych elementów
  digitalWrite(BUZZER, 0);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, 0);
  pinMode(L_SIDE_SENSOR, INPUT_PULLUP); //koniguracja pinu jak przyckiski
  pinMode(R_SIDE_SENSOR, INPUT_PULLUP);
  randomSeed(analogRead(5)); //inicjalizacja generatora liczb losowych
  pinMode(trigPin, OUTPUT); //Deklaracja pinów dla czujnika zbliżeniowego
  pinMode(echoPin, INPUT);

}

void loop() {
  
  if (ZmianaTrybu == false) { //sprawdzenie obecnego trybu jazdy

    if (rc5.read(&toggle, &address, &command)) { //jeśli odebrano komendę
    switch(command) {
      case 12:
        digitalWrite(BUZZER, 1);
        delay(500);
        digitalWrite(BUZZER, 0);
      break;
      
      case 2: //do przodu
        leftMotor(predkosc);
        rightMotor(predkosc);
      break;

      case 4: //obrot w lewo
        leftMotor(-(predkosc-10));
        rightMotor(predkosc-10);
      break;

      case 5: //stop
        StopMotors();
      break;

      case 6: //w prawo
        leftMotor(predkosc-10);
        rightMotor(-(predkosc-10));
      break;

      case 8: //do tyłu
        leftMotor(-predkosc);
        rightMotor(-predkosc);
      break;

      case 3: //łuk w prawo do przodu
        leftMotor(predkosc);
        rightMotor(predkosc-20);
      break;

      case 1: //łuk w lewo do przodu
        leftMotor(predkosc-20);
        rightMotor(predkosc);
      break;

      case 7: //łuk w lewo do tyłu 
        leftMotor(-(predkosc-20));
        rightMotor(-predkosc);
      break;

      case 9: //łuk w prawo do tyłu
        leftMotor(-predkosc);
        rightMotor(-(predkosc-20));
      break;

      case 16: //zwiekszenie predkosci jazdy
        if (predkosc < 80) { //okreslenie maksymalnej dopuszczalnej predkosci
          predkosc++;
        } else {
            sygnalizacjaBuzzer(4);
          }
       break;

       case 17: //zmniejszenie predkosci jazdy
       if (predkosc > 40) { //okreslenie minimalnej dopuszczalnej predkosci
           predkosc--;
       } else {
           sygnalizacjaBuzzer(4);
       }
       break;

       case 56:

          ZmianaTrybu = !ZmianaTrybu;
          sygnalizacjaUruchomienia();
        break;
        
    }
  } 
  } else { //cześć dla światłoluba oraz omijania przeszkód
    int odczytLewy = analogRead(L_LIGHT_SENSOR); //odczytanie wartości z lewego czujnika
    int odczytPrawy = analogRead(R_LIGHT_SENSOR); //odczytanie wartości z prawego czujnika
    int roznica = odczytLewy - odczytPrawy;
    int los = random(5, 40) * 10; //wylosowanie liczby dla czasu obrotu
    int randomSpeed = random(2, 6) * 10; //wylosowanie predkosci jazdy do przodu

    if (roznica < ROZNICA_MIN) { //ewentualna korekcja skrajnych warotści róznic
        roznica = ROZNICA_MIN;
    } else if (roznica > ROZNICA_MAX) {
        roznica = ROZNICA_MAX;
    }

	int zmianaPredkosci = map(roznica, ROZNICA_MIN, ROZNICA_MAX, -40, 40);
	//zmienna pozawalająca przeliczenie odczytów z czuników na zmianę prędkości silników
      
      leftMotor(30+zmianaPredkosci); //korekty prędkości zależnie od natężenia światła
      rightMotor(30-zmianaPredkosci);

      if (digitalRead(L_SIDE_SENSOR) == LOW)
    { //jeśli przeszkoda zostanie wykryta po lewej stronie
     
        int odleglosc = zmierzOdlegosc(); //zmienna odczytująca dystans z czujnika US
 
        if (odleglosc > 30) //jeśli odległość jest większa niż 30 cm to robot zdąży wykonać pełny zadany ruch
        {
            leftMotor(-40);
            rightMotor(-40);
            digitalWrite(BUZZER, 1);
            delay(1000);
        }
        else
        {
            while (odleglosc > 8) //jeśli odległość mniejsza niż 30 cm sprawdzanie kolejnych odległości do momentu osiągnięcia wartości 8 cm
            {
 
                leftMotor(-40);
                rightMotor(-40);
                digitalWrite(BUZZER, 1);
                odleglosc = zmierzOdlegosc(); //zamiana wartości odległości
                delay(50);
 
            }
        }
 
        //obrót w miejscu w prawo
        leftMotor(randomSpeed);
        rightMotor(-randomSpeed);
        digitalWrite(BUZZER, 0);
        delay(150 + los);
        //koniec warunku, wracamy do jazdy prosto
 
    }
 
    if (digitalRead(R_SIDE_SENSOR) == LOW)
    { //jeśli przeszkoda zostanie wykryta po prawej stronie
      //jedź wstecz i wydawaj dźwięk
        int odleglosc = zmierzOdlegosc(); //powtarzamy co w poprzednim warunku
 
        if (odleglosc > 30)
        {
            leftMotor(-40);
            rightMotor(-40);
            digitalWrite(BUZZER, 1);
            delay(1000);
        }
        else
        {
            while (odleglosc > 8)
            {
 
                leftMotor(-40);
                rightMotor(-40);
                digitalWrite(BUZZER, 1);
                odleglosc = zmierzOdlegosc();
                delay(50);
 
            }
        }
        //obrót w miejscu w lewo
        leftMotor(-randomSpeed);
        rightMotor(randomSpeed);
        digitalWrite(BUZZER, 0);
        delay(150 + los);
        //koniec warunku, wracamy do jazdy prosto
 
    }
    
    TrybJazdy(); //funckja odpowiedzialna za zmianę trybu pracy

  }

}

void leftMotor(int V) { //funkcja odpowiedzialna za sterowanie lewym silnikiem
  if (V > 0) { //jeśli wartość prędkości więszka od 0
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 0); //do przodu
    analogWrite(L_PWM, V); //zadanie prędkości
  } else {
    V = abs(V); //wyciągnięcie wartości bezwzględnej
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 1); //do tyłu
    analogWrite(L_PWM, V); //zadanie prędkości   
  }
}

void rightMotor(int V) { //to samo co wyżej tylko dla prawego
    if (V > 0) {
        V = map(V, 0, 100, 0, PWM_MAX);
        digitalWrite(R_DIR, 0);
        analogWrite(R_PWM, V);
    } else {
        V = abs(V);
        V = map(V, 0, 100, 0, PWM_MAX);
        digitalWrite(R_DIR, 1);
        analogWrite(R_PWM, V);
    }
}

void StopMotors() { //zatrzymanie silników 
    analogWrite(L_PWM, 0);
    analogWrite(R_PWM, 0);
}

void sygnalizacjaBuzzer(int powtorzenia) {
    int i = 0; 
    for (i = 0; i < powtorzenia; i++) {
        digitalWrite(BUZZER, HIGH);
        delay(200);
        digitalWrite(BUZZER, LOW);
        delay(200);
    }
}

void sygnalizacjaUruchomienia() { //sygnalizacja dźwiękowa startu
    
 int i = 0; 
    for (i; i < 3; i++) { 
        digitalWrite(BUZZER, HIGH);
        delay(200);
        digitalWrite(BUZZER, LOW);
         delay(200);
    }
}


int zmierzOdlegosc() //funkcja dla mierzenia odległości przez czujnik SC
{
    long czas, dystans;
 
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
 
    czas = pulseIn(echoPin, HIGH);
    dystans = czas / 58;
 
    return dystans;
}

void TrybJazdy() { //funckja odpowidzialna za zmianę trybu jazdy
     if (rc5.read(&toggle, &address, &command)) {
       switch(command) {
           case 56:
            ZmianaTrybu = !ZmianaTrybu;
            StopMotors();
            sygnalizacjaUruchomienia();
        break;
       } 
    }

  } 
  

oraz krótki film z działania: 

 

Edytowano przez BHBmacieg
  • Lubię! 1
Link to post
Share on other sites

Super! Fajnie że porządnie zabierasz się za wszystkie zadania i dodajesz coś od siebie. Powodzenia w dalszych projektach i chętnie zobaczę kolejne postępy 🙂 

Link to post
Share on other sites

Dzień Dobry,

Mam małą zagwozdkę odnośnie zmiennych globalnych.

Bardzo proszę o wyjaśnienie mi poniższego prostego zresztą kodu:

#include <RC5.h>
#define TSOP_PIN 3
RC5 rc5(TSOP_PIN);
byte address;
byte command;
byte toggle;

int robotMode = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  if (rc5.read(&toggle, &address, &command)) {
    switch (command) {
      case 10:
        robotMode = 1;
        break;
      case 146:
        robotMode = 0;
        break;
    }
    Serial.println("Tryb pracy robota: " + String(robotMode) + " Tutaj widać zmieniona wartosc zmiennej globalnej!!!");
    delay(300);
  }
  //Serial.println("Tryb pracy robota: " + String(robotMode) + " Tutaj nie widać zmienionej wartosci zmiennej globalnej!!!");
  //delay(300);
}

W pierwszej kolejności proszę uruchomić kod w takiej postaci w jakiej go tutaj umieściłem a potem za komentować Serial i delay wewnątrz instrukcji if i od komentować Serial i delay poza instrukcją if. 

Dlaczego wewnątrz ciała instrukcji if zmienna ulega zmianie podczas gdy poza tą instrukcją ta zmiana nie obowiązuje?

Edytowano przez Gieneq
Zachęcam do używania bloku kodu
Link to post
Share on other sites

Możliwe że delay powoduje problemy. W programach z RC5 nie powinno się tworzyć większych opóźnień, bo potrafią uniemożliwić odbiór.

A czym objawia się to, że nie widać zmiennej? Możesz opisać jakie wartości otrzymujesz a jakie byś oczekiwał przy konkretnych naciśnięciach przycisku?

Edytowano przez Gieneq
Link to post
Share on other sites

Podłączyłem baterie do pilota, napisałem program i próbuje testować... zero reakcji... Pomyślałem że pewnie coś zasłania odbiornik IR więc sprawdzam i szczęka mi opadła... Na płytce nie ma odbiornika IR... nie został wlutowany:/ Bawiąc się wcześniej nie zwróciłem na to uwagi...

Zgłosiłem reklamacje do botland i czekam na reakcje. To tak w ramach ciekawostek i ponarzekania.

Dzięki za kurs i poświęcony czas:) Będzie kolejny bardziej zaawansowany cykl...? @Treker może coś więcej o line followerach... pisałeś że lubisz...🙂

Link to post
Share on other sites

@HanulaM oj to nie dobrze, takiej reklamacji jeszcze nie było. Przepraszam za zamieszanie i dziękuję za sygnał - sprawdzę to jeszcze dokładniej po swojej stronie.

22 godziny temu, HanulaM napisał:

Dzięki za kurs i poświęcony czas:) Będzie kolejny bardziej zaawansowany cykl...? @Treker może coś więcej o line followerach... pisałeś że lubisz...🙂

Na ten moment nie mam w planach kolejnego kursu o robotach, ale na pewno kiedyś się za to wezmę, bo faktycznie swego czasu sporo działałem z linefollowerami 😉

  • Lubię! 1
Link to post
Share on other sites
(edytowany)
Dnia 2.04.2020 o 14:08, BHBmacieg napisał:

Część, ominąłem póki co line followera bo chciałem połączyć zdalne sterowanie ze światłolubem oraz omijaniem przeszkód. Obecnie robot może być sterowany zdalnie, z możliwością płynnej regulacji prędkości jazdy. Osiągnięcie zarówno wartości maksymalnej jak i minimalnej sygnalizowane jest BUZZERem. Odpowiadają za to przyciski "vol up" oraz "vol down" na pilocie. Przycisk source natomiast powoduje zmianę trybu jazdy. W drugim trybie jazdy robot jeździ autonomicznie omijając przeszkody. Z przodu, jak poprzednio, przeszkody wykrywa za pomocą "czułek". Z tyłu posiada również czujnik ultradźwiękowy, który pozwala uniknąć tratowania obiektów za robotem podczas zawracania. W dowolnym momencie jednym kliknięciem mogę się przełączać między trybami. Zmiana trybu również sygnalizowana jest przez piknięcie BUZZERa.

Kod:



#include <Arduino.h>
#define TSOP_PIN 3
#define L_PWM 5
#define L_DIR 4
#define R_PWM 6
#define R_DIR 9
#define R_LIGHT_SENSOR A0
#define L_LIGHT_SENSOR A1
#define L_SIDE_SENSOR A2
#define R_SIDE_SENSOR 12
#define ROZNICA_MIN -400
#define ROZNICA_MAX 400
#define PWM_MAX 165
#define trigPin 8
#define echoPin 7

#define BUZZER 10
#define LED 13

#include <RC5.h>

RC5 rc5(TSOP_PIN); //ifnormcaja o podłączeniu odbiornika

//zmienne dla RC5
byte address;
byte command;
byte toggle;
int predkosc = 40; //zmienna poczatkowa dla predkosci
bool ZmianaTrybu = false; //zmienna dla określenia trybu jazdy


void setup() {
  

  pinMode(L_DIR, OUTPUT); //konfiguracja pinów dla mostka H
  pinMode(R_DIR, OUTPUT);
  pinMode(L_PWM, OUTPUT);
  pinMode(R_PWM, OUTPUT);

  pinMode(BUZZER, OUTPUT); //konfiguracja pozostałych elementów
  digitalWrite(BUZZER, 0);
  pinMode(LED, OUTPUT);
  digitalWrite(LED, 0);
  pinMode(L_SIDE_SENSOR, INPUT_PULLUP); //koniguracja pinu jak przyckiski
  pinMode(R_SIDE_SENSOR, INPUT_PULLUP);
  randomSeed(analogRead(5)); //inicjalizacja generatora liczb losowych
  pinMode(trigPin, OUTPUT); //Deklaracja pinów dla czujnika zbliżeniowego
  pinMode(echoPin, INPUT);

}

void loop() {
  
  if (ZmianaTrybu == false) { //sprawdzenie obecnego trybu jazdy

    if (rc5.read(&toggle, &address, &command)) { //jeśli odebrano komendę
    switch(command) {
      case 12:
        digitalWrite(BUZZER, 1);
        delay(500);
        digitalWrite(BUZZER, 0);
      break;
      
      case 2: //do przodu
        leftMotor(predkosc);
        rightMotor(predkosc);
      break;

      case 4: //obrot w lewo
        leftMotor(-(predkosc-10));
        rightMotor(predkosc-10);
      break;

      case 5: //stop
        StopMotors();
      break;

      case 6: //w prawo
        leftMotor(predkosc-10);
        rightMotor(-(predkosc-10));
      break;

      case 8: //do tyłu
        leftMotor(-predkosc);
        rightMotor(-predkosc);
      break;

      case 3: //łuk w prawo do przodu
        leftMotor(predkosc);
        rightMotor(predkosc-20);
      break;

      case 1: //łuk w lewo do przodu
        leftMotor(predkosc-20);
        rightMotor(predkosc);
      break;

      case 7: //łuk w lewo do tyłu 
        leftMotor(-(predkosc-20));
        rightMotor(-predkosc);
      break;

      case 9: //łuk w prawo do tyłu
        leftMotor(-predkosc);
        rightMotor(-(predkosc-20));
      break;

      case 16: //zwiekszenie predkosci jazdy
        if (predkosc < 80) { //okreslenie maksymalnej dopuszczalnej predkosci
          predkosc++;
        } else {
            sygnalizacjaBuzzer(4);
          }
       break;

       case 17: //zmniejszenie predkosci jazdy
       if (predkosc > 40) { //okreslenie minimalnej dopuszczalnej predkosci
           predkosc--;
       } else {
           sygnalizacjaBuzzer(4);
       }
       break;

       case 56:

          ZmianaTrybu = !ZmianaTrybu;
          sygnalizacjaUruchomienia();
        break;
        
    }
  } 
  } else { //cześć dla światłoluba oraz omijania przeszkód
    int odczytLewy = analogRead(L_LIGHT_SENSOR); //odczytanie wartości z lewego czujnika
    int odczytPrawy = analogRead(R_LIGHT_SENSOR); //odczytanie wartości z prawego czujnika
    int roznica = odczytLewy - odczytPrawy;
    int los = random(5, 40) * 10; //wylosowanie liczby dla czasu obrotu
    int randomSpeed = random(2, 6) * 10; //wylosowanie predkosci jazdy do przodu

    if (roznica < ROZNICA_MIN) { //ewentualna korekcja skrajnych warotści róznic
        roznica = ROZNICA_MIN;
    } else if (roznica > ROZNICA_MAX) {
        roznica = ROZNICA_MAX;
    }

	int zmianaPredkosci = map(roznica, ROZNICA_MIN, ROZNICA_MAX, -40, 40);
	//zmienna pozawalająca przeliczenie odczytów z czuników na zmianę prędkości silników
      
      leftMotor(30+zmianaPredkosci); //korekty prędkości zależnie od natężenia światła
      rightMotor(30-zmianaPredkosci);

      if (digitalRead(L_SIDE_SENSOR) == LOW)
    { //jeśli przeszkoda zostanie wykryta po lewej stronie
     
        int odleglosc = zmierzOdlegosc(); //zmienna odczytująca dystans z czujnika US
 
        if (odleglosc > 30) //jeśli odległość jest większa niż 30 cm to robot zdąży wykonać pełny zadany ruch
        {
            leftMotor(-40);
            rightMotor(-40);
            digitalWrite(BUZZER, 1);
            delay(1000);
        }
        else
        {
            while (odleglosc > 8) //jeśli odległość mniejsza niż 30 cm sprawdzanie kolejnych odległości do momentu osiągnięcia wartości 8 cm
            {
 
                leftMotor(-40);
                rightMotor(-40);
                digitalWrite(BUZZER, 1);
                odleglosc = zmierzOdlegosc(); //zamiana wartości odległości
                delay(50);
 
            }
        }
 
        //obrót w miejscu w prawo
        leftMotor(randomSpeed);
        rightMotor(-randomSpeed);
        digitalWrite(BUZZER, 0);
        delay(150 + los);
        //koniec warunku, wracamy do jazdy prosto
 
    }
 
    if (digitalRead(R_SIDE_SENSOR) == LOW)
    { //jeśli przeszkoda zostanie wykryta po prawej stronie
      //jedź wstecz i wydawaj dźwięk
        int odleglosc = zmierzOdlegosc(); //powtarzamy co w poprzednim warunku
 
        if (odleglosc > 30)
        {
            leftMotor(-40);
            rightMotor(-40);
            digitalWrite(BUZZER, 1);
            delay(1000);
        }
        else
        {
            while (odleglosc > 8)
            {
 
                leftMotor(-40);
                rightMotor(-40);
                digitalWrite(BUZZER, 1);
                odleglosc = zmierzOdlegosc();
                delay(50);
 
            }
        }
        //obrót w miejscu w lewo
        leftMotor(-randomSpeed);
        rightMotor(randomSpeed);
        digitalWrite(BUZZER, 0);
        delay(150 + los);
        //koniec warunku, wracamy do jazdy prosto
 
    }
    
    TrybJazdy(); //funckja odpowiedzialna za zmianę trybu pracy

  }

}

void leftMotor(int V) { //funkcja odpowiedzialna za sterowanie lewym silnikiem
  if (V > 0) { //jeśli wartość prędkości więszka od 0
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 0); //do przodu
    analogWrite(L_PWM, V); //zadanie prędkości
  } else {
    V = abs(V); //wyciągnięcie wartości bezwzględnej
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 1); //do tyłu
    analogWrite(L_PWM, V); //zadanie prędkości   
  }
}

void rightMotor(int V) { //to samo co wyżej tylko dla prawego
    if (V > 0) {
        V = map(V, 0, 100, 0, PWM_MAX);
        digitalWrite(R_DIR, 0);
        analogWrite(R_PWM, V);
    } else {
        V = abs(V);
        V = map(V, 0, 100, 0, PWM_MAX);
        digitalWrite(R_DIR, 1);
        analogWrite(R_PWM, V);
    }
}

void StopMotors() { //zatrzymanie silników 
    analogWrite(L_PWM, 0);
    analogWrite(R_PWM, 0);
}

void sygnalizacjaBuzzer(int powtorzenia) {
    int i = 0; 
    for (i = 0; i < powtorzenia; i++) {
        digitalWrite(BUZZER, HIGH);
        delay(200);
        digitalWrite(BUZZER, LOW);
        delay(200);
    }
}

void sygnalizacjaUruchomienia() { //sygnalizacja dźwiękowa startu
    
 int i = 0; 
    for (i; i < 3; i++) { 
        digitalWrite(BUZZER, HIGH);
        delay(200);
        digitalWrite(BUZZER, LOW);
         delay(200);
    }
}


int zmierzOdlegosc() //funkcja dla mierzenia odległości przez czujnik SC
{
    long czas, dystans;
 
    digitalWrite(trigPin, LOW);
    delayMicroseconds(2);
    digitalWrite(trigPin, HIGH);
    delayMicroseconds(10);
    digitalWrite(trigPin, LOW);
 
    czas = pulseIn(echoPin, HIGH);
    dystans = czas / 58;
 
    return dystans;
}

void TrybJazdy() { //funckja odpowidzialna za zmianę trybu jazdy
     if (rc5.read(&toggle, &address, &command)) {
       switch(command) {
           case 56:
            ZmianaTrybu = !ZmianaTrybu;
            StopMotors();
            sygnalizacjaUruchomienia();
        break;
       } 
    }

  } 
  

oraz krótki film z działania: 

 

Wszystko fajnie, też chciałem zrobić takiego kombajna, tylko doszedłem do wniosku że nie da się, ponieważ wszystkie te czujniki z kursu podlącza się pod te same piny, więc została opcja sterowanie pilotem + omijanie przeszkód albo światłolub. Jak koledzy podłączyli tyle czujników?

Edytowano przez radekwrc
Link to post
Share on other sites

@radekwrc możesz podłączyć inne czujniki pod wolne wyprowadzenia w płytce, jakoś się to uda 😉 

Problem natomiast pojawi się gdy będziesz chciał zrobić wiele funkcji i jeszcze RC5 które nie toleruje opóźnień. Kod programu będzie musiał być nieblokujący - zero opóźnień zrobionych z delayów, a RC5 ma mieć najwyższy priorytet.

  • Lubię! 1
Link to post
Share on other sites

Witam,

czy biblioteka RC5 obsłuży też odbiornik CHQ? Testowałem z biblioteką IRremote i działa, ale jak stosuję tutaj podany przykład, to zero rezultatu.

Link to post
Share on other sites

@LDor jaki dokładnie odbiornik masz na myśli? Możesz podać jakiś konkretny symbol? Masz pewność, że Twój pilot nadaje w RC5? Nie masz zarejestrowanego zestawu do tego kursu, więc niestety nie wiem jakim sprzętem dysponujesz.

Link to post
Share on other sites
(edytowany)

@Adampi314
Kod na jazdę tylko gdy przycisk wciśnięty w najprostszej chyba formie

unsigned long aktualnyCzas = 0;
unsigned long czasNacisniecia = 0;

void loop() {
 aktualnyCzas = millis();

 if (rc5.read(&toggle, &address, &command)){
   czasNacisniecia = millis();
   // wyciąłem, żeby nie zaciemniać
  }

  if (aktualnyCzas - czasNacisniecia >= 300UL){
        stopMotors();
  }

Wartość 300UL jest przykładowy, im większą damy, tym dłużej będzie jechał po puszczeniu przycisku. 

Edytowano przez Juzbrig
Link to post
Share on other sites

Cześć,

ostatnio kupiłem zestaw i zacząłem się bawić tym kursem. Udoskonaliłem trochę kod, tak aby robot wykonywał akcję tak długo, jak długo wciśnięty jest przycisk i zatrzymywał się po puszczeniu. Zaimplementowałem również oszczędzanie energii. Wklejam kod, być może się komuś przyda. Dopiero się uczę, więc jeśli bardziej doświadczeni robotycy mają jakieś uwagi, co można tu zrobić optymalniej, to będą bardzo mile widziane. Szczególnie interesuje mnie, czy można jeszcze bardziej ograniczyć zużycie energii.

Mam też jedną ważną uwagę do zestawu. Nie wiem, czy tylko mnie się tak trafiło, ale kółka były bardzo luźne i cały czas odpadały od silników. Na szczęście miałem inne, więc nie popsuło to zabawy, ale jeśli we wszystkich zestawach są takie kółka, to zdecydowanie trzeba je wymienić.

#include <LowPower.h>
#include <RC5.h>

unsigned long counter = 0;
byte previousToggle = 100;

RC5 rc5receiver(3);

void nop() {}

// !!! PWM_MAX == 165
void leftMotor(int speed) {
    if (speed > 0) {
        speed = map(speed, 0, 100, 0, 165);
        digitalWrite(4, 0);
        analogWrite(5, speed);
    } else {
        speed = abs(speed);
        speed = map(speed, 0, 100, 0, 165);
        digitalWrite(4, 1);
        analogWrite(5, speed);   
    }
}

void rightMotor(int speed) {
    if (speed > 0) {
        speed = map(speed, 0, 100, 0, 165);
        digitalWrite(9, 1);
        analogWrite(6, speed);
    } else {
        speed = abs(speed);
        speed = map(speed, 0, 100, 0, 165);
        digitalWrite(9, 0);
        analogWrite(6, speed);   
    }
}

void goForward(int speed) {
    leftMotor(speed);
    rightMotor(speed);
}

void turnLeft(int speed) {
    leftMotor(speed);
    rightMotor(-speed);
}

void turnRight(int speed) {
    leftMotor(-speed);
    rightMotor(speed);
}

void goBackward(int speed) {
    leftMotor(-speed);
    rightMotor(-speed);
}

void stopMotors() {
    leftMotor(0);
    rightMotor(0);
}

void setup() {
    pinMode(2, INPUT_PULLUP); // Przycisk z filtrem
    pinMode(13, OUTPUT);      // Dioda
    pinMode(10, OUTPUT);      // Buzzer
    pinMode(3, INPUT);        // IR

    // Prędkość = V = PWM(0 - 165)
    // 0 = przód 1 = tył
    pinMode(5, OUTPUT); // Prędkość L
    pinMode(4, OUTPUT); // Kierunek obrotów L
    pinMode(6, OUTPUT); // Prędkość P
    pinMode(9, OUTPUT); // Kierunek obrotów P

    digitalWrite(13, HIGH);
}

void loop() {
    byte address;
    byte command;
    byte toggle;
    if (rc5receiver.read(&toggle, &address, &command)) {
        counter = 0;
        if (toggle != previousToggle) {
            switch (command) {
                case 80:
                    goForward(40);
                break;
                
                case 81:
                    goBackward(40);
                break;

                case 85:
                    turnLeft(40);
                break;

                case 86:
                    turnRight(40);
                break;

                default:
                    stopMotors();
                break;
            }
        }

        previousToggle = toggle;
    } else {
        if (counter < 4000000) {
            counter++;
        } 
        
        if (counter == 20000) {
            stopMotors();
        } else if (counter == 4000000) {
            digitalWrite(13, LOW);
            counter = 20000;
            attachInterrupt(digitalPinToInterrupt(3), nop, LOW);
            LowPower.powerStandby(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
            detachInterrupt(digitalPinToInterrupt(3));
            digitalWrite(13, HIGH);
        }
    }

}

 

Edytowano przez ghost1313
  • Lubię! 1
Link to post
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

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

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