Skocz do zawartości

Problem z podłączeniem czujnika DHT i serwa do robota


Danyeru

Pomocna odpowiedź

Hej.

Mój robot dostał czujnik DHT11 i było fajnie.
Chcę teraz dołożyć serwo i kiedy w programie jest obsługa czujnika, to serwo pulsuje (odchył o kilka stopni i powrót na pozycję).

https://youtu.be/jo1NQZ17fqU


Zakładam, że to obsługa czujnika miesza, bo po zakomentowaniu funkcji serwo się nie porusza.

Również po odpięciu linii danych czujnika, bez zmian w kodzie, serwo przestaje mieć czkawkę.



Funkcja DHT.

 void humitemp() {
  float wilg = dht.getHumidity();
  float temp = dht.getTemperature();
  czas = millis();
  roznica = czas - odmierz;
  if (roznica >= 1000UL){
    odmierz = czas;
    if (dht.getStatusString() == "OK"){
      mybt.print(temp);
      mybt.print(" °C");
      mybt.print("|");
      mybt.print(wilg);
      mybt.println(" %");
    }
  }
}

 

Mogę coś z tym zrobić? 🤔

Proszę mieć na uwadze, że mój poziom to bardzo początkujący. Poza robotem, moja wiedza to aktualnie tutejszy kurs arduino poziomu I (z jednym małym wyprzedzeniem w kwestii tego millisa i czujnika DHT11).

Zasilane pakietem baterii 6*1,5V
Aktualnie na wejściu jest ~8,45V, podczas ruchu serwa przy tym pulsie spada o ~0,2V.

 

W ogóle, może źle podchodzę, kiedy mam spiętą całość, to (poza tym pulsowaniem) odbieram odczyty z czujnika, sterowanie działa, ale jak załączam jazdę autonomiczną, to robot jedzie prosto w przeszkodę.

Aktualny kod całości:

#include <SoftwareSerial.h>
#include <Servo.h>
#include <DHT.h>
#define SERWO_PIN 11
#define DHT11_PIN 12 //Czujnik temperatury i wilgotnosci
#define L_PWM 5 //Kierunki i wypelnienie silnikow
#define L_DIR 4
#define R_PWM 6
#define R_DIR 9
#define PWM_MAX 220 //Ustalenie maksymalnego wypelnienia dla silnikow wzgledem napiecia zasilania
#define BUZZER 10
#define LED 13
#define TSOP_PIN 3
#define trigPin 1 //szary
#define echoPin 0 //bialy
SoftwareSerial mybt(8, 7); //Tx, Rx
unsigned long czas = 0;
unsigned long odmierz = 0;
unsigned long roznica = 0;
boolean lights = false;
DHT dht;
Servo serwo;
 
void setup() {
  //Konfiguracja pinow od mostka H
  pinMode(L_DIR, OUTPUT);
  pinMode(R_DIR, OUTPUT);
  pinMode(L_PWM, OUTPUT);
  pinMode(R_PWM, OUTPUT);
 
  //Konfiguracja pozostalych elementow
  pinMode(BUZZER, OUTPUT);
  digitalWrite(BUZZER, 0); //Wylaczenie buzzera  
  pinMode(LED, OUTPUT); 
  digitalWrite(LED, 0); //Wylaczenie diody
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
 
  mybt.begin(9600);
  dht.setup(DHT11_PIN);
  serwo.attach(SERWO_PIN);
}
 
void loop() {
 humitemp();
 if (mybt.available() > 0){
     char jazda = mybt.read(); //Odczyt danych z BT
     switch(jazda) {
      case 'F': //Do przodu
        leftMotor(95);
        rightMotor(95);
      break;
 
      case 'B': //Do tyłu
        leftMotor(-95);
        rightMotor(-95);
      break;
 
      case 'S': //STOP
        stopMotors();
      break;
 
      case 'L': //Obrót w lewo w miejscu
        leftMotor(-80);
        rightMotor(80);
      break;   
      
      case 'R': //Obrót w prawo w miejscu
        leftMotor(80);
        rightMotor(-80);
      break;

      case 'G': //Lewy luk do przodu
        leftMotor(65);
        rightMotor(95);
      break;

      case 'I': //Prawy luk do przodu
        leftMotor(95);
        rightMotor(65);
      break;

      case 'H': //Lewy luk do tylu
        leftMotor(-65);
        rightMotor(-95);
      break;

      case 'J': //Prawy luk do tylu
        leftMotor(-95);
        rightMotor(-65);
      break;
      
      case 'V':
        digitalWrite(BUZZER, 1);
        delay(200);
        digitalWrite(BUZZER, 0);
      break;
      
      case 'X':
        if (lights == false) {
          digitalWrite(LED, 1);
          lights = true;
        }
        else {
          digitalWrite(LED, 0);
          lights = false;
        }
      break;
      
      case 'A':
        jazdaAutonomiczna();
      
      break;
    }
  }
}
 
