Skocz do zawartości
jasiekk913

Arduino - pomoc z programem do buttonbox'a

Pomocna odpowiedź

Witam,


posiadam arduino leonardo na które zrobiłem program do buttonbox'a, a bardziej przełącznikobox'a ;). Problem polega na tym że podczas przełączania przełącznika arduino wyśle sygnał 2 razy przez co w grze pozycja przełącznika jest odwrotna do tego co mam w rzeczywistości. Załączam mój aktualny kod:

#include <Joystick.h>

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID,JOYSTICK_TYPE_GAMEPAD,
  27, 0,                  // Button Count, Hat Switch Count
  false, false, false,     // X and Y, but no Z Axis
  false, false, false,   // No Rx, Ry, or Rz
  false, false,          // No rudder or throttle
  false, false, false);

bool p2=false;
bool p3=false;
bool p4=false;
bool p5=false;
bool p6=false;
bool p7=false;
bool p8=false;
bool p9=false;
bool p10=false;
bool p11=false;
bool p12=false;
bool p13=false;
bool pa0=false;
bool pa1=false;
bool pa2=false;
bool pa3=false;
bool pa4=false;
bool pa5=false;
char d=' ';
bool przod=false;
bool nic=true;
bool tyl=false;

void setup(){
  Serial.begin(115200);
  Serial1.begin(115200);
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(7, INPUT);
  pinMode(8, INPUT);
  pinMode(9, INPUT);
  pinMode(10, INPUT);
  pinMode(11, INPUT);
  pinMode(12, INPUT);
  pinMode(13, INPUT);
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);
  pinMode(A3, INPUT);
  pinMode(A4, INPUT);
  pinMode(A5, INPUT);
  Joystick.begin();
}

void loop(){
  sprawdzprzyciski();
  sprawdzczysadane();
}

void sprawdzczysadane(){
  if(Serial1.available()){
    d=Serial1.read();
    odczytajdane(d);
  }
}

void klima(){
  if(pa2==true&&pa3==false){
    Serial1.println('a');
  }
  if(pa2==false&&pa3==true){
    Serial1.println('b');
  }
  if(pa2==false&&pa3==false){
    Serial1.println('c');
  }
}

void ekrany(String e){
  if(e=="pojazd"){
    Serial1.println('d');
  }
  if(e=="ekran"){
    Serial1.println('e');
  }
}

void odczytajdane(char c){
  if(c=='a'){
    Joystick.setButton(8, 1);
  }
  if(c=='b'){
    Joystick.setButton(8, 0);
  }
  /*                                          NA KONIEC                                                   */
  /*if(c=='c'){
    Joystick.setButton(15, 1);
  }
  if(c=='d'){
    Joystick.setButton(15, 0);
  }
  if(c=='e'){
    Joystick.setButton(16, 1);
  }
  if(c=='f'){
    Joystick.setButton(16, 0);
  }*/
  /*                                  NA KONIEC                                                             */
  if(c=='g'){
    Joystick.setButton(19, 1);
    delay(25);
    Joystick.setButton(19, 0);
  }
  if(c=='h'){
    Joystick.setButton(19, 1);
    delay(25);
    Joystick.setButton(19, 0);
  }
  if(c=='i'){
    Joystick.setButton(17, 1);
  }
  if(c=='j'){
    Joystick.setButton(17, 0);
  }
  if(c=='k'){
    Joystick.setButton(21, 1);
    delay(25);
    Joystick.setButton(21, 0);
  }
  if(c=='l'){
    Joystick.setButton(21, 1);
    delay(25);
    Joystick.setButton(21, 0);
  }

  //SWIATLA


  if(c=='m'){
    Joystick.setButton(24, 1);
    delay(25);
    Joystick.setButton(24, 0);
  }
  if(c=='n'){
    Joystick.setButton(23, 1);
    delay(25);
    Joystick.setButton(23, 0);
  }
  if(c=='o'){
    Joystick.setButton(23, 1);
    delay(25);
    Joystick.setButton(23, 0);
  }
  if(c=='p'){
    Joystick.setButton(23, 1);
    delay(25);
    Joystick.setButton(23, 0);
  }

  //\\ SWIATLA //\\


  if(c=='q'){
    Joystick.setButton(22, 1);
    delay(25);
    Joystick.setButton(22, 0);
  }
  if(c=='r'){
    Joystick.setButton(22, 1);
    delay(25);
    Joystick.setButton(22, 0);
  }
  if(c=='s'){
    Joystick.setButton(20, 1);
    delay(25);
    Joystick.setButton(20, 0);
  }
  if(c=='t'){
    Joystick.setButton(20, 1);
    delay(25);
    Joystick.setButton(20, 0);
  }
  if(c=='x'){
    Joystick.setButton(18, 1);
  }
  if(c=='z'){
    Joystick.setButton(18, 0);
  }
}

