Skocz do zawartości
Emte

Sterowanie serwomechanizmem z pliku tekstowego

Pomocna odpowiedź

Witam,

Jestem użytkownikiem Arduino Leonardo. Napisałem prosty program do sterowania serwomechanizmem o określony kąt obrotu(np. 5 = 50°) wpisywany w Monitor portu. Jakich funkcji/bibliotek użyć by zmienna odczytywana była z pliku tekstowego umieszczonego w systemie Windows, do którego wcześniej ręcznie wpisał bym daną wartość? Chciałbym przerobić program.

Oto kod programu:

#include <SoftwareSerial.h> //importowanie biblioteki
#include <Servo.h> //importowanie biblioteki
Servo myservo; 
int pozycja1 = 50; // zmienna z pozycją nr 1
int pozycja2 = 100; // zmienna z pozycją nr 2
int pozycja3 = 110; // zmienna z pozycją nr 3 
int pozycja4 = 120; // zmienna z pozycją nr 4
int pozycja5 = 130; // zmienna z pozycją nr 5
int pozycja6 = 140; // zmienna z pozycją nr 6 
int pozycja7 = 150; // zmienna z pozycją nr 7
int pozycja8 = 160; // zmienna z pozycją nr 8
int pozycja9 = 170; // zmienna z pozycją nr 9


int serwo = 7; // zmienne z pinem serwa - pin 7
int data; // zmienna, w której przechowujemy odebrane dane

void setup() {
 myservo.write(pozycja1);
myservo.attach(serwo); //ustawienie pinu serwa na 7 (int serwo = 7;)
Serial.begin(9600); // ustawienie odpowiedniej prędkości 
Serial.println("System sterowania serwomechanizmem uruchomiony! Wpisz: 1 - 9 aby zmienic pozycje ramion serwa."); // wypisanie zdania w monitorze serial portu
}

void loop() {
if (Serial.available() > 0) { 
data=Serial.read(); // odczytane dane = data
if(data=='1'){ // jeżeli odczyta 1
myservo.write(pozycja1); // ustawienie pozycji serwa na "pozycja1"
Serial.println("Pozycja 0'"); // wypisanie zdania
}
if(data=='2'){
myservo.write(pozycja2);
Serial.println("Pozycja 10'");
}
if(data=='3'){
myservo.write(pozycja3);
Serial.println("Pozycja 20'");
}
 if(data=='4'){
myservo.write(pozycja4);
Serial.println("Pozycja 30'");
}
 if(data=='5'){
myservo.write(pozycja5);
Serial.println("Pozycja 40'");
}
 if(data=='6'){
myservo.write(pozycja6);
Serial.println("Pozycja 50");
 }
  if(data=='7'){
myservo.write(pozycja7);
Serial.println("Pozycja 60");
 }
  if(data=='8'){
myservo.write(pozycja8);
Serial.println("Pozycja 70");
 }
  if(data=='9'){
myservo.write(pozycja9);
Serial.println("Pozycja 80");
 }
}
delay(100); //oczekiwanie na kolejne dane...
}

Udostępnij ten post


Link to post
Share on other sites

To musisz oprogramować od strony Windowsa a nie Arduino.

Niech program czyta linijkę po linijce z pliku i wysyła zawartość linii na odpowiedni port serial.

Pomijam tu na razie jakieś zależności czasowe - po prostu niech program co sekudę wysyła dane na port.

Masz jakiekolwiek doświadczenie z programowaniem na PC? Jeśli nie - proponuję zacząć od prostego programiku w Pythonie.

Aha, i zacznij od wywalenia tego debilnego delaya, bo to nie ma nic wspólnego z oczekiwaniem na kolejne dane.

Udostępnij ten post


Link to post
Share on other sites

Jeśli ktoś ma wstręt do programowania PC, to można zrobić tak:

1. Stworzyć plik tekstowy ze współrzędnymi wychyleń (np. w jednej linii jedna komenda: czas, kąt) na dysku komputera.

2. Za pomocą jednego z typowych programów terminalowych wysłać plik jednym z protokołów zapewniających jakąś kontrolę poprawności (XMODEM chociażby).

3. Odbierać plik w Arduino, kompletować na bieżąco nadchodzące pełne linie, dekodować je i zapamiętywać komendy w tablicy. Jeśli będzie tego maks. kilkaset sztuk Ardu nie powinno wyzionąć ducha.

4. Po zakończonym odbiorze pliku (lub po jakiejś specjalnej komendzie, naciśnięciu przycisku czy co tam jeszcze) zacząć wykonywać zapamiętaną sekwencję.

Albo jeszcze trochę inaczej:

1. Napisać na Arduino edytor umożliwiający wpisywanie, przenoszenie, listowanie, usuwanie i poprawianie kolejnych komend dla serwa. To wydaje się banalne.

2. Konsolą edytora może być dowolny program terminalowy na PC połączony przez UART.

3. Gotowy "program" dla serwa można trzymać w EEPROMie Arduino i mieć go zawsze gotowym do wykonania po włączeniu zasilania.

4. 2K EEPROM powinien wystarczyć na kilkaset pozycji "programu".

Udostępnij ten post


Link to post
Share on other sites

Jeśli ktoś ma wstręt do programowania PC polecam onet, wp, interię... w każdym razie wskazana jest zmiana forum na jakieś przyjemniejsze.

Ostatnio na juli był fajny artykuł o szyciu butów dla lalek, wyszły fajnie.

Udostępnij ten post


Link to post
Share on other sites

