I2C su tastierino

Ho un tastierino Touch che comunica con Arduino grazie all’I2C ho un codice che verifica la pressione del tasto …in pratica con un interrupt

attachInterrupt(0,getNumber,LOW);

richiama la funzione getNumber quando il pin 2 dell’interrupt va LOW

questa funzione è void e ha il compito di scrivere sulla seriale il bottone premuto :slight_smile:

vorrei sapere se è possibile memorizzare la variazione di stato del bottone su una variabile di tipo intero come prima facevo digitalRead( BUTTON ); ???
non so se sono stato chiaro.

semmai provo ad essere + chiaro :slight_smile:

// include the atmel I2C libs
#include "mpr121.h"
#include "i2c.h"

// 11 max digits used
#define DIGITS 11 

// Match key inputs with electrode numbers
#define ONE 8
#define TWO 5
#define THREE 2
#define FOUR 7
#define FIVE 4
#define SIX 1
#define SEVEN 6
#define EIGHT 3
#define NINE 0

//extras (not used)
#define ELE9 9
#define ELE10 10
#define ELE11 11

//interupt pin
int irqpin = 2;  // D2

void setup()
{
  //make sure the interrupt pin is an input and pulled high
  pinMode(irqpin, INPUT);
  digitalWrite(irqpin, HIGH);
  
  //configure serial out
  Serial.begin(9600);
  
  //output on ADC4 (PC4, SDA)
  DDRC |= 0b00010011;
  // Pull-ups on I2C Bus
  PORTC = 0b00110000; 
  // initalize I2C bus. Wiring lib not used. 
  i2cInit();
  
  delay(100);
  // initialize mpr121
  mpr121QuickConfig();
  
  // Create and interrupt to trigger when a button
  // is hit, the IRQ pin goes low, and the function getNumber is run. 
  attachInterrupt(0,getNumber,LOW);
  
  // prints 'Ready...' when you can start hitting numbers
  Serial.println("Ready...");
}

void loop()
{
  //You can put additional code here. The interrupt will run in the backgound. 
}

void getNumber()
{
  int i = 0;
  int touchNumber = 0;
  uint16_t touchstatus;
  char digits[DIGITS];
  
  touchstatus = mpr121Read(0x01) << 8;
  touchstatus |= mpr121Read(0x00);
  
  for (int j=0; j<12; j++)  // Check how many electrodes were pressed
  {
    if ((touchstatus & (1<<j)))
      touchNumber++;
  }
  
  if (touchNumber == 1)
  {
    if (touchstatus & (1<<SEVEN))
      digits[i] = '7';
    else if (touchstatus & (1<<FOUR))
      digits[i] = '4';
    else if (touchstatus & (1<<ONE))
      digits[i] = '1';
    else if (touchstatus & (1<<EIGHT))
      digits[i] = '8';
    else if (touchstatus & (1<<FIVE))
      digits[i] = '5';
    else if (touchstatus & (1<<TWO))
      digits[i] = '2';
    else if (touchstatus & (1<<NINE))
      digits[i] = '9';
    else if (touchstatus & (1<<SIX))
      digits[i] = '6';
    else if (touchstatus & (1<<THREE))
      digits[i] = '3';
      
    Serial.print(digits[i]);
    i++;
  }
  //do nothing if more than one button is pressed
  else if (touchNumber == 0)
    ;
  else
    ;
}

Invece che stampare il valore con il Serial.print memorizzalo in una variabile globale per il tuo uso.

leo72: Invece che stampare il valore con il Serial.print memorizzalo in una variabile globale per il tuo uso.

ma si può fare??

http://arduino.cc/en/Reference/AttachInterrupt

qui dice che function non ritorna niente mi sbaglio...ho interpretato male?

poi scusa una cosa data la mia ignoranza ...prima i due Arduino Uno quando facevo accendere e spegnere i led comunicavano credo grazie all'ethernet shield ora non è montata sopra all'arduino client ho solo questo tastierino possono continuare a comunicare ugualmente??? tramite le funzioni della libreria EthernetShield tipo connect connected available ecct ???

Usi una variabile globale.... In qualunque punto del codice essa è visibile. Quindi se la cambi nella routine A il nuovo valore sarà letto anche all'interno della routine B.

Sulla seconda domanda non so risponderti, non mi intendo di ethernet shield.