void leftMotor(int V) {
  if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 1); //Kierunek: do przodu
    analogWrite(L_PWM, V); //Ustawienie predkosci 
  } else {
    V = abs(V); //Funkcja abs() zwroci wartosc V  bez znaku
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 0); //Kierunek: do tyłu
    analogWrite(L_PWM, V); //Ustawienie predkosci    
  }
}
 
void rightMotor(int V) {
  if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 0); //Kierunek: do przodu
    analogWrite(R_PWM, V); //Ustawienie predkosci 
  } else {
    V = abs(V); //Funkcja abs() zwroci wartosc V  bez znaku
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 1); //Kierunek: do tyłu
    analogWrite(R_PWM, V); //Ustawienie predkosci    
  }
}
 
void stopMotors() {
  analogWrite(L_PWM, 0); //Wylaczenie silnika lewego
  analogWrite(R_PWM, 0); //Wylaczenie silnika prawego
}

void humitemp() {
  float wilg = dht.getHumidity();
  float temp = dht.getTemperature();
  czas = millis();
  roznica = czas - odmierz;
  if (roznica >= 1000UL){
    odmierz = czas;
    if (dht.getStatusString() == "OK"){
      mybt.print(temp);
      mybt.print(" °C");
      mybt.print("|");
      mybt.print(wilg);
      mybt.println(" %");
    }
  }
}

