pca9555 io port expander hoe 1 enkel uitgang te wijzigen zonder andere te wijzig

Hallo allemaal,

ik ben al een tijdje aan het stoeien met een pca9555 16 poort io uitbreiding.

ik zou graag de uitgangen individueel willen aansturen.
tot nu toe heb ik alleen maar voorbeelden gevonden die alle uitgangen elke keer geheel sturen.
dus als er 1 uitgang wijzigt moeten ook de al ingeschakelde uitgangen ook meegestuurd worden.

heeft iemand een idee/voorbeeld om dit wel te kunnen doen, net als bij de adruino zelf.

mvg adriaan

Als je de uitgangen individueel wil aansturen zul je eigen functies moeten maken. De meest eenvoudige manier is bijvoorbeeld in het geheugen een byte reserveren voor elke port. En als je dan een pin wilt wijzigen dan die port ANDen of ORen met het juiste bit en dan de hele byte wegschrijven. Bij de Arduino gebeurt er ook iets vergelijkbaars. Vandaar dat de IO van de Arduino verschikkelijk traag is en ze niet voor niets met FastIO libraries zijn gekomen.

zie pagina 7 van de datasheet: http://www.nxp.com/documents/data_sheet/PCA9555.pdf

@edit
Of je maakt zelf een class PCA9555 die de functies pinMode(), digitalread(), digitalWrite() en indien nodig Init() ondersteund en je kan er gewoon een zooi aan elkaar knopen enz.
Die byte met de waarde van elke pin kun je dan opslaan in de class zelf.

Het is niet noodzakelijk om in het arduino geheugen plaats te reserveren voor de actuele toestand van een output. De actuele status van alle outputs kan gelezen worden in de "Registers 2 and 3: Output port registers" zoals beschreven in de datasheet op pagina 7.

Het nadeel van de van output pins status bijhouden in het arduino geheugen is namelijk dat na een reset alle pin_status toestanden verloren gaan. Terwijl de werkelijke output status van de pins na een arduino reset niet verandert. Dit kan tot hardware conflikten leiden.

In een routine is het vrij simpel om de aktuele status van alle output pins te lezen en dan dit te combineren met de gewenste toestand van een enkele output pin.

Ik had mijn twijfels over die zin. Dat het alleen de flip-flop waarde was en niet de feitelijke pin waarde. Dat maakte het allemaal wat vaag. Maar dat kan de TS mooi uittesten. Die heeft zo'n ding.

ja carfreak je zult altijd een hele byte moeten sturen.

er is verschil tussen de inputregister die kijkt naar het voltage van de inputpin als je het register leest, ongeacht of de pin een In of Out is.
dat betekent dat als de pin extern naar beneden wordt getrokken de ingang ook LOW zal zijn.

De out register gaat niet verder als de flipflop dus niet de actuele situatie, maar de situatie waar jij de pin in wil hebben.
de pinnen worden bediend aan het einde van het zenden van een byte.

nicoverduin:
Ik had mijn twijfels over die zin. Dat het alleen de flip-flop waarde was en niet de feitelijke pin waarde. Dat maakte het allemaal wat vaag. Maar dat kan de TS mooi uittesten. Die heeft zo'n ding.

Het is inderdaad 'typisch datasheet' vaag maar ik kan het niet anders interpreteren dan dat je in de praktijk de outputwaarde leest.
Tenzij de uitgang defect is. Het output-port-register kan dat niet 'meten' en zegt doodleuk wat er in de flipflop staat terwijl de uitgang een hoge of lage spanning kan afgeven ofwel dat die hoogohmig is geworden.

Maar misschien heeft T.S. daar een heel andere mening over.

het idee met de class spreekt me wel aan, alleen heb ik dit nog nooit gedaan.

ik ga me daar eens in verdiepen.

Alle voorbeelden zijn natuurlijk welkom.

ook het idee "In een routine is het vrij simpel om de aktuele status van alle output pins te lezen en dan dit te combineren met de gewenste toestand van een enkele output pin."

spreekt me ook wel aan, ook hierin geen ervaring.

mvg Adriaan

Gewoon omdat ik toch niets anders te doen had, heb ik de class bijna klaar. En daar ik echter niet zo'n ding heb, moet jij maar testen :slight_smile:
code tot nu toe:

include file clsPCA9555.h

/*
 * clsPCA9555.h
 *
 *  Created on: 27 jul. 2015
 *      Author: Nico
 */

#ifndef CLSPCA9555_H_
#define CLSPCA9555_H_

#include "Arduino.h"

/** enum with names of ports ED0 - ED15 */
enum {
    ED0, ED1, ED2 , ED3 , ED4 , ED5 , ED6 , ED7 ,
    ED8, ED9, ED10, ED11, ED12, ED13, ED14, ED15
};

