Skocz do zawartości

Zapis danych z portu i sterowanie serwem


Mialek

Pomocna odpowiedź

Witam wszystkich 😁

Mam arduino UNO do którego przesyłam dane za pomocą portu szeregowego. Dane wyglądają następująco(przykład):

1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,1,1,1,1,1,11,11,

Dane są z jedynek i zer, wysyłane są od nowej Lini. Po serii jedynek, jak zaczną się zera(nie jedno, minimum np.5) serwo ma wykonać ruch, znów po serii jedynek np. 5 jedynkach pod rząd, i pieciu zerach, wykonaj ruch.

Stworzyłem taki kod, ale nie działa za dobrze, jak zapisywać do zmiennych po kolei dane z portu szeregowego ? np. 10 zmiennych które mają się zapisywać jak pętla?


#include <Servo.h>
Servo myservo;
String odebraneDane = ""; //Pusty ciąg odebranych danych
String l1 = "";
String l2 = "";
String l3 = "";
String l4 = "";
String l5 = "";
String l6 = "";
String l7 = "";
void setup() {
  Serial.begin(9600); //Uruchomienie komunikacji
  myservo.attach(3);
}
 
void loop() {
  myservo.write(20);
  if(Serial.available() > 0) { 
    
    odebraneDane = Serial.readStringUntil('\n'); 
    Serial.println("dane" + odebraneDane); 
  }
    
    if(odebraneDane == "1" && Serial.available() > 0) {
    l1 = Serial.readStringUntil('\n');
    Serial.println("l1 " + l1);
    
    }
    if(odebraneDane == "1" && l1 == "1" && Serial.available() > 0) {
    l2 = Serial.readStringUntil('\n');
    Serial.println("l2 " + l2);
    
    }
    if(odebraneDane == "1" && l1 == "1" && l2 == "1" && Serial.available() > 0) {
    l3 = Serial.readStringUntil('\n');
    Serial.println("l3 " + l3);
    
    } 
    if(odebraneDane == "1" && l1 == "1" && l2 == "1" && l3 == "1" && Serial.available() > 0) {
    l4 = Serial.readStringUntil('\n');
    Serial.println("l4 " + l4);
    
    } 
    if(odebraneDane == "1" && l1 == "1" && l2 == "1" && l3 == "1" && l4 == "1" && Serial.available() > 0) {
    l5 = Serial.readStringUntil('\n');
    Serial.println("l5 " + l5);
    
    }              
      }

Przepraszam, troszkę ciężko mi to wytłumaczyć co chcę osiągnąć, pytajcie.

Dzięki 🤠

Link do komentarza
Share on other sites

4 godziny temu, Mialek napisał:

Stworzyłem taki kod, ale nie działa za dobrze, jak zapisywać do zmiennych po kolei dane z portu szeregowego ? np. 10 zmiennych które mają się zapisywać jak pętla?

Zawsze możesz stworzyć tablicę i po kolei wpisywać w pętli 😉 a jak już jesteśmy przy tablicach.. to wskaźniki... ale tutaj urywam

Link do komentarza
Share on other sites

Anonim
4 godziny temu, Mialek napisał:

Stworzyłem taki kod, ale nie działa za dobrze, jak zapisywać do zmiennych po kolei dane z portu szeregowego ? np. 10 zmiennych które mają się zapisywać jak pętla?

Cóż, może spróbuj właśnie tejże pętli rzeczonej? może for z ifem w środku? Masz głowę i h..umor to kombinuj.

Link do komentarza
Share on other sites

Ja bym do tego sprawdzania tak ogólnie to użył przesuwania bitowego, coś takiego jak rejestr przesuwny może już miałeś okazję zobaczyć.

W skrócie:

biorę np. 1 bajt (jakaś zmienna)

{
odbieramdane
jeśli 1 to np. najmłodszy bit dostaje wartość 1
jeśli 0 to ten sam bit dostaje wartość 0
przesuwam bity tego bajtu w odpowiednią stronę
 

i tutaj: jeśli te 5 bitów mają wartość 11111 (zwykłe porównanie) to zrób to, jeśli coś innego to coś innego i tak dalej
}

 

Edytowano przez BananWszyscy
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

Rozumiem że to ma działać tak:

