Go Down

Topic: MCP23S17 per comandare dei relay (Read 4610 times) previous topic - next topic

MauroTec

Scrivo solo questo e poi vado a nanna, ci ho gli occhi a pampinedda. :P

Il 23017 dovrebbe essere idendico al quello che usi tu, con la differenza che il tuo dialoga tramite ISP, mentre il "017" tramite I2C.
Leggendo il manuale del 23017 ho notato che è possibile farlo funzionare in due modalità, 8 bit o 16 bit, ora non ho la lucidità per indagare e i risultati sarebbero pessimi, ma vado per intuito, cioè se è impostato per 16 bit ed invii 16 bit di cui riempi solo i meno significativi, gli altri non si accenderanno, se invece è in modo 8 bit devi inviare due byte distinti, ma qui c'è di mezzo la libreria, io al tuo posto avrei estrapolato il codice sensibile da quella lib e scritto uno sketch con le istruzioni indispensabili per eccitare tutti i 16 relè così da vedere cosa cambia tra modo 8 bit e 16 bit.

Ciao.
AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

gamby

Grazie dei suggerimenti.

La libreria funziona in diverse modalità:
- Impostando un pin per volta, ed i pin sono numerati da 1 a 16
- Impostando tutti i pin in un solo colpo con una stringa di 16 bit (esempio 0B1111111111111111 per impostare tutti i pin a HIGH) oppure con una word esadecimale (0xFF se non ricordo male per tutti HIGH).
Non ho ancora ben chiaro se ci siano anche altri modi di funzionamento. Sono partito da questi perchè sono i più semplici e proprio per questo non vedo perchè non dovrebbero funzionare.
Ho già fatto anche un po' di prove per eccitare tutto insieme, o un pin singolo, o una sequenza. Ieri sera ho anche provato senza relay, solo con led e resistenze collegati ad un singolo pin. Il risultato è sempre lo stesso... Alcuni pin vanno, altri no, il tutto sempre in modo molto instabile.

L'unica prova che devo ancora fare è sostituire i cavetti del bus SPI con qualcosa di schermato, ma ho i miei dubbi che sia una cosa risolutiva perchè a quanto pare il bus trasmette correttamente... Comunque potrebbe essere un passo avanti per rendere il tutto più stabile.

gamby

Altra prova rapida...

Con questo codice funzionano i famosi 8 ingressi, mentre gli altri restano fissi alcuni LOW e alcuni HIGH senza una logica apparente:

Code: [Select]
#include <SPI.h>
#include <MCP23S17.h>

MCP switcher(0);

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

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);
}


Con quest'altra sento delle commutazioni che non hanno niente a che vedere con ciò che c'è scritto nel programma: ho delle commutazioni sull'uscita 9 con tempi diversi da quelli scritti nello sketch e un'altra commutazione sull'uscita 7 che non so da dove arriva!!!

Code: [Select]
#include <SPI.h>
#include <MCP23S17.h>

MCP switcher(0);

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

void loop() {

    switcher.digitalWrite(9, HIGH);
    delay(200);
    switcher.digitalWrite(9, LOW);
    delay(500);
}


Qui addirittura ho commutazioni su 4 relè diversi:

Code: [Select]
#include <SPI.h>
#include <MCP23S17.h>

MCP switcher(0);

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

void loop() {

    switcher.digitalWrite(1, HIGH);
    delay(200);
    switcher.digitalWrite(1, LOW);
    delay(500);
}


Adesso ho anche sostituito i cavetti con un cavo a 4 poli schermato, ed in effetti sembra un po' meno sensibile ai disturbi del tester, delle mani, ecc.
Però non cambia il funzionamento.

MauroTec


Grazie dei suggerimenti.