class PCA9555 {
public:
    PCA9555(uint8_t port);                                // constructor
    void pinMode(uint8_t pin, uint8_t IOMode );        // pinMode
    uint8_t digitalRead(uint8_t pin);                    // digitalRead
    void digitalWrite(uint8_t pin, uint8_t value );    // digitalWrite

private:
    union {
        struct {
            uint8_t _configurationRegister_low;            // low order byte
            uint8_t _configurationRegister_high;        // high order byte
        };
        uint16_t _configurationRegister;                // 16 bits presentation
    };
    union {
        struct {
            uint8_t _valueRegister_low;                    // low order byte
            uint8_t _valueRegister_high;                // high order byte
        };
        uint16_t _valueRegister;
    };
    uint8_t _port;                                        // address of port this class is supporting
};


#endif /* CLSPCA9555_H_ */

clsPCA9555.cpp

/**
 * @file    clsPCA9555.cpp
 * @author     Nico Verduin
 * @date      dd-mm-yyyy
 *
 * @mainpage  clsPCA9555
 * Class to enable pinMode(), digitalRead() and digitalWrite() functions on IO expanders
 *
 *
 * @par Version Control
 * | Revision     | Author         | Date         |
 * | :-------     | :-----         | :----        |
 * | $Revision$ | $Author$         | $Date$     |
 *
 *
 * @par License info
 *
 * <one line to give the program's name and a brief idea of what it does.>
 *
 * Copyright (C) 2015  Nico Verduin
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Program : clsPCA9555  Copyright (C) 2015  Nico Verduin
 * This is free software, and you are welcome to redistribute it.
 *
 */

#include "Arduino.h"
#include "clsPCA9555.h"
#include "Wire.h"


/**
 * @name PCA9555 constructor
 * @param port I2C address of the IO port
 * Creates the class interface and sets the I2C Address of the port
 */
PCA9555::PCA9555(uint8_t port) {
    _port = port;            // save the port id
    Wire.begin();            // start I2C communication
}

/**
 * @name pinMode
 * @param pin        pin number
 * @param IOMode    mode of pin INPUT or OUTPUT
 * sets the mode of this IO pin
 */
void PCA9555::pinMode(uint8_t pin, uint8_t IOMode) {
    //
    // first determine the correct bit to set
    //
    uint16_t x = 1;                // set lowest bit
    x = x << pin;                // shift to the correct bit.
    //
    // now set the correct bit in the configuration register
    //
    if (IOMode == OUTPUT) {
        //
        // mask correct bit to 0 by inverting x so that only
        // the correct bit is LOW. The rest stays HIGH
        //
        x = ~x;
        _configurationRegister = _configurationRegister && x;
    } else {
        //
        // or just the required bit to 1
        //
        _configurationRegister = _configurationRegister || x;
    }
    //
    // write configuration register to chip
    //
    Wire.beginTransmission(_port);              // setup direction registers
    Wire.write(0x06);                              // pointer to DDR port 0
    Wire.write(_configurationRegister_low);      // DDR Port0
    Wire.write(_configurationRegister_high);      // DDR Port1
    Wire.endTransmission();
}
/**
 * @name digitalRead Reads the high/low value of specified pin
 * @param pin
 * @return value of pin
 */
uint8_t PCA9555::digitalRead(uint8_t pin) {
    //
    // first determine the correct bit to read
    //
    uint16_t x = 1;                // set lowest bit
    x = x << pin;                // shift to the correct bit.
    //
    // read the port input register
    //
    Wire.beginTransmission(_port);              // setup read registers
    Wire.requestFrom(0x00, 2);                  // pointer to input register port 0
    _valueRegister_low     = Wire.read();          // Input register 0
    _valueRegister_high = Wire.read();          // Input register 1
    Wire.endTransmission();
    //
    // now mask the bit required and see if it is a HIGH
    //
    if ((_valueRegister & x) > 0){
        //
        // the bit is HIGH otherwise we would hava a zero value
        //
        return HIGH;
    } else {
        return LOW;
    }
}