Idą sobie jedynki. Idą, idą... zaczynają iść zera. Po piątym zerze serwo się rusza. Następnie idą sobie dalej zera, nie reagujemy, aż znowu pójdą sobie jedynki...

Jeśli tak, to nie trzeba w ogóle zapisywać żadnych bitów. Wystarczy liczyć zera, reagować gdy licznik osiągnie wartość 5 i zerować go przy otrzymaniu jedynki. Oczywiście licznik musi być zerowany również na początku linii.

Coś w stylu:

static int licznik;

if (odebrany_bit == 1) {
   licznik = 0;
}
else {
	if (++licznik == 5) rusz_serwem();
}

Oczywiście, jeśli również ilość jedynek jest ważna (w pierwszej części zdania o tym nie wspomniałeś, w drugiej coś tam było o pięciu) potrzebne będą dwa liczniki i trochę bardziej rozbudowany kod. W żadnym razie nie trzeba pamiętać poszczególnych bitów.

W podobny sposób przekazywane są dane np. w faxach (zamiast poszczególnych bitów przesyła się po prostu informacje o długości ciągów jedynek i zer, kompresja G4). Podobnie kompresowane są np. formaty BMP czy Amigowe IFF/ILBM (kompresja G4 to szczególny przypadek kompresji RLE).

9 godzin temu, Mialek napisał:

troszkę ciężko mi to wytłumaczyć

Mógłbyś np. pokazać przykładowe ciągi i zaznaczyć, w którym momencie ma reagować serwo... a przy okazji co zrobić, jeśli odebranym znakiem nie będzie ani jedynka, ani zero, ani znak nowej linii.

Link do komentarza
Share on other sites

Czy znak(i) nowej linii łamie regułę liczenia długości ciągów czy nie, a jeśli nie to po co w ogóle je przesyłać? Czy to tylko formatowanie bo nie umiesz wysyłać bez podziału na linie, czy ma to jakiś głębszy sens?

Co dokładnie oznacza " serwo ma wykonać ruch"? Czy ma się przesunąć dokładnie o ileśtam np. stopni (w którą stronę) czy ma zacząć ruch a zatrzymać się kiedyś w przyszłości (kiedy?). I co ma się stać gdy serwo jeszcze jedzie w jedną stronę (i nie wykonało pełnego zaplanowanego(?) przesunięcia) a ciąg już wskazuje na konieczność zawrócenia? Jak często przychodzą te znaki/komendy?

Najlepiej byłoby, gdybyś raczej opisał skąd się te ciągi liczb biorą (próbkowanie jakiegoś czujnika?) i jaki jest sens tego sterowania, tj. co to serwo naprawdę robi. Czy zamyka/otwiera jakiś zawór czy ma nadążnie śledzić położenie czegoś, ale bez drgawek (stąd opóźnienia 5 cykli) itp. Wtedy każdy by sobie sam odpowiedział ne wszystkie szczegółowe pytania, bo by rozumiał ideę. Co więcej, być może można wymyślić znacznie lepszy sposób sterowania niż to co opisałeś. Może jakieś filtrowanie sygnału i sterowanie analogowe zamiast pewnego rodzaju histerezy jaką próbujesz wprowadzić. Musimy rozumieć co tam się dzieje. Teraz to wygląda tak: zróbcie mi pewną magię zmyśloną na kolanie żeby działało to co skleciłem, ale sam nie wiem jak.

Link do komentarza
Share on other sites

(edytowany)

Dzięki za odpowiedzi 🤩

 

Tworzę sortownik, mam komputer z ubuntu i bibliotekami przetwarzania obrazu.

Skleiłem program który wykrywa złe nasiona.

Czyli:

Mam podpiętą kamerkę usb która patrzy na taśmociąg, program do arduino po porcie wysyła co klatkę(ok. 30 klatek/s)

Zero - jeźeli nie ma nic lub leci dobre.

Jedynkę - gdy na danej klatce wykryje złe nasionko.

Za kamerą jest servo które ma za zadanie przesunąć ziarno.

Więc zadaniem arduino jest ruch serwa po serii jedynek, gdy zaczną się zera.

 

000000000000001111111111111111111111111110000000000000000001111111111111111111111000000000000000000000

l_________________l_________________________________l______________________l___________________________l__________________________l

              l                                                 l                                                l                                                 l                                                 l

          brak                                   złe nasiono                                    brak                                    złe nasiono                                   brak, lub dobre.

 

Czasami gdy leci dobre złapie jako złe przez jedną lub dwie klatki, tak samo gdy leci złe, zrobi lekką przerwę, przykad:

00000001000000000001111111111111110101111111111110000000000000000000111111111111011111111111000000000000000000

 

W tej sytuacji może inne rozwiązanie będzie lepsze?

Dzięki za pomoc !!! 😉

Edytowano przez Mialek
Link do komentarza
Share on other sites

To nie lepiej zwalić całą robotę na Ubunciaka, a do Arduino przesyłać tylko sygnał "machnij serwem"?

Poza tym po jakiego grzyba tam znaki nowej linii?

Jeśli serwem masz machnąć jak wykryjesz złe/dobre nasionko skąd jakieś minimalne wartości w ciągu "dobry/zły"? Nie mogą być po kolei dwa dobre albo dwa złe?

 

Link do komentarza
Share on other sites

Dzięki za odpowiedź.

Hehe, tak, mogą być po kolei dwa złe, czy też dobre, gdzie w tym przypadku będzie 90% dobrych a 10% złych.

Program do wykrywania, jak napisałem, skleiłem z różnych gotowych źródeł z github, i ciężko mi cokolwiek edytować bo się na tym za bardzo nie znam 🙃

Metodą prób i błędów udało mi się wszystko skleić. 

Oczywiście że lepiej żeby ubuntu dawało sygnał o ruchu, tylko nie potrafię tego zrobić 😰

Udało mi się dodać wysyłanie do arduino danych, klatka po klatce, i do arduino jest więcej poradników i gotowych rozwiązań, więc zdecydowałem że będzie mi łatwiej na nim to ogarnąć ale jak widać idzie średnio 😫

 

 

Link do komentarza
Share on other sites

51 minut temu, Mialek napisał:

ale jak widać idzie średnio

Jeszcze nic się nie zadziało a Ty już nos na kwintę. Przecież na razie jesteś w fazie opowiadania nam co w ogóle robisz i jak ma to działać. Machanie serwem - nawet z jakimś tam filtrowaniem ciągu danych jest trywialne. Oczywistym więc, że nikt kto się zna na tego typu programowaniu (nawet i w Arduino) nie skupia się na tej podstawowej funkcjonalności - bo to pestka - tylko myśli jakby tu coś poprawić albo ulepszyć działanie Twojego pomysłu. To bardzo ładne zadanie i można się naprawdę wykazać (A Ty i tak już odwaliłeś kawał roboty), ale na mojego nosa diabeł może tkwić w szczegółach i poprawne i niezawodne działanie urządzenia może być trudne do osiągnięcia (easy to play, hard to master) a algorytm wcale nie musi być tak trywialny jak to wymyśliłeś na poczekaniu. Dlatego proponuję wrzucenie prostego szkicu (który zaraz ktoś tu napisze 🙂) do Arduino i sprawdzenie pierwszych oznak. Musisz to jednak potraktować jako proof-of-concept a nie rozwiązanie finalne, bo jako jedyna obecna tam miejscu osoba będziesz musiał w tym nieźle pogrzebać żeby osiągnąć sensowną pewność działania. Także ne zniechęcaj się pytaniami, bo na razie są to próby zamodelowania sobie w głowie tej maszyny i wypracowania jakiegoś (innego niż Twój?) pomysłu. Jeszcze raz: program w takiej formie jak to opisałeś jest prosty jak mruganie diodą. Z dokładnością rzecz jasna do okolic znaków nowej linii (czy na pewno potrzebne), pozycji serwa (czy tylko dwie skrajne?) itp. Oczywiście w najprostszym przypadku program może ignorować wszystko oprócz cyfr '0' i '1', choć być może przydałoby się rozpoznawanie jakichś innych znaków sterujących np. 'S" - zacznij pracę (przenośnik pracuje i nasionka nadjeżdżają), 'P' - stop działania (przestań machać tym serwem i nie, to że nie przychodzą zera i jedynki to nie jest urwany kabel), "U120" - górna pozycja serwa, "D27" - dolna pozycja serwa od tej pory obowiązująca itp...

Edytowano przez marek1707
Link do komentarza
Share on other sites

Zdaje się że wszyscy zapomnieliśmy o podstawowej sorawie:

Kamera (i cały system rozpoznawania) pracuje na 30 fps. A z jaką częstotliwością nadjeżdżają nasionka? Bo może trzeba zmienić ten cały system rozpoznawania i analizować obraz raz na nasionko, a nie ileśtam na sekundę?

Link do komentarza
Share on other sites

(edytowany)

Dzięki za odpowiedzi, fajnie że jest ktoś chętny do pomocy 😉

Udało mi się to co chciałem, dokładnie: gdy jest 5 jedynek pod rząd, serwo na 20 stopni, gdy jest 5 zer pod rząd, serwo na 100 stopni.

Działający kod jak by ktoś miał ten sam problem: 

#include <Servo.h>
Servo myservo;
String dane = "";
int liczba = 0;
int liczba0 = 0;
void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600); //Uruchomienie komunikacji
  myservo.attach(3);
}

void loop() {

if(Serial.available() > 0) { 
  dane = Serial.readStringUntil('\n');
    if(dane == "1") {
      liczba0 = 0;
      Serial.print("liczba ");
      Serial.println(liczba);
      liczba = liczba + 1;
  }
    if(dane == "0") {
      liczba = 0;
      Serial.print("liczba0 ");
      Serial.println(liczba0);
      liczba0 = liczba0 + 1;

}
}
if(liczba == 5) {
  myservo.write(20);
  liczba = 0;
}
if(liczba0 == 5) {
  myservo.write(100);
  liczba0 = 0;
}
}

Czekam, na kamerki USB z aliexpress, mają mieć w mniejszej rozdzielczości aż 120fps, dodatkowo, z oprogramowania dostęp do ustawień kamery, takich jak przysłona i kilka innych wpływające na rozróżnianie kolorów.

Co do fps, to chciałbym wycisnąć jak najszybciej, nawet spróbuję w locie wykrywać, jak przyjdą mi kamerki, chciałbym osiągnąć chociaż 100kg/godz.

Projekt sortownika wykonałem za pomocą desingSparka i drukarki 3D, działa ciekawie.

Gdy dostanę kamerki, zamontuję ustawię program, zobaczę co się będzie dziać, i na pewno się tym podzielę.

Ethank widzę że ogarniasz Python, może chciałbyś coś pomóc, tak jak piszesz, dodać linijki kodu który poprawi pracę serwa, a nawet samego wykrywania, chcę dodać na kamerę kilka rzędów nasion, tylko trzeba ogarnąć żeby wykrywało w jakby podzielonym ekranie na paski, tzn. rząd pierwszy wykrycie, rząd trzeci wykrycie. itd. 

Oczywiście szanujemy siebie i swój czas,  więc jestem w stanie zapłacić.

 

Pozdrawiam 🤓

 

 

Edytowano przez Mialek
Link do komentarza
Share on other sites

Skoro kamera jest umiejscowiona sztywno nad taśmociągiem, to można na sztywno podzielić obraz i analizować po kawałku (ale wystarczy lekko kopnąć kamerę i kaplica na całej linii). Jakiś znacznik w zasięgu widzenia kamery i od niego dzielić obraz na te twoje "paski". Tylko tutaj trzeba też w odpowiednim momencie wyzwolić kamerę (wiesz, odpowiednie zdjęcie do analizy). To takie prostsze rozwiązania

Link do komentarza
Share on other sites

(edytowany)

Dzięki za odpowiedź

Kamera jest sztywno nad taśmociągiem i nic się nie zmieni, przekręci.

Jak podzielić na sztywno obraz? 

Np. żeby pokazać każdy pasek w oddzielnym oknie ? 

 

Edytowano przez Mialek
Link do komentarza
Share on other sites

Skoro obraz to trzywymiarowa tablica (każdy kolor osobno) to wystarczy zrobić trzy obrazki po 1/3 pierwotnego (te obszary co cię interesują :P). W matlabie obrazy rgb są macierzami trójwymiarowymi więc wnioskuję, że w pythonie są przedstawianie jako tablica 3-wymiarowa.

Edytowano przez BananWszyscy
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.