Skocz do zawartości

Pomocna odpowiedź

Podoba Ci się ten projekt? Zostaw pozytywny komentarz i daj znać autorowi, że zbudował coś fajnego!

Masz uwagi? Napisz kulturalnie co warto zmienić. Doceń pracę autora nad konstrukcją oraz opisem.

@ZbychuW ciekawy projekt, dziękujemy za publikację 🙂 

9 godzin temu, ZbychuW napisał:

Po stronie Ardiuno, cała kontrola napędów i czujników. Po stronie RPi moduł rozpoznawania obrazów bazujący na OpenCV, generator komunikatów słownych wykorzystujący kartę dźwiękową WM8960 oraz moduł odwzorowania terenu wykorzystujący pomiary odległości, lokalizację w pomieszczeniu i rozpoznawanie przedmiotów.

Mógłbyś umieścić kod programu lub inne szczegóły?

Link to post
Share on other sites
(edytowany)

Ponieważ kod programów po stronie RPi i Arduino jest dosyć obszerny postanowiłem umieszczać poszczególne fragmenty z odpowiednimi komentarzami. 

Na pierwszy ogień sterowanie silnikami DC z enkoderami. W załączniku umieściłem kod programu na Arduino po usunięciu wszystkich zbędnych fragmentów. W kolejnych wpisach będę dodawał opisu kolejnych funkcji.

Do napędu wykorzytuję 4 silniki z enkoderami (SJ02 120:1 6V 160RPM + enkoder). Umieszczone w dolnej części podstawy i mocowane za pomocą wsporników wydrukowanych na drukarce Ender 3D (pliki w formacie STL w załączniku - lewy i prawy) . Do paczki plików dodałem elementy osłony kabli, ochrony otworu w podstawie i podstawkę pod Arduino.

Ponieważ wykorzystuje 4 silniki i do każdego należy utworzyć niezależne zmenne i metody, do osbługi utworzyłem klasę Motor. Opis znaczenia poszczególnych zmiennych i metod znajduje się w komentarzach kodu.

Najważniejsze w programie są dwa elementy: obsługa enkodera i algorytm PID.