int zmierzOdleglosc() {
  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 jazdaAutonomiczna() {
  //Czy wykryto przeszkode w zakresie 0-40 cm
  if (zmierzOdleglosc() > 30) {
    leftMotor(95); //Jesli nie, to jedz prosto
    rightMotor(95);
  } else {
     //Jesli przeszkoda
     stopMotors(); //Zatrzymaj robota
     serwo.write(25); //Skrec czujnikiem w prawo
     delay(800); //Poczekaj 800ms dla ustabilizowania konstrukcji
 
    //Sprawdz, czy po prawej stronie jest przeszkoda
    if (zmierzOdleglosc() > 30) {
       //Jesli jest pusto
      leftMotor(80);
      rightMotor(-80);
      delay(400); //Obracaj w prawo przez 400 ms
    } else {
      //Jeśli po prawej jest przeszkoda
      serwo.write(160); //Obroc czujnik w lewo
      delay(800); //Poczekaj 800ms dla ustabilizowania konstrukcji
 
      //Sprawdz, czy po lowej stronie jest przeszkoda
      if (zmierzOdleglosc() > 30) {
         //Jesli jest pusto
        leftMotor(-80);
        rightMotor(80);
        delay(400); //Obracaj w lewo przez 400 ms
      } else {
        //Jesli z przodu, z lewej i prawej jest przeszkoda
        digitalWrite(BUZZER, 1);
        delay(500);
        digitalWrite(BUZZER, 0);
        //Daj sygnal buzzerem
      }
    }
    //Po sprawdzeniu przeszkod po bokach
    //Ustaw czujnik prosto    
    serwo.write(85);
  }
 
  //Opoznienie 100ms, ponieważ nie ma potrzeby sprawdzać przeszkod czesciej
  delay(100); 
}

 

Edytowano przez Danyeru
Link do komentarza
Share on other sites

@Danyeru film, który umieściłeś jest prywatny i nie można go zobaczyć.

Dla uporządkowania - rozumiem, że samo odłączenie czujnika sprawia, że serwo działa poprawnie, a jak podłączysz czujnik to masz poprawne odczyty, ale serwo źle działa tak? Z której dokładnie biblioteki do czujnika DHT korzystasz?

 

Link do komentarza
Share on other sites

(edytowany)

@Treker poprawiłem ten film.

Biblioteka do której kieruje tutejszy kurs:

https://github.com/markruys/arduino-DHT

Już samo odłączenie linii danych czujnika sprawia, że czkawka na serwo mija.

Podłączony czujnik działa poprawnie, wysyła odczyty zgodne z tym, co pokazuje stacja pogodowa w domu.

Podłączone i czujnik i serwo, odczyty są ok, serwo ma czkawkę.

 

EDIT:

Podpiąłem się do zasilacza, żeby się upewnić, że to nie baterie, objawy takie same.

Edytowano przez Danyeru
Link do komentarza
Share on other sites

@Danyeru niestety nie mam pod ręką dziś tych modułów, aby to sprawdzić, a analizowanie całego kodu "na oko" nie będzie dobrym rozwiązaniem. Raczej te układy nie powinny się "zakłócać". Proponuję żebyś dla testu zrobił osobny program, w którym będzie tylko DHT i serwo. Napisz jakiś krótki kod, który używa obu elementów i sprawdź czy też są takie problemy. Jeśli wszystko zadziała poprawnie, to będziemy wtedy analizować ten duży kod 😉

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

@Treker o tym samym pomyślałem, bo nie daje mi to spokoju.

Skleciłem na szybko poniższy program, przeniosłem czujnik i serwo na płytkę stykową (plug'n'play, żeby zachować okablowanie jak w robocie), i działa - dostaję odczyty z czujnika i mogę sterować serwem.
 

#include <Servo.h>
#include <DHT.h>
#define SERWO_PIN 11
#define DHT11_PIN 12
DHT dht; //Utworzenie obiektu odwolan do czujnika
Servo serwo; //Tworzeniu obiektu do odwolan do serwa
String pozycja = ""; //Zadana pozycja wprowadzona przez UART
int ruch = 0; //Zmienna przekonwertowana z pozycji
unsigned long czas = 0;
unsigned long odmierz = 0;
unsigned long roznica = 0;

void setup() {
  Serial.begin(9600);
  dht.setup(DHT11_PIN);
  serwo.attach(SERWO_PIN);
}

void loop() {
  humitemp();
  Serial.println("Witaj!");
  Serial.println("Podaj oczekiwaną pozycję (0-180)");
  while(Serial.available() == 0) {} //Czekaj na dane z portu
  pozycja = Serial.readStringUntil('\n'); //Odzczyt danych z portu
  ruch = pozycja.toInt(); //Konwersja danych z portu do zmiennej int

  if (ruch >= 0 && ruch <= 180) { //Warunek wykonywany jezeli podano liczbe z zakresu 0-180
    delay(5);
    Serial.print("Gotowe, ustawiona pozycja to: ");
    Serial.println(ruch);
    serwo.write(ruch);
  } else {
    Serial.println("Podałeś złą wartość!");
    Serial.println("Spróbuj ponownie");
    delay(200);
  }
}
void humitemp() {
  float wilg = dht.getHumidity();
  float temp = dht.getTemperature();
  czas = millis();
  roznica = czas - odmierz;
  if (roznica >= 1000UL){
    odmierz = czas;
    if (dht.getStatusString() == "OK"){
      Serial.print(temp);
      Serial.print(" °C");
      Serial.print("|");
      Serial.print(wilg);
      Serial.println(" %");
    }
  }
}

Żeby wyeliminować problem z arduino, podmieniłem to w robocie na to z płytki i dalej problem występuje przy moim programie, natomiast kiedy wgram powyższe do robota, to problem znika.
Jednakże tam linijka wstrzymuje program, w oczekiwaniu na dane i dane z czujnika wysyłają się raz przy komunikacji.
Zatem wrzuciłem jeszcze poniższe, żeby DHT nadawał cały czas (serwo na starcie miałem ustawione w innej pozycji), także się ustawia na zadaną pozycję i nie drga, nie ma czkawki.

#include <Servo.h>
#include <DHT.h>
#define SERWO_PIN 11
#define DHT11_PIN 12
DHT dht; //Utworzenie obiektu odwolan do czujnika
Servo serwo; //Tworzeniu obiektu do odwolan do serwa
int pozycja = 85; //Aktualna pozycja serwa 0-180
unsigned long czas = 0;
unsigned long odmierz = 0;
unsigned long roznica = 0;

void setup() {
  Serial.begin(9600);
  dht.setup(DHT11_PIN);
  serwo.attach(SERWO_PIN);
}

void loop() {
  humitemp();
  serwo.write(pozycja); //Wykonaj ruch

}
void humitemp() {
  float wilg = dht.getHumidity();
  float temp = dht.getTemperature();
  czas = millis();
  roznica = czas - odmierz;
  if (roznica >= 1000UL){
    odmierz = czas;
    if (dht.getStatusString() == "OK"){
      Serial.print(temp);
      Serial.print(" °C");
      Serial.print("|");
      Serial.print(wilg);
      Serial.println(" %");
    }
  }
}

Wygląda, że trzeba usiąść na spokojnie do kodu, no chyba, że ktoś będzie miał jeszcze jakiś inny pomysł, bo program robota na arduino tylko z  serwem i dht też nie powodował drgawek... 😅

Link do komentarza
Share on other sites

@Danyeru akurat zarówno serwo, jak i DHT są elementami, przy których bardzo ważne są czasy wysyłania/odbierania sygnałów. Więc widocznie coś gdzieś Ci się gryzie. Najprościej będzie teraz sprawdzać program krok po kroku. Możesz zamontowywać kolejne fragmenty kodu i sprawdzać czy problem nadal występuje.

PS Wydzielę później te pytania do innego tematu, aby nie mieszać osobom, które wykonują ćwiczenia z tej części kursu 🙂

Link do komentarza
Share on other sites

Moja głowa już nie ogarnia...

Zacząłem od programu jazdy autonomicznej, gdzie dorzuciłem funkcję czujnika.
Serwo ma się dobrze, czujnik nie wysyła poprawnych danych (albo dostaję nic, albo same nan kiedy usunę getStatusString), zmiany czasu odczekania nic nie zmieniają.

//DHT i BT
#include <SoftwareSerial.h>
#include <DHT.h>
DHT dht;
SoftwareSerial mybt(8, 7); //Tx, Rx
unsigned long czasDHT = 0;
unsigned long odmierz = 0;
unsigned long roznica = 0;
//Biblioteka od serwomechanizmu
#include <Servo.h>
Servo serwo;
#define SERWO_PIN 11
 
#define L_PWM 5
#define L_DIR 4
#define R_PWM 6
#define R_DIR 9
#define PWM_MAX 220
 
#define BUZZER 10
 
//Piny od czujnika odleglosci
#define trigPin 12
#define echoPin 13
 
void setup() {
  //Konfiguracja pinow od mostka H
  pinMode(L_DIR, OUTPUT);
  pinMode(R_DIR, OUTPUT);
  pinMode(L_PWM, OUTPUT);
  pinMode(R_PWM, OUTPUT);
 
  //Konfiguracja pozostalych elementow
  pinMode(BUZZER, OUTPUT);
  digitalWrite(BUZZER, 0); //Wylaczenie buzzera    
 
  //Czujnik odleglosci
  pinMode(trigPin, OUTPUT); //Pin, do którego podłączymy trig jako wyjście
  pinMode(echoPin, INPUT); //a echo, jako wejście
 
  //Serwo do pinu 11
  serwo.attach(SERWO_PIN);
  //Serwo na pozycje srodkowa 90 (bo zakres 0-180)
  serwo.write(85);
  Serial.begin(9600);
  mybt.begin(9600);
}
 
void loop() {
  humitemp();
  //Czy wykryto przeszkode w zakresie 0-40 cm
  if (zmierzOdleglosc() > 40) {
    leftMotor(90); //Jesli nie, to jedz prosto
    rightMotor(90);
  } else {
     //Jesli przeszkoda
     stopMotors(); //Zatrzymaj robota
     serwo.write(20); //Skrec czujnikiem w prawo
     delay(800); //Poczekaj 800ms dla ustabilizowania konstrukcji
 
    //Sprawdz, czy po prawej stronie jest przeszkoda
    if (zmierzOdleglosc() > 40) {
       //Jesli jest pusto
      leftMotor(70);
      rightMotor(-70);
      delay(400); //Obracaj w prawo przez 400 ms
    } else {
      //Jeśli po prawej jest przeszkoda
      serwo.write(160); //Obroc czujnik w lewo
      delay(800); //Poczekaj 800ms dla ustabilizowania konstrukcji
 
      //Sprawdz, czy po lowej stronie jest przeszkoda
      if (zmierzOdleglosc() > 40) {
         //Jesli jest pusto
        leftMotor(-70);
        rightMotor(70);
        delay(400); //Obracaj w lewo przez 400 ms
      } else {
        //Jesli z przodu, z lewej i prawej jest przeszkoda
        digitalWrite(BUZZER, 1);
        delay(500);
        digitalWrite(BUZZER, 0);
        //Daj sygnal buzzerem
      }
    }
    //Po sprawdzeniu przeszkod po bokach
    //Ustaw czujnik prosto    
    serwo.write(85);
  }
 
  //Opoznienie 100ms, ponieważ nie ma potrzeby sprawdzać przeszkod czesciej
  delay(100); 
}
 
void humitemp() {
  float wilg = dht.getHumidity();
  float temp = dht.getTemperature();
  czasDHT = millis();
  roznica = czasDHT - odmierz;
  if (roznica > 1000UL){
    odmierz = czasDHT;
    if (dht.getStatusString() == "OK"){
      mybt.print(temp);
      mybt.print(" °C");
      mybt.print("|");
      mybt.print(wilg);
      mybt.println(" %");
      Serial.print(temp);
      Serial.print(" °C");
      Serial.print("|");
      Serial.print(wilg);
      Serial.println(" %");
    }
  }
}

int zmierzOdleglosc() {
  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 leftMotor(int V) {
  if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 1); //Kierunek: do przodu
    analogWrite(L_PWM, V); //Ustawienie predkosci 
  } else {
    V = abs(V); //Funkcja abs() zwroci wartosc V  bez znaku
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 0); //Kierunek: do tyłu
    analogWrite(L_PWM, V); //Ustawienie predkosci    
  }
}
 