La libreria funziona in diverse modalità:
- Impostando un pin per volta, ed i pin sono numerati da 1 a 16
- Impostando tutti i pin in un solo colpo con una stringa di 16 bit (esempio 0B1111111111111111 per impostare tutti i pin a HIGH) oppure con una word esadecimale (0xFF se non ricordo male per tutti HIGH).
Non ho ancora ben chiaro se ci siano anche altri modi di funzionamento. Sono partito da questi perchè sono i più semplici e proprio per questo non vedo perchè non dovrebbero funzionare.
Ho già fatto anche un po' di prove per eccitare tutto insieme, o un pin singolo, o una sequenza. Ieri sera ho anche provato senza relay, solo con led e resistenze collegati ad un singolo pin. Il risultato è sempre lo stesso... Alcuni pin vanno, altri no, il tutto sempre in modo molto instabile.

L'unica prova che devo ancora fare è sostituire i cavetti del bus SPI con qualcosa di schermato, ma ho i miei dubbi che sia una cosa risolutiva perchè a quanto pare il bus trasmette correttamente... Comunque potrebbe essere un passo avanti per rendere il tutto più stabile.


Si ok la libreria ti da l'impressione di poter gestire il 23S17 in modo diverso, ma è una impressione o è la realtà?

Nel datasheet c'è anche scritto che è possibile impostare la polarità per ogni pin di GPIO, quindi se metti alto un pin in uscita avrai 1 negato cioè zero. Queste cose la lib non le gestisce.

Comunque, la lib che ho guardato io usa l'include:
Code: [Select]

#include <SPI.h>                 // Arduino IDE SPI library - uses AVR hardware SPI features
#include "MCP23S17.h"            // Header files for this class


Nel codice di esempio non c'è necessità di includere nuovamente SPI.
Per ultimo una cosa molto importante:
Code: [Select]

#define    SS            (10)          // SPI bus slave select output to pin 10 - READ ARDUINO SPI DOCS BEFORE CHANGING!!!



SS è definito ma non usato nella lib, in sua vece c'è una costante numerica espressa in binario, questo è il codice:
Code: [Select]

// GENERIC BYTE WRITE - will write a byte to a register, arguments are register address and the value to write

void MCP::byteWrite(uint8_t reg, uint8_t value) {      // Accept the register and byte
  PORTB &= 0b11111011;                                 // Direct port manipulation speeds taking Slave Select LOW before SPI action
  SPI.transfer(OPCODEW | (_address << 1));             // Send the MCP23S17 opcode, chip address, and write bit
  SPI.transfer(reg);                                   // Send the register we want to write
  SPI.transfer(value);                                 // Send the byte
  PORTB |= 0b00000100;                                 // Direct port manipulation speeds taking Slave Select HIGH after SPI action
}

Guarda caso PORTB |= 0b00000100 è il digital pin 10 di arduino 2009/UNO, che corrisponde al pin SS (16) del 328.

Ora tu devi cambiare sia porta che valore fino a selezionare il pin 53 della MEGA e questi cambiamenti li devi fare su tutta la lib.

Poi c'è ancora una cosa che non ho capito, il 23S17 ha dei pin chiamati A0, A1, A2 che possono essere disabilitati o abilitati, sono abilitati di default nella versione I2C perchè manca il bit HAEN e disabilitati per la versione ISP ma abilitabili grazie ad HAEN.

Il documento che ho consultato e questo che è valido per entrambe le versioni ISP e I2C, alla pagina 18 c'è la descrizine di importati bit.
DS21952B-page 18

Ciao.

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

gamby

Sto facendo riferimento a questa pagina: http://playground.arduino.cc/Main/MCP23S17

A un certo punto è scritto:
Quote
The class does include several more methods that can be used to simplify configuration in the same "Arduino-ish" way, methods for writing/reading 8-bit registers (configuration and I/O ports) at once, as well as writing/reading consecutive registers (allowing all 16 bits to be read or written with one method call)