void sprawdzprzyciski(){
    if(digitalRead(2)==HIGH&&p2==false){
      Joystick.setButton(0, 1);
      p2=true;
    }
    if(digitalRead(2)==LOW&&p2==true){
      Joystick.setButton(0, 0);
      p2=false;
    }

    //KOLEJNE
    if(digitalRead(3)==HIGH&&p3==false){
      Joystick.setButton(11, 1);
      p3=true;
    }
    if(digitalRead(3)==LOW&&p3==true){
      Joystick.setButton(11, 0);
      p3=false;
    }

    //SKRZYNIA BIEGOW

    //14D pin 4
    //15N
    //16R pin 13

    if(digitalRead(4)==HIGH&&p4==false){
      p4=true;
    }
    if(digitalRead(4)==LOW&&p4==true){
      p4=false;
    }
    if(digitalRead(13)==HIGH&&p13==false){
      p13=true;
    }
    if(digitalRead(13)==LOW&&p13==true){
      p13=false;
    }

    if((p4==true&&p13==false)&&przod==false){
      Joystick.setButton(14, 1);
      delay(25);
      Joystick.setButton(14, 0);
      nic=false;
      tyl=false;
      przod=true;
    }
    if((p4==false&&p13==false)&&nic==false){
      Joystick.setButton(15, 1);
      delay(25);
      Joystick.setButton(15, 0);
      nic=true;
      tyl=false;
      przod=false;
    }
    if((p4==false&&p13==true)&&tyl==false){
      Joystick.setButton(16, 1);
      delay(25);
      Joystick.setButton(16, 0);
      nic=false;
      tyl=true;
      przod=false;
    }


    //\\ SKRZYNIA BIEGOW //\\

    //KOLEJNE
    if(digitalRead(5)==HIGH&&p5==false){
      Joystick.setButton(3, 1);
      p5=true;
    }
    if(digitalRead(5)==LOW&&p5==true){
      Joystick.setButton(3, 0);
      p5=false;
    }

    //KOLEJNE
    if(digitalRead(6)==HIGH&&p6==false){
      Joystick.setButton(6, 1);
      delay(25);
      Joystick.setButton(6, 0);
      p6=true;
    }
    if(digitalRead(6)==LOW&&p6==true){
      Joystick.setButton(6, 1);
      delay(25);
      Joystick.setButton(6, 0);
      p6=false;
    }

    //KOLEJNE
    if(digitalRead(7)==HIGH&&p7==false){
      Joystick.setButton(13, 1);
      p7=true;
    }
    if(digitalRead(7)==LOW&&p7==true){
      Joystick.setButton(13, 0);
      p7=false;
    }

    //KOLEJNE
    if(digitalRead(8)==HIGH&&p8==false){
      Joystick.setButton(9, 1); //ZMIENIONE
      p8=true;
    }
    if(digitalRead(8)==LOW&&p8==true){
      Joystick.setButton(9, 0);
      p8=false;
    }

    //KOLEJNE
    if(digitalRead(9)==HIGH&&p9==false){
      Joystick.setButton(5, 1);
      delay(25);
      Joystick.setButton(5, 0);
      p9=true;
    }
    if(digitalRead(9)==LOW&&p9==true){
      Joystick.setButton(5, 1);
      delay(25);
      Joystick.setButton(5, 0);
      p9=false;
    }

    //KOLEJNE
    if(digitalRead(10)==HIGH&&p10==false){
      Joystick.setButton(2, 1);
      p10=true;
    }
    if(digitalRead(10)==LOW&&p10==true){
      Joystick.setButton(2, 0);
      p10=false;
    }

    //KOLEJNE
    if(digitalRead(11)==HIGH&&p11==false){
      Joystick.setButton(12, 1);
      p11=true;
    }
    if(digitalRead(11)==LOW&&p11==true){
      Joystick.setButton(12, 0);
      p11=false;
    }

    //KOLEJNE
    if(digitalRead(12)==HIGH&&p12==false){
      Joystick.setButton(7, 1);
      delay(25);
      Joystick.setButton(7, 0);
      p12=true;
    }
    if(digitalRead(12)==LOW&&p12==true){
      Joystick.setButton(7, 1);
      delay(25);
      Joystick.setButton(7, 0);
      p12=false;
    }

    //KOLEJNE
    if(digitalRead(A0)==HIGH&&pa0==false){
      Joystick.setButton(4, 1);
      pa0=true;
    }
    if(digitalRead(A0)==LOW&&pa0==true){
      Joystick.setButton(4, 0);
      pa0=false;
    }

    //KOLEJNE
    if(digitalRead(A1)==HIGH&&pa1==false){
      Joystick.setButton(1, 1);
      pa1=true;
    }
    if(digitalRead(A1)==LOW&&pa1==true){
      Joystick.setButton(1, 0);
      pa1=false;
    }

    //KOLEJNE
    if(digitalRead(A2)==HIGH&&pa2==false){
      pa2=true;
      klima();
    }
    if(digitalRead(A2)==LOW&&pa2==true){
      pa2=false;
      klima();
    }

    //KOLEJNE
    if(digitalRead(A3)==HIGH&&pa3==false){
      pa3=true;
      klima();
    }
    if(digitalRead(A3)==LOW&&pa3==true){
      pa3=false;
      klima();
    }

    //KOLEJNE
    if(digitalRead(A4)==HIGH&&pa4==false){
      pa4=true;
      Joystick.setButton(10, 1);
      ekrany("ekran");
    }
    if(digitalRead(A4)==LOW&&pa4==true){
      pa4=false;
      Joystick.setButton(10, 0);
    }

    //KOLEJNE
    if(digitalRead(A5)==HIGH&&pa5==false){
      pa5=true;
      ekrany("pojazd");
    }
    if(digitalRead(A5)==LOW&&pa5==true){
      pa5=false;
    }
}