void PCA9555::digitalWrite(uint8_t pin, uint8_t value) {
    uint16_t valueToSend;
    uint16_t x;
    //
    // next convert the value we want to set to HIGH or LOW
    //
    if (value > 0){
        valueToSend = HIGH;
    } else {
        valueToSend = LOW;
    }
    //
    // now read the output register first.
    //
    Wire.beginTransmission(_port);              // setup read registers
    Wire.requestFrom(0x02, 2);                  // pointer to input register port 0
    _valueRegister_low     = Wire.read();          // Input register 0
    _valueRegister_high = Wire.read();          // Input register 1
    Wire.endTransmission();
    //
    // next set the bit we want to set
    // if the value is LOW we will and the register value with correct bit set to zero
    // if the value is HIGH we will or the register value with correct bit set to HIGH
    //
    if (valueToSend) {
        //
        // this is a High value so we will or it with the value register
        //
        x = valueToSend;                        // set the bit to set
        x = x << pin;                            // shift to correct position
        _valueRegister = _valueRegister | x;    // and OR bit in register
    } else {
        //
        // this is a LOW value so we have to AND it with 0 into the _valueRegister
        //
        x = 1;                                    // set bit on lowest bit position
        x = x << pin;                            // shift to correct position
        x = ~x;                                    // invert x. Now bit position is 0 and the rest is 1
        _valueRegister = _valueRegister & x;    // now AND all bits with corresponding in x
    }
    //
    // write output register to chip
    //
    Wire.beginTransmission(_port);              // setup direction registers
    Wire.write(0x06);                              // pointer to DDR port 0
    Wire.write(_configurationRegister_low);      // DDR Port0
    Wire.write(_configurationRegister_high);      // DDR Port1
    Wire.endTransmission();
}

Dus nog ff geduld.

En een test programmatje

/**
 * @file    testclass.ino
 * @author     Nico Verduin
 * @date      dd-mm-yyyy
 *
 * @mainpage testclass
 * <Put your main text description here>
 *
 *
 * @par Version Control
 * | Revision     | Author         | Date         |
 * | :-------     | :-----         | :----        |
 * | $Revision$ | $Author$         | $Date$     |
 *
 *
 * @par License info
 *
 * <one line to give the program's name and a brief idea of what it does.>
 *
 * Copyright (C) 2015  Nico Verduin
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Program : testclass  Copyright (C) 2015  Nico Verduin
 * This is free software, and you are welcome to redistribute it.
 *
 */

//
// Pin definitions
//

//
// global defines & parameters
//

//
// global variables
//

#include "clsPCA9555.h"                // IO Expander class

PCA9555 ioport0(0x21);                // one port on address 0x21
PCA9555 ioport1(0x22);                // and another on address 0x22
/**
 * @name setup()
 * initialize the program
 */
void setup()
{
    pinMode(3, OUTPUT);                // normal digital IO
    //
    // set all expander ports to output
    //
    for (uint8_t i = 0; i < 16; i++){
        ioport0.pinMode(i, OUTPUT);    // expander port
    }
}

/**
 * @name loop()
 * main loop of program and runs endlessly
 */
void loop()
{
    //
    // turn all leds in sequence on
    //
    for (uint8_t i = 0; i < 16; i++) {
        ioport0.digitalWrite(i, HIGH);
        delay(500);
    }
    //
    // turn all leds in sequence on
    //
    for (uint8_t i = 0; i < 16; i++) {
        ioport0.digitalWrite(i, LOW);
        delay(500);
    }

}

Hallo Nico,

ik heb jou voorzetje even geprobeerd.

bij het compilen heb ik ik ieder geval geen fouten, ook het uploaden naar de arduino uno geeft geen problemen.

als het programma start in de arduino gekoppeld met de pca9555 ( en een zooi leds op de uitgangen ) dan gaan na een aantal seconden alle uitgangen aan op de pca9555.

om wat te kunnen debuggen heb ik een zooi Serial.println opdrachten erin gezet om te kijken waar hij p dat moment in het programma is.

het lijkt erop dat er iets mis gaat in de configuratie bits.
hieronder de verschillende delen van de class en het programma met de debug lines voor serial output.
Ik heb vanavond meer tijd om nog meer te debuggen.

Dan heb je in ieder geval even een status update. ( gaat de goede kant op )

/*
 * clsPCA9555.h
 *
 *  Created on: 27 jul. 2015
 *      Author: Nico
 */

#ifndef CLSPCA9555_H_
#define CLSPCA9555_H_

#include "Arduino.h"

/** enum with names of ports ED0 - ED15 */
enum {
    ED0, ED1, ED2 , ED3 , ED4 , ED5 , ED6 , ED7 ,
    ED8, ED9, ED10, ED11, ED12, ED13, ED14, ED15
};

class PCA9555 {
public:
    PCA9555(uint8_t port);                                // constructor
    void pinMode(uint8_t pin, uint8_t IOMode );        // pinMode
    uint8_t digitalRead(uint8_t pin);                    // digitalRead
    void digitalWrite(uint8_t pin, uint8_t value );    // digitalWrite

private:
    union {
        struct {
            uint8_t _configurationRegister_low;            // low order byte
            uint8_t _configurationRegister_high;        // high order byte
        };
        uint16_t _configurationRegister;                // 16 bits presentation
    };
    union {
        struct {
            uint8_t _valueRegister_low;                    // low order byte
            uint8_t _valueRegister_high;                // high order byte
        };
        uint16_t _valueRegister;
    };
    uint8_t _port;                                        // address of port this class is supporting
};


