Skocz do zawartości

Arduino i transmisja szeregowa


Zolw2305

Pomocna odpowiedź

Witam, mam pewien mały problem. Mam zamiar za pomocą systemu Arduino sterować trzema regulatorami silników bezszczotkowych (ESC). Sterowanie to przebiega tak samo jak w przypadku serwomechanizmów (PWM). Wartość wypełnienia w us jest przesyłana do Arduino przez port szeregowy. Problem polega na tym że docelowo wartości te mają być generowane przez odpowiednie wychylenia potencjometrów z konsoli sterującej (x i y). Chciałbym przesłać równocześnie obie te wartości (x,y) serialem, a następnie rozdzielić je na zmienną x i zmienną y.

Nie proszę oczywiście o gotowy kod źródłowy ale byłbym wdzięczny za podsunięcie jakiś pomysłów jak to zrobić?

Poniżej fragment kodu, który działa dla przesyłania 1 wartości:

void set_speeds(int servo, int usvalue)
{
 escservos[servo].writeMicroseconds(usvalue);
}

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

 // Attaches the ESC's on pins 2, 3, 4 to the servo object.
 for(int s=0; s<3; s++)
   escservos[s].attach(s+2, FULLREWARD, FULLTHROTTLE);
}

void loop()
{
 if(Serial.available())
 {
   usvalue = Serial.read();        
 }
 for(int s=0; s<3; s++)
   set_speeds(s, usvalue);
}
Link do komentarza
Share on other sites

W tym momencie nie pomogę za wiele, ale sprawdź czy wysyłanie jednej po drugiej faktycznie jest zbyt wolne. Może akurat Cię zadowala, a oszczędza kombinacji w kodzie.

Przykładowy loop():

void loop(){

if(Serial.Available() > 0)

a = Serial.Read();

b = Serial.Read();

}

Jeżeli zawsze wysyłasz 2 bajty to powinno działać.

Link do komentarza
Share on other sites

Serial.available() zwraca ilość bajtów w buforze przychodzącym. Można zatem poczekać aż będą dwa i zakładając, że zawsze wysyłasz je w tej samej kolejności, zrobić tak:

if(Serial.available()>1) {
  x = Serial.read();
  y = Serial.read();
}

Przed pętlą główną dodałbym jeszcze Serial.flush() żeby pozbyć się śmieci, które mogły się wcześniej pojawić i już... Jeśli zdarzało by się, że odbierasz te dane w złej kolejności, to trzeba by coś pokombinować z synchronizacją przez jakiś znak startu ramki. Nie wydaje mi się to jednak konieczne.

Link do komentarza
Share on other sites

Dzięki, trochę to rozjaśniliście. Synchronizację myślałem żeby i tak zrobić, co by uniknąć jakiś pomyłek w transmisji. Jutro będę próbował. Jeszcze raz dzięki.

Aktualizacja:

Pojawił się natomiast inny problem. Nie mogę wysłać dowolnego bajtu danych przez Serial Monitor. Mając np taki program:

void setup() 

 Serial.begin(9600); 

void loop() 
{ 
 if(Serial.available()) 

   int x = Serial.read();        

 Serial.println(x);
} 

Wpisując w serial monitor wartość np. 251, wyświetla się najpierw 2 potem 5 a na końcu 1 (a właściwie ich odpowiedniki w ascii). Problem w tym że nie mogę wysłać całego bajtu x = 0....255, tylko każdy znak wysyła się oddzielnie, czyli w przypadku 255 zamiast 1 bajtu, arduino odbiera 3. Da się coś z tym zrobić?

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

Też niedawno miałem z tym problem i znalazłem rozwiązanie gdzieś na arduino.cc

Napisałem na bazie tego rozwiązania swój mały kawałek kodu, ale nie mem teraz dostępu do tamtego komputera.

Postaram się znaleźć tamto.

Chyba to było to, ale sam zobacz w praktyce:

