Skocz do zawartości

Tablice w Arduino – #1 – szybki start


Pomocna odpowiedź

(edytowany)
1 godzinę temu, tenNowy napisał:

Od D4 do D36 mam przekaźniki od A0 do A15 i od D37 do D52 włączniki ot to co chce osiągnąć za pomocą pętli

I teraz wystarczyłoby sobie uświadomić, że aliasy od A0 do A15 istnieją po to, by ułatwić zapis kodu przy wykorzystania analogowych możliwości danych pinów czy np. zmianę wariantu płytki. A tak naprawdę Twoje włączniki podłączone są do pinów od 37 do 69, z pominięciem 53.

Także wystarczy:

#define BUTTON(number) \
	({ int _n = (number); \
	  _n < 0 || _n >= 32 ? -1 : (_n < 16 ? 37 + _n : 54 - 16 + _n); })

Lub, jeżeli wolisz życie na krawędzi:

#define BUTTON(n) (n < 0 || n >= 32 ? -1 : (n < 16 ? 37 + n : 54 - 16 + n))

Biblioteki wbudowane Arduino stosują drugi styl, ale to wybucha, jeżeli ktoś użyje tego w formie BUTTON(zmienna++) czy z innymi wyrażeniami. Kompilator przy włączonej jakiejkolwiek optymalizacji i tak zamieni użycie wersji pierwszej na jedną liczbę (a chyba Arduino IDE domyślnie używa -Os). 

Ach, no i zmieniłem logikę numeracji Twoich przycisków, którą sobie ustawiłeś w głowie, bo mam jednak podejrzenie, że wynika ona właśnie z nierozumienia numeracji pinów. Ja bym wolał podłączyć po kolei. Ale jak się uprzesz, to łatwo możesz zmienić te makra pod założoną kolejność. Albo życie sobie bardziej ułatwić i użyć też pinu 53, o ile nie ma on jakichś nieznanych mi wad i wtedy może używać po prostu:

const byte BUTTONS_START = 53;
const byte BUTTONS_COUNT = 32;
  
...
  
for (int i = 0; i < BUTTONS_COUNT; ++i)
  cośtam(BUTTONS_START + i);

Można też po prostu zrobić funkcję int button(int n). Kompilator też taką potrafi zoptymalizować do pojedynczej stałej. Więc nie trzeba męczyć się z preprocesorem.

Edytowano przez trainee
  • Lubię! 2
(edytowany)

Kolega wyżej pokazał sposób, jednak od siebie mogę powiedzieć, że trzeba być doświadczoną osobą, by w ogóle zrozumieć co ten kod robi.

Jeśli chcesz wpisać po prostu Piny do tablicy to nie musisz przecież wpisywać nazw. Te nazwy jak Trainee powiedział służa tylko programiście by wiedział, który pin jest który. Pod spodem A0-A15 to zwykłe cyferki wstawiane przy kopilacji w to miejsce gdzie piszesz np A0: 


image.thumb.png.e4ade68851a8c4699412ca36f264182a.png

Możesz sobie wpisać do tablicy Włączniki[32] po prostu pętla numery od 37 do 52 a później od od 54 do 69 jeśli to ma być jak najprościej. 

edit: ewentualnie na chama gdybyś chciał wyłaczyć 32-52 😛

for(uint8_t i = 32; i < 53; i++)
{
  digitalWrite(i, LOW);
}

 

Edytowano przez Dantey
(edytowany)

Co do mojej wzmianki o optymalizacji, przykład w Compiler Explorer. Dodałem jeszcze static do funkcji, dzięki czemu sama funkcja nie jest generowana. To co wystarczy wiedzieć, to że w linii 7 assemblera jest ldi r24,lo8(42) i ta linijka będzie się zmieniać przy zmianie argumentu funkcji button(). Podstawiony jest wynik wyliczony na etapie kompilacji.

Mówiąc prościej: używanie preprocesora jest trudne, ma pułapki. A kompilator radzi sobie równie dobrze, jak nie lepiej, sam.

Edytowano przez trainee
(edytowany)

A0 to 54, A15 to 69. Jeśli używasz standardowego IDE do arduino to zainstaluj sobie Visual studio Code z Platform IO. W samym VSC pisanie to zupełnie inna liga, z racji autouzupełniania i pokazywania co jest co. Najedziesz sobie na nazwe A0 i pokaże Ci co w ogóle to znaczy, jak ten mój screen wyżej 😉 

