Skocz do zawartości
Komentator

Kurs Arduino - #3 - UART (komunikacja z PC), zmienne

Pomocna odpowiedź

Kod przepisywałem samodzielnie 😃 Zaraz sprawdzę czy działa.

Wszystko pięknie działa, dziękuję za pomoc 🙂

Udostępnij ten post


Link to post
Share on other sites

Moje rozwiązanie zadania 2.5.

String kolor = "";
boolean on1 = false;
boolean on2 = false;

void setup () {
 pinMode(2, OUTPUT);
 pinMode(3, OUTPUT);
 Serial.begin(9600);
}

void loop () {
if (Serial.available() > 0) {
 kolor = Serial.readStringUntil('\n');

 if ( kolor == "1" and on1 == false) {
   digitalWrite(2, HIGH);
   Serial.println("Czerwona ON!");
   on1 = true;
   kolor = "0";
 } else {
     if (kolor == "1") {
       digitalWrite(2, LOW);
       Serial.println("Czerwona OFF!");
         while (kolor == "1" and on1 == true) {
          on1 = false;
   }
  }
 }

 if (kolor == "2" and on2 == false) {
   digitalWrite(3, HIGH);
   Serial.println("Zielona ON!");
   on2 = true;
   kolor = "0";
 } else {
     if (kolor == "2") {
      digitalWrite(3, LOW);
      Serial.println("Zielona OFF!");
       while (kolor == "2" and on2 == true) {
        on2 = false; 
   }
  }
 }
}
}

Działa. 🙂

Udostępnij ten post


Link to post
Share on other sites

olinpus, super - plus za ładne wcięcia. Minus za brak komentarzy 🙂 Trzeba o tym pamiętać!

Udostępnij ten post


Link to post
Share on other sites

Cześć,

generalnie na początku wielkie dzięki za ten kurs! Bardzo fajnie i przejrzyście napisany.

Szybka historia - natchniony promocjami na ebooki zakupiłem kilka o arduino. Bardzo mi się spodobało więc wczoraj na botlandzie zamówiłem zestaw do Waszego kursu. Dzis przyszedł i po pracy usiadłem do działania 🙂.

Generalnie zrobiłem tę lekcję ale postanowiłem ją trochę skomplikować dodając więcej diód (diod?). Niestety nie działa to to tak jakbym tego oczekiwał 🙂.

Poniżej mój kod, a jeszcze niżej pytania.

Aha - nie jestem pewien czy to jest dobry dział na to pytanie bo całośc trochę wykracza poza materiał tej konkretnej lekcji - jeżeli to nie jest odpowiednie miejsce to przepraszam.

// Deklaracja stałych coby nie powtarzać. Ta dioda systemowa to pozostałość z pierwszych 
// prób - nie usuwałem po prostu. W tym szkicu nie uzywana do niczego.
#define hPin 13 // Dioda systemowa
#define redPin 8 // Dioda czerwona 
#define yelPin 7 // Dioda pomarańczowa
#define grePin 6 // Dioda zielona
#define btnPin 4 // Przycisk

// Tablica trzymająca piny pod którymi mamy LEDy
// Po tej tablicy przeiterujemy unikając kopiowania kodu
// Wzięte z książki: Arduino w akcji
int ledArray[] = { hPin, redPin, yelPin, grePin };
// Licznik do pętli
int count = 0;

// Tablica ze stanami konkretnych diod
// Zasada jak powyżej - zamiast tworzyć kilka zmienny mamy jedną tablicę 
// która będzie indeksowana po numerze pinu (część indeksów będzie pusta)
int ledStates[] = {};

// Inicjalizacja zmiennej trzymającej dane wejściowe z Serial`a
String data = "";

// Setup
void setup() {
   Serial.begin(9600);
   Serial.println("Arduino wstaje...");
//    Pętla iterująca po wszystkich pin`ach z diodami LED 
//    i ustawiająca ich tryb na OUTPUT
   for (count = 0; count < 4; count++) {
       pinMode(ledArray[count], OUTPUT);        
   }

//    @PROBLEM
//    Inicjalizacja wartości odpowiednich LED`ów na 0 (LOW)
//    ta pętla powoduje, że szkic nie działa - po jakiejkolwiek akcji - czy to wciśnięciu
//    przycisku czy wpisaniu czegoś do konsoli pojawia się log: "Arduino wstaje..." 
//    To musi zostać wykomentowane, żeby dojść do problemu nr 2. 
   for (count = 0; count < 9; count++) {
       ledStates[count] = 0;
   }

//    Ustawiamy tryb pinu przycisku
   pinMode(btnPin, INPUT_PULLUP);    
}