/ zoomkat 8-6-10 serial I/O string test
// type a string in serial monitor. then send or enter
// for IDE 0019 and later

String readString;

void setup() {
   Serial.begin(9600);
       Serial.println("serial test 0021"); // so I can keep track of what is loaded
       }

void loop() {

       while (Serial.available()) {
       delay(10);  
       if (Serial.available() >0) {
       char c = Serial.read();
       readString += c;}
       }

     if (readString.length() >0) {
     Serial.println(readString);

     readString="";
     }
  }


Link do komentarza
Share on other sites

Czytajcie dokumentację na www.arduino.cc, a nie kombinujecie 😋

Wystarczy:

Serial.println(x,BYTE)

BYTE oznacza, że zmienna nie będzie wysłana w kodzie ASCII, tylko jako wartość liczbowa.

Tak, ale Serial.println wysyła z Arduino do Serial Monitor, a mi chodzi o transmisję w drugą stronę, czyli z Serial monitor do Arduino. Przykład który podał tomly działa, tylko nie wiem czy wysyłając za pomocą string wartości dajmy na to 179, wysyłam to w formie 1 czy więcej bajtów?

Link do komentarza
Share on other sites

W formie 3 bajtów, nigdzie tam konwersji nie ma. Nie doczytałem o tym Serial Monitorze... Koniecznie potrzebujesz żeby tam był wysyłany jeden bajt, czy wystarczy Ci konwersja ze stringa na liczbę po stronie Arduino?

Link do komentarza
Share on other sites

mactro, dokumentacja to rzecz święta, ale nie ma w niej niestety prostego rozwiązania.

Arduino może wysyłać po Serialu w różnej postaci, ale przyjmuje zawsze po 1 bajcie. Dlatego przyjęcie jako char i zrobienie stringa dopisująć na końcu nie jest chyba takie złe.

Oczywiście wszystkie inne rozwiązania mile widziane 🙂

Link do komentarza
Share on other sites

Tak jak pisałem, nie doczytałem, że chodzi o dane odbierane przez Arduino, a nie wysyłane, kajam się 😉

W każdym razie widzę dwa rozwiązania: jeśli nie jest przeszkodą to, że liczby są wysyłane jako znaki ASCII, to można zastosować sposób tomly'ego z dodaną na końcu konwersją string->int. Spróbuj czy zadziała

x=int(ciag_znakow)

Kompilować się kompiluje, ale nie mam pod ręką Arduino, żeby przetestować.

Drugie rozwiązanie to napisać aplikację na PC, która będzie wysyłała liczby wpisane jako ciąg znaków już przekształcone na wartość liczbową. W C#/.net jakieś 20 minut roboty.

Link do komentarza
Share on other sites

Dobrze prawicie z tą zewnętrzną aplikacją, oczywiście takowa będzie. Postaram się pokrótce opisać co i jak. Arduino będzie sterowało trzema regulatorami silników bezszczotkowych, za pomocą PWM (tak jak sterowanie serwami). Wartość wypełnienia będzie wysyłana z aplikacji LabView przez RS232. Wysyłane będą wartości od 0 do 200 (tak aby mieściły się w 1 bajcie) i konwertowane na odpowiednie wartości wypełnienia PWM (920....2120 us). 3 silniki = 3 bajty wysłanych danych.

Serial monitor ma mi posłużyć do sprawdzenia czy komunikacja i konwersja przebiega prawidłowo (zanim ukończymy aplikację LV), dlatego właśnie zależy mi na tym aby wartość 0...200 była wysłana w 1 bajcie. Ale widzę że to chyba nie wykonalne za pomocą serial monitora.

Nie wiem tylko gdzie leży problem, czy to wartości w serial monitor są konwertowane na pojedyncze znaki ascii, czy to instrukcja serial.read() odczytuje tylko po jednym znaku i konwertuje go na ascii?

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.