Arduino oprócz tego że sprawdza przyciski, dostaje też sygnały z drugiego arduino przez Serial1 ;).

W przypadku chęci pomocy proszę o przykład jak powinien skrypt wyglądać w przypadku przycisku 2, tj. pinu 10:
 

if(digitalRead(10)==HIGH&&p10==false){
  Joystick.setButton(2, 1);
  p10=true;
}
if(digitalRead(10)==LOW&&p10==true){
  Joystick.setButton(2, 0);
  p10=false;
}



Pozdrawiam
jasiekk

Udostępnij ten post


Link to post
Share on other sites

Kiedy widzę tego typu inwencję twórczą w programowaniu to odczuwam pewną formę zniechęcenia do analizowania takiego kodu. Cóż, każdy kiedyś zaczynał mimo to warto jednak uruchomić pokłady własnej kreatywności czasami zamiast liczyć na cudzą a samemu zbierać uznania. Jak wspomniałem nie chce mi się tego analizować ale jeśli nic w logice tych przełączników nie sknociłeś to może nie procedura jest tu winna a elektryka. Może wykrywasz drgania styków na tych przełącznikach i dlatego masz 2 sygnały na wejściu.



                               R           _o_ SW1
[pin]-----------------o-----[/\/\/]-------*   *--------
                      |                               |
                    -----                             |
                    -----  C1                         |
                      |                               |
                    __|__                           __|__
                    \   /                           \   /
                     \ /  gnd                        \ /  gnd
                      