Quindi se non ho capito male sarebbe possibile impostare i pin da 1 a 16 senza preoccuparsi dei due registri. Cosa che io ho prontamente evitato  ]:D
Non avevo invece controllato la presenza del pin SS nella libreria. Avevo cambiato da 10 a 53 nella #define ma non avevo notato che non era presente nel codice.

Però ho anche provato ad assegnare manualmente il segnale al pin 53 con un semplice digitalWrite(53,LOW).
Non ricordo se lo avevo letto o se è una mia convinzione, ma non è la stessa cosa? Anche perchè se così non fosse come si fa a controllare più slaves? Occorre modificare la libreria di ogni periferica per assegnare un pin di slave select diverso?

A questo punto devo provare a modificare quel "PORTB |= 0b00000100" per puntare al pin 53.

gamby

Rieccomi...
Ho dato un'occhiata al datasheet e alle librerie di questo benedetto MCP23S17, ma ho le idee ancora più confuse di prima.

Si parlava di Slave select e di quel valore "PORTB |= 0b00000100" che corrisponderebbe al pin slave select sul ATMEGA328.
Ma come faccio a modificarlo per dare la corrispondenza al relativo pin sul ATMEGA2560? A quanto vedo non è sufficiente ricavare il valore binario corrispondente al pin SS.

Quei pin A0,A1,A2 identificano l'indirizzo del 23S17. Vanno settati HIGH o LOW in base all'indirizzo che si vuole dare al chip. In questo modo è possibile collegare fino a 8 dispositivi in parallelo con un solo pin SS, e attivare quello corretto attraverso l'indirizzo che lo identifica.
Nel codice l'indirizzo va inizializzato assieme al nome del chip.
Nel mio circuito ho messo i tre pin a massa, quindi ho inizializzato il componente con l'indirizzo zero in questo modo:
Code: [Select]
MCP switcher(0);
Così che in seguito nel codice farò riferimento a quel chip con il nome switcher che identifica il dispositivo con indirizzo zero.

MauroTec

Il pin SS vedo che si trova nella porta B ma nella prima posizione della porta, cioè in PB0 (pin19).

Nel codice mi pare che c'è una constante "#define SS" che non viene usata, beh usala più o meno così:

#define SPI_SS  0b00000001

Nel codice sostituisci :

PORTB |= 0b00000100
con
PORTB |= SPI_SS

Anche quando rimette il bit a zero usando "&=" al posto di "|=" devi fare la sostituzione.
PS: non mi ricordo il codice.

Sempre che tu non abbia già provato senza risolvere.

Ciao.
AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

gamby

YESSSSSSSSSS..... PERFETTO!!!!!

:D :D :D :D

Inizio a capire la logica... Non avevo capito che quel "PORTB" era riferito al registro dell'ATMEGA, pensavo fosse ancora del 23S17!
Praticamente ho sostituito il valore binario di PORTB in tutta la libreria in questo modo:

Code: [Select]
PORTB |= 0b00000001
PORTB &= 0b11111110


Ora funziona correttamente. Non ho fatto dei test intensivi ma a quanto pare il ciclo for del mio programmino di test funziona correttamente!
Grazie a tutti per il supporto, specialmente a MauroTec per essere andato a studiare datasheet e libreria...

