Go Down

Topic: Problema di risposta da selettore (Read 492 times) previous topic - next topic

enrico24

Jun 23, 2019, 08:19 pm Last Edit: Jun 23, 2019, 08:22 pm by enrico24
Buongiorno a tutti, ho recentemente ripreso un vecchio progetto Arduino, aggiungendo un selettore rotativo evitando una serie d'interruttori.

Tutto bene, ma quando ho cercato d'inviare con un HC-12 il codice ottenuto mi sono accorto che non sempre l'invio era corrispondente alla posizione selezionata. Ho provato a cambiare il Mega (cinese!) ma il risultato non cambiava, rifatto i collegamenti, cambiato i PIN di riferimento, cambiato l'interruttore … stesso risultato!

Qualcuno può mettermi sulla giusta strada per correggere l'errore (che io non ho trovato?).

Allego file con lo schema dei collegamenti dell'interruttore (P.S.: i resistori sono da 470 ohm).



Code: [Select]

/*
   Prova selettore
   18.06.19
*/

#include <SoftwareSerial.h>
SoftwareSerial HC12(52, 50); // HC-12 TX Pin, HC-12 RX Pin

const int p_verde = A15;
const int p_giallo = A14;
const int p_rosso = A13;

// Sequenziale

#define seq1 23 // pin di input dove è collegato il pulsante
#define seq2 25 // pin di input dove è collegato il pulsante
#define seq3 27 // pin di input dove è collegato il pulsante
#define seq4 29 // pin di input dove è collegato il pulsante
#define seq5 31 // pin di input dove è collegato il pulsante
#define seq6 33 // pin di input dove è collegato il pulsante
#define seq7 35 // pin di input dove è collegato il pulsante
#define seq8 37 // pin di input dove è collegato il pulsante
#define seq9 39 // pin di input dove è collegato il pulsante
#define seq10 41 // pin di input dove è collegato il pulsante

char nr6 = 'i';
int nr7 = 0;  // pulsanti
char stringa;
int v_alt = 0;

void setup() {
  pinMode( p_verde, INPUT);
  pinMode( p_giallo, INPUT);
  pinMode( p_rosso, INPUT);

  pinMode(seq1, INPUT);     // imposta il pin digitale come input
  pinMode(seq2, INPUT);     // imposta il pin digitale come input
  pinMode(seq3, INPUT);     // imposta il pin digitale come input
  pinMode(seq4, INPUT);     // imposta il pin digitale come input
  pinMode(seq5, INPUT);     // imposta il pin digitale come input
  pinMode(seq6, INPUT);     // imposta il pin digitale come input
  pinMode(seq7, INPUT);     // imposta il pin digitale come input
  pinMode(seq8, INPUT);     // imposta il pin digitale come input
  pinMode(seq9, INPUT);     // imposta il pin digitale come input
  pinMode(seq10, INPUT);     // imposta il pin digitale come input

  Serial.begin(9600);
  HC12.begin(9600);

}

void loop() {
  // controlla lo stato dei pulsanti
  if (digitalRead(p_verde) == LOW) {
    nr7 = 1;  // Avvio
  } else if (digitalRead(p_giallo) == LOW)  {
    nr7 = 2;  // azzera
  }  else if (digitalRead(p_rosso) == LOW) {
    nr7 = 3;  // stop
  } else {
    nr7 = 0;
  }

  // controlla la posizione dell'interruttore sequenziale
  if (digitalRead(seq1) == HIGH) {
    nr6 = 'a';
  } else if (digitalRead(seq2) == HIGH)  {
    nr6 = 'b';
  }  else if (digitalRead(seq3) == HIGH) {
    nr6 = 'c';
  } else if (digitalRead(seq4) == HIGH)  {
    nr6 = 'd';
  }  else if (digitalRead(seq5) == HIGH) {
    nr6 = 'e';
  } else if (digitalRead(seq6) == HIGH) {
    nr6 = 'f';
  } else if (digitalRead(seq7) == HIGH)  {
    nr6 = 7;
  }  else if (digitalRead(seq8) == HIGH) {
    nr6 = 8;
  }  else if (digitalRead(seq9) == HIGH) {
    nr6 = 'g';
  }  else if (digitalRead(seq10) == HIGH) {
    nr6 = 'h';
  } else {
    nr6 = 'i';
  }


  if (nr6 != 'i') {
    Serial.println(nr6);
    trasmetti();
  }
  delay(1000);
}

