[Risolto] Problema encoder rotativo button box

Ciao a tutti.
Il mio problema e il seguente:
Ho una scheda arduino pro micro con uno sketch per utilizzare 32 pulsanti e encoder rotativi.
Fino a poco tempo fa usavo dei encoder rotativi a 24 scatti che mi davano a ogni scatto un impulso. Adesso ho un altro tipo di encoder rotativ a 16 scatti che per qualche motivo mi da un impulso ogni 4 scatti. Io ho bisogno che mi da un impulso ad ogni scatto come quelli di prima. Lo sketch usato e identico per tutti e due.
Chiedo a voi se e possibile modificare lo sketch per avere un impulso per ogni scatto di questi nuovi encoder rotativi.
Vi metto sotto il codice e vi ringrazio in anticipo.

//BUTTON BOX 
//USE w ProMicro

#include <Keypad.h>
#include <Joystick.h>

#define ENABLE_PULLUPS
#define NUMROTARIES 4
#define NUMBUTTONS 24
#define NUMROWS 5
#define NUMCOLS 5


byte buttons[NUMROWS][NUMCOLS] = {
  {0,1,2,3,4},
  {5,6,7,8,9},
  {10,11,12,13,14},
  {15,16,17,18,19},
  {20,21,22,23},
};

struct rotariesdef {
  byte pin1;
  byte pin2;
  int ccwchar;
  int cwchar;
  volatile unsigned char state;
};

rotariesdef rotaries[NUMROTARIES] {
  {0,1,24,25,0},
  {2,3,26,27,0},
  {4,5,28,29,0},
  {6,7,30,31,0},
};

#define DIR_CCW 0x10
#define DIR_CW 0x20
#define R_START 0x0

#ifdef HALF_STEP
#define R_CCW_BEGIN 0x1
#define R_CW_BEGIN 0x2
#define R_START_M 0x3
#define R_CW_BEGIN_M 0x4
#define R_CCW_BEGIN_M 0x5
const unsigned char ttable[6][4] = {
  // R_START (00)
  {R_START_M,            R_CW_BEGIN,     R_CCW_BEGIN,  R_START},
  // R_CCW_BEGIN
  {R_START_M | DIR_CCW, R_START,        R_CCW_BEGIN,  R_START},
  // R_CW_BEGIN
  {R_START_M | DIR_CW,  R_CW_BEGIN,     R_START,      R_START},
  // R_START_M (11)
  {R_START_M,            R_CCW_BEGIN_M,  R_CW_BEGIN_M, R_START},
  // R_CW_BEGIN_M
  {R_START_M,            R_START_M,      R_CW_BEGIN_M, R_START | DIR_CW},
  // R_CCW_BEGIN_M
  {R_START_M,            R_CCW_BEGIN_M,  R_START_M,    R_START | DIR_CCW},
};
#else
#define R_CW_FINAL 0x1
#define R_CW_BEGIN 0x2
#define R_CW_NEXT 0x3
#define R_CCW_BEGIN 0x4
#define R_CCW_FINAL 0x5
#define R_CCW_NEXT 0x6

const unsigned char ttable[7][4] = {
  // R_START
  {R_START,    R_CW_BEGIN,  R_CCW_BEGIN, R_START},
  // R_CW_FINAL
  {R_CW_NEXT,  R_START,     R_CW_FINAL,  R_START | DIR_CW},
  // R_CW_BEGIN
  {R_CW_NEXT,  R_CW_BEGIN,  R_START,     R_START},
  // R_CW_NEXT
  {R_CW_NEXT,  R_CW_BEGIN,  R_CW_FINAL,  R_START},
  // R_CCW_BEGIN
  {R_CCW_NEXT, R_START,     R_CCW_BEGIN, R_START},
  // R_CCW_FINAL
  {R_CCW_NEXT, R_CCW_FINAL, R_START,     R_START | DIR_CCW},
  // R_CCW_NEXT
  {R_CCW_NEXT, R_CCW_FINAL, R_CCW_BEGIN, R_START},
};
#endif

byte rowPins[NUMROWS] = {21,20,19,18,15}; 
byte colPins[NUMCOLS] = {14,16,10,9,8}; 

Keypad buttbx = Keypad( makeKeymap(buttons), rowPins, colPins, NUMROWS, NUMCOLS); 