Per chi dovesse incappare nello stesso problema dopo di me allego la libreria corretta (non ho usato le #define perchè in realtà i valori sono due).

MauroTec

Stappa lo spumante che brindiamo  :P

Puoi usare la define con questa modifica:
#define SPI_SS 0b00000001
PORTB |= SPI_SS
PORTB &= ~SPI_SS

oppure accendi e spegni bit con la macro _BV(bit)

PORTB |= _BV(PB0)
PORTB &= ~_BV(PB0)

Nota che PB0 PB1 ecc sono i nomi dei pin che nella avrlibc sono stati definiti tramite #define, quindi la define SS diventa

#define SPI_SS PB0

e al posto di _BV(PB0) scrivi _BV(SPI_SS)

Occhio al "~" che inverte tutti i bit.

Io pensavo tu avessi una discreta competenza con il software tanto da potertela cavare da solo, e invece mi sbagliavo ora
per punizione ti tocca sbatterti un poco a studiare le porte del micro, macro ecc.  :P

Ciao.


AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

gamby

In effetti mi sto rendendo conto che un po' di pratica vale molto più di tante ore passate sui libri.
Ho già fatto i corsi di base sul C all'università, ma vedo che la teoria è molto diversa dalla pratica... Cioè un conto è scrivere un programmino con qualche ciclo, usare la ricorsione, le funzioni delle librerie standard, ecc, e un conto è mettersi a scrivere software, seppur semplice, per far funzionare qualcosa di reale.
Per non parlare di "trucchetti" (messo tra virgolette perchè mi rendo conto che per un programmatore sono cose basilari), vedi la tilde per invertire i bit di cui non ricordavo minimamente l'esistenza.

Per punizione mi ci metto volentieri a imparare un po' di cosette  :smiley-mr-green:
Sono ben accetti consigli su cosa iniziare a studiare.

Tornando alle cose importanti... Quasi quasi lo spumante lo stappo davvero!!!  ]:)

MauroTec

Io ho il brutto vizio di dire le cose come stanno, tendo a dipingere la realtà in modo più aderente che riesca a fare, ma inevitabilmente vengo frainteso.

Quindi onde evitare fraintendimenti:
Arduino è una ottima scheda, l'ide è pessimo, il modo di sviluppare non forma il programmatore, ma ha il vantaggio di apparire semplice e intuitivo e senza limitazioni cosa che per un principiante è un aspetto allettante. Il principiante ancora non è cosciente che ogni cosa è complessa e nulla di facile esiste, persino bere un bicchiere di acqua può essere complicato quando non hai le mani.
PS: ci sono anche altri vantaggi e il corrispettivo rovescio della medaglia.

Ok allora ogni cosa che ci circonda è complessa e può apparire semplice perché altri hanno lavorato per farla sembrare semplice, purtroppo qualunque semplificazione ha il rovescio della medaglia e credo che sia un vantagio saperlo perchè nel caso di arduino quando non bastano le funzioni del core lib, l'ide ecc, si può ricorrere ad altre funzioni sulle quali arduino core lib è costruito.

Il C non è nato specificamente per applicazioni embedded, ma la grande flessibilità del linguaggio ha permesso un adattamento che per tanto tempo non è stato messo in discussione ( in realtà si, ma in modo marginale tanto che il C è il linguaggio più usato in applicazioni embedded).

Consigli:
Trova un IDE decente con cui ti trovi bene, questo deve essere in grado di avviare il compilatore nativo, cioè crea codice per la piattaforma su cui è eseguito il compilatore e l'ide. Io uso GNU/Linux e come ide uso QtCreator.

L'obbiettivo è quello di testare:
1) La rappresentazione delle informazioni, stringhe, stringhe di array, valori numerici in esadecimale, decimale e ottale
2) tutti gli operatori unari e quelli logici and, or e xor
3) tutte le operazioni bitwise fino a comprenderle senza cadere nell'inganno, le macro _BV() e altre.
4) alcune funzioni delle libreria standard C, ma in avrlibc alcune non sono standard e allora bisogna trovare il codice e portarlo sul
pc compilarlo e testarlo.
5) L'uso delle classi in C++, delle strutture in C e i puntatori a funzioni.

L'uso di esprimere un numero in formato binario 0b0010ecc non lo trovo educativo, ma è utile per il principiante che deve imparare a contare in binario ed esadecimale a mente, A=10, B=11 C=12 ecc. Esprimere il valore in formato binario è merito di arduino core lib, che crea delle macro 0b11011111  223.

Io per contare in binario ed esadecimale uso una applicazione calcolatrice  :* , specie per i numeri esadecimali, ma anche per i binari da 16 bit.