void trasmetti() {

  if ((nr7 > 0) && (stringa != 'i')) {

    if ((nr7 == 1) && (v_alt == 0)) {
      /*
          invia l'istruzione di avvio
      */

      HC12.print(stringa);
      Serial.println(stringa);

    } else if ((nr7 == 2) && (v_alt == 0)) {
      /*
         azzera il tiner
      */

      stringa = 'm';

      HC12.print(stringa);

    } else if ((nr7 == 3) && (v_alt == 0)) {
      /*
         invia l'istruzione di STOP
      */
      v_alt = 1;
      stringa = 'n';

      HC12.print(stringa);

    } else if (v_alt == 1)   {

      if ((nr7 == 1) || (nr7 == 2)) {
        /*
          invia l'istruzione di Ripresa gara
        */
        stringa = 'o';
        v_alt = 0;
        HC12.print(stringa);
      }
    }
    delay(250);
  }

  nr7 = 0;
}



Grazie anticipatamente per l'eventuale aiuto.

Saluti

Enrico


docdoc

#1
Jun 25, 2019, 11:11 am Last Edit: Jun 25, 2019, 11:12 am by docdoc
Scusa ma a parte le resistenze in serie (inutili perché solo uno dei pin sarà collegato quindi al massimo ti basta metterne UNA sola tra il centrale del selettore e +5V), quei pin non sono né pullup né pulldown, quindi se li lasci fluttuanti hai letture potenzialmente sballate!

Possibili soluzioni:

1) Imposti i pin come INPUT_PULLUP ed il centrale del commutatore lo metti a GND invece che a 5V, quindi ogni pin va confrontato con LOW per sapere se è selezionato

2) Metti una resistenza di pulldown per ognuno dei pin (ossia  sposti le attuali per collegarle tra il pin del selettore e GND, non tra pin e selettore!)

Ma direi che invece di usare 10 pin digitali potrebbe bastare usarne uno solo ma analogico se li colleghi con un opportuno partitore resistivo tra ogni pin (per cui la lettura analogica avrà 10 livelli di tensione, ammettendo un minimo di variabilità sul valore centrale).
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

enrico24

Grazie per le informazioni.

Avevo già provato ad utilizzare un PIN analogico "leggendo" le diverse tensioni, ma saltuariamente ottenevo risultati "sballati" (probabilmente causa la mia scarsa manualità ed esperienza). Visto che disponevo di un Mega ho preferito usare più PIN digitali.

Proverò quindi una delle altre due soluzioni.

GRAZIE.

Saluti

Enrico

docdoc

Avevo già provato ad utilizzare un PIN analogico "leggendo" le diverse tensioni, ma saltuariamente ottenevo risultati "sballati" (probabilmente causa la mia scarsa manualità ed esperienza). Visto che disponevo di un Mega ho preferito usare più PIN digitali.
Sicuramente avendoli a disposizione male non fa, quindi ok così basta che li imposti o con pullup o pulldown.. :D

Però per il futuro, posso dirti che io ho usato commutatori in quel modo (ad esempio per i commutatori di un pannello per Flight Simulator che feci per mio figlio) senza problemi, l'importante è che tu faccia un partitore fatto benino, ossia mettendo una resistenza tra due contatti adiacenti esempio:



Quindi nel codice devi verificare i valori che leggi per ognuna delle posizioni, ed ammettere un certo scarto (ossia non cercare il valore esatto).