#endif /* CLSPCA9555_H_ */
/**
 * @file    clsPCA9555.cpp
 * @author     Nico Verduin
 * @date      dd-mm-yyyy
 *
 * @mainpage  clsPCA9555
 * Class to enable pinMode(), digitalRead() and digitalWrite() functions on IO expanders
 *
 *
 * @par Version Control
 * | Revision     | Author         | Date         |
 * | :-------     | :-----         | :----        |
 * | $Revision$ | $Author$         | $Date$     |
 *
 *
 * @par License info
 *
 * <one line to give the program's name and a brief idea of what it does.>
 *
 * Copyright (C) 2015  Nico Verduin
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Program : clsPCA9555  Copyright (C) 2015  Nico Verduin
 * This is free software, and you are welcome to redistribute it.
 *
 */

#include "Arduino.h"
#include "clsPCA9555.h"
#include "Wire.h"


/**
 * @name PCA9555 constructor
 * @param port I2C address of the IO port
 * Creates the class interface and sets the I2C Address of the port
 */
PCA9555::PCA9555(uint8_t port) {
    _port = port;            // save the port id
 Serial.println("ccp port adres overzetten in variabele ");
 Serial.print("ccp adres is ");
 Serial.println(_port);
    Wire.begin();            // start I2C communication
 Serial.println("ccp Start I2c Communicatie");
}

/**
 * @name pinMode
 * @param pin        pin number
 * @param IOMode    mode of pin INPUT or OUTPUT
 * sets the mode of this IO pin
 */
void PCA9555::pinMode(uint8_t pin, uint8_t IOMode) {
    //
    // first determine the correct bit to set
    //
 Serial.print("ccp Pin-number ");
 Serial.println(pin);
    uint16_t x = 1;                // set lowest bit
    x = x << pin;                // shift to the correct bit.
    //
    // now set the correct bit in the configuration register
    //
    if (IOMode == OUTPUT) {
        //
        // mask correct bit to 0 by inverting x so that only
        // the correct bit is LOW. The rest stays HIGH
        //
 Serial.println("ccp in if statement io-mode = output");
 Serial.print("ccp waarde x ");
 Serial.println(x,BIN);
        x = ~x;
        _configurationRegister = _configurationRegister && x;
    } else {
        //
        // or just the required bit to 1
        //
        _configurationRegister = _configurationRegister || x;
    }
    //
    // write configuration register to chip
    //
 Serial.println("begin wire transmission");
 Serial.println(_port,HEX);
    Wire.beginTransmission(_port);              // setup direction registers
    Wire.write(0x06);                              // pointer to DDR port 0
    // Wire.write(_configurationRegister_low);      // DDR Port0
    // Wire.write(_configurationRegister_high);      // DDR Port1
    Wire.write(0x00);      // DDR Port0
    Wire.write(0x00);      // DDR Port1

    Wire.endTransmission();
}
/**
 * @name digitalRead Reads the high/low value of specified pin
 * @param pin
 * @return value of pin
 */
uint8_t PCA9555::digitalRead(uint8_t pin) {
    //
    // first determine the correct bit to read
    //
    uint16_t x = 1;                // set lowest bit
    x = x << pin;                // shift to the correct bit.
    //
    // read the port input register
    //
    Wire.beginTransmission(_port);              // setup read registers
    Wire.requestFrom(0x00, 2);                  // pointer to input register port 0
    _valueRegister_low     = Wire.read();          // Input register 0
    _valueRegister_high = Wire.read();          // Input register 1
    Wire.endTransmission();
    //
    // now mask the bit required and see if it is a HIGH
    //
    if ((_valueRegister & x) > 0){
        //
        // the bit is HIGH otherwise we would hava a zero value
        //
        return HIGH;
    } else {
        return LOW;
    }
}