// Main loop
void loop() {    
//    Wywołanie funkcji obsługującej wejście z poziomu konsoli
   lightLedFromInput();
//    Jeżeli przycisk został wciśnięty
   if(digitalRead(btnPin) == LOW) {     
//        Wywołanie funkcji zmieniającej stan diody 
       toggleLED(grePin);
//        Zapobiegamy wielokrotnemu odpaleniu się toggleLED poprzez wstrzymanie
//        wykonywania kodu dopóki przycisk jest wciśnięty
       while(digitalRead(btnPin) == LOW) {            
           delay(25);
       }
   }
}

//Funkcja obsługująca wejście z Serial
void lightLedFromInput() {
   if(Serial.available() > 0) {
       data = Serial.readStringUntil('\n');
//        Sprawdzenie wszystkich możliwych wartości - to na pewno da się inaczej zrobić
//        ale na razie miałem inne problemy :)
       if(data == "6" || data == "7" || data == "8") {
           int led = data.toInt(); 
           toggleLED(led);
       }
       else {
           Serial.println("Podano zły numer diody.");
       }
   }
}

// Funkcja zmieniająca stan diody 
// @param led - numer pinu diody
void toggleLED(int led) {
   int state = 0;
//    Ten fragment kodu jest potrzebny tylko dlatego, że pętla w setup() nie działa
//    i przy pierwszym odpaleniu ledStates[led] nie jest ustawione
   if(ledStates[led]) {
//        @PROBLEM2 
//        Tutaj dzieje się bardzo dziwna rzecz - mianowicie ledStates[led] przyjmuje 
//        przy pierwszym wywołaniu 197 dla led = 7 i 196 dla led = 8. Stąd ten if sprawdzający
//        czy wartość mieści się w przedziale.
//        Dlaczego tak się dzieje?
       if(ledStates[led] == 1 || ledStates[led] == 0) {
           state = ledStates[led];            
       }
   }
//    Debug
   Serial.println(String(state));
   ledStates[led] = !state;

   digitalWrite(led, ledStates[led]);
   Serial.println("Turning the " + (String)led + " LED to state: " + (String)ledStates[led]);      
}

Czyli mam 2 główne problemy (szczegóły w komentarzach w kodzie):

@PROBLEM1. Pętla całkowicie psuje szkic - powoduje "reset" - i nie mam pojęcia dlaczego.

@PROBLEM2. Wartości w tablicy (jeżeli wykomentujemy tę pętlę z punktu pierwszego) przyjmują dziwne wartości nawet jeżeli tablica jest inicjalizowana jako pusta. Czyli tam gdzie spodziewałbym się czegoś w stylu NULL czy pustego wpisu jest np wartość 196 co mnie zupełnie rozbija 🙂.

No i jest jeszcze problem numer 3, którego też nie rozumiem - jeżeli kilka razy zmienię stan diody zielonej używając przycisku, po czym zmienię go poprzez konsolę to może się okazać, że zmiana nie następuje (albo inaczej - następuje ale w obu przypadkach dioda np zostaje włączona. albo w obu wyłączona - tak jakby globalna wartość w tablicy nie ulegała zmianie).

Mam nadzieję, że ma to sens i że to dobry dział. Jeśli nie to przepraszam i proszę o usunięcie / ewentualnie przeniesienie do dobrego działu.

Dzięki z góry!

Tomek

Udostępnij ten post


Link to post
Share on other sites

cinekk, witam na forum i dziękuję za miłe słowa na temat kursu 🙂

Faktycznie Twoje problemy wybiegają poza tę lekcje (z powodu tablic), ale zajmijmy się ich wspólnym rozwiązaniem.

Zacznijmy od problemu 1:

int ledStates[] = {}; 
[..]
for (count = 0; count < 9; count++) { 
  ledStates[count] = 0; 
} 