void rightMotor(int V) {
  if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 0); //Kierunek: do przodu
    analogWrite(R_PWM, V); //Ustawienie predkosci 
  } else {
    V = abs(V); //Funkcja abs() zwroci wartosc V  bez znaku
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 1); //Kierunek: do tyłu
    analogWrite(R_PWM, V); //Ustawienie predkosci    
  }
}
 
void stopMotors() {
  analogWrite(L_PWM, 0); //Wylaczenie silnika lewego
  analogWrite(R_PWM, 0); //Wylaczenie silnika prawego
}

Dorzucając od nowa, myślałem, że jest ok, bo na początku był spokój, ale jednak nie.
Program niby ten sam co pierwotny, ale tutaj serwo przez ok. pół minuty jest spokojne, potem przez ok. pół minuty ma tą czkawkę i tak w kółko...

#include "DHT.h"
#define DHT11_PIN A2
DHT dht;
unsigned long czasDHT = 0;
unsigned long odmierz = 0;
unsigned long roznica = 0;
#include <SoftwareSerial.h>
SoftwareSerial mybt(8, 7); //Tx, Rx
#include <Servo.h>
Servo serwo;
#define SERWO_PIN 11
 
#define L_PWM 5
#define L_DIR 4
#define R_PWM 6
#define R_DIR 9
#define PWM_MAX 220
 