xk al Capo ho detto che prima scambiavo i comandi tramite le funzioni client.println(); ecct perchè c'era un collegamento sulla porta 23 mo senza ethernet shield montata sopra la vedo difficile....bo???

lollo1100: xk al Capo ho detto che prima scambiavo i comandi tramite le funzioni client.println(); ecct perchè c'era un collegamento sulla porta 23 mo senza ethernet shield montata sopra la vedo difficile....bo???

Per favore spiegati.... :sweat_smile: Cosa vuoi farne della lettura?? Prima hai detto che volevi memorizzarla in una variabile... ora sembra quasi che ti serva spedirla ad un'altra scheda...

leo72:

lollo1100: xk al Capo ho detto che prima scambiavo i comandi tramite le funzioni client.println(); ecct perchè c'era un collegamento sulla porta 23 mo senza ethernet shield montata sopra la vedo difficile....bo???

Per favore spiegati.... :sweat_smile: Cosa vuoi farne della lettura?? Prima hai detto che volevi memorizzarla in una variabile... ora sembra quasi che ti serva spedirla ad un'altra scheda...

se trasformo getNumber da void ad int...asp mi spiego meglio

la situazione è la seguente prima avevo dei bottoni collegati ai pin digitali di arduino e sopra montavo un ethernet shield nel lato client vedevo lo stato dei bottoni attraverso digitalread dei pin digitali e tutto ok poi se avveniva una variazione di stato mi collegavo tramite porta 23 ad un'altra scheda arduino con sopra ethernet shield e facevo accendere e spegnere dei led

Ora lo scenario è cambiato ho montato un touch shield sulla scheda client dove prima avevo i bottoni e questa funziona con i2c ovvero c'è tipo un interrupt (vedi codice scritto prima) che legge se è stato premuto uno dei 9 bottoni del tastierino touch. Il mio obiettivo è quello di adattare il codice dei bottoni di prima a quello del tastierino che ho ora...sono stato + chiaro dopo per inviare il comando all'altra scheda sta dentro all'if della variazione del tastierino non è un problema a parte il fatto che non ho l'ethernet shield montata sopra all'arduino con il tastierino touch :)

scusate ha senso scrivere una cosa di questo tipo

// include the atmel I2C libs
#include "mpr121.h"
#include "i2c.h"
#include <SPI.h>                                              //  IMPORTA LIBRERIA SPI
#include <Ethernet.h>                                         //  IMPORTA LIBRERIA ETHERNET

// 11 max digits used
#define DIGITS 11 

// Match key inputs with electrode numbers
#define ONE 8
#define TWO 5
#define THREE 2
#define FOUR 7
#define FIVE 4
#define SIX 1
#define SEVEN 6
#define EIGHT 3
#define NINE 0

int ts1st;                                            //  ts1st LEGGE E MEMORIZZA IL LIVELLO DI BUTTON  
int stato1;                                           //  stato1 MANTIENE LO STATO DI BUTTON
int ts2st;                                            //  ts2st LEGGE E MEMORIZZA IL LIVELLO DI BUTTON  
int stato2;                                           //  stato2 MANTIENE LO STATO DI BUTTON
int ts3st;                                            //  ts1st LEGGE E MEMORIZZA IL LIVELLO DI BUTTON  
int stato3;                                           //  stato1 MANTIENE LO STATO DI BUTTON
int ts4st;                                            //  ts2st LEGGE E MEMORIZZA IL LIVELLO DI BUTTON  
int stato4;                                           //  stato2 MANTIENE LO STATO DI BUTTON

//extras (not used)
#define ELE9 9
#define ELE10 10
#define ELE11 11

//interupt pin
int irqpin = 2;  // D2

void setup()
{
  //make sure the interrupt pin is an input and pulled high
  pinMode(irqpin, INPUT);
  digitalWrite(irqpin, HIGH);
  
  //configure serial out
  Serial.begin(9600);
  
  //output on ADC4 (PC4, SDA)
  DDRC |= 0b00010011;
  // Pull-ups on I2C Bus
  PORTC = 0b00110000; 
  // initalize I2C bus. Wiring lib not used. 
  i2cInit();
  
  delay(100);
  // initialize mpr121
  mpr121QuickConfig();
  
  // Create and interrupt to trigger when a button
  // is hit, the IRQ pin goes low, and the function getNumber is run. 

 int valore =  attachInterrupt(0,getNumber,LOW);
  
  // prints 'Ready...' when you can start hitting numbers
  Serial.println("Ready...");
}

