MCP23S17 per comandare dei relay

Ciao a tutti,

tempo fa ho aperto un thread a proposito dei un progetto che ho iniziato tempo fa e che ora sto riprendendo in mano seriamente. La discussione originale è questa: http://arduino.cc/forum/index.php/topic,122245.0.html

Nell'ultimo post avevo chiesto consigli a proposito di un circuito di switching a relay, ma non avendo ancora fatto i test opportuni non avevo nemmeno fornito dettagli precisi. Oggi ho avuto un paio di ore di tempo ed ho terminato le prove sul circuito, il cui schema è il seguente: https://dl.dropbox.com/u/13991650/Switcher.png

Si tratta in particolare di una catena di relay, comandata da un MCP23S17 (expander SPI) tramite un paio di ULN2003. L'alimentazione dei relay è data da un regolatore da 6,5V mentre l'expander è alimentato direttamente da Arduino tramite l'header ICSP (questo forse non è ben chiaro dallo schema).

Il problema che ho riscontrato è il seguente: dei 15 relay solo 4 commutano correttamente (K11-12-13-14), mentre gli altri non funzionano.
Rilevando le tensioni sui relay funzionanti mi trovo i seguenti valori:

  • tensione sulla bobina circa 4,5V (leggermente inferiore ai 5V nominali ma comunque corretto)
  • tensione sulle uscite dell'expander circa 2,5V (qui mi sarei aspettato qualcosa in più)
    Sui relay non funzionanti invece ho ovviamente tensioni pari a circa zero, anche sulle uscite dell'expander.

Ho utilizzato un semplice programma che tramite due cicli for attiva e disattiva tutte le uscite, ma non sono per nulla sicuro di aver impostato correttamente il tutto. Riporto il codice che sto utilizzando.

#include <SPI.h> 
#include <MCP23S17.h>

MCP switcher(0);

void setup() {
  pinMode(53, OUTPUT);
  digitalWrite(53,LOW);
  switcher.pinMode(0B00000000000000);
}

void loop() {
  int i;
  for (i=1;i<=16;i++) {
    switcher.digitalWrite(i, HIGH);
    delay(100);
  }
  delay(200);
  for (i = 1; i <=16; i++) {
    switcher.digitalWrite(i, LOW);
    delay(100);
  }
  delay(200);
}

Potrebbe essere semplicemente un problema software? Non sono per niente sicuro di aver capito il funzionamento della libreria MCP23S17.h
Oppure c'è qualche errore nel circuito?

Grazie infinite per l'aiuto!

P.S. Ho un problema con il forum... Se tento di aggiungere un allegato (in questo caso lo schema che ho linkato sopra) non mi crea il thread e si blocca tutto su una pagina bianca!

gamby:
P.S. Ho un problema con il forum... Se tento di aggiungere un allegato (in questo caso lo schema che ho linkato sopra) non mi crea il thread e si blocca tutto su una pagina bianca!

Spesso e volentieri ci sono dei tipi di file che non sono allegabili ai post (per motivi di sicurezza), così come ci sono anche dimensioni massime sugli allegati stessi. Magari ci può essere anche un piccolo errore sul server stesso, non è detto.

Ho acquistato da poco gli MCP in oggetto e non li ho ancora messi alla prova, ho solo letto il datasheet in modo veloce.

Il codice mi sembra corretto, ho solo qualche dubbio sul modo per inizializzare le porte switcher.pinMode(0B00000000000000); mi sembra un codice binario di 14 bit mentre penso debbano essere 16.

Prova ad inizializzare con 0xFFFF.

Ciao.

Non ho capito perché hai usato dei ULN2003 al posto dei ULN2803 che hanno 8 uscite.
Hai collegato le masse (massa di Arduino DGND e quella del alimentatore dei relé)?

Dove hai preso la libreria?
Ciao Uwe

Riguardo le masse, sono sicuro che lo ha fatto. Riguardo gli ULN aveva quelli dentro.

Mentre per il software anche io voglio sapre dove a preso la libreria, perchè io ho comprato la versione i2c di quegli integrati, ma questo sono unsano la SPI.
Sapevo che aveva intenzione di collegare tutto in SPI, ma mi sono ricordato solo ora, guardando la sigla del chip che ha la S.

Comuque guardando lo schema non mi saltano errori, quindi c'è da controllare la libreria.

Ciao.

non credo che abbia usato questa libreria, ma vorrei segnalarne la presenza per tutti quelli che la cercavano in vano:
http://playground.arduino.cc/Main/MCP23S17