#define BUZZER 10
 
//Piny od czujnika odleglosci
#define trigPin 12
#define echoPin 13
 
void setup()
{
  //Konfiguracja pinow od mostka H
  pinMode(L_DIR, OUTPUT);
  pinMode(R_DIR, OUTPUT);
  pinMode(L_PWM, OUTPUT);
  pinMode(R_PWM, OUTPUT);
 
  //Konfiguracja pozostalych elementow
  pinMode(BUZZER, OUTPUT);
  digitalWrite(BUZZER, 0); //Wylaczenie buzzera    
 
  //Czujnik odleglosci
  pinMode(trigPin, OUTPUT); //Pin, do którego podłączymy trig jako wyjście
  pinMode(echoPin, INPUT); //a echo, jako wejście
  Serial.begin(9600);
  mybt.begin(9600);
  dht.setup(DHT11_PIN);
  serwo.attach(SERWO_PIN); 
}
 
void loop() {
  humitemp();
  if (mybt.available() > 0){
     char jazda = mybt.read(); //Odczyt danych z BT
     switch(jazda) {
      case 'F': //Do przodu
        leftMotor(95);
        rightMotor(95);
      break;
 
      case 'B': //Do tyłu
        leftMotor(-95);
        rightMotor(-95);
      break;
 
      case 'S': //STOP
        stopMotors();
      break;
 
      case 'L': //Obrót w lewo w miejscu
        leftMotor(-80);
        rightMotor(80);
      break;   
      
      case 'R': //Obrót w prawo w miejscu
        leftMotor(80);
        rightMotor(-80);
      break;
 
      case 'G': //Lewy luk do przodu
        leftMotor(65);
        rightMotor(95);
      break;
 
      case 'I': //Prawy luk do przodu
        leftMotor(95);
        rightMotor(65);
      break;
 
      case 'H': //Lewy luk do tylu
        leftMotor(-65);
        rightMotor(-95);
      break;
 
      case 'J': //Prawy luk do tylu
        leftMotor(-95);
        rightMotor(-65);
      break;
      
      case 'V':
        digitalWrite(BUZZER, 1);
        delay(200);
        digitalWrite(BUZZER, 0);
      break;
      
      case 'A':
        jazdaAuto();
      break;
    }
  }
}
 
void humitemp()
{
  //Pobranie informacji o wilgotnosci
  int wilgotnosc = dht.getHumidity();
  //Pobranie informacji o temperaturze
  int temperatura = dht.getTemperature();
  czasDHT = millis();
  roznica = czasDHT - odmierz;
  
  if (roznica >= 1000UL){ 
    odmierz = czasDHT;
    if (dht.getStatusString() == "OK") {
      mybt.print(temperatura);
      mybt.print(" °C");
      mybt.print("|");
      mybt.print(wilgotnosc);
      mybt.println(" %");
    }
  }
}
 
int zmierzOdleglosc() {
  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 leftMotor(int V) {
  if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 1); //Kierunek: do przodu
    analogWrite(L_PWM, V); //Ustawienie predkosci 
  } else {
    V = abs(V); //Funkcja abs() zwroci wartosc V  bez znaku
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 0); //Kierunek: do tyłu
    analogWrite(L_PWM, V); //Ustawienie predkosci    
  }
}
 
void rightMotor(int V) {
  if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 0); //Kierunek: do przodu
    analogWrite(R_PWM, V); //Ustawienie predkosci 
  } else {
    V = abs(V); //Funkcja abs() zwroci wartosc V  bez znaku
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 1); //Kierunek: do tyłu
    analogWrite(R_PWM, V); //Ustawienie predkosci    
  }
}
 