void loop()
{
  //You can put additional code here. The interrupt will run in the backgound. 
}

int getNumber()
{
  int i = 0;
  int touchNumber = 0;
  uint16_t touchstatus;
  char digits[DIGITS];
  int stato;
  touchstatus = mpr121Read(0x01) << 8;
  touchstatus |= mpr121Read(0x00);
  
  for (int j=0; j<12; j++)  // Check how many electrodes were pressed
  {
    if ((touchstatus & (1<<j)))
      touchNumber++;
  }
  
  if (touchNumber == 1)
  {
    if (touchstatus & (1<<SEVEN))
      digits[i] = '7';
    else if (touchstatus & (1<<FOUR))
      digits[i] = '4';
    else if (touchstatus & (1<<ONE))
      digits[i] = '1';
    else if (touchstatus & (1<<EIGHT))
      digits[i] = '8';
    else if (touchstatus & (1<<FIVE))
      digits[i] = '5';
    else if (touchstatus & (1<<TWO))
      digits[i] = '2';
    else if (touchstatus & (1<<NINE))
      digits[i] = '9';
    else if (touchstatus & (1<<SIX))
      digits[i] = '6';
    else if (touchstatus & (1<<THREE))
      digits[i] = '3';
      
    Serial.print(digits[i]);
    i++;
  }
  //do nothing if more than one button is pressed
  else if (touchNumber == 0)
    ;
  else
    ;
return stato;
}

a dire il vero dice che non ha senso

Se è una tastiera touch non penso ti ci voglia un debounce, quindi il codice andrebbe rivisto rispetto a quello necessario alla gestione di un pulsantino hardware.

leo72: Se è una tastiera touch non penso ti ci voglia un debounce, quindi il codice andrebbe rivisto rispetto a quello necessario alla gestione di un pulsantino hardware.

scusa che intendi? :roll_eyes:

Vedo che hai aggiunto delle variabile "stato corrente" e "stato precedente". Se vuoi replicare la lettura dei pulsanti che avevi fatto con l'altro codice, dove si faceva anche il debounce software, ti dico che prima di perderci il capo prova la tastiera touch senza debounce. Probabilmente non serve, essendo appunto touch.

scusa continuo a non capire :(

lollo1100: scusa continuo a non capire :(

Ok... dicevi di avere nel progetto precedente la lettura di pulsantini classici. Avevi messo del debounce software, se non ricordo male, giusto? O era un altro utente, forse? :sweat_smile:

leo72:

lollo1100: scusa continuo a non capire :(

Ok... dicevi di avere nel progetto precedente la lettura di pulsantini classici. Avevi messo del debounce software, se non ricordo male, giusto? O era un altro utente, forse? :sweat_smile:

No leo ricordi bene ma il mio problema non è tanto l'antirimbalzo che so non esserci in questo tastierino bensì fare la lettura della pressione del tasto quello che prima era banalmente digitalRead ora è una gestione con interrupt su i2c o sbaglio? il tastierino in questione è TouchShield della sparkfun

Allora non ci sono problemi.
Hai lo sketch funzioante che hai postato, devi solo togliere il Serial.print ed assegnare il valore letto dalla funzione ad una variabile globale, che può essere letta da qualunque punto dello sketch.
Vedi qui “variable scope”:
http://www.arduino.cc/en/Reference/VariableDeclaration

scusa prima facevo semplicemente digitalRead credo che tutt'ora sia uguale ? è un touch shield della sparkfun il link è questo c'è anche un codice... https://www.sparkfun.com/products/10508

grazie

Nel 1° post hai pubblicato un codice in cui la lettura della tastiera tattile viene fatta con un interrupt. Non è la stessa cosa di una digitalRead.

leo72: Nel 1° post hai pubblicato un codice in cui la lettura della tastiera tattile viene fatta con un interrupt. Non è la stessa cosa di una digitalRead.

si d'accordo io vorrei farla come con il vecchio codice con digitalRead(); è possibile ...il tastierino come noti comunica tramite i2c con arduino come posso riadattare il codice con interrupt evitando quindi l'interrupt e inserendo la lettura dello stato con digitalRead() ; è possibile??

La domanda che mi pongo non posso gestire i pad del tastierino con la stessa modalità di lettura precedente? ...come si gestiscono shield che comunicano con I2C con arduino a quanto ho capito questo accade tra il Touch Shield e Arduino Uno su cui è montata la shield