Allora... Innanzitutto grazie a tutti per le numerose risposte!

BrainBooster:
non credo che abbia usato questa libreria, ma vorrei segnalarne la presenza per tutti quelli che la cercavano in vano:
Arduino Playground - MCP23S17 Class for Arduino

In realtà sto facendo riferimento a questa: Arduino Playground - Mcp23s17
Devo assolutamente provare anche quella che hai suggerito tu, che mi sembra più completa, soprattutto per quanto riguarda la documentazione.

MauroTec:
Riguardo le masse, sono sicuro che lo ha fatto. Riguardo gli ULN aveva quelli dentro.

Mentre per il software anche io voglio sapre dove a preso la libreria, perchè io ho comprato la versione i2c di quegli integrati, ma questo sono unsano la SPI.
Sapevo che aveva intenzione di collegare tutto in SPI, ma mi sono ricordato solo ora, guardando la sigla del chip che ha la S.

Si esatto, avevo già gli ULN2003 e teoricamente mi dovevano bastare 13 relay... Poi ne ho aggiunti due all'ultimo momento, quindi ho occupato anche l'ultima uscita dell'ULN2003 e aggiunto un transistor per l'ultimo relay.
SPI lo ho scelto in modo da collegare tutto con un unico bus. Prima ovviamente avevo controllato l'esistenza delle librerie per tutti i chip che mi servono.

uwefed:
Hai collegato le masse (massa di Arduino DGND e quella del alimentatore dei relé)?

Si, le masse sono collegate

MauroTec:
Ho acquistato da poco gli MCP in oggetto e non li ho ancora messi alla prova, ho solo letto il datasheet in modo veloce.

Il codice mi sembra corretto, ho solo qualche dubbio sul modo per inizializzare le porte switcher.pinMode(0B00000000000000); mi sembra un codice binario di 14 bit mentre penso debbano essere 16.

Prova ad inizializzare con 0xFFFF.

Ho appena provato con 0xFFFF ma non funziona, mentre probabilmente avevi ragione sul codice di 14 bit (mi era sfuggito). Ho provato ad aggiungere i due bit mancanti ma non è cambiato nulla.

leo72:
Spesso e volentieri ci sono dei tipi di file che non sono allegabili ai post (per motivi di sicurezza), così come ci sono anche dimensioni massime sugli allegati stessi. Magari ci può essere anche un piccolo errore sul server stesso, non è detto.

Ah ok... Era un'immagine .png di circa 1MB

Comunque appena riesco provo la libreria suggerita da BrainBooster e vi faccio sapere i risultati.
Grazie di nuovo!

Come non detto... Le due librerie sembrerebbero equivalenti. L'unica differenza è che in quella indicata da BrainBooster è inclusa la documentazione, che comunque è la stessa presente sul sito. Ed infatti il comportamento è lo stesso.

Vorrei comunque far notare che la libreria non è del tutto aggiornata. Per funzionare con l'ultima versione di arduino bisogna correggere una riga nel file MCP23S17.h
In particolare bisogna sostituire #include <Wprogram.h> con #include <Arduino.h>

Nella pagina da te indicata che il link a GitHub dove è presente la libreria --> GitHub - dreamcat4/Mcp23s17: Arduino library for the Microchip MCP23S17
C'è anche un esempio

// This example demonstrates control over SPI to the Microchip MCP23S17 16-bit IO expander
// SPI Pinouts are for Arduino Uno and Arduino Duemilanove board (will differ for Arduino MEGA)

// Download these into your Sketches/libraries/ folder...

// The Spi library by Cam Thompson. It was originally part of FPU library (micromegacorp.com)
// Available from http://arduino.cc/playground/Code/Fpu or http://www.arduino.cc/playground/Code/Spi
// Including Spi.h vv below initializea the MOSI, MISO, and SPI_CLK pins as per ATMEGA 328P
#include <Spi.h>

// Mcp23s17 library available from https://github.com/dreamcat4/Mcp23s17
#include <Mcp23s17.h>

// Wire up the SPI Interface common lines:
// #define SPI_MOSI             11 //arduino   <->   SPI Master Out Slave In   -> SI  (Pin 13 on MCP23S17 DIP)
// #define SPI_MISO             12 //arduino   <->   SPI Master In Slave Out   -> SO  (Pin 14 on MCP23S17 DIP)
// #define SPI_CLOCK            13 //arduino   <->   SPI Slave Clock Input     -> SCK (Pin 12 on MCP23S17 DIP)

