Settare un MCP23017

Salve questa mattina sono alle prese con il Port Expander MCP23017, ho scaricato questa libreria:

Stò cercando di fare un semplice sketch come questo sotto:

/*
  Button
 
 Turns on and off a light emitting diode(LED) connected to digital  
 pin 13, when pressing a pushbutton attached to pin 2. 
 
 
 The circuit:
 * LED attached from pin 13 to ground 
 * pushbutton attached to pin 2 from +5V
 * 10K resistor attached to pin 2 from ground
 
 * Note: on most Arduinos there is already an LED on the board
 attached to pin 13.
 
 
 created 2005
 by DojoDave <http://www.0j0.org>
 modified 30 Aug 2011
 by Tom Igoe
 
 This example code is in the public domain.
 
 http://www.arduino.cc/en/Tutorial/Button
 */

// constants won't change. They're used here to 
// set pin numbers:
const int buttonPin = 2;     // the number of the pushbutton pin
const int ledPin =  13;      // the number of the LED pin

// variables will change:
int buttonState = 0;         // variable for reading the pushbutton status

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);      
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);     
}

void loop(){
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {     
    // turn LED on:    
    digitalWrite(ledPin, HIGH);  
  } 
  else {
    // turn LED off:
    digitalWrite(ledPin, LOW); 
  }
}

Ora guardando lo sketch di esempio allegato alla libreria:

#include <Wire.h>
#include <Adafruit_MCP23017.h>

// Basic pin reading and pullup test for the MCP23017 I/O expander
// public domain!

// Connect pin #12 of the expander to Analog 5 (i2c clock)
// Connect pin #13 of the expander to Analog 4 (i2c data)
// Connect pins #15, 16 and 17 of the expander to ground (address selection)
// Connect pin #9 of the expander to 5V (power)
// Connect pin #10 of the expander to ground (common ground)

// Input #0 is on pin 21 so connect a button or switch from there to ground

Adafruit_MCP23017 mcp;
  
void setup() {  
  mcp.begin();      // use default address 0

  mcp.pinMode(0, INPUT);


  pinMode(13, OUTPUT);  // use the p13 LED as debugging
}



void loop() {
  // The LED will 'echo' the button
  digitalWrite(13, mcp.digitalRead(0));
}

vediamo che:
Adafruit_MCP23017 mcp; // apre un istanza chiamata mcp
mcp.begin(); // imposta I2C adress a 0 (default)
mcp.pinMode(0, INPUT); // imposta come input il pin 0 presumo si stia parlando del pin GPA0 vedi immagine sopra

Ora non capisco come dare un nome hai pin del MCP23017, per poi richiamarli successivamene con digitalRead o Digital Write.

Esempio:
const int mcp01 = 1 // imposta il pin del MCP23017 dove è collegato il pushbutton chiamato mcp01
const int mcp02 = 2 // imposta il pin del MCP23017 dove è collegato il led chiamato mcp02