Oj tam, nie bądź taki zasadniczy. Jeśli ktoś zaczął od płyteczki Ardunio, zainstalował IDE i napisał mniej lub bardziej samodzielnie kilka pierwszych programów to wcale nie znaczy, że łatwo będzie mu przejść na pisanie aplikacji na PC. A przyznasz, że podane metody zadziałają bez napisania linijki kodu w kompie. Poza tym protokoły komunikacyjne to odrębne zagadnienie i wcale nie jest oczywiste jak je tworzyć by były proste a przesyłane dane -spójne. Korzystanie z gotowców (terminal na PC / biblioteka na Arduino) jednak bardzo to upraszcza.

No nic, poczekajmy co powie Autor wątku. Mam wrażenie, że w ogóle jest trochę zaskoczony.

Udostępnij ten post


Link to post
Share on other sites

Emte, witam na forum!

Tak jak koledzy wyżej już napisali, to nie jest kwestia leżąca po stronie Arduino. Można ją jednak rozwiązać bardzo prosto. Dla testu przygotowałem plik z następującą zawartością:

5
25
30
5
2
3
5
20
35

Następnie wgrałem dla uproszczenia sytuacji do Arduino program, który odbierał dane przez UART i wypisywał odebraną informację na ekranie:

String odebraneDane = ""; //Pusty ciąg odebranych danych

void setup() {
 Serial.begin(9600); //Uruchomienie komunikacji
}

void loop() {
 if(Serial.available() > 0) { //Czy Arduino odebrało dane
   odebraneDane = Serial.readStringUntil('\n'); //Jeśli tak, to odczytaj je do znaku końca linii i zapisz w zmiennej odebraneDane
   Serial.println("Odebrana pozycja " + odebraneDane); //Wyświetl komunikat
 }
}

Następnie wykorzystałem program Realterm. W zakładce Port wybrałem odpowiedni port COM oraz prędkość transmisji i połączyłem się z Arduino. Następnie wykorzystałem opcję Dump File to Port, która znajduje się na zakładce Send. Wskazałem tam powyższy plik, ustawiłem opóźnienie, które ma być dodawane po każdej linii pliku. Następnie kliknąłem Send File i wszystkie linie zostały wysłane do Arduino, co widać na poniższym zrzucie ekranu:

Oczywiście możesz również napisać własny program na PC, który będzie realizował to zadanie. Tutaj pomocny będzie poniższy artykuł: Port szeregowy i interfejs USART, czyli komunikacja z PC

Udostępnij ten post


Link to post
Share on other sites

@Treker: artykuł jest bardzo fajny, ale nie dla początkującego. A taki program napisany w Pythonie będzie miał dosłownie parę linijek.

@marek1707: nikt tu nie mówi o jakichś skomplikowanych aplikacjach. Ale coś w stylu:

otwórz port COM;
otwórz plik tekstowy;
dla każdej linijki {
  wyślij zawartość na port;
  odczekaj jakiś czas;
}

nie jest chyba czymś bardziej skomplikowanym niż program na Arduino, który porusza serwem na podstawie danych otrzymanych z seriala...

Udostępnij ten post


Link to post
Share on other sites

Dziękuję za liczną odpowiedź i pomoc w moim problemie.

Treker skorzystałem z twoich podpowiedzi. Wielkie dzięki.

Oto mój przerobiony kod:

#include <SoftwareSerial.h>
#include <Servo.h> //importowanie biblioteki
Servo myservo; 
int pozycja3 = 150;
int pozycja2 = 100;
int pozycja1 = 50;
int odebraneDane = "";  
int serwo = 7;  
void setup() { 
myservo.write(pozycja1);
myservo.attach(serwo); 
Serial.begin(9600); //Uruchomienie komunikacji 

} 

void loop() { 
 if(Serial.available() > 0) { //Czy Arduino odebrało dane 
   odebraneDane = Serial.read(); //Jeśli tak, to odczytaj je do znaku końca linii i zapisz w zmiennej odebraneDane 
   Serial.println("Odebrana pozycja " + odebraneDane); //Wyświetl komunikat 
   if(odebraneDane=='2'){
   myservo.write(pozycja2);
   }
 if(odebraneDane=='3'){
myservo.write(pozycja3);
 }
}
}

Jak można zauważyć użyłem zmiennej typu int zamiast string ponieważ nie mogłem sobie poradzić z odczytywaniem zmiennej "odebraneDane" tak by serwo ustawiało się na odpowiedniej pozycji. Zdefiniowałem więc wcześniej przykładowe liczby 3,2,1 jako odpowiednie ustawienia serwa.

Jak wczytać "odebraneDane" tak by ich wartość wprost oznaczała pozycje serwa?

Dla przykładu gdy z pliku wczytam wartość 2 serwo obróci się o daną wartość. Gdyż np taki oto kod jest błędny:

if(odebraneDane=='2'){
   myservo.write(odebraneDane);
   }

Mam również kłopot jeśli chodzi o wyświetlanie komunikatów.

Są one przesunięte w lewo:

Serdecznie pozdrawiam

Udostępnij ten post


Link to post
Share on other sites

Emte, cieszę się, że poradziłeś sobie z tym problemem. Jeśli chodzi o:

Jak można zauważyć użyłem zmiennej typu int zamiast string ponieważ nie mogłem sobie poradzić z odczytywaniem zmiennej "odebraneDane" tak by serwo ustawiało się na odpowiedniej pozycji.

To przydatna może być funkcja toInt(), za pomocą której możesz przekonwertować liczbę z postaci "tekstowej" do wartości liczbowej. Więcej na ten temat znajdziesz w dokumentacji Arduino: https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/toint/ Problem z przesunięciem odebranych danych to chyba kwestia konfiguracji Realterm'a. Spróbuj na pierwszej zakładce (Display) wybrać tryb Ansi zamiast domyślnego Ascii.

Udostępnij ten post


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!

Gość
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...