// Then choose any other free pin as the Slave Select (pin 10 if the default but doesnt have to be)
#define MCP23S17_SLAVE_SELECT_PIN  9 //arduino   <->   SPI Slave Select           -> CS  (Pin 11 on MCP23S17 DIP)

// SINGLE DEVICE
// Instantiate a single Mcp23s17 object
MCP23S17 Mcp23s17 = MCP23S17( MCP23S17_SLAVE_SELECT_PIN );

// MULTIPLE DEVICES
// Up to 8 MCP23S17 devices can share the same SPI bus and slave select pins.
// Assign each chip a unique 3-bit device address (by setting the A2,A1,A0 pins)
// Then below, device address is optional 2nd parameter to the constructor fn...
// MCP23S17 Mcp23s17_0 = MCP23S17(MCP23S17_SLAVE_SELECT_PIN,0x0);
// ...
// MCP23S17 Mcp23s17_7 = MCP23S17(MCP23S17_SLAVE_SELECT_PIN,0x7);

void setup()
{
  // Example usage

  // Set all pins to be outputs (by default they are all inputs)
  Mcp23s17.pinMode(OUTPUT);

  // Change all pins at once, 16-bit value
  Mcp23s17.port(0x0F0F);

  // Write to individual pins
  Mcp23s17.digitalWrite(8,LOW);
  Mcp23s17.digitalWrite(12,HIGH);

  // Read all pins at once, 16-bit value
  uint16_t pinstate = Mcp23s17.port();

  // Set pin 14 (GPIO B6) to be an input
  Mcp23s17.pinMode(14,INPUT);

  // Read the value of pin 14
  Mcp23s17.digitalRead(14);
}

// Cycle the output lines at a staggered rate, pin/2 milliseconds
long timeoutInterval = 1;
long previousMillis = 0;
uint16_t counter = 0x0000;

void timeout()
{
  Mcp23s17.port(counter++);
}  

void loop()
{
  // handle timeout function, if any
  if (  millis() - previousMillis > timeoutInterval )
  {
    timeout();
    previousMillis = millis();
  }
  // Loop.
}

La parte relativa al settaggio di tutti i pin è questa

// Change all pins at once, 16-bit value
  Mcp23s17.port(0x0F0F);

La parte della libreria che si occupa del comando è

void MCP23S17::port(uint16_t value)
{
  write_addr(GPIO,value);
}

che accetta un valore a 16 bit

Anch'io ho seguito gli esempi inclusi nella libreria. Fra l'altro la libreria del github richiede la libreria Spi.h, mentre di default su Arduino c'è SPI.h che è una cosa diversa.
L'altra libreria di cui si parlava sopra invece funziona appunto con SPI.h, quindi probabilmente è più aggiornata.

Per il settaggio dei pin ho provato in diversi modi, incluso un ciclo for che imposta come output un pin per volta (uno degli esempi è strutturato proprio in questo modo).
Quello che non capisco è perchè soltanto 4 relay switchano mentre gli altri rimangono sempre con la bobina eccitata, anche se sono collegati nello stesso identico modo all'expander e il ciclo for esegue sempre la stessa operazione su tutti i pin.

Fra l'altro notavo che sui relay che non funzionano si sente un leggero "tic", come se tentasse di commutare, ma misurando la tensione sulla la bobina risulta essere sempre eccitata (infatti si scaldano più di quelli che funzionano correttamente).

Ora sto leggendo meglio la guida e gli esempi. Farò qualche nuovo tentativo nei prossimi giorni.

Nel frattempo grazie ancora e... Buon anno!

sicuro che l'alimentatore ce la fà?
hai provato ad accendere solo i pin che sembrano non funzionare?

Scusate la lentezza delle risposte ma il tempo è sempre limitato...

Sull'alimentatore non ho dubbi, è uno switching da 5A che uso anche per alimentare circuiti più "esosi", quindi non ha problemi a pilotare qualchè relay. Mentre l'MCP ora è alimentato direttamente da Arduino ma ho provato ad alimentare anche con lo stesso alimentatore dei relay ed il risultato è lo stesso

Ho provato ad eseguire un ciclo che accende e spegne un pin per volta, in modo da attivare un unico relay alla volta. Non appena riprenderò in mano il circuito proverò anche ad attivare semplicemente uno dei pin, senza usare nessun ciclo.