Help? =(

Non ho capito il problema. Non ti sei risposto da solo alla fine del post?

ma se scrivo:

const int mcp01 = 1 // imposta il pin del MCP23017 dove è collegato il pushbutton chiamato mcp01 const int mcp02 = 2 // imposta il pin del MCP23017 dove è collegato il led chiamato mcp02

non imposto il pin 1 e 2 di arduino?

perchè io devo impostare il pin dove sono collegati il led ed il pushbutton nel MCP32017, per richiamarlo all'occorrenza con il digitalRead o digitalWrite.

Dipende dove usi la variabile. Se la metti dentro a pinMode, imposti il pin di Arduino. Se la metti dentro a mcp.pinMode imposti il pin dell'MCP.

non capisco perchè entrambi i codici funzionano.

Dunque questo e il codice che funziona ma senza constanti con nome assegnato

#include <Wire.h>
#include "Adafruit_MCP23017.h"

/*
 Accendere un Led tramite Pushbutton collegati ad un MCP23017 tramite bus I2C
 * pushbutton collegato al pin 0 del MCP23017
 * Led collegato al pin 1 del MCP23017
 * MCP23017 pin GND A1-A2-A3 collegati a GND di Arduino
 * MCP23017 5v collegato a 5v Arduino
 * MCP23017 SDA collegato al pin A4 di Arduino
 * MCP23017 SCL collegato al pin A5 di Arduino
*/

Adafruit_MCP23017 mcp;

int buttonState = 0; 
  
void setup() {
  mcp.begin();           // use default address 0
  mcp.pinMode(0, INPUT);
  mcp.pinMode(1, OUTPUT);
}

void loop() {
  buttonState = mcp.digitalRead(0);
  if (buttonState == HIGH) {
    mcp.digitalWrite(1, HIGH);    // turn LED on
  }
  else {
    mcp.digitalWrite(1, LOW);     // turn LED off:
  }
}

Questo è il codice che funziona anche con le constanti con nome assegnato, dichiarate all’inizio del programma

#include <Wire.h>
#include "Adafruit_MCP23017.h"

/*
 Accendere un Led tramite Pushbutton collegati ad un MCP23017 tramite bus I2C
 * pushbutton collegato al pin 0 del MCP23017
 * Led collegato al pin 1 del MCP23017
 * MCP23017 pin GND A1-A2-A3 collegati a GND di Arduino
 * MCP23017 5v collegato a 5v Arduino
 * MCP23017 SDA collegato al pin A4 di Arduino
 * MCP23017 SCL collegato al pin A5 di Arduino
*/

Adafruit_MCP23017 mcp;

const int buttonPin = 0;     // the number of the pushbutton pin
const int ledPin =  1;      // the number of the LED pin

int buttonState = 0; 
  
void setup() {
  mcp.begin();           // use default address 0
  mcp.pinMode(buttonPin, INPUT);
  mcp.pinMode(ledPin, OUTPUT);
}

void loop() {
  buttonState = mcp.digitalRead(buttonPin);
  if (buttonState == HIGH) {
    mcp.digitalWrite(ledPin, HIGH);    // turn LED on
  }
  else {
    mcp.digitalWrite(ledPin, LOW);     // turn LED off:
  }
}

Quello che non capisco è il perchè funziona lo stesso anche il secondo codice.

Mi spiego meglio, quando ho scritto il secondo codice mi aspettavo che non funzionasse perche quando scrivo:

const int buttonPin = 0; // the number of the pushbutton pin
const int ledPin = 1; // the number of the LED pin

pensavo che impostassero i pin di arduino, dato che non viene specificato “mcp.” da nessuna parte, ed invece funziona.

Nel caso che ci fossero da definire anche i pin 0 e 1 di Arduino oltre a quelli di MCP23017 come mi dovrei comportare?

Tu ragioni in termini "umani" e basi il significato di una cosa per il nome che ha. Quindi se leggi "const byte pinDellArduino = 0;" pensi che quella costante si debba usare solo dove si usano i pin dell'Arduino ;)

Invece una variabile puoi anche chiamarla pippo oppure questaVariabileDistruggeIlPinNonUsarla, ma al compilatore non gliene importa nulla del suo nome, a lui conta il valore che essa ha.

Quindi:

mcp.pinMode(0, INPUT);
const int buttonPin = 0;    
mcp.pinMode(buttonPin, INPUT);

hanno lo stesso senso, buttonPin vale 0 e come tale è interpretato.

non riesco a capire il tuo concetto, o forse mi sono espresso male.

dunque tu mi dici che qualsiasi etichetta mnemonica metto al compilatore non importa nulla perchè a lui importa il valore che uno gli associa e fin qui ci sono.

la mia domanda è se devo attribuire una etichetta ad entrambi i pin: pin 0 di Arduino pin 0 del MCP23017

Come faccio?

Biagetti: dunque tu mi dici che qualsiasi etichetta mnemonica metto al compilatore non importa nulla perchè a lui importa il valore che uno gli associa e fin qui ci sono.

Perfetto! Immagina la rubrica di un cellulare. Tu sai che mi chiamo Leonardo Miliani. Per chiamarmi mi cerchi per nome, ma poi mica il telefonino spedisce il mio nome al gestore telefonico ;) Il telefonino recupera, tramite il mio nome (il nome della variabile), il mio numero di telefono (il valore della variabile) dalla rubrica (la memoria.

la mia domanda è se devo attribuire una etichetta ad entrambi i pin: pin 0 di Arduino pin 0 del MCP23017

Come faccio?

Non vedo il problema. Puoi usare anche la stessa variabile. Infatti il compilatore ti permette di fare anche così:

const int pin = 0;
pinMode(pin , INPUT);
mcp.pinMode(pin , INPUT);

E' la funzione che chiami che si incarica di trattare il valore per quello che sa farci. pinMode sa che un numero passato è un pin dell'Arduino, mcp sa invece che quello è un pin dell'MCP23017.

PS: non ti offendere, ma credo che una piccola infarinatura di programmazione ti serva per capire almeno i concetti base principali :sweat_smile: http://staff.polito.it/claudio.fornaro/CorsoC/ http://www.html.it/guide/guida-c/

non ti preoccupare non mi offendo, ci mancherebbe, hai ragione da vendere devo imparare tante cose e per questo stò cercando di dedicare tutto il mio tempo libero a studiare per imparare le basi.

tornando a noi:

dunque ragionando a mente lucida e pancia piena :), da quello che hai scritto mi sembra di capire che creando la costante con etichetta comunico solo al controllore che questa costante a valore 0 ogni volta che la interpellerò.

cioè:

const int pin = 0;    //comunico che la costante con etichetta "pin" a valore "0", che in questo caso è un numero di pin 
const int led = 1;    //comunico che la costante con etichetta "pin" a valore "1", che in questo caso è un numero di pin

poi nelle funzioni comunico se mi riferisco ad Arduino o al MCP23017