void PCA9555::digitalWrite(uint8_t pin, uint8_t value) {
    uint16_t valueToSend;
    uint16_t x;
    //
    // next convert the value we want to set to HIGH or LOW
    //
    if (value > 0){
        valueToSend = HIGH;
    } else {
        valueToSend = LOW;
    }
    //
    // now read the output register first.
    //
    Wire.beginTransmission(_port);              // setup read registers
    Wire.requestFrom(0x02, 2);                  // pointer to input register port 0
    _valueRegister_low     = Wire.read();          // Input register 0
    _valueRegister_high = Wire.read();          // Input register 1
    Wire.endTransmission();
    //
    // next set the bit we want to set
    // if the value is LOW we will and the register value with correct bit set to zero
    // if the value is HIGH we will or the register value with correct bit set to HIGH
    //
    if (valueToSend) {
        //
        // this is a High value so we will or it with the value register
        //
        x = valueToSend;                        // set the bit to set
        x = x << pin;                            // shift to correct position
        _valueRegister = _valueRegister | x;    // and OR bit in register
    } else {
        //
        // this is a LOW value so we have to AND it with 0 into the _valueRegister
        //
        x = 1;                                    // set bit on lowest bit position
        x = x << pin;                            // shift to correct position
        x = ~x;                                    // invert x. Now bit position is 0 and the rest is 1
        _valueRegister = _valueRegister & x;    // now AND all bits with corresponding in x
    }
    //
    // write output register to chip
    //
    Wire.beginTransmission(_port);              // setup direction registers
    Wire.write(0x06);                              // pointer to DDR port 0
    Wire.write(_configurationRegister_low);      // DDR Port0
    Wire.write(_configurationRegister_high);      // DDR Port1
    Wire.endTransmission();
}

de rest hier want de post was langer dan 9000 karakters

/**
 * @file    testclass.ino
 * @author     Nico Verduin
 * @date      dd-mm-yyyy
 *
 * @mainpage testclass
 * <Put your main text description here>
 *
 *
 * @par Version Control
 * | Revision     | Author         | Date         |
 * | :-------     | :-----         | :----        |
 * | $Revision$ | $Author$         | $Date$     |
 *
 *
 * @par License info
 *
 * <one line to give the program's name and a brief idea of what it does.>
 *
 * Copyright (C) 2015  Nico Verduin
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Program : testclass  Copyright (C) 2015  Nico Verduin
 * This is free software, and you are welcome to redistribute it.
 *
 */

//
// Pin definitions
//

//
// global defines & parameters
//

//
// global variables
//

#include "clsPCA9555.h"                // IO Expander class
#include "Wire.h"

PCA9555 ioport0(0x20);                // one port on address 0x21
/** PCA9555 ioport1(0x22);                // and another on address 0x22
/**
 * @name setup()
 * initialize the program
 */
void setup()
{
    Serial.begin(9600);
    Serial.println("setup serial port");
    pinMode(3, OUTPUT);                // normal digital IO
    Serial.println("pin 3 mode op output gezet");
    //
    // set all expander ports to output
    //
    for (uint8_t i = 0; i < 16; i++){
        Serial.println("in for loop instellen expander port mode op output");
        Serial.println(i);
        ioport0.pinMode(i, OUTPUT);    // expander port
    }
}

/**
 * @name loop()
 * main loop of program and runs endlessly
 */
void loop()
{
  Serial.println("start van Loop");
    //
    // turn all leds in sequence on
    //
    for (uint8_t i = 0; i < 16; i++) {
        ioport0.digitalWrite(i, HIGH);
        Serial.println(i);
        delay(500);
    }
    //
    // turn all leds in sequence on
    //
    for (uint8_t i = 0; i < 16; i++) {
        ioport0.digitalWrite(i, LOW);
        delay(500);
        Serial.println(i);
    }

}

in de Serial.println lijnen waar ik "cpp" voorgezet heb zit het programma in de CPP file

Serial output ( Debug log )