Joystick_ Joystick(JOYSTICK_DEFAULT_REPORT_ID, 
  JOYSTICK_TYPE_JOYSTICK, 32, 0,
  false, false, false, false, false, false,
  false, false, false, false, false);

void setup() {
  Joystick.begin();
  rotary_init();}

void loop() { 

  CheckAllEncoders();

  CheckAllButtons();

}

void CheckAllButtons(void) {
      if (buttbx.getKeys())
    {
       for (int i=0; i<LIST_MAX; i++)   
        {
           if ( buttbx.key[i].stateChanged )   
            {
            switch (buttbx.key[i].kstate) {  
                    case PRESSED:
                    case HOLD:
                              Joystick.setButton(buttbx.key[i].kchar, 1);
                              break;
                    case RELEASED:
                    case IDLE:
                              Joystick.setButton(buttbx.key[i].kchar, 0);
                              break;
            }
           }   
         }
     }
}


void rotary_init() {
  for (int i=0;i<NUMROTARIES;i++) {
    pinMode(rotaries[i].pin1, INPUT);
    pinMode(rotaries[i].pin2, INPUT);
    #ifdef ENABLE_PULLUPS
      digitalWrite(rotaries[i].pin1, HIGH);
      digitalWrite(rotaries[i].pin2, HIGH);
    #endif
  }
}


unsigned char rotary_process(int _i) {
   unsigned char pinstate = (digitalRead(rotaries[_i].pin2) << 1) | digitalRead(rotaries[_i].pin1);
  rotaries[_i].state = ttable[rotaries[_i].state & 0xf][pinstate];
  return (rotaries[_i].state & 0x30);
}

void CheckAllEncoders(void) {
  for (int i=0;i<NUMROTARIES;i++) {
    unsigned char result = rotary_process(i);
    if (result == DIR_CCW) {
      Joystick.setButton(rotaries[i].ccwchar, 1); delay(50); Joystick.setButton(rotaries[i].ccwchar, 0);
    };
    if (result == DIR_CW) {
      Joystick.setButton(rotaries[i].cwchar, 1); delay(50); Joystick.setButton(rotaries[i].cwchar, 0);
    };
  }
}

Buonasera,
essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con molta attenzione tutto il su citato REGOLAMENTO ... Grazie. :slight_smile:

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposito thread, nessuno ti potrà rispondere, quindi ti consiglio di farla al più presto. :wink:

Scusate per l'ingresso abusivo. :-[ Non era di certo la mia intenzione cominciare cosi su questo forum. Sono stato disattento.
Ho fatto la presentazione e adesso provo a fare un nuovo ingresso. ;D
Grazie in anticipo per l'aiuto.

Direi posta un link agli encoder che usavi prima con quel codice, ed uno a quelliche hai preso, così vediamo meglio cosa consigliarti.

Grazie per la celere risposta.

Questi sono quelli che usavo prima.

E questi sono quelli che voglio usare adesso.
https://www.digikey.it/products/it?keywords=288T232R161A2%20

Io ho bisogno di uno sketch da caricare su arduino pro micro per poter utilizzare 4 encoder rotativi e 20 pulsanti. Quello che ho postato andava benissimo con gli encoder di prima. Funziona bene anche con i nuovi encoder solo che avendo un impulso ogni 4 scatti praticamente utilizzo solo 4 dei 16 step che ha.

Ho trovato uno sketch in internet che non fa il caso mio (ha solo 3 encoder rotativi e 5 pulsanti), però con questo mi da 1 impulso ogni 2 scatti.
Allego qui sotto.

2 scatti.ino (8.14 KB)

Leggo:
Impulsi per giro 4

Datman:
Leggo:
Impulsi per giro 4

Ho visto anch'io ma andando più a fondo ho scoperto che sono rapportati 1:1 commutazione a 90° anzichè rapportati 1:4 commutazione a 360° come la magior parte. Quindi a 360° ha 16 scatti.

Nel datasheet leggo che per il 2bit si possono avere "4, 6, 8, 10, or 12 pulses per 360°" quindi da subito escludo che possa averne 16.

Ma sempre stando al datasheet, dal codice prodotto "288T232R161A2" di quello che hai, leggo che sarebbe:

288 T 2 32 R 16 1 A 2