pinMode(pin , INPUT);   // con questa indico che il pin 0 di Arduino è impostato come input
pinMode(led , OUTPUT);   // con questa indico che il pin 1 di Arduino è impostato come output

mcp.pinMode(pin , INPUT);   //con questa indico che il pin 0 di MCP23017 è impostato come input
mcp.pinMode(led , INPUT);   //con questa indico che il pin 1 di MCP23017 è impostato come input

e di conseguenza nel loop:

  buttonState = digitalRead(pin);   // nel caso voglia leggere il pin del MCP23017
  if (buttonState == HIGH) {
    mcp.digitalWrite(led, HIGH);    // turn LED on

  mcpbuttonState = mcp.digitalRead(pin);   // nel caso voglia leggere il pin del MCP23017
  if (mcpbuttonState == HIGH) {
    mcp.digitalWrite(led, HIGH);    // turn LED on

Ho capito bene?

Perfetto. Per il compilatore "pin" e "0" sono solo 2 modi diversi per indicare la stessa cosa. E' poi il contesto in cui sono usati che gli fanno assumere significati diversi.

@Leo :

Scusa Leo, hai mai provato a vedere se si risparmia memoria invece di usare :

const int pin = 0;
const int led = 1;

che comunque occupano un int ciascuna, ad usare le

#define   pin   0
#define   led   1

che invece effettuano solo una sostituzione al momento della compilazione senza allocare delle variabili dichiarate costanti ?

Perché in casi come quello di cui parliamo, la #define mi sembra molto più adatta ... ;)

Guglielmo

Non sono entrato nell'argomento "int/byte" per definire un pin, altrimenti confondevo ancor di più le idee al nostro amico. ;)

Per test precedenti, posso però affermare con dati alla mano che per il compilatore

#define pin 1

e

const byte pin = 1;

hanno lo stesso identico impatto perché il compilatore, vedendo il dichiaratore di costante, esegue la sostituzione di "1" con "pin" proprio come fa la #define. Quindi per dati che nel programma non cambiano va sempre usato "const".

Sull'occupazione di flash, siccome la memoria dei micro Atmel è organizzata in word da 16 byte, usare un const byte ($01) oppure un const int ($0001) porta alla stessa occupazione di Flash.

Prova questo:

const int pin = 1;
void setup() {
    pinMode(pin, OUTPUT);
}
void loop() {}

Sono 622 byte di Flash

Prova questo:

const byte pin = 1;
void setup() {
    pinMode(pin, OUTPUT);
}
void loop() {}

Sono ancora 622 byte di Flash.

leo72: ..... Per test precedenti, posso però affermare con dati alla mano che per il compilatore

#define pin 1

e

const byte pin = 1;

hanno lo stesso identico impatto perché il compilatore, vedendo il dichiaratore di costante, esegue la sostituzione di "1" con "pin" proprio come fa la #define. .....

Perfetto, era quanto mi interessava ... compilatore intelligente. Grazie :)

Guglielmo

Ringrazio tutti quelli che sono intervenuti in particolare Leo72.

Comunque rileggendo il mio post, nella parte finale ho commesso un errore di copia incolla, nella descrizione di buttonstate ho messo 2 volte MCP23017.

metto il codice corretto perchè potrebbe essere fuorviante per qualcuno alle prime armi com me.

  buttonState = digitalRead(pin);   // nel caso voglia leggere il pin di Arduino
  if (buttonState == HIGH) {
    mcp.digitalWrite(led, HIGH);    // turn LED on

  mcpbuttonState = mcp.digitalRead(pin);   // nel caso voglia leggere il pin del MCP23017
  if (mcpbuttonState == HIGH) {
    mcp.digitalWrite(led, HIGH);    // turn LED on

Arrivederci al prossimo banalissimo problema! :)

Buona Giornata

gpb01:

leo72: ..... Per test precedenti, posso però affermare con dati alla mano che per il compilatore

#define pin 1

e

const byte pin = 1;

hanno lo stesso identico impatto perché il compilatore, vedendo il dichiaratore di costante, esegue la sostituzione di "1" con "pin" proprio come fa la #define. .....

Perfetto, era quanto mi interessava ... compilatore intelligente. Grazie :) Guglielmo

@gb, c'e' una discussione recente sull'argomento, ma non trovo il link. Aggiungerei una cosa importante, con la const devi anche dichiarare il tipo, con la define no. Meglio perciò la const. La define non sai mai dove l'andrai a sostituire, magari in posti dove poi il compilatore ti ci mette un bel cast non richiesto.

Salve, la settimana scorsa avevo trovato in rete uno sketch in cui si impostavano le porte di un MCP23017 tramite un byte es: 0b00000001, purtroppo non lo ritrovo più, avete qualche link in cui posso capire come impostare il codice?

Saluti

Questa discussione dovrebbe fare al caso tuo: http://forum.arduino.cc/index.php/topic,168313.0.html