setup serial port
pin 3 mode op output gezet
in for loop instellen expander port mode op output
0
ccp Pin-number 0
ccp in if statement io-mode = output
ccp waarde x 1
begin wire transmission
20
in for loop instellen expander port mode op output
1
ccp Pin-number 1
ccp in if statement io-mode = output
ccp waarde x 10
begin wire transmission
20
in for loop instellen expander port mode op output
2
ccp Pin-number 2
ccp in if statement io-mode = output
ccp waarde x 100
begin wire transmission
20
in for loop instellen expander port mode op output
3
ccp Pin-number 3
ccp in if statement io-mode = output
ccp waarde x 1000
begin wire transmission
20
in for loop instellen expander port mode op output
4
ccp Pin-number 4
ccp in if statement io-mode = output
ccp waarde x 10000
begin wire transmission
20
in for loop instellen expander port mode op output
5
ccp Pin-number 5
ccp in if statement io-mode = output
ccp waarde x 100000
begin wire transmission
20
in for loop instellen expander port mode op output
6
ccp Pin-number 6
ccp in if statement io-mode = output
ccp waarde x 1000000
begin wire transmission
20
in for loop instellen expander port mode op output
7
ccp Pin-number 7
ccp in if statement io-mode = output
ccp waarde x 10000000
begin wire transmission
20
in for loop instellen expander port mode op output
8
ccp Pin-number 8
ccp in if statement io-mode = output
ccp waarde x 100000000
begin wire transmission
20
in for loop instellen expander port mode op output
9
ccp Pin-number 9
ccp in if statement io-mode = output
ccp waarde x 1000000000
begin wire transmission
20
in for loop instellen expander port mode op output
10
ccp Pin-number 10
ccp in if statement io-mode = output
ccp waarde x 10000000000
begin wire transmission
20
in for loop instellen expander port mode op output
11
ccp Pin-number 11
ccp in if statement io-mode = output
ccp waarde x 100000000000
begin wire transmission
20
in for loop instellen expander port mode op output
12
ccp Pin-number 12
ccp in if statement io-mode = output
ccp waarde x 1000000000000
begin wire transmission
20
in for loop instellen expander port mode op output
13
ccp Pin-number 13
ccp in if statement io-mode = output
ccp waarde x 10000000000000
begin wire transmission
20
in for loop instellen expander port mode op output
14
ccp Pin-number 14
ccp in if statement io-mode = output
ccp waarde x 100000000000000
begin wire transmission
20
in for loop instellen expander port mode op output
15
ccp Pin-number 15
ccp in if statement io-mode = output
ccp waarde x 1000000000000000
begin wire transmission
20
start van Loop
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
start van Loop
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
start van Loop

Oh je gaat al sneller dan ik :). Ik kwam sowieso later nog wat fouten tegen. o.a. bij het schrijven van I2C. Dat moet ik splitsen in 2 aparte writes. Maar mooi dat je al bent gaan testen :slight_smile:

@edit: Ik heb hier nog een bordje met een PCF8574 liggen. die kan ik ook wel gebruiken om te testen. Hooguit andere opdrachten en registers.

pcf8574 class - Arduino/libraries/PCF8574 at master · RobTillaart/Arduino · GitHub

Hi Rob
Thanks. Ik had die inmiddels al gevonden.
Grtz
Nico

Na veel ideën van de class van Rob :). Zou jij dit eens willen testen?

/**
 * @file    clsPCA9555.cpp
 * @author     Nico Verduin
 * @date      dd-mm-yyyy
 *
 * @mainpage  clsPCA9555
 * Class to enable pinMode(), digitalRead() and digitalWrite() functions on IO expanders
 *
 *
 * @par Version Control
 * | Revision     | Author         | Date         |
 * | :-------     | :-----         | :----        |
 * | $Revision$ | $Author$         | $Date$     |
 *
 *
 * @par License info
 *
 * <one line to give the program's name and a brief idea of what it does.>
 *
 * Copyright (C) 2015  Nico Verduin
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Program : clsPCA9555  Copyright (C) 2015  Nico Verduin
 * This is free software, and you are welcome to redistribute it.
 *
 */

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#include "clsPCA9555.h"
#include "Wire.h"


/**
 * @name PCA9555 constructor
 * @param address I2C address of the IO Expander
 * Creates the class interface and sets the I2C Address of the port
 */
PCA9555::PCA9555(uint8_t address) {
    _address = address;        // save the address id
    Wire.begin();            // start I2C communication
}

/**
 * @name pinMode
 * @param pin        pin number
 * @param IOMode    mode of pin INPUT or OUTPUT
 * sets the mode of this IO pin
 */
void PCA9555::pinMode(uint8_t pin, uint8_t IOMode) {
    //
    // check valid pin first
    //
    if (pin <= 15) {
        //
        // now set the correct bit in the configuration register
        //
        if (IOMode == OUTPUT) {
            //
            // mask correct bit to 0 by inverting x so that only
            // the correct bit is LOW. The rest stays HIGH
            //
;
            _configurationRegister = _configurationRegister && ~(1 << pin);
        } else {
            //
            // or just the required bit to 1
            //
            _configurationRegister = _configurationRegister || (1 << pin);
        }
        //
        // write configuration register to chip
        //
        Wire.beginTransmission(_address);              // setup direction register
        Wire.write(0x06);                              // Port A
        Wire.write(_configurationRegister_low);
        _error = Wire.endTransmission();

#ifdef DEBUG
Serial.print("pinMode : Configure Port A _error = ");
Serial.println(_error);
#endif
        Wire.beginTransmission(_address);              // setup direction register
        Wire.write(0x07);                              // port B
        Wire.write(_configurationRegister_high);
        _error = Wire.endTransmission();

#ifdef DEBUG
Serial.print("pinMode : Configure Port B _error = ");
Serial.println(_error);
#endif
    }
}
/**
 * @name digitalRead Reads the high/low value of specified pin
 * @param pin
 * @return value of pin
 */