Spróbuj dać na pin jakiś kondensator np. 10 - 100n do masy i rezystor w razie potrzeby z 1k, a najlepiej sprawdź oscyloskopem jak te przełączenia wyglądają jeśli masz taką możliwość.

Udostępnij ten post


Link to post
Share on other sites

Proponuję zacząć od ustalenia wersji. Co masz w końcu podłączone do tego urządzenia:

Dnia 1.09.2019 o 17:34, jasiekk913 napisał:

podczas przełączania przełącznika

czy

Dnia 1.09.2019 o 17:34, jasiekk913 napisał:

Arduino oprócz tego że sprawdza przyciski

Czyli masz tam przełączniki (np. 2-pozycyjne) czy przyciski (monostabilne), bo to dość duża różnica w tym przypadku 😉

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Możliwe że warunek jaki dałeś ze zmienną p10 powoduje, że wykonają się oba warunki - bo jeżeli pierwszy warunek zostanie spełniony, to daje on zielone światło dla drugiego warunku.

Może spróbuj dać else, który sprawi że nawet po ustawieniu zmiennej, nie wpłynie ona na warunek w bieżącej iteracji. Nalezy go umieścić przed drugim if'em. Ewentualnie przemodelować warunek w ten sposób.


if(p10==false){
  if(digitalRead(10)==HIGH){
    Joystick.setButton(2, 1);
    p10=true;
  }
} else {
  if(digitalRead(10)==LOW){
    Joystick.setButton(2, 0);
    p10=false;
  }
}

Poza tym fajnym pomysłem, byłaby redukcja dziesiątek zmiennych do tablicy i ewentualnie ponazywanie jakoś indeksów. Dodanie funkcji, która by wyzwalała jakieś zdarzenia, itd...

#define PIN_COUNT 18

#define INDEX_PRZELACZNIK_PRAWY 0
#define INDEX_PRZELACZNIK_LEWY 1
#define INDEX_PRZELACZNIK_JAKISTAM 2
//ITD...

uint8_t pinNumbers[PIN_COUNT] = {2,3,4,5,6,7,8,9,10,11,12,13,A0,A1,A2,A3,A4,A5};
bool latchState[PIN_COUNT];
for(uint8_t i=0; i < PIN_COUNT; ++i)
  latchState[i] = false;
//tu juz odpada ponad 18 lini kodu.

//zdarzenie gdy stan zmienia się z niskiego na wysoki
void onTriggerRising(uint8_t index){
  //tu wystarczy ze sprawdzisz czy index tablicy odpowiada wczesniej zdefiniowanemu np.:
  if(index == INDEX_PRZELACZNIK_PRAWY)
      Joystick.setButton(10, 0);
}

//zdarzenie gdy stan zmienia się z niskiego na wysoki
void onTriggerFalling(uint8_t index){
  //tu wystarczy ze sprawdzisz czy index tablicy odpowiada wczesniej zdefiniowanemu np.:
  if(index == INDEX_PRZELACZNIK_PRAWY)
      Joystick.setButton(10, 1);
}

//funkcje te wywolaj w petli, ona sprawdza wszystkie ustawione w tablicy peryferia
void processTrigger() {
  for(uint8_t i=0; i < PIN_COUNT; ++i){
    if(latchState[i] == false){
      if(digitalRead(pinNumbers[i] == HIGH)){
        onTriggerRising(i);
        latchState[i] = true;
      }
    } else {
      if(digitalRead(pinNumbers[i] == LOW)){
        onTriggerFalling(i);
        latchState[i] = false;
      }
    }
  }
}

void loop(){
  processTrigger();
}

Te uzupełnienie tablicy jest średnio elastyczne, możesz jakoś inaczej to uzupełnić. Ale i tak kod jest już zlekka czytelniejszy...

Edytowano przez Gieneq
  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Ja bym to zrobił bardziej ogólnie - coś w stylu "jeśli zmienił się stan przełącznika, wyślij bieżący stan na urządzenie". Można to zrobić klasą i obiektami "przełącznik", można po prostu zwykłymi tablicami zawierającymi konkretne dane (numer pinu, numer komunikatu, stan).