gamby:
Anch'io ho seguito gli esempi inclusi nella libreria. Fra l'altro la libreria del github richiede la libreria Spi.h, mentre di default su Arduino c'è SPI.h che è una cosa diversa.
L'altra libreria di cui si parlava sopra invece funziona appunto con SPI.h, quindi probabilmente è più aggiornata.

Ho controllato i vari link riportati nella libreria e pare che la Spi.h che originariamente era a corredo del coprocessore matematico della micromega adesso sia stata inglobata nel core di Arduino e diventata SPI.h
Quindi, a parte qualche ottimizzazione successiva e il cambio di nome (il C è case sensitive), sono la medesima libreria.

Alla file le librerie disponibili per questo componente sono 2
--> Arduino Playground - MCP23S17 Class for Arduino (http://www.k0usy.org/arduino/MCP23S17.zip)
e
--> Arduino Playground - Mcp23s17 (GitHub - dreamcat4/Mcp23s17: Arduino library for the Microchip MCP23S17)

Quale ti funziona?

In realtà "funzionano" entrambe... Solo che con la prima va bene la libreria SPI.h già presente di default, mentre con la seconda bisogna andare a pescare Spi.h nel web, oppure (ma in questo caso non ho so se potrebbe dare problemi) modificare l'include della libreria per puntare al nuovo SPI.h

Comunque sto usando SPI.h e la libreria da Arduino Playground - MCP23S17 Class for Arduino
Ma dire "funziona" ora come ora è una parola grossa, visti i risultati che ho ottenuto fin'ora XD

Ho avuto modo di fare ancora qualche prova... Sono andato un po' a tentativi e nell'inizializzazione ho sostituito switcher.pinMode(0B0000000000000000) con switcher.pinMode(0B1111111111111111). In teoria è sbagliato, perchè gli 1 indicano un input, mentre a me servono gli output. Però così funzionano ben 8 uscite, praticamente la prima metà dell'expander da GPA0 a GPA7!!! Come è possibile???? Non dovrebbe nemmeno funzionare!!

Riporto il programma aggiornato:

#include <SPI.h> 
#include <MCP23S17.h>

MCP switcher(0);

void setup() {
  pinMode(53, OUTPUT);
  digitalWrite(53,LOW);
  switcher.pinMode(0B1111111111111111);
}

void loop() {
  int i;
  for (i=1;i<=16;i++) {
    switcher.digitalWrite(i, LOW);
    delay(100);
  }
  delay(200);
  for (i = 1; i <=16; i++) {
    switcher.digitalWrite(i, HIGH);
    delay(100);
  }
  delay(200);
}

Non so più che pesci pigliare...
In compenso ho provato il circuito che ho preparato per la gestione dei display 7-segmenti (sempre SPI) e funziona perfettamente 8)

:astonished:

Ho letto il link alla spiegazione della libreria ma non riesco a capire perchè hai messo nel codice il pin 53 a low...
Negli esempi non dice di impostarlo a low o almeno non ho visto scritto in merito .
Poi ho letto che per impostarlo in output puoi semplicemente scrivere

pinMode(LOW);

Il pin 53 sarebbe lo slave select per SPI... Non deve essere messo LOW per abilitare la periferica?

Per la funzione pinMode la guida della libreria riporta questo, che però da quanto ho capito imposta un pin per volta:

onechip.pinMode(4, HIGH); // sets pin 4 as an input

Mentre questo imposta tutti i pin in un solo comando

twochip.pinMode(0B0000111100001111); // sets pins 1-4 and 9-12 as input, 5-8 and 13-16 as output

PaoloP:
:astonished:

Non ti torna? :grin:

Il pin 53 sarebbe lo slave select per SPI... Non deve essere messo LOW per abilitare la periferica?

Se usi la Spi si...ma in questo caso potrebbe essere la lib stessa che gestisce il tutto,anche guardando gli esempi non mostra impostazione a LOW del pin ss (select slave) che chiamiamo cs.

Non ti torna?

Si,mi torna ma dice anche che se vuoi semplicemente settare tutti i pin allo stesso modo puoi semplicemente fare

onechip.pinMode(LOW);

Mentre se hai bisogno di impostare un solo pin come output

onechip.pinMode(4,LOW);

ed invece nel caso ti servisse una svariata configurazione usi il set sui singoli pin direttamente con i bit corrispondenti

twochip.pinMode(0B0000111100001111);

Ok forse adesso ho un po' più chiara la situazione... Appena riprendo in mano il circuito provo a modificare un po' di cosette nel programma e vedo i risultati.

Grazie!