uint8_t PCA9555::digitalRead(uint8_t pin) {
    //
    // we wil only process pins <= 15
    //
    if (pin <= 15) {
        //
        // read the address input register
        //
        Wire.beginTransmission(_address);              // setup read registers
        Wire.requestFrom(NXP_INPUT, 2);              // pointer to input register address 0
        _error = Wire.endTransmission();

#ifdef DEBUG
Serial.print("digitalRead : Read Input register error code = ");
Serial.println(_error);
#endif

        //
        // wait for data
        //
        while (Wire.available() != 2 ) {};
        //
        // read data
        //
        _valueRegister_low     = Wire.read();          // Input register 0
        _valueRegister_high = Wire.read();          // Input register 1

#ifdef DEBUG
Serial.print("digitalRead : value of INPUT register reads = ");
Serial.println(_valueRegister, BIN);
#endif

        //
        // now mask the bit required and see if it is a HIGH
        //
        if ((_valueRegister & (1 << pin)) > 0){
            //
            // the bit is HIGH otherwise we would hava a zero value
            //
            return HIGH;
        } else {
            return LOW;
        }
    } else {
        //
        // invalid pin
        //
        return 255;
    }
}

void PCA9555::digitalWrite(uint8_t pin, uint8_t value) {
    uint16_t valueToSend;
    //
    // check valid pin first
    //
    if (pin <= 15) {
        //
        // next convert the value we want to set to HIGH or LOW
        //
        if (value > 0){
            valueToSend = HIGH;
        } else {
            valueToSend = LOW;
        }
        //
        // now read the output register first.
        //
        Wire.beginTransmission(_address);              // setup read registers
        Wire.requestFrom(NXP_OUTPUT, 2);              // pointer to input register address 0
        _error = Wire.endTransmission();

#ifdef DEBUG
Serial.print("digitalWrite : Read OUTPUT register Error code = ");
Serial.println(_error);
#endif

        //
        // wait for data
        //
        while (Wire.available() != 2 ) {};
        //
        // and read the actual data
        //
        _valueRegister_low     = Wire.read();          // Output register 0
        _valueRegister_high = Wire.read();          // Output register 1


#ifdef DEBUG
Serial.print("digitalRead : value of OUTPUT register reads = ");
Serial.println(_valueRegister, BIN);
#endif

        //
        // next set the bit we want to set
        // if the value is LOW we will and the register value with correct bit set to zero
        // if the value is HIGH we will or the register value with correct bit set to HIGH
        //
        if (valueToSend) {
            //
            // this is a High value so we will or it with the value register
            //
            _valueRegister = _valueRegister | (valueToSend << pin);    // and OR bit in register
        } else {
            //
            // this is a LOW value so we have to AND it with 0 into the _valueRegister
            //
            _valueRegister = _valueRegister & ~(valueToSend << pin);    // AND all bits
        }
        //
        // write output register to chip
        //
        Wire.beginTransmission(_address);              // setup direction registers
        Wire.write(0x06);                              // pointer to DDR address 0
        Wire.write(_configurationRegister_low);      // DDR Port0
        _error = Wire.endTransmission();

#ifdef DEBUG
Serial.print("digitalWrite : Write Output register 0 error code = ");
Serial.println(_error);
#endif

        Wire.beginTransmission(_address);              // setup direction registers
        Wire.write(0x07);                              // pointer to DDR address 0
        Wire.write(_configurationRegister_high);      // DDR Port1
        _error = Wire.endTransmission();

#ifdef DEBUG
Serial.print("digitalWrite : Write Output register 1 error code = ");
Serial.println(_error);
#endif

    }
}

[/code]

en de .h file

/*
 * clsPCA9555.h
 *
 *  Created on: 27 jul. 2015
 *      Author: Nico
 */

#ifndef CLSPCA9555_H_
#define CLSPCA9555_H_

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif

#define DEBUG 1

/** enum with names of ports ED0 - ED15 */
enum {
    ED0, ED1, ED2 , ED3 , ED4 , ED5 , ED6 , ED7 ,
    ED8, ED9, ED10, ED11, ED12, ED13, ED14, ED15
};

//
// PCA9555 defines
//
#define NXP_INPUT      (0)  // For NXP9555
#define NXP_OUTPUT     (2)  // See data sheet
#define NXP_INVERT     (4)  // for details...
#define NXP_CONFIG     (6)