Problem prawdopodobnie leży w deklaracji tablicy. Rozumiem, że chciałeś utworzyć początek tablicy, do którego będzie można coś odpisać, a zawsze wartość początkowa będzie pusta. Niestety, jeśli nie podajesz od razu elementów, które muszą znaleźć się w tablicy, to tak nie można działać. W takim przypadku musisz określić ile elementów będzie w tej tablicy, bo inaczej kompilator nie wie ile miejsc ma zarezerwować.

Nie jestem specem od analizy takich przypadków, pewnie ktoś bardziej zaawansowany w programowaniu mnie poprawi, jednak prawdopodobnie w tej chwili tworzysz tablicę o zerowej ilości elementów (?). W późniejszej pętli for odwołujesz się do 9 elementów, więc w praktyce wychodzisz poza jej zakres - i to nawet bardzo daleko. Nadpisujesz pamięć układu i dlatego program nie działa.

Udostępnij ten post


Link to post
Share on other sites

Możesz skorzystać z Wectora z STL - dynamiczna tablica gdzie, możesz edytować tablicę w czasie działania programu (dopiero ogarniam arduino i nie wiem jak to będzie współdziałać :/).

http://andybrown.me.uk/2011/01/15/the-standard-template-library-stl-for-avr-with-c-streams/

http://cpp0x.pl/kursy/Kurs-STL-C++/Kontener-tablicy-std-vector/119

" jednak prawdopodobnie w tej chwili tworzysz tablicę o zerowej ilości elementów (?). W późniejszej pętli for odwołujesz się do 9 elementów, więc w praktyce wychodzisz poza jej zakres - i to nawet bardzo daleko. Nadpisujesz pamięć układu i dlatego program nie działa."

Dokładnie tak to działa 🙂

// Wy edytowałem post by nie podawać nie aktualnych danych 🙂

Częste pytanie #define czy const?

#define kro 8

#define kre 10

lub

const int kro = 8, kre = 10;

Osobiście wolę stosować consta w programach komputerowych, Arduino raczej define ze względu na pamięć 🙂

Chociaż to też zależy od programu, a właściwie wykorzystania "zmiennej".

Ciekawostka x = x + 1; Możemy także zapisać x += 1; Efekt ten sam.

Polecam:

http://cpp0x.pl/forum/temat/?id=1209

https://forum.4programmers.net/C_i_C++/32270-CC++_define_czy_globalna_zmienna_typu_const

Udostępnij ten post


Link to post
Share on other sites
Ciekawostka x = x + 1; Możemy także zapisać x += 1; Efekt ten sam.

Albo x++, wiemy. Tutaj formą ogólną byłoby raczej "x = x + n; Możemy także zapisać x += n;".

Ale to jest definicja operatora +=. Istnieje analogiczny operator dla chyba każdego "pojedynczego" operatora (+, -, /, *, ^, |, &, i tak dalej).

Mam silne podejrzenie że define i const przy O3 skończy się na tych samych instrukcjach.

Udostępnij ten post


Link to post
Share on other sites
Zawartość tablicy to const, w czasie programu ni możesz jej zmienić, chyba że skorzystasz z Wectora z STL - dynamiczna tablica gdzie, pamieć możesz edytować tablicę w czasie działania programu (dopiero ogarniam arduino i nie wiem jak to będzie współdziałać :/).

Przepraszam, ale kompletnie tego nie rozumiem. Tablica w przykładzie, który tu omawiany została zadeklarowana jako int, więc dlaczego twierdzisz, że jest stała i nie można jej zmieniać?

Udostępnij ten post


Link to post
Share on other sites

Nie chodziło mi o typ tablicy int, float, double, char tab ... tylko o liczbę określającą ilość elementów w tablicy 🙂 int tablica [liczba która jest tutaj] = {1,2,3 ...};

Musi być ona const i int; // jednak nie musi standard C99

W Wektorach nie definiujesz ile "pól ma tablica" możesz je definiować w czasie działania programu.

Taki zapis spowoduje błąd:

 const int tablica_const = 1;
 int tablica = 1;
 const double tblica_const_double = 1;

 int tab1 [tablica] = {1}; // błąd nie const

 int tab2 [tablica_const] = {1};

 int tab3 [tablica_const_double]= {1}; // błąd double 

Udostępnij ten post


Link to post
Share on other sites

Crax, nie do końca masz rację... C99 pozwala na używanie zmiennych do deklarowania wielkości tablicy: https://en.wikipedia.org/wiki/Variable-length_array