Kluczowym elementem umożliwiającym odczyt pulsów z enkodera jest metoda podpięta pod odpowiednie przerwanie. Ponieważ liczba dostępnych przerwań jest zależna od modelu Arduino a ja potrzebowałem aż 4 wybrałem wersję Mega. Udostępnia ona aż 6 przerwań (https://www.arduino.cc/en/Reference/AttachInterrupt) . W moim przykładzie wykorzystuję przerwania  2,3,4,5 podpięte do pinów 21,20,19 i 18.

void interrupt(int motorId) 
{
  int val = digitalRead(motors[motorId].getEncoderPinB());
  if(val == LOW && motors[motorId].getDirection() == FORWARD)
  {
    motors[motorId].setDirection(BACKWARD);
  }
  else if(val == HIGH && motors[motorId].getDirection() == BACKWARD)
  {
    motors[motorId].setDirection(FORWARD);
  }

  if(motors[motorId].getDirection() == BACKWARD)  
    motors[motorId].IncreasePulses();
  else  
    motors[motorId].DecreasePulses();
}  

Metoda interrupt() przy zmianie stanu na niski na odpowiednim pinie (port A enkodera) sprawdza stan na pinie portu B i w zależności od stanu pinu jest w stanie określić kierunek obrotu silnika.  

Każde wywołanie metody zwiększa lub zmniejsza licznik pulsów. 

Liczba ta jest istotna, ponieważ jest przekazywana na wejście do algorytmu PID.

Do obsługi algorytmu wykorzytałem standardową bibliotekę  Arduino-PID-Library. W każdym obiekcie utworzonym z klasy Motor jest jeden obiekt klasy PID.

void calculateSpeed()
    {
      input = abs(pulses);
      int result=pid->Compute();//Po okresie ustalonym w parametrze, algorytm wylicza wymaganą prędkość silnika
      if (result)
      {
        motor->setSpeed(output); //ustawienie nowej prędkości silnika
        pulses = 0; //zerowanie licznika  
      }
    }

Algorytm PID jest wywoływany co 100 milisekund (pid->SetSampleTime(100)) w trybie automatycznym (pid->SetMode(AUTOMATIC)). Oznacza to, że co 0.1 sekundy na wejście algorytmu podawany jest aktualny stan licznika pulsów enkodera. Jeśli algorytm stwierdzi odchylenia od wymaganej prędkości obrotowej (speed), koryguje odpowiednio prędkość chwilową (output). Kluczowe są tutaj odpowiednie wielkości parametru proporcjonalnego, całkującego i różniczkującego (Kp, Ki, Kd). Testowałem wiele opcji i te podane w kodzie dają "miekkie" dochodzenie do prędkości wymaganej.

Prędkość poszczególnych silników jest ustalana w programie Python uruchomionym na Raspberrypi. Wysyła od odpowiednie polecenia w zależności od ustalonego kierunku i ewentualnych od niego odchyleń. Ponieważ pojazd nie ma osi skrętnej, zakręty są realizowane odpowiednimi nastawami poszczególnych kół. Wspomnę tylko, że za kontrole kierunku odpowiedzialny jest moduł IMU (GY-801). Ale o tym w kolejnym wpisie. 

Pozdrawiam

Zbigniew Włodarczyk   

AutonomicznyRobot-PID.zip

Edytowano przez ZbychuW
  • 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

A ja tak z ciekawości - co poprawiałeś w espeaku? Pytam bo oryginalnie tabele translacji i parę funkcji specyficznych dla polskiego były moje, ale w ng ktoś to równo spaprał...

Link to post
Share on other sites

Nie zmieniałem nic w pakietach. Jedynie podmieniłem pliki definicji dźwięków. Korzystałem z tutoriala na youtube:

 

Link to post
Share on other sites

Rozwiązanie nie jest na razie doskonałe, bo przytyka mi trochę RPi, gdy generuję dźwięk. Ograniczam się do prostych komunikatów z informacjami o zmianach trasy więc jakość nie jest kluczowa. 

Jeśli masz jakieś doświadczenie i porady, chętnie skorzystam 🙂

 

Link to post
Share on other sites

Czyli po prostu zmieniłeś głos z Klatta na Mbrolę.

15 godzin temu, ZbychuW napisał:

Jeśli masz jakieś doświadczenie i porady, chętnie skorzystam

A na przykład Kedrigern

Też oparty na Mbroli. Działa bez problemu z Pythonem (tylko poczekaj na nową wersję softu, albo dziś wieczorem albo jutro wrzucę) bo te mają błąd.

A tak przy okazji - Klatt jest chyba bardziej czytelny (przynajmniej w przypadku eSpeaka) niż kulejąca Mbrola.

 

Link to post
Share on other sites
(edytowany)

Uruchomiłem tą wersję, którą znalazłem na twoim repozytoriu. Muszę powiedzieć, że efekt jest bardzo dobry. Sprawdzę, jak wrzucisz coś nowego.

Narazie uruchamiam polecenia z poziomu pythona wywołując linie poleceń

import subprocess as cmdLine
cmdLine.run("clear")
speech = 'Uwaga, skręcam w prawo'
command = 'milena_say ' + chr(34) + speech + chr(34)


result = cmdLine.run(command, shell=True, capture_output=True, text=True)

Nie udało mi sie uruchomić serwera ponieważ jest niezgodność wersji bibliotek.

Edytowano przez ZbychuW
Link to post
Share on other sites

Najlepiej skompilować wszystko samemu, wtedy biblioteki będą pasować. Zresztą począwszy od tych wersji nie będzie już plików deb (właśnie ze względu na biblioteki).

Milena: ściągasz najnowszą wersję z http://milena.polip.com/download.shtml - aktualnie http://www.polip.com/files/milena-0.2.95.1.tar.gz

Rozpakowujesz, wchodzisz w rozpakowany katalog i instalujesz przez:

sudo bash install_rpi.sh

Zresztą jeśli masz w miarę świeżą wersję Mileny to możesz na razie jej używać.

Co do kedrigerna:

ściągasz najnowszą wersję źródeł - aktualnie http://www.polip.com/files/raspberry/kedrigern_0.2.3.orig.tar.gz i http://www.polip.com/files/raspberry/libkedrigern_0.2.2.orig.tar.gz

Dla każdego pliku rozpakowujesz go, wchodzisz do rozpakowanego katalogu i wykonujesz:

make && sudo make install

Reszta jak w opisie na stronie.

Ważne aby użyć kedrigerna w wersji 0.2.3!

Twój sposób oczywiście zadziała - pod warunkiem że nie będzie znaku " w tekście. Poza tym blokuje to działanie programu (kedrigern nie).

 

 

Link to post
Share on other sites

@ZbychuW jakby były dalej jakieś problemy to pisz - kedrigern był stworzony przede wszystkim do takich zastosowań jak Twoje i dobrze by było, aby działał bezbłędnie.

Link to post
Share on other sites
(edytowany)

Witam ethanak. Pobrałem wskazane biblioteki ale wydaje mi sie, że brakuje plików. 

Przy kompilacji dostaję komunikat: audio.c:27:10: fatal error: ao/ao.h: No such file or directory

Szukałem tego pliku w pozostałych repozytoriach ale nie mogę znaleźć. Czy to z innej paczki, czy coś robię nie tak?

To z pakietu libao ? Mam, przynajmniej teoretycznie, zainstalowany

pi@raspberrypi:~ $ sudo apt search libaio
Sorting... Done
Full Text Search... Done
libaio-dev/stable 0.3.112-9+rpi1 armhf
  Linux kernel AIO access library - development files

libaio1/stable,now 0.3.112-9+rpi1 armhf [installed]
  Linux kernel AIO access library - shared library


 

Edytowano przez ZbychuW
Link to post
Share on other sites

libao-dev (potrzebny do kompilacji)

Później napiszę więcej, wypadam do lekarza. Przepraszam za sklerozę 🙂

Link to post
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.