class PCA9555 {
public:
    PCA9555(uint8_t address);                            // constructor
    void pinMode(uint8_t pin, uint8_t IOMode );            // pinMode
    uint8_t digitalRead(uint8_t pin);                    // digitalRead
    void digitalWrite(uint8_t pin, uint8_t value );        // digitalWrite

private:
    union {
        struct {
            uint8_t _configurationRegister_low;            // low order byte
            uint8_t _configurationRegister_high;        // high order byte
        };
        uint16_t _configurationRegister;                // 16 bits presentation
    };
    union {
        struct {
            uint8_t _valueRegister_low;                    // low order byte
            uint8_t _valueRegister_high;                // high order byte
        };
        uint16_t _valueRegister;
    };
    uint8_t _address;                                    // address of port this class is supporting
    int _error;                                            // error code from I2C
};


#endif /* CLSPCA9555_H_ */

Hallo Nico,

ik denk dat ik nog iets mis, je hebt wat wijzigingen gedaan in de variabelenamen port naar address.
compille gaat nu niet goed.

ik neem aan dat de .h ook is gewijzigd en ook de .ino

Met vriendelijke groeten

Adriaan Bodewits

oeps, 2de pagina gemist.

gr Adriaan

Hoi Nico,

ben even weer aan het debuggen geslagen.

compile gaat nu goed.

programma blijft steken op onderstaande loop
als ik de != 2 weghaal begint het programma weer te lopen, alleen gebeurt er op de uitgangen niets. ( alles is aan, of als je alles omgekeerd aansluit is alles natuurlijk uit.
)

#ifdef DEBUG
Serial.print("digitalWrite : Read OUTPUT register Error code = ");
Serial.println(_error);
#endif

        //
        // wait for data
        //
        while (Wire.available() != 2 ) {};
		#ifdef DEBUG
			Serial.print("in while wire.available loop");
		#endif
        //
        // and read the actual data
        //
        _valueRegister_low  = Wire.read();          // Output register 0
        _valueRegister_high = Wire.read();          // Output register 1

debuglog

setup serial port
pin 3 mode op output gezet
in for loop instellen expander port mode op output
0
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
1
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
2
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
3
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
4
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
5
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
6
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
7
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
8
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
9
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
10
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
11
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
12
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
13
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
14
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
in for loop instellen expander port mode op output
15
pinMode : Configure Port A _error = 0
pinMode : Configure Port B _error = 0
start van Main Loop
in for loop turn all leds in sequence on nummer address.digitalwrite = 0 HIGH
Wire.beginTransmission  : address = 32
Wire.requestFrom NXP_OUTPUT,2 error = 0
digitalWrite : Read OUTPUT register Error code = 0
in while wire.available loopdigitalRead : value of OUTPUT register reads = 1111111111111111
digitalWrite : Write Output register 0 error code = 0
digitalWrite : Write Output register 1 error code = 0
in for loop turn all leds in sequence on nummer address.digitalwrite = 1 HIGH
Wire.beginTransmission  : address = 32
Wire.requestFrom NXP_OUTPUT,2 error = 0
digitalWrite : Read OUTPUT register Error code = 0
in while wire.available loopdigitalRead : value of OUTPUT register reads = 1111111111111111
digitalWrite : Write Output register 0 error code = 0
digitalWrite : Write Output register 1 error code = 0
in for loop turn all leds in sequence on nummer address.digitalwrite = 2 HIGH
Wire.beginTransmission  : address = 32
Wire.requestFrom NXP_OUTPUT,2 error = 0
digitalWrite : Read OUTPUT register Error code = 0
in while wire.available loopdigitalRead : value of OUTPUT register reads = 1111111111111111
digitalWrite : Write Output register 0 error code = 0
digitalWrite : Write Output register 1 error code = 0
in for loop turn all leds in sequence on nummer address.digitalwrite = 3 HIGH
Wire.beginTransmission  : address = 32
Wire.requestFrom NXP_OUTPUT,2 error = 0
digitalWrite : Read OUTPUT register Error code = 0
in while wire.available loopdigitalRead : value of OUTPUT register reads = 1111111111111111
digitalWrite : Write Output register 0 error code = 0
digitalWrite : Write Output register 1 error code = 0
in for loop turn all leds in sequence on nummer address.digitalwrite = 4 HIGH
Wire.beginTransmission  : address = 32
Wire.requestFrom NXP_OUTPUT,2 error = 0
digitalWrite : Read OUTPUT register Error code = 0
in while wire.available loopdigitalRead : value of OUTPUT register reads = 1111111111111111

Is het address wel goed van die IO Expander? Ik had er zomaar iets in gezet.

@edit:
Kwam nog een fout in pinmode tegen. Daar staan 2 x && en 2 x || achter elkaar. Dat moeten er uiteraard 1 van elk zijn. Dus 1 x & en verderop 1 x |