L'uso e la vendità di librerie di estensione al linguaggio è comune in ambito non embedded, cioè con il PC, meno anzi molto meno in applicazioni embedded perchè il programmatore deve tenere sotto controllo le risorse limitate e per questo ha bisogno di sapere nel dettaglio cosa accade istruzione per istruzione, questo è vero in ambito professionale specie su commisione, perchè l'hardware viene scelto dal committente è il programmatore deve farci stare dentro tutte le richieste del committente e stranamente l'hardware è sempre appena sufficiente e mai abbondantemente sufficiente.

Mentre in ambito obistico anche evoluto torna sempre comodo spulciare nella libreria che si sta usando al fine di capire cosa fanno quelle funzioni, per fortuna il codice di avrlibc, di arduino core lib e dell'ide è rilasciato sotto GPL o LGPL che sia è quindi è consultabile oltre che modificabile, e li dentro impari cose che non trovi nei libri.

Tornando al progetto, ora non penso che siano altri intoppi e puoi procedere con magiore celerità e non dimenticare di fare partecipe tutto il forum circa i risultati raggiunti e penso proprio che la sezione Megatopic sia il posto migliore per condividere il progetto.

In modo assolutamente non informale:
Ti è andata di culo che il datasheet del 23S17 è lo stesso del 23017 che devo usare io, che quindi prima poi dovevo leggere. :smiley-mr-green:

Ciao.
AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

gamby

Ottimo! grazie per le delucidazioni!
In ogni caso mi fa piacere che tu dica le cose come stanno... Ormai ho capito che è inutile scrivere programmi bypassando i problemi sfruttando pezzi di codice trovati qua e la... Vista l'esperienza con questo MCP23S17 mi sembra chiaro che è meglio andare a fondo e capire cosa c'è dietro a un semplice programmino di 10 righe.

Un paio di riflessioni tra me e me, anche se il thread tratta di tutt'altro.

Partiamo dall'IDE... Personalmene ho provato un po' di tutto sia per quanto riguarda i sistemi operativi sia per l'ambiente di programmazione: per il primo corso di C ho usato il vecchio Dev-C++ sotto windows, ma in quella fase era veramente solo questione di scrivere qualche ciclo e eseguire operazioni di base.
Dopodichè sono passato a linux e per il corso più "evoluto" consigliavano di scrivere il programma con uno dei vari editor standard di linux (Vim,nano,gedit e simili) e compilare con GCC. Ho poi provato per qualche tempo eclipse, più per curiosità che per necessità.
Ora sono principalmente su MacOS, anche se ho a disposizione ancora linux su macchina virtuale e windows su una partizione secondaria.
La scelta più ovvia sarebbe continuare ad usare eclipse sotto MacOS.

Non ho però capito come dovrei utilizzare un IDE diverso da Arduino. Sarebbe soltanto un'interfaccia più completa da sostituire alla solita interfaccia standard "verde e bianca" oppure mi permetterebbe di sviluppare tutto il software, compilarlo e caricarlo sulla scheda sempre dalla stessa interfaccia? Mi sembra di intuire che dovrei caricare tutte le librerie di Arduino nel nuovo IDE, ma non capisco come un diverso IDE si dovrà interfacciare con la scheda Arduino connessa al mio PC.

gamby

Come non detto... Nel frattempo sono andato a cercare qualche informazione e mi sono schiarito un po' le idee...
Ho visto che esistono dei plugin per estendere le funzionalità dei vari IDE al nostro AVR. Si tratta ora di capire se Eclipse va d'accordo con qusti plugin sotto Mac OSX... Altrimenti proverò a cercare un'altrnativa.

MauroTec


Ottimo! grazie per le delucidazioni!
In ogni caso mi fa piacere che tu dica le cose come stanno... Ormai ho capito che è inutile scrivere programmi bypassando i problemi sfruttando pezzi di codice trovati qua e la... Vista l'esperienza con questo MCP23S17 mi sembra chiaro che è meglio andare a fondo e capire cosa c'è dietro a un semplice programmino di 10 righe.