Edytowano przez Dantey
(edytowany)

@tenNowy, a na deser zostawię Ci taką myśl: 32 przyciski mógłbyś też obsłużyć używając 12 pinów zamiast 32. Ot tak tylko, by Cię ta myśl trochę mobilizowała do dalszych przemyśleń, na przyszłość.

Edytowano przez trainee
3 godziny temu, trainee napisał:

Lub, jeżeli wolisz życie na krawędzi:

😅 

Fajna dyskusja się rozwinęła, cieszę się 🙂 

(edytowany)

Pokusiłbym się stwierdzeniem, że w idealnych warunkach obsłużyłbym je tylko 1 pinem z pomocą rezystorów czy o to Ci chodzi? Jednak trzeba wziąć pod uwagę długości żył i spadki napięć. Wole jednak pewne rozwiązanie 1 do 1 co nie znaczy, że to o czym mówisz by nie działało, swoją drogą masz rację mało ambitnie do tego podszedłem.

Edytowano przez tenNowy

Aha o krzyżowanie Ci chodzi ja myślałem o dzielniku napięcia bo Arduino jest w stanie mierzyć napięcie w zakresie od 0-5v z dokładnością bodajże 10bitów więc obsłuży wszystkie przyciski jednym pinem analogowym.

(edytowany)
36 minut temu, tenNowy napisał:

Aha o krzyżowanie Ci chodzi ja myślałem o dzielniku napięcia bo Arduino jest w stanie mierzyć napięcie w zakresie od 0-5v z dokładnością bodajże 10bitów więc obsłuży wszystkie przyciski jednym pinem analogowym.

Tak, chodzi mi o sensowną metodę, na bazie której skonstruowana jest m.in. klawiatura Twojego komputera. Nie o metodę kreatywno-szaloną, której nikt pewnie nigdzie nie użył, bo tu same problemy na każdym kroku by były.

Edytowano przez trainee
  • 4 tygodnie później...

witam

w kwestii tablic mam jedno pytanie, bo nie doczytałem się tego i nie wiem czy to wogóle jest możliwe - a mianowicie problem wygląda tak:

mam dwie tablice:

image.png.97f60e0c908884d898eca042b0103444.png

w związku z tym pytanie, czy znając wartość tablicy numer - np. 65 co daje nam numer [2] który jest odpowiednikiem tablicy maszyna [2] mogę zmienić jej wartość np. z 2 na 10  ... nie mam zielonego pojecia jak to zapisać w postaci funcji by zadziałało ... z góry dziękuję za pomoc 

8 minut temu, merinum napisał:

w związku z tym pytanie, czy znając wartość tablicy numer - np. 65 co daje nam numer [2] który jest odpowiednikiem tablicy maszyna [2] mogę zmienić jej wartość np. z 2 na 10  ... nie mam zielonego pojecia jak to zapisać w postaci funcji by zadziałało ... z góry dziękuję za pomoc 

int numer[] = {63, 64, 65};
int maszyna[] = {1, 2, 2};

void update_maszyna(int numerVal, int newVal)
{
  // Tymczasowa zmienna określająca indeks w tablicy numer
  int index = 0;
  
  // Dla każdej wartości w tablicy numer
  for(int i = 0; i < sizeof(numer)/sizeof(numer[0]); i++)
  {
    // Jeżeli wartość jest identyczna jak oczekiwana zakończ iterację z obecną wartością zmiennej index
	if (numer[i] == numerVal) break;
    
    // W przyciwnym razie przejdź do następnej iteracji, bądź zakończ pętlę w przypadku zakończenia tablicy
    index++;
  }
  
  // Sprawdź czy indeks nie wykracza poza zakres, jeżeli tak zakończ funkcję
  if(index >= sizeof(maszyna)/sizeof(maszyna[0])) return;
  
  // Zaktualizuj wartość 
  maszyna[index] = newVal;
}

Jakoś tak, pisane na kolanie 😉 Musisz przeiterować przez tablicę numer szukając wartości i zwiększając wartość index. Bez zmiennej index też by się obyło, ale wolę taki system zapisu.

Potem sprawdzasz czy tablica maszyna zawiera dany indeks i aktualizujesz jego wartość 😉 

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...