void stopMotors() {
  analogWrite(L_PWM, 0); //Wylaczenie silnika lewego
  analogWrite(R_PWM, 0); //Wylaczenie silnika prawego
}
 
void jazdaAuto() {
  //Czy wykryto przeszkode w zakresie 0-40 cm
  if (zmierzOdleglosc() > 40) {
    leftMotor(90); //Jesli nie, to jedz prosto
    rightMotor(90);
  } else {
     //Jesli przeszkoda
     stopMotors(); //Zatrzymaj robota
     serwo.write(20); //Skrec czujnikiem w prawo
     delay(800); //Poczekaj 800ms dla ustabilizowania konstrukcji
 
    //Sprawdz, czy po prawej stronie jest przeszkoda
    if (zmierzOdleglosc() > 40) {
       //Jesli jest pusto
      leftMotor(70);
      rightMotor(-70);
      delay(400); //Obracaj w prawo przez 400 ms
    } else {
      //Jeśli po prawej jest przeszkoda
      serwo.write(160); //Obroc czujnik w lewo
      delay(800); //Poczekaj 800ms dla ustabilizowania konstrukcji
 
      //Sprawdz, czy po lowej stronie jest przeszkoda
      if (zmierzOdleglosc() > 40) {
         //Jesli jest pusto
        leftMotor(-70);
        rightMotor(70);
        delay(400); //Obracaj w lewo przez 400 ms
      } else {
        //Jesli z przodu, z lewej i prawej jest przeszkoda
        digitalWrite(BUZZER, 1);
        delay(500);
        digitalWrite(BUZZER, 0);
        //Daj sygnal buzzerem
      }
    }
    //Po sprawdzeniu przeszkod po bokach
    //Ustaw czujnik prosto    
    serwo.write(85);
  }
 
  Opoznienie 100ms, ponieważ nie ma potrzeby sprawdzać przeszkod czesciej
  //delay(100); 
}

 

Link do komentarza
Share on other sites

Tonący brzydkiej się chwyta, może to nieładnie, ale spróbowałem wyłączyć urządzenie, które nie działa, czyli serwo w setupie zapinam, ustawiam na pozycję wyjściową i odpinam. Czkawka minęła. 😅

Teraz drugi problem, o którym napomknąłem wcześniej.
Kod jazdy autonomicznej ładnie działa w pętli głównej (czemu ma nie działać, skoro jest z kursu), ale jak przenoszę go do osobnej funkcji, którą wywołuję w switch case, to już nie działa.

Jeżeli zasłonię czujnik z przodu i wywołam case, to obróci się w prawo i nie widząc przeszkód przeszkód zaczyna obrót w prawo, ale nie przerywa go po tych 400 ms.
Jeżeli zasłonię czujnik z przodu i z prawej, to obraca się w lewo i jak wyżej, uruchamia silnika do obrotu w lewo i nie przerywa.
Jeżeli nie zasłonię czujnika od razu, to po wywołaniu tego case robot zaczyna jechać do przodu i wjeżdża w przeszkody.
Aktualnie w kodzie są te zapięcia/odpięcia serewa, ale wcześniej było tak samo (przy tej serwo-czkawce).
Wrzuciłem funkcję pomiaru odległości do loopa, bo pomyślałem, że może coś w tej kwestii (jak drukowałem dystans, to otrzymywałem 0, po wrzuceniu do loopa, zacząłem otrzymywać odczyty).

Może czegoś z tym switch case nie ogarnąłem?
Na tym etapie do szczęścia brakuje mi tego, żeby mi się robot nie obijał. 😄

A jazda autonomiczna jest w case, bo generalnie ma być sterowany ręcznie, ale czasami też ma zostać pozostawiony sam sobie.

Kod z serwem bez czkawki poprzez jego odpięcie:

#include "DHT.h"
#define DHT11_PIN A2
DHT dht;
unsigned long czasDHT = 0;
unsigned long odmierz = 0;
unsigned long roznica = 0;
#include <SoftwareSerial.h>
SoftwareSerial mybt(8, 7); //Tx, Rx
#include <Servo.h>
Servo serwo;
#define SERWO_PIN 11
 
#define L_PWM 5
#define L_DIR 4
#define R_PWM 6
#define R_DIR 9
#define PWM_MAX 220
 
#define BUZZER 10
 
//Piny od czujnika odleglosci
#define trigPin 12
#define echoPin 13
long dystans = 0;
long czas = 0;
 
