Poll
Question: come fare ad associare una numerazione cosecutiva ai pin dell'' espansione?
? - 4 (66.7%)
? - 2 (33.3%)
Total Voters: 6

Pages: [1] 2   Go Down
Author Topic: expanders  (Read 967 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao a tutti, vorrei un aiuto per risolvere un mio crucio.
sto da poco facendo dei test su arduino per poterlo espandere tramite I2C.
ho optato per l' integrato PCF8574 che controllo ormai in maniera molto semplice tramite delle librerie recuperate dalla rete.
il mio problema è ora capire come faccio a far prendere ai pin digitali dell' espansione una numerazione coerente con la numerazione dei pin di arduino.
per esempio io ho un servo collegato sul pin 1 dell'expander2, quale codifica devo dare allo sketch per poter usare un comando tipo : servo1.attach(x); della libreria servo.h?
cosa devo mettere al posto della x? normalmente metti il pin della scheda dove è collegato il servo.

immagino che ci sia una libreria che mi permette di far ciò ma non son riuscito a trovar nulla, la mia esperienza attuale purtroppo non mi consente di arrivare a scrivere librerie ad-hoc per i miei progetti.
grazie a tutti
Logged

0
Offline Offline
Faraday Member
**
Karma: 47
Posts: 5909
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

io ho votato la prima opzione  smiley-yell
Logged

- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

non ho ben capito che fossero....pardon smiley-red
Logged

BZ (I)
Online Online
Brattain Member
*****
Karma: 266
Posts: 21664
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

La libreria servo.h funziona solo con i Pin del Arduino.
Se vuoi pilotare tanti Servo prendi un Arduino MEGA oppure una scheda come  queste http://www.pololu.com/catalog/category/12
Gli expander sono ideati per avere entrate/uscite statiche e non modiulate in PWM o PPM
Altra possibilitá: usa i pin del Arduino per pilotare i Servo e le entrate/uscite del expander per i pulsanti o per il display.

Ciao Uwe
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

innanzitutto grazie per aver risposto.
ok per quanto riguarda la gestione dei servo, ma supponiamo che io voglia in qualche modo remotizzare uno o più ricevitori ir che normalmente generano un output digitale. come posso fare in modo che il mio arduino legga attraverso I2C questa segnalazione?

chiedo scusa se faccio richieste strane...
Logged

BZ (I)
Online Online
Brattain Member
*****
Karma: 266
Posts: 21664
+39 349 2158303
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

É possibile usare un expander I2C ma é complicato e un gran impegno scrivere un codice ben funzionante. Te lo sconsiglio.
Ciao Uwe
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

mmm....pensavo che fosse complicato per me che sono inesperto....
questo mi consola un po.
fatto stà che non mi risolve il dilemma smiley
in sostanza se io avessi la necessità di leggere ed interpretare sensori a distanza su I2C non lo posso fare dagli ingressi digitali delle mie espansioni.
dovrei usare queste solo per gestire ingressi e uscite digitali e per i sensori ed eventuali attuatori dovrei affidarmi a integrati specifici posti su bus I2C.
Grazie comunque per i preziosi consigli. e grazie a chi si prodiga così tanto per rendere sempre più potente l'open!
Logged

italy
Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ciao speleoduracell
potresti indicarmi un collegamento per le librerie che hai usato per la gestione del PCF8574.
vorrei provare a gestire una serie di relè ma dal esempio del playground ho capito poco.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

di seguito intervallate dagli * le librerie e un piccolo esempio di funzionamento.



*****************************************************la PCF8574.cpp:*********************************************************

#include "PCF8574.h"
#include "PCint.h"

PCF8574::PCF8574(){
   resetRegister();
}

PCF8574::~PCF8574(){
   /* DO NOTHING */
}

void PCF8574::begin(int SADR){
   PCFaddress=SADR;
   Wire.begin();
}

void PCF8574::pinMode(int pin, int mode){
   bitWrite(PCFTRISA,pin,mode);
}

void PCF8574::digitalWrite(int pin,int value){
   if((pin >= 0) && (pin < smiley-cool){
      bitWrite(PCFPORTA,pin,value);
      i2cSend();
   }
}

int PCF8574::digitalRead(int pin){
   if((pin >= 0) && (pin < smiley-cool){
      i2cRead();
      return bitRead(PCFPORTA,pin);
   }
}

void PCF8574::write(int value){
   PCFPORTA = value;
   i2cSend();
}

void PCF8574::pullUp(int pin){
   if((pin >= 0) && (pin < smiley-cool){
      PCFPULL[pin] == 1;
      i2cRead();
      bitWrite(PCFPORTA,pin,1);
      i2cSend(PCFPORTA);
   }
}

void PCF8574::pullDown(int pin){
   if((pin >= 0) && (pin < smiley-cool){
      PCFPULL[pin] == 2;
      i2cRead();
      bitWrite(PCFPORTA,pin,0);
      i2cSend(PCFPORTA);
   }
}

int PCF8574::read(){
   i2cRead();
   return PCFPORTA;
}

void PCF8574::clear(){
      PCFPORTA = 0x00;
      i2cSend();
}

void PCF8574::set(){
      PCFPORTA = 0xFF;
      i2cSend();
}

void PCF8574::toggle(int pin){
   if((pin >= 0) && (pin < smiley-cool){
      i2cRead();
      bitWrite(PCFPORTA,pin,!bitRead(PCFPORTA,pin));
      i2cSend();
   }
}

void PCF8574::blink(int pin,int time,int wait){
   if((pin >= 0) && (pin < smiley-cool){
      i2cRead();
      for(int i=0;i<time;i++){
         bitWrite(PCFPORTA,pin,0);
         i2cSend();
         delay(wait);
         bitWrite(PCFPORTA,pin,1);
         i2cSend();
         delay(wait);
      }
   }
}

void PCF8574::enableInterrupt(int pin,void(* selfCheckFunction)(void)){
   PCFIntPin = pin;
   pinMode(PCFIntPin,INPUT);
   PCattachInterrupt(PCFIntPin,selfCheckFunction,FALLING);
}

void PCF8574::disableInterrupt(){
   PCdetachInterrupt(PCFIntPin);
}

#ifdef INT_INPUT_ONLY
#define INT_CHECK (PCFTRISA == INPUT)
#else
#define INT_CHECK true
#endif

void PCF8574::checkForInterrupt(){
   sei();
   PCFBUFFER = i2cRead(0x00);
   for(int i=0;i<8;i++){
      switch(PCFINT){
         case CHANGE:
            if(INT_CHECK && (bitRead(PCFPORTA,i) != bitRead(PCFBUFFER,i)))
               PCFJMP();
            break;
         case LOW:
            if(INT_CHECK && (bitRead(PCFBUFFER,i) == 0))
               PCFJMP();
            break;
         case FALLING:
            if(INT_CHECK && (bitRead(PCFPORTA,i) == 1) && (bitRead(PCFBUFFER,i) == 0))
               PCFJMP();
            break;
         case RISING:
            if(INT_CHECK && (bitRead(PCFPORTA,i) == 0) && (bitRead(PCFBUFFER,i) == 1))
               PCFJMP();
            break;
         case 255:
            break;
      }
   }
}

void PCF8574::attachInterrupt(int pin,void (*userFunc)(void),int mode){
   if((pin >= 0) && (pin < smiley-cool){
      PCFINT[pin] = mode;
      PCFJMP[pin] = userFunc;
   }
}

void PCF8574::detachInterrupt(int pin){
   if((pin >= 0) && (pin < smiley-cool){
      PCFINT[pin] = 255;
   }
}

void PCF8574::resetRegister(){
   PCFPORTA =0;
   PCFTRISA =0;
   PCFBUFFER =0;
   for(int i=0;i<8;i++)
         PCFINT = 255;
}

void PCF8574::i2cSend(){
   PCFBUFFER = i2cRead(0x00);
   for(int i=0;i<8;i++){
      if(bitRead(PCFTRISA,i) == INPUT)
         bitWrite(PCFPORTA,i,bitRead(PCFBUFFER,i));
      if(PCFPULL == 1) bitWrite(PCFPORTA,i,1); // Required for unblock pull level
      if(PCFPULL == 2) bitWrite(PCFPORTA,i,0); // Required for unblock pull level
   }
   Wire.beginTransmission(PCFaddress);
   Wire.write(PCFPORTA);
   Wire.endTransmission();
}

void PCF8574::i2cSend(int mask){
   Wire.beginTransmission(PCFaddress);
   Wire.write(PCFPORTA);
   Wire.endTransmission();
}

void PCF8574::i2cRead(){
  uint8_t value = 0x00;
  Wire.requestFrom(PCFaddress, 1);
  if(Wire.available()) {
    value = Wire.read();
  }
  PCFPORTA = (int)value;
}

int PCF8574::i2cRead(uint8_t value){
  Wire.requestFrom(PCFaddress, 1);
  if(Wire.available()) {
    value = Wire.read();
  }
  return (int)value;
}

****************************************** la libreria PCF8574.h smiley-kiss*****************************************************

#ifndef PCF8574_H
#define PCF8574_H

#include <Arduino.h>
#include <Wire.h>

typedef void (*FunctionPointer)(void);

class PCF8574 {
public:
        PCF8574();
        ~PCF8574();
      void begin(int SADR);
      void pinMode(int pin, int mode);
      void digitalWrite(int pin,int value);
      int digitalRead(int pin);
                void write(int value);
      int read();
      void clear();
      void set();
      void pullUp(int pin);
      void pullDown(int pin);
      void toggle(int pin);
      void blink(int pin,int time,int wait);
      void enableInterrupt(int pin,void(* selfCheckFunction)(void)); // Require pointer to an user create gateway function because checkForInterrupt() is in PCF8574 namespace.
      void disableInterrupt();
      void attachInterrupt(int pin,void (*userFunc)(void),int mode);
      void detachInterrupt(int pin);
      void checkForInterrupt();
private:
      volatile int PCFPORTA;
      volatile int PCFPULL[8];
      volatile int PCFTRISA;
      volatile int PCFBUFFER;
      volatile int PCFaddress;
      int PCFIntPin;
      volatile int PCFINT[8];
      volatile FunctionPointer PCFJMP[8];
      void resetRegister();
      void i2cSend();
      void i2cSend(int mask);
      void i2cRead();
      int i2cRead(uint8_t value);
};
 

#endif


*************************************un piccolo esempio che ho usato per testare il funzionamento:*****************************************************



#include <PCF8574.h> // Required for ... all

#include <Wire.h> // Required for I2C communication

PCF8574 A; // Create object from PCF8574 class
PCF8574 B;


void setup(){
    B.begin(0x20);
    A.begin(0x27); 
    pinMode(13,OUTPUT);
  Serial.begin(9600); // Setup serial for read echo
 
  A.pinMode(0,OUTPUT); // Setup pin D0 as output
  A.pinMode(1,OUTPUT); // Setup pin D1 as output
  A.pinMode(2,OUTPUT); // Setup pin D2 as output
  A.pinMode(3,OUTPUT); // Setup pin D3 as input
  A.pinMode(4,INPUT); // Setup pin D0 as output
  B.pinMode(5,INPUT); // Setup pin D1 as output
  B.pinMode(6,INPUT); // Setup pin D2 as output
  B.pinMode(7,INPUT); // Setup pin D3 as input
 


  }
  void loop(){
  if(A.digitalRead(4))
    {
      A.digitalWrite(0,HIGH);
      delay(500);
      A.digitalWrite(1,HIGH);
      delay(500);
      A.digitalWrite(2,HIGH);
      delay(500);
      A.digitalWrite(3,HIGH);
      delay(500);
       digitalWrite(13,HIGH);
       delay(500);
     }
     else
    {
    A.digitalWrite(0,LOW);
    A.digitalWrite(1,LOW);
    A.digitalWrite(2,LOW);
    A.digitalWrite(3,LOW);
      digitalWrite(13,LOW);
    }
 
}



ciao Speleoduracell.
Logged

italy
Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

grazie
questa sera provo a vedere se ci capisco qualche cosa.
poi se non ne salto fuori penso che tornerò a chiedere.

a grandi linee tu hai usato il PCF dando
da 0 a 3 come ingressi
da 4 a 7 come uscite
 
poi non ho capito perchè dai due indirizzi al PCF

B.begin(0x20);
 A.begin(0x27); 

lo sketch in base al cambio di stato degli ingressi dovrebbe accendere o spegnere dei led.
Logged

italy
Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

un altra cosa che ho notato ora

guardando il tuo messaggio
riguardo la PCF8574.cpp:

#include "PCF8574.h"          OK  la trovo nel tuo precedente post
#include "PCint.h"               non è inclusa

che libreria è questa?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ciao scusa il delay...
ho impostato ingressi ed uscite a naso, il software ti permette di usare ingressi e uscite come se fossero i pin digitali di arduino, con notevole semplificazione di sintassi.
il fatto che do due indirizzi è perchè ho messo nell' esempio due pcf8574 collegati sullo stesso bus nessuno ti vieta di usarne uno solo oppure du usarne fino a 8 della stessa specie(se integri gli pcf8574af puoi arrivare a 16 indirizzi....trovi tutto sul datasheet).


la libreria PCint.h dovrebbe gestire gli interrupt, mi ricordavo fosse inclusa nel software di arduino e invece no... te la copio:


#include "pins_arduino.h"

volatile uint8_t *port_to_pcmask[] = {
  &PCMSK0,
  &PCMSK1,
  &PCMSK2
};

static int PCintMode[24];

typedef void (*voidFuncPtr)(void);

volatile static voidFuncPtr PCintFunc[24] = {
  NULL };

volatile static uint8_t PCintLast[3];

/*
 * attach an interrupt to a specific pin using pin change interrupts.
 */
 void PCattachInterrupt(uint8_t pin, void (*userFunc)(void), int mode) {
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  uint8_t slot;
  volatile uint8_t *pcmask;

  // map pin to PCIR register
  if (port == NOT_A_PORT) {
    return;
  }
  else {
    port -= 2;
    pcmask = port_to_pcmask[port];
  }

// -- Fix by Baziki. In the original sources it was a little bug, which cause analog ports to work incorrectly.
  if (port == 1) {
     slot = port * 8 + (pin - 14);
  }
  else {
     slot = port * 8 + (pin % smiley-cool;
  }
// --Fix end
  PCintMode[slot] = mode;
  PCintFunc[slot] = userFunc;
  // set the mask
  *pcmask |= bit;
  // enable the interrupt
  PCICR |= 0x01 << port;
}

void PCdetachInterrupt(uint8_t pin) {
  uint8_t bit = digitalPinToBitMask(pin);
  uint8_t port = digitalPinToPort(pin);
  volatile uint8_t *pcmask;

  // map pin to PCIR register
  if (port == NOT_A_PORT) {
    return;
  }
  else {
    port -= 2;
    pcmask = port_to_pcmask[port];
  }

  // disable the mask.
  *pcmask &= ~bit;
  // if that's the last one, disable the interrupt.
  if (*pcmask == 0) {
    PCICR &= ~(0x01 << port);
  }
}

// common code for isr handler. "port" is the PCINT number.
// there isn't really a good way to back-map ports and masks to pins.
static void PCint(uint8_t port) {
  uint8_t bit;
  uint8_t curr;
  uint8_t mask;
  uint8_t pin;

  // get the pin states for the indicated port.
  curr = *portInputRegister(port+2);
  mask = curr ^ PCintLast[port];
  PCintLast[port] = curr;
  // mask is pins that have changed. screen out non pcint pins.
  if ((mask &= *port_to_pcmask[port]) == 0) {
    return;
  }
  // mask is pcint pins that have changed.
  for (uint8_t i=0; i < 8; i++) {
    bit = 0x01 << i;
    if (bit & mask) {
      pin = port * 8 + i;
      // Trigger interrupt if mode is CHANGE, or if mode is RISING and
      // the bit is currently high, or if mode is FALLING and bit is low.
      if ((PCintMode[pin] == CHANGE
          || ((PCintMode[pin] == RISING) && (curr & bit))
          || ((PCintMode[pin] == FALLING) && !(curr & bit)))
          && (PCintFunc[pin] != NULL)) {
        PCintFunc[pin]();
      }
    }
  }
}


SIGNAL(PCINT0_vect) {
  PCint(0);
}
SIGNAL(PCINT1_vect) {
  PCint(1);
}
SIGNAL(PCINT2_vect) {
  PCint(2);
}


non mi riesco a ricordare da dove attinsi tutto questo ma devo dire che è veramente ben fatto e io mi son trovato davvero bene, riesco ad avere 128 ingressi/uscite sul mio arduino lasciando liberi totalmente i pin della scheda!

ciaoo
Logged

italy
Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

grazie


Comunque è necessaria la libreria PCint.h perchè se non erro dovrevve servire se collego il piedino INT dell'integrato.
Se ho detto una cosa giusta riguardo l'uso della libreria,ti dico questo perchè ho visto su altri post che non collegano anche il pin INT per la gestione degli IO.

a questo punto aspetto che mi arrivi il PCF e provo realmente la gestione degli IO
in modo da andare a step e capire come funziona.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

esatto, quel pin è l' uscita interrupt appunto. vedi la pagina dodici del datasheet è tutto scritto li.
questa libreria la usi quando colleghi questo pin quindi quando di questo hai bisogno.
se non usi il pin non ti serve inserirla.
Logged

italy
Offline Offline
Jr. Member
**
Karma: 0
Posts: 54
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

ok
ma in pratica a cosa serve il pin INT.
Logged

Pages: [1] 2   Go Up
Jump to: