Cómo deshacer seis botones en un pin analógico con Arduino

4

Estoy usando el pin analógico 5 en Arduino para detectar pulsaciones de 6 botones. En la imagen, el botón de arriba a la derecha es el número 1 y luego, de derecha a izquierda, van como 2, 3, 4, 5, 6. El programa debe imprimir 0 cuando no se presiona ninguno de los botones y si se presiona uno de ellos, debería Imprime su posición como he mencionado antes. Actualmente, el problema es que si presiono el segundo botón, algunas veces se imprimirá 2 veces (en lugar de una sola vez). Supongo que se debe al "ruido" cuando se presiona el botón y que se debe rebotar, pero no sé cómo rebotar el pin analógico.

Mi código:

int old_button = 0;
int button;
int pressed_button;
int z;

void setup () {
  Serial.begin(9600);
  pinMode(A5, INPUT);
}

void loop () {
  z = analogRead(5);
  if (z > 1021) button = 0;                                           
  else if (z > 511 && z < 514) button = 1;                     
  else if (z > 680 && z < 684) button = 2;                
  else if (z > 766 && z < 770) button = 3;                
  else if (z > 817 && z < 822) button = 4;             
  else if (z > 851 && z < 856) button = 5; 
  else if (z > 875 && z < 880) button = 6;
  else button = 0;                                                      

  if (old_button == button) {                                           
    old_button = button;                                              
    pressed_button = 0;                                               
  }  

  else {                                                                
    old_button = button;                                             
    pressed_button = button;                                        
  }
  Serial.println(pressed_button);
}

Circuito (resistencias de 2200 ohmios):

    
pregunta Nick

4 respuestas

4

Cuando detectes una diferencia significativa en la lectura de ADC, espera 20 milisegundos y luego promedia algunas lecturas y luego toma una decisión. Si una de las lecturas aún se ve mal cuantificable, espere otro corto período de tiempo.

    
respondido por el Andy aka
2

Sí, es ruido de rebote. Debe esperar un poco (por ejemplo, 50 ms) y volver a leer la entrada analógica. Si el resultado coincide, entonces el valor del botón puede considerarse válido. Algo como esto:

int old_button = 0;

int getButton()
{
  int i, z, sum
  int button;

  sum = 0;
  for (i=0; i < 4; i++)
  {
     sum += analogRead(5);
  }
  z = sum / 4;
  if (z > 1021) button = 0;                                           
  else if (z > 511 && z < 514) button = 1;                     
  else if (z > 680 && z < 684) button = 2;                
  else if (z > 766 && z < 770) button = 3;                
  else if (z > 817 && z < 822) button = 4;             
  else if (z > 851 && z < 856) button = 5; 
  else if (z > 875 && z < 880) button = 6;
  else button = 0;

  return button;
}


void loop ()
{
  int button, button2, pressed_button;  
  button = getButton();
  if (button != old_button)
  {
      delay(50);        // debounce
      button2 = getButton();

      if (botton == button2)
      {
         old_button = button;
         presed_button = button;
         Serial.println(pressed_button);
      }
   }
}

Como Andy no quería proporcionar ningún código, agregué un promedio al tomar las lecturas de ADC. Por lo tanto, el promedio dentro de getButton da cuenta de cualquier ruido al leer la línea analógica que ingresa al ADC, y el retraso de 50 ms se encarga de detectar el rebote del interruptor.

    
respondido por el tcrosley
2

Recientemente empecé a trabajar con Arduino, y aunque esta es una pregunta antigua, encontré este hilo al intentar ampliar el número de botones que podía escuchar.

Trabajé desde la ilustración original de Fritzing y produje una ligera variante en hardware y software.

Modifiquéelconjuntoderesistenciasparausarvaloresdiferentesparaintentarproducirunpasomásconsistenteentrelosconmutadoresenlugardelospasoslogarítmicosproducidosalusarlasmismasresistenciasentodo.

De5V,lasresistenciasson:

  • 1kΩ
  • 180Ω
  • 240Ω
  • 330Ω
  • 510Ω
  • 800Ω

Estoproducepasosdealrededorde0.5Ventrecadainterruptor.

Tambiénconstruíunsoftwarebásicoquebuscaelmismovalorpara3lecturasseguidasantesdeconfirmaruncambioenelvoltaje.Estoeliminapequeñasvariacionesenlalectura.