void setup()
{
  //Konfiguracja pinow od mostka H
  pinMode(L_DIR, OUTPUT);
  pinMode(R_DIR, OUTPUT);
  pinMode(L_PWM, OUTPUT);
  pinMode(R_PWM, OUTPUT);
 
  //Konfiguracja pozostalych elementow
  pinMode(BUZZER, OUTPUT);
  digitalWrite(BUZZER, 0); //Wylaczenie buzzera    
 
  //Czujnik odleglosci
  pinMode(trigPin, OUTPUT); //Pin, do którego podłączymy trig jako wyjście
  pinMode(echoPin, INPUT); //a echo, jako wejście
  Serial.begin(9600);
  mybt.begin(9600);
  dht.setup(DHT11_PIN);
  serwo.attach(SERWO_PIN);
  serwo.write(85);
  delay(200);
  serwo.detach();
}
 
void loop() {
  humitemp();
  zmierzOdleglosc();  
  if (mybt.available() > 0){
     char jazda = mybt.read(); //Odczyt danych z BT
     switch(jazda) {
      case 'F': //Do przodu
        leftMotor(95);
        rightMotor(95);
      break;
 
      case 'B': //Do tyłu
        leftMotor(-95);
        rightMotor(-95);
      break;
 
      case 'S': //STOP
        stopMotors();
      break;
 
      case 'L': //Obrót w lewo w miejscu
        leftMotor(-80);
        rightMotor(80);
      break;   
      
      case 'R': //Obrót w prawo w miejscu
        leftMotor(80);
        rightMotor(-80);
      break;
 
      case 'G': //Lewy luk do przodu
        leftMotor(65);
        rightMotor(95);
      break;
 
      case 'I': //Prawy luk do przodu
        leftMotor(95);
        rightMotor(65);
      break;
 
      case 'H': //Lewy luk do tylu
        leftMotor(-65);
        rightMotor(-95);
      break;
 
      case 'J': //Prawy luk do tylu
        leftMotor(-95);
        rightMotor(-65);
      break;
      
      case 'V':
        digitalWrite(BUZZER, 1);
        delay(200);
        digitalWrite(BUZZER, 0);
      break;
      
      case 'A':
        jazdaAuto();
      break;
    }
  }
}
 
void humitemp()
{
  //Pobranie informacji o wilgotnosci
  int wilgotnosc = dht.getHumidity();
  //Pobranie informacji o temperaturze
  int temperatura = dht.getTemperature();
  czasDHT = millis();
  roznica = czasDHT - odmierz;
  
  if (roznica >= 1000UL){ 
    odmierz = czasDHT;
    if (dht.getStatusString() == "OK") {
      mybt.print(temperatura);
      mybt.print(" °C");
      mybt.print("|");
      mybt.print(wilgotnosc);
      mybt.println(" %");
    }
  }
}
 
int zmierzOdleglosc() {
  digitalWrite(trigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);
 
  czas = pulseIn(echoPin, HIGH);
  dystans = czas / 58;
  
  return dystans;
}
 
void leftMotor(int V) {
  if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 1); //Kierunek: do przodu
    analogWrite(L_PWM, V); //Ustawienie predkosci 
  } else {
    V = abs(V); //Funkcja abs() zwroci wartosc V  bez znaku
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(L_DIR, 0); //Kierunek: do tyłu
    analogWrite(L_PWM, V); //Ustawienie predkosci    
  }
}
 
void rightMotor(int V) {
  if (V > 0) { //Jesli predkosc jest wieksza od 0 (dodatnia)
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 0); //Kierunek: do przodu
    analogWrite(R_PWM, V); //Ustawienie predkosci 
  } else {
    V = abs(V); //Funkcja abs() zwroci wartosc V  bez znaku
    V = map(V, 0, 100, 0, PWM_MAX);
    digitalWrite(R_DIR, 1); //Kierunek: do tyłu
    analogWrite(R_PWM, V); //Ustawienie predkosci    
  }
}
 
void stopMotors() {
  analogWrite(L_PWM, 0); //Wylaczenie silnika lewego
  analogWrite(R_PWM, 0); //Wylaczenie silnika prawego
}
 
void jazdaAuto() {
  //Czy wykryto przeszkode w zakresie 0-40 cm
  if (zmierzOdleglosc() > 40) {
    leftMotor(90); //Jesli nie, to jedz prosto
    rightMotor(90);
  } else {
     //Jesli przeszkoda
     serwo.attach(SERWO_PIN);
     stopMotors(); //Zatrzymaj robota
     serwo.write(20); //Skrec czujnikiem w prawo
     delay(800); //Poczekaj 800ms dla ustabilizowania konstrukcji
 
    //Sprawdz, czy po prawej stronie jest przeszkoda
    if (zmierzOdleglosc() > 40) {
      //Jesli jest pusto
      leftMotor(70);
      rightMotor(-70);
      serwo.write(85);
      delay(400); //Obracaj w prawo przez 400 ms
      serwo.detach();
    } else {
      //Jeśli po prawej jest przeszkoda
      serwo.write(160); //Obroc czujnik w lewo
      delay(800); //Poczekaj 800ms dla ustabilizowania konstrukcji
 
      //Sprawdz, czy po lowej stronie jest przeszkoda
      if (zmierzOdleglosc() > 40) {
        //Jesli jest pusto
        leftMotor(-70);
        rightMotor(70);
        serwo.write(85);
        delay(400); //Obracaj w lewo przez 400 ms
        serwo.detach();
      } else {
        //Jesli z przodu, z lewej i prawej jest przeszkoda
        digitalWrite(BUZZER, 1);
        delay(500);
        digitalWrite(BUZZER, 0);
        //Daj sygnal buzzerem
      }
    }
  }
 
  //Opoznienie 100ms, ponieważ nie ma potrzeby sprawdzać przeszkod czesciej
  delay(100); 
}

 