We wcześniejszych wersjach C faktycznie tak było jak piszesz, ale biorąc pod uwagę, że to już 17 lat od ogłoszenia tego standardu (jest już C11), chyba można potraktować tą informację jako nieaktualną (nawet jeśli nie wszystkie kompilatory w pełni akceptują standard C99).

Różnica nie dotyczy typu zmiennej podczas tworzenia tablicy, ale tego co z tablicą dzieje się dalej. W przypadku tradycyjnych tablic C/C++ ich rozmiar nie ulega zmianie. Natomiast stosując inne struktury danych (listy, tablice dynamiczne itd), można dodawać kolejne elementy i zmieniać rozmiar "tablicy" dynamicznie.

Udostępnij ten post


Link to post
Share on other sites

Na C się akurat nie znam :/

Pracuje dużo na VS2010 (tak wiem że czas zmienić versie IDE, ale projekt gry ma coś ok, + 5k linii kodu i mi się nie chce) i stąd też się biorą problemy 🙂

Dzięki za sprostowanie, postaram się odświeżyć wiedzę.

Udostępnij ten post


Link to post
Share on other sites

Elvis, Tak, ale.

VLA nie ma możliwości sprawdzenia czy alokowanie pamięci się powiodło.

Malloc ma a nie jest wiele trudniejszy do zastosowania.

Udostępnij ten post


Link to post
Share on other sites

Ja wcale nie namawiam do używania tej opcji. Chciałem tylko zwrócić uwagę na nieścisłość we wcześniejszym wpisie.

Jest natomiast duża różnica między używaniem malloc, a VLA lub tablic o ustalonej wielkości. W przypadku malloc przydzielana jest pamięć ze sterty (heap), natomiast VLA i zmienne automatyczne używają stosu (stack). Dla dużych obiektów sterta wydaje się dobrym rozwiązaniem, natomiast jeśli często (i na krótko) przydzielamy pamięć dla małych obiektów (np. napisów), używanie sterty może być bardzo niewydajne (zajmuje czas, może powodować fragmentację oraz marnowanie pamięci na dane dodatkowe związane z mechanizmem alokacji).

Oczywiście wszystko zależy od architektury systemu i konkretnego zastosowania. Warto natomiast wiedzieć, że są takie opcje i kiedy warto po nie sięgnąć.

Udostępnij ten post


Link to post
Share on other sites

Crax, ok rozumiem, jednak w swoim poście napisałeś o niemożliwości zmiany zawartości tablicy, co może wprowadzać w błąd, jeśli miałeś na myśli tylko ilość elementów 🙂

Udostępnij ten post


Link to post
Share on other sites
int odczytanaWartosc = 0; //Zmienna do przechowywania odczytu ADC

void setup() {
 pinMode(8, OUTPUT); //Konfiguracja wyjść pod diodę LED
}

void loop() {
 odczytanaWartosc = analogRead(A5);//Odczytanie wartości z ADC
 digitalWrite(2, HIGH);//Włączenie diody
 delay(odczytanaWartosc);//Uzależnienie czasu oczekiwania od ADC
 digitalWrite(2, LOW);//Wyłączenie diody
 delay(odczytanaWartosc);//Uzależnienie czasu oczekiwania od ADC 
}

Nie wiem jak to się stało że nikt tego jeszcze nie wyłapał ale w przykładzie do lekcji 4 o Arduino - najpierw ustawimy pin 8 na wyjście, potem zmieniamy stan pinu 2 🙂

Jest jeszcze jedna sprawa.

int odczytanaWartosc = 0;

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

void loop() {
 odczytanaWartosc = analogRead(A5);//Odczytujemy wartość napięcia
 Serial.println(odczytanaWartosc);//Wysyłamy ją do terminala
 delay(200);//Czekamy, aby wygodniej odczytywać wyniki  
}

Po załadowani tego kodu na Arduino jak wepnę styk do A5 a drugą stronę nie podepnę niczego, monitor szeregowy odczytuje mi zera, jednak co jakiś czas skoczy do 1023, zdjęcie:

// na początku są zera potem taki "wierszyk i dalej zera" jakieś pomysły czy wina mojego Ardu - uno klonu?

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ść
Napisz odpowiedź...

×   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...