intsensorPin=A5;//TheinputportintsensorValue;//CurrentreadingintoutputValue;//ThereportedreadingintlastValues[3]={0,0,0};//Thelast3readingsvoidsetup(){Serial.begin(9600);}voidloop(){//readthevaluefromthesensor:sensorValue=analogRead(sensorPin);//Initialisevariablesforchecksinti;intupdateOutput=1;//Loopthroughpreviousreadingsfor(i=0;i<3;i++){//Ifthishistoricvaluedoesn'tmatchthecurrentreading,//wewillnotupdatetheoutputvalueif(lastValues[i]!=sensorValue){updateOutput=0;}//Shiftthearrayelementstomakeroomfornewvalueif(i>0){lastValues[(i-1)]=lastValues[i];}}//Updateifneededif(updateOutput==1){outputValue=sensorValue;}//AppendthenewvaluelastValues[2]=sensorValue;//DebuggingoutputSerial.print(sensorValue);Serial.print(" ");
  Serial.println(outputValue);
}

Obviamente, la matriz lastValues se puede hacer a la longitud que desee: cuanto más larga sea la matriz, más tiempo se debe presionar un interruptor para que se detecte.

En mis pruebas, los valores de los sensores informados fueron:

  • 1023: sin botón
  • 0: Botón # 1
  • 196: Botón # 2
  • 301: Botón # 3
  • 405: Botón # 4
  • 508: Botón # 5
  • 613: Botón # 6

(Probado según el diagrama)

Mis cálculos matemáticos sugieren que incluso podría extender esto a 8 botones, agregando las siguientes resistencias a continuación (que deberían ver la caída de voltaje en pasos de 0.5V):

  • 1.7kΩ
  • 5kΩ
respondido por el Luke Stevenson
1

Muchos modificadores del estilo que estás usando son difíciles de rebotar bien, y tratar de usar un multiplexor resistivo no lo hará más fácil. Aún así, si puede pagar dos pines de puerto (uno analógico), puedo ofrecerle una receta para el éxito que debería funcionar incluso si sus conmutadores son muy malos. Yo sugeriría mover la resistencia de la barra de bus (ignorar la barra de bus inferior de la placa de pruebas) a la izquierda de la que está más a la izquierda, y cablear eso a un pin de puerto no analógico. El cable común en la parte superior debe conectarse al pin del puerto analógico. El cable de la resistencia más a la derecha debe conectarse a tierra.

Cuando su unidad está "inactiva" [no cree que se haya presionado ningún botón], establezca la salida común a alta y flote la otra. Se leerá en un nivel bajo cuando no se presione ningún botón y se leerá cerca de VDD cuando se presione cualquier botón.

Para averiguar qué botón se presiona, haga flotar el cable común y coloque el cable del lado izquierdo en alto. Brevemente establezca el cable común alto o bajo (vea la nota) y vuélvalo a flotar, luego lea el voltaje en ese pin un poco más tarde (manteniendo el cable del lado izquierdo alto). Una vez que se haya tomado la lectura, puede, si lo desea, apagar el cable del lado izquierdo (volver a encenderlo antes del siguiente ciclo de lectura).

Mientras se presiona un botón, el voltaje en el cable común debe ser una buena fracción de VDD (si hay seis botones y siete resistencias, los botones deben leer 1/7, 2/7, 3/7, etc. hasta 6/7); la tensión no debe verse afectada por si el pin común ha sido pulsado brevemente alto o bajo. Si no se presiona ningún botón, las lecturas después de que el pin haya sido pulsado alto serán mucho más altas que cuando después de haber sido pulsado bajo. Esto indicará que el botón ha sido liberado.

Una vez que se suelta el botón, puede volver a la configuración "inactiva". Cuando la resistencia de la izquierda es alta, la cadena de la resistencia dibujará corriente si se presionan o no los botones, pero cuando el pin izquierdo está flotando y el cable común es alto, no se dibujará corriente hasta que se presione un botón.

Para obtener buenos resultados con los interruptores económicos, debe demorar lo suficiente después de cada pulso momentáneo de "conexión a tierra" o "VDD" en su cable común para que, si el interruptor está haciendo algún contacto, obtenga una buena lectura (intente poner una resistencia de 100K en paralelo con un interruptor, y ajuste el retardo y la sensibilidad para que "apenas" registre el interruptor como mantenido). Los interruptores baratos tienen una resistencia de más de un megas cuando se lanzan por completo, y menos de 10 ohmios cuando se presionan por completo, pero su resistencia puede divagar por todos los lugares entre esos estados, y la temporización de rebote convencional no ayuda. Lo que ayudará será tener un circuito que no detectará la presión de un botón hasta que la resistencia sea bastante baja, y considerará que un botón se mantiene presionado a menos que su resistencia sea mucho mayor. Para el circuito que he descrito, el botón del lado izquierdo será más "sensible" al botón "nuevo" que el botón del lado derecho, y la sensibilidad de "mantener" puede ser diferente para los seis botones, pero debería tener poca problemas para garantizar que la sensibilidad de "retención" de cada botón sea mucho más alta que su sensibilidad de "nuevo empuje", que es el requisito para un rebote confiable.

    
respondido por el supercat

Lea otras preguntas en las etiquetas