Un paio di riflessioni tra me e me, anche se il thread tratta di tutt'altro.

Partiamo dall'IDE... Personalmene ho provato un po' di tutto sia per quanto riguarda i sistemi operativi sia per l'ambiente di programmazione: per il primo corso di C ho usato il vecchio Dev-C++ sotto windows, ma in quella fase era veramente solo questione di scrivere qualche ciclo e eseguire operazioni di base.
Dopodichè sono passato a linux e per il corso più "evoluto" consigliavano di scrivere il programma con uno dei vari editor standard di linux (Vim,nano,gedit e simili) e compilare con GCC. Ho poi provato per qualche tempo eclipse, più per curiosità che per necessità.
Ora sono principalmente su MacOS, anche se ho a disposizione ancora linux su macchina virtuale e windows su una partizione secondaria.
La scelta più ovvia sarebbe continuare ad usare eclipse sotto MacOS.

Non ho però capito come dovrei utilizzare un IDE diverso da Arduino. Sarebbe soltanto un'interfaccia più completa da sostituire alla solita interfaccia standard "verde e bianca" oppure mi permetterebbe di sviluppare tutto il software, compilarlo e caricarlo sulla scheda sempre dalla stessa interfaccia? Mi sembra di intuire che dovrei caricare tutte le librerie di Arduino nel nuovo IDE, ma non capisco come un diverso IDE si dovrà interfacciare con la scheda Arduino connessa al mio PC.


Mi sono spiegato male o hai capito male ma non importa il risultato sempre quello è.
Quote
Consigli:
Trova un IDE decente con cui ti trovi bene, questo deve essere in grado di avviare il compilatore nativo, cioè crea codice per la piattaforma su cui è eseguito il compilatore e l'ide. Io uso GNU/Linux e come ide uso QtCreator.


Deve essere in grado di avviare il compilatore nativo:
        Il compilatore nativo genera codice per la stessa piattaforma su cui viene eseguito, detto alla carlona "compili codice che gira
        sul PC.
Il compilatore non nativo è il cross-compiler il quale "gira" sul PC ma genera codice binario per una piattaforma diversa dal PC.
Si è più semplice dire che avrgcc gira sul pc e genera codice binario specifico per architettura AVR quindi è un cross-compiler.
Però avrgcc può anche essere compilato per girare su architettura "ARM" e quindi può essere eseguito su ARM ma genera codice per AVR.

Insomma nel cross-compiler la piattaforma su cui viene eseguito e diversa da quella per il quale genera codice binario.

Quindi io *non* ti ho consigliato di cambiare IDE per arduino, ma ti consiglio di usare il PC per testare codice che poi andrai a compilare con arduino. In questo modo per prendere confidenza con le classi ecc non devi flashare ma basta che usi le printf del C
o cin cout di C++ per fare debug. Puoi testare le bitwise, le macro, i calcoli per settare i timer ecc.

Per Mac puoi usare anche QtCreator come pure per windows, solo che per linux tutto si risolve con l'installazione di pacchetti pronti, per Mac e windows non credo che sia così immediato, in quanto mancano tutte le dipendenze, cioè il compilatore gcc per windows o Mac, make ecc che mi pare si trovino tutte in un unico file compresso da scaricare e sistemare nel filesystem manualmente. Mentre per Qt e QtCreator ci sono gli exe autoinstallanti e per Mac non lo so.

Ciao.



AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

gamby

Ah beh... Ora è chiaro! Avevo interpretato male la cosa.
Pensavo che il consiglio di utilizzare un altro IDE fosse più che altro per un fatto di "leggibilità" del codice, ma non mi ero posto il problema del testare il codice senza flashare, cosa che in effetti sarebbe molto ma molto comoda.

A questo punto parto subito con qualche test...

Grazie di nuovo!

Go Up