Link do komentarza
Share on other sites

11 godzin temu, Danyeru napisał:

Tonący brzydkiej się chwyta, może to nieładnie, ale spróbowałem wyłączyć urządzenie, które nie działa, czyli serwo w setupie zapinam, ustawiam na pozycję wyjściową i odpinam. Czkawka minęła. 😅

To może to jest jednak jakiś problem z zasilaniem? Warto sprawdzić czy jakiś kondensator przy zasilaniu serwa nie wyeliminuje tego problemu.

11 godzin temu, Danyeru napisał:

Jeżeli zasłonię czujnik z przodu i wywołam case, to obróci się w prawo i nie widząc przeszkód przeszkód zaczyna obrót w prawo, ale nie przerywa go po tych 400 ms.

Jeśli dobrze widzę, to robot przechodzi do trybu autonomicznej jazdy po naciśnięciu odpowiedniego klawisza, ale... wtedy wykonuje tę funkcję raz i koniec. Żeby robot działał autonomicznie to ta funkcja musiałaby wykonywać się w jakiejś pętli. Pytanie jak z niej wyjść -  tu już musisz pogłówkować, aby znaleźć jakieś sensowne rozwiązanie 🙂

Link do komentarza
Share on other sites

3 godziny temu, Treker napisał:

Jeśli dobrze widzę, to robot przechodzi do trybu autonomicznej jazdy po naciśnięciu odpowiedniego klawisza, ale... wtedy wykonuje tę funkcję raz i koniec. Żeby robot działał autonomicznie to ta funkcja musiałaby wykonywać się w jakiejś pętli. Pytanie jak z niej wyjść -  tu już musisz pogłówkować, aby znaleźć jakieś sensowne rozwiązanie 🙂

Tak mnie z rana olśniło, że switch case wykonuje się raz. 😅
Zmyliło mnie trochę, że nie kończył obrotów po zadanym delayu.

Jakiś pomysł na pętlę oflagowaną/sterowaną booleanem mi w głowie świta, zobaczymy, czy dobrze kombinuję. Dam znać na pewno. 😁

 

3 godziny temu, Treker napisał:

To może to jest jednak jakiś problem z zasilaniem? Warto sprawdzić czy jakiś kondensator przy zasilaniu serwa nie wyeliminuje tego problemu.

Dla upewnienia. Buduję się na tym shieldzie z kursu. Kondenstar wpiąć tam, gdzie wpinam serwo na tej płytce? 🙂

Link do komentarza
Share on other sites

@Danyeru

1 godzinę temu, Danyeru napisał:

Tak mnie z rana olśniło, że switch case wykonuje się raz. 😅
 

Generalnie case wykonuje się tak do jak if...czyli dopóki zmienna w switch ma wartość danego case to ten case się wykonuje...oczywiście po zakończeniu case program go opuszcza i leci dalej z kodem .

 

Link do komentarza
Share on other sites

Jazdę autonomiczną włączaną przez case ogarnąłem ifem i booleanem.

 

boolean autonomik = false;
case 'A':
  autonomik = !autonomik;
break;
  if(autonomik){
    jazdaAuto();
  }

Działa tak, jak chciałem. 😄

 

 

39 minut temu, Treker napisał:

@Danyeru tak, kondensator możesz tam wpiąć między GND, a Vcc.

Niestety, ani na serwie, ani na DHT (bo też spróbowałem) nie pomogło.
Spróbowałem 222 uF, 1000 uF, 1000 + 220 uF i 2 x 1000 uF.

 

 

14 minut temu, farmaceuta napisał:

@Danyeru

Generalnie case wykonuje się tak do jak if...czyli dopóki zmienna w switch ma wartość danego case to ten case się wykonuje...oczywiście po zakończeniu case program go opuszcza i leci dalej z kodem .

 

Tak. Źle się wyraziłem. Chodziło mi o to, że w moim przypadku, bo nie wysyłam ciągle tego A, tylko wysyłam raz i czekam co dalej.

Link do komentarza
Share on other sites

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.