288 = fisso per tutte le versioni
T = SOLDER LUG
2 = BUSHING 0.25"
32 = SHAFT 1"
R = ROUND SHAFT
16 = RESOLUTION 16 COM (4 PULSES-2bit)
1 = 2 BIT BINARY
A = NO SWITCH
2 = 16 DETENTS

Quindi con questo modello anche se hai 16 "scatti" fisici in realtà hai solo 4 impulsi, uno ogni 4 "scatti".

Per cui secondo me devi prendere l'encoder che usavi prima se vuoi avere lo stesso comportamento (ma perché hai cambiato??).

Hai perfettamente ragione. Ieri mi sono fatto anch'io una bella lettura in internet.
Dopo varie prove con qualche file trovato in internet sono riuscito ad avere uno sketch con 24 pulsanti e 4 encoder rotativi che mi da un impulso ogni 2 scatti (allego sotto). E già sono a un buon punto.
No essendo esperto di codici ho perso ore ieri a capire come mai il file che ho allegato nel post di prima (che non faceva caso mio) mi dava un impulso ogni 2 scatti.
So che per voi è una cosa semplice ma per me era arabo.
;D ;D Ho solo dovuto aggiungere #define HALF_STEP per far funzionare il mio vecchio sketch con un impulso ogni 2 scatti. Studiando si impara. :grinning:
Guardando in internet ho visto che ci sono: full step, half step e quarter step.
E possibile in qualche modo definire questo quarter step nel mio sketch?
Se a full_step mi dava 1 impulso ogni 4 step, a half_step mi da 1 impulso ogni 2 step, a quarter_step dovrebbe darmi 1 impulso ogni step. Magari sto dicendo una stronzata.
Comunque questi encoder funzionano sicuro 1:1 perché li o già provati. Non erano montati su una arduino ma su una scheda più costosa di Leobodnar. Quando giravo un scatto mi dava un impulso. Sono gli encoder più utilizzati in assoluto per volanti o button box custom. Devo solo capire come fare andare 1:1 su una arduino.
Ho trovato una discussione su un altro forum (se posso posto il link) dove l'autore ha compilato uno sketch per 24 pulsanti e 4 encoder che funzionava con questi nuovi encoder. Il post e vecchio e i file non sono più disponibili. Non riesco a rintracciare l'autore.
Ammetto che capisco poco o niente di codici arduino e non voglio fare perdere tempo a nessuno.
Se qualcuno riesce ad aiutarmi ben venga. Sempre se è possibile fare quello che io ho richiesto. Se mi dite che è impossibile fare una cosa del genere allora mi arrendo e cerco di cambiare scheda o gli encoder.

docdoc:
Nel datasheet
Per cui secondo me devi prendere l'encoder che usavi prima se vuoi avere lo stesso comportamento (ma perché hai cambiato??).

Ho cambiato perchè questi sono molto più precisi e performanti. Non salta nessun step. Invece glia altri se giri veloce qualche step salta. E poi ero sicuro che funzionano 1:1.

Grazie.

modificato_a_2_scatti.ino (4.03 KB)

Datman:
Leggo:
Impulsi per giro 4

Queste sono le tipiche risposte per fare numeri di non per aiutare. So leggere anch'io.

docdoc:
Nel datasheet leggo che per il 2bit si possono avere "4, 6, 8, 10, or 12 pulses per 360°" quindi da subito escludo che possa averne 16.

Invece ti sbagli.

Pensavo che il posto migliore dove trovare aiuto per i codici arduino e il forum arduino. Invece qui mi sbagliavo io.

Comunque vi posso dire che funziona. Ho 16 pulsi per 360°. L'encoder ha si solo 4 pulsi per 360° ma facendolo andare a QUARTER_STEP come vi dicevo nel post di prima praticamente da un impulso ad ogni scatto.
Cosi imparate anche voi una cosa nuova :wink:. Oppure già sapevate ma nessuno si e degnato di darmi una mano. Non saprò mai.
Visto che gli aiuti su questo forum sono stati pari a zero, non postero il risultato ne spiegherò come sono riuscito a risolvere da solo.
Signori, io vi saluto.

Bene, visto che l'utente ci saluta ... chiudiamo il thread ed evitiamo inutili polemiche.

Guglielmo