Nel tuo caso se hai 10 posizioni avrai valori da 0 a +5V quindi in media intervalli da circa 1024/10 = 102 quindi andando sulla metà di ogni intervallo potrai considerare valori:
Pos 0 = 0 (GND)
Pos 1 = 102
Pos 2 = 204
... eccetera
Pos 9 = 1023 (+5V)
quindi puoi fare una funzioncina che dato il valore letto dall'analogico ti restituisce l'indice della posizione del cursore.
Per farlo ti basta considerare un range di +-51 centrato sul valore base, ossia del tipo:

Code: [Select]
int Analog2Rotary(int cur) {
return int( (cur+51) /102);

Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

enrico24

BELLO!

Mi sembra un'ottima soluzione, proverò ad applicarla comandando i singoli LED tramite PIN.

Grazie

Enrico

PS: quali resistori consiglieresti di usare?

steve-cr

Mi sembra un'ottima soluzione, proverò ad applicarla comandando i singoli LED tramite PIN.
E' sicuramente una OTTIMA soluzione per diversi motivi:
- utilizzi solo un ingresso
- utilizzi solo un filo per tutte le posizioni (più il gnd e il +5, chiaro)
- hai meno possibilità di commettere errori, falsi contatti, eccetera e meno fili in giro.
- il risultato con un solo ingresso è garantito come se avessi i tuoi 12 ingressi.
Samantha Cristoforetti: "Mi fai fare un giro sul tuo ultraleggero?". "Certamente, però piloto io !"

enrico24

Certo, però devo gestire separatamento i 10 LED che mi indicano quale punto del selettore è collegato!

Saluti

Enrico

enrico24

Ops, solo adesso mi sono accorto che non avevo mai menzionato il fatto che ad ogni posizione del selettore corrisponde una luce LED!

Scusate-

Enrico

steve-cr

Beh, no, si vedeva dallo schema che hai postato che usi i led per ogni posizione. Nel caso usassi un potenziometro puro sarebbero indispensabili per vedere a che posizione stai andando. Nel caso del commutatore che ti ha suggerito docdoc non servono. Se però ti interessa metterli ugualmente, puoi pensare ad un commutatore doppio: su un piano fai lo schema di docdoc e sul secondo arrivi con la +5v e la commuti sui relativi led.
Samantha Cristoforetti: "Mi fai fare un giro sul tuo ultraleggero?". "Certamente, però piloto io !"

Standardoil

La scelta del partitore su pin analogico è concettualmente sbagliata
Lo OP avrebbe cosi 1 un ingresso ad alta impedenza (disturbi) e 10 uscite 11 pin usati

La scelta dello OP è invece corretta concettualmente, solo 10 ingresso a bassa impedenza
Il problema è realizzativo
Ha messo gli ingressi tra led è resistenza,in questa maniera l'ingresso non sente 5v, ma la tensione del led, insufficiente per gli ingressi di Arduino
Prima legge di Nelson (che sono io): fai le stesse cose sempre alla stessa maniera, quegli errori li hai già corretti

Non bado a studenti, che vadano a copiare da un'altra parte

Se io ti domando e tu non mi rispondi vuol dire che non ti serve più

steve-cr

#10
Jul 01, 2019, 11:57 am Last Edit: Jul 01, 2019, 11:57 am by steve-cr
Secondo ciò che ho detto sopra, i pin utilizzati sarebbero... solo 1 e per i led non ha senso prelevarli dalle uscite ma solo utilizzare il commutatore per saperne la posizione.
Però, se vogliamo dire che non ci fidiamo dell'ingresso e allora vogliamo controllare anche l'uscita, allora va bene...
Samantha Cristoforetti: "Mi fai fare un giro sul tuo ultraleggero?". "Certamente, però piloto io !"

Standardoil

E scegliere quindi un commutatore a due vie 10 posizioni?
Mi sa che costa di più...
Prima legge di Nelson (che sono io): fai le stesse cose sempre alla stessa maniera, quegli errori li hai già corretti

Non bado a studenti, che vadano a copiare da un'altra parte

Se io ti domando e tu non mi rispondi vuol dire che non ti serve più

docdoc

La scelta del partitore su pin analogico è concettualmente sbagliata
Lo OP avrebbe cosi 1 un ingresso ad alta impedenza (disturbi) e 10 uscite 11 pin usati
A meno di avere dei cavi lunghi (cosa che mi pare si possa escludere) che potrebbero indurre fluttuazioni nell'ingresso ad alta impedenza, non ci sono problemi ad usare un commutatore in quel modo, ossia come partitore resistivo (con resistenze ad esempio da 1k), cosa ci sia di "concettualmente sbagliato" non è molto chiaro, e tra l'altro è una configurazione molto diffusa proprio per questi casi (commutatori o pulsanti da premere solo uno per volta), ed io stesso l'ho usata con pieno successo su più commutatori per Flight Simulator.

E comunque è solo per ottimizzare i pin, nel suo caso dato che usa una Mega non ha problemi e può anche lasciare tutto com'è, il mio era solo un suggerimento "per il futuro" (e meno male che l'avevo pure scritto...) non necessariamente per questa applicazione specifica.

Ops, solo adesso mi sono accorto che non avevo mai menzionato il fatto che ad ogni posizione del selettore corrisponde una luce LED!
Come già correttamente evidenziato da steve-cr, se vuoi puoi utilizzare un commutatore doppio ossia con doppi contatti, sul secondo cablerai (ricorda la resistenza per limitare la corrente!) i LED corrispondenti ad ognuna delle posizioni mandando ad esempio +5V sul comune (tramite resistenza limitatrice) ed i LED tutti a GND.

In alternativa, potresti pensare ad una coppia di 74HC595 (con i quali gestire fino a 16 LED), ma insomma, se hai una Mega e non hai problemi di pin sarebbe una inutile complicazione.
Alex "docdoc" - ** se ti sono stato d'aiuto, un punto karma sarà gradito, clicca su "add" qui a sinistra, vicino al mio nome ;) **

Standardoil

Oddiobbono...
Per NON voler correggere l'errore di cablaggio di aver messo l'ingresso dopo la resistenza invece che prima, ci mettiamo a giocare con gli shift register?
Ma pensare easy non si usa più?
Certo che poi servono 12 pagine per 2 pomodori (piante di)...
Prima legge di Nelson (che sono io): fai le stesse cose sempre alla stessa maniera, quegli errori li hai già corretti

Non bado a studenti, che vadano a copiare da un'altra parte

Se io ti domando e tu non mi rispondi vuol dire che non ti serve più

enrico24

#14
Jul 01, 2019, 02:34 pm Last Edit: Jul 01, 2019, 02:36 pm by enrico24
Grazie a tutti, al momento ho "girato" LED e alimentazione e tutto sembra funzionare. Certo la tensione che va al PIN è un po' bassina (1.6/1.7 V) ma sembrerebbe funzionare.

Ecco il nuovo programma e lo schema

Code: [Select]

…...

// Sequenziale
#define SIZESEQ 10//Il numero di posizioni presenti
const byte sequenziale [SIZESEQ] = {22, 24, 26, 28, 30, 32, 34, 36, 38, 40}; //I pin a cui sono collegati
const int significato [SIZESEQ + 1] = {  1, 2, 3, 4, 5, 6, 7, 8, 9, 0}; //L'insieme dei valori da trasmettere

i-----

void setup() {

  ….

  for (byte i = 0; i < SIZESEQ; i++)
  {
    pinMode (sequenziale[i], INPUT);
  }

  Serial.begin(9600);

}

void loop() {
…..

  // controlla la posizione dell'interruttore sequenziale
  byte i;
  for (i = 0; i < SIZESEQ; i++)//I va da 0 a 10
  {
    if (digitalRead (sequenziale[i]) == LOW) //==HIGH è sottinteso
      break;//Ma si ferma se sento pulsante
  }
  nr6 = significato[i];
  if (nr6 > 9) {
    nr6 = 0;
  }

…..
  }





Go Up