Po to w C są funkcje i struktury, a w C++ klasy, obiekty i metody - aby z nich korzystać. Bez tego można traktować C jako wygodny zapis kodu w asemblerze...

Wróć, w asemblerze też można korzystać z tablic i pętli!

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

Dzięki za pomysły 😉 jak będę miał chwilę i coś zrobię dam znać 

 

Pozdrawiam

jasiekk

Udostępnij ten post


Link to post
Share on other sites

A czy wykorzystanie przerwań nie było by dobrym pomysłem?

void setup() {
  Serial.begin(9600);
  bitSet(PCICR, PCIE0); 
// enable pin change interrupt bank 0
  bitSet(PCMSK0, PCINT4); 
// enable pin change interrupt on PCINT4/D12
 pinMode(12,INPUT_PULLUP);
}

void loop() {
                   
}

ISR(PCINT0_vect) {
if(digitalRead(12) == HIGH) {
Serial.println("Button OFF");
} else {
Serial.println("Button ON");
 }
}

Dla jednego pinu działa. A jak było by ze wszystkimi?

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites

@slon Arduino nie jest wstanie obsłużyć aż tylu przerwań zewnętrznych. Niestety w tym konkretnym przypadku to rozwiązanie się nie sprawdzi.

Udostępnij ten post


Link to post
Share on other sites

Ok dzięki. Trzy wektory po jednym dla każdej z grup pinów

Udostępnij ten post


Link to post
Share on other sites

W dodatku masz Serial.print() w funkcji obsługującej przerwanie - a to niezbyt mądre rozwiązanie.

Jak mniemam docelowo chciałbyś tam umieścić Joystick.setButton(), a to jeszcze gorszy pomysł.

W przypadku takiego buttonboxa polling jest najprostszym i najlepszym rozwiązaniem.

  • Lubię! 1

Udostępnij ten post


Link to post
Share on other sites
3 godziny temu, ethanak napisał:

W dodatku masz Serial.print() w funkcji obsługującej przerwanie - a to niezbyt mądre rozwiązanie.

Dlaczego? Uzasadnij w odniesieniu do tego kodu który podałem (nie do projektu)

3 godziny temu, ethanak napisał:

Jak mniemam docelowo chciałbyś tam umieścić Joystick.setButton(), a to jeszcze gorszy pomysł.

nie.

3 godziny temu, ethanak napisał:

W przypadku takiego buttonboxa polling jest najprostszym i najlepszym rozwiązaniem.

Ok.

Udostępnij ten post


Link to post
Share on other sites
2 minuty temu, slon napisał:

Dlaczego? Uzasadnij w odniesieniu do tego kodu który podałem (nie do projektu)

Serial używa swoich przerwań do wysyłania danych "w tle", wejście w inne przerwanie powoduje zablokowanie. Podobnie nie powinien działać delay który bazuje na timerach. W przerwaniu najlepiej umieszczać kod który ma się wykonywać szybko, bez zawiłości.

Jeżeli jednak chcesz powiązać wysłanie czegoś na UART albo jakieś opóźnienie, to możesz to zrobić po opuszczeniu bloku przerwania. Możesz użyć do tego jakiś zmiennych-flag które ustawiasz w przerwaniu ale mają efekt dopiero w głównej pętli.

  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites
6 minut temu, slon napisał:

Dlaczego?

Bo procedura przerwania powinna wykonywać się jak najszybciej, a w szczególności nie powinna wywoływać innych procedur zależnych od przerwań.

  • Lubię! 1
  • Pomogłeś! 1

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Dziękuje za odpowiedzi.  Czy taki zapis z punktu widzenia istoty przerwania będzie poprawny ? (pomijając, że można by użyć bitSet() lub PORTB)

ISR(PCINT0_vect) {
if(digitalRead(12) == HIGH) {
  liczynik=1;
  digitalWrite(13, HIGH);
} else {
  digitalWrite(13, LOW);
 }
}

 

Edytowano przez slon

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