[Tronixstuff] MCP23017 | I2C Port | Help wanted

Hello, I've trying to test my I2c expander chip (mcp23017) I came across this Tutorial: Maximising your Arduino’s I/O ports with MCP23017 | tronixstuff.com tutorial. Now I've wired up the expander as described in the article with the of the 4.7k resistors on the Ic2 line, I'm using 10K resistors and on the i/o pin I'm using 330ohm resistors as opposed to the 560 ohm used in the blog post. However I get on result from the LEDs, meaning nothing lights up. After reading the article over and over I found this "Please note that the tutorials are not currently compatible with Arduino IDE v1.0. Please continue to use v22 or v23 until further notice. " I tryed to use v22 and v23 of the IDE but that just lead to problem in the compiler. So my question is what can I do to make this code compatible with V1.0 of the Ardunio IDE? What am I doing wrong? I'm trying to turn 16 LEDs on/off in sequence a.k.a knight rider scanner.
Here's the code:

/*
 Example 41.1 - Microchip MCP23017 with Arduino
 http://tronixstuff.wordpress.com/tutorials > chapter 41
 John Boxall | CC by-sa-nc
*/

// pins 15~17 to GND, I2C bus address is 0x20

#include "Wire.h"

void setup()
{
  Wire.begin(); // wake up I2C bus

  // setup addressing style
  Wire.beginTransmission(0x20);
  Wire.send(0x12);
  Wire.send(0x20); // use table 1.4 addressing
  Wire.endTransmission();

  // set I/O pins to outputs
  Wire.beginTransmission(0x20);
  Wire.send(0x00); // IODIRA register
  Wire.send(0x00); // set all of bank A to outputs
  Wire.send(0x00); // set all of bank B to outputs
  Wire.endTransmission();
}

void binaryCount()
{
  for (byte a=0; a<256; a++)
  {
    Wire.beginTransmission(0x20);
    Wire.send(0x12); // GPIOA
    Wire.send(a);    // bank A
    Wire.send(a);    // bank B
    Wire.endTransmission();
    delay(100);
  }
}

void loop()
{
  binaryCount();
  delay(500);
}

Any ideas?

Read the release notes:

  • The Wire library has also been modified to use the standard read() and
    write() functions instead of send() and receive(). You can also use
    print() and println() for outgoing data.

A little code tweaking is needed.

I've written a library for the Centipede Shield, which uses four MCP23017. However, it'll work just fine for plain MCP23017 chips, as long as you have them wired and addressed correctly. I've made it compatible with both Arduino 1.0 and the older versions.

http://docs.macetech.com/doku.php/centipede_shield

Please post a drawing or photo of your wiring, to make sure there aren't any mistakes there too.

Centipede didn't work for me. What am i doing wrong?
My wiring

the twisted pair (white and orange) are the SDA and SCL lines. First I had SDA pin 13 going to arduino pin 5 and SCL pin 12 going to arduino pin 4. Then I placed a 10K resistor in the middle of each of those wires and connected them to +5V along with pin 18. The resistors on the mcp23017's i/o and LED are 330ohm. I'm note sure if that's right but that what I could gleam from this schematic.


found here : Tutorial: Maximising your Arduino’s I/O ports with MCP23017 | tronixstuff.com

Have you tested to make sure the MCP23017 is getting any power? Those breadboard rails are often split in the middle, where the slightly wider gap is.

I'm now using 4.7kohm resistors on SCL AND SDA. Updated my wiring but still nothing, even with the centipede sheild sketch and libraray.
Here's my updated wiring. I hope it's clear enough

  • The Wire library has also been modified to use the standard read() and
    write() functions instead of send() and receive(). You can also use
    print() and println() for outgoing data.

A little code tweaking is needed.

I saw that in the release notes, but not sure what those tweaks might be. I'm thinking.... the

    Wire.send(a);    // bank A
    Wire.send(a);    // bank B

needs to the set to a byte or hex address and the individual addresses placed in an array. But that's only a guess. Any ideas? perhaps sudo code.
The datasheet:

cheers!

4.7 ohms? That won't work.

Did you pay attention to my warning about the possibly split power rails on the breadboard?

not sure I understand the point about the breadboard, I don't see any current at the i/o pin ( using a volt meter) I see a small voltage swing on the power line (the two outer lines on on the bread board, interestingly there is a W at the halfway point i.e. 25 pins left and 25 pins right ) but a current only appears on the lower 25 power line pins. Not sure whats going on here. and what do you recommend for the resistor value?

btw: I was able to get the thie tronixstuff sketch to compile on my mac running IDEv22 but it still the LEDs are all LOW.

I no longer know what you're saying. Measuring a current, with a voltmeter? A W at a halfway point? Current appearing on power pins? Are you measuring current or voltage here? What's a "small voltage swing" in your opinion? Do you have a number to go with that, say, 1 volt? 3 volts? 5 volts?

You need to measure good, solid, 5V all the way to the actual MCP23017 power pins. Until you've actually verified that, you're wasting your time and mine.

I2C pullups should be between 4.7Kohm and 47Kohm.

LED OUTPUTS

bottom line. there was some issues with the previous breadboard. I was able to get the centipede sheild sketch to work ( although I think only 15 of the 16 led's work thus far). No pull up resistors on either SCL or SDA are used in this wiring. MCP23017 Pins 10 and 18 going to +5v. More detail later. Thanks all!
Stay tuned.

Was the problem that the breadboard power rails were split at the midpoint?
:roll_eyes: :roll_eyes: :roll_eyes:

macegr,
Thanks much. Yes the breadboard, but also I no longer have the 4k7 resistors tied to 5V. I'm very new to this stuff so please forgive the misuse of terms and stupid question (not every question can be a "great question!"). Moving on...
Now that I've been able to test the chip now to put it to use. I need to turn the 16 LEDs ON/OFF individually based on the condition of 16 physical switches (piezo sensors to be exact) being ON/ or OFF. So each piezo has a corresponding LED and is either HIGH or LOW.
Can you show me how I may use the centipede shield or one MCP23017 - i2c 16 input/output port expander : ID 732 : $6.95 : Adafruit Industries, Unique & fun DIY electronics and kits MPC23017 chip to accomplish this.
A perfect example of what I'm trying to do is the midi_footsteps controller, it could be found in the playground on it's homepage MIDI Footsteps. I've got the multiplexers work thanks to Grumpy_mike, Crossroads and others. And now the final part it to add the LED section. Can anyone help me get this finale piece in place.

My code goes like this except no muxs are used here ( in my actual project I'm using the mux shield a total of 48 pads and the midi shield to output midi) but you can get the basic idea. It's like a piano with keys that light up or drums with pads that light up on inpact. So noteON = LED on.

SpikenzieLabs offers a pre-written code that looks like this:

/
// DESCRIPTION:
// Arduino analog input used to sense piezo drum hits then sent serialy to processing.

//*******************************************************************************************************************
// User settable variables
//*******************************************************************************************************************

unsigned char PadNote[6] = {52,16,66,63,40,65}; // MIDI notes from 0 to 127 (Mid C = 60)

int PadCutOff[6] = {600,600,600,600,600,600}; // Minimum Analog value to cause a drum hit

int MaxPlayTime[6] = {90,90,90,90,90,90}; // Cycles before a 2nd hit is allowed

#define midichannel 0; // MIDI channel from 0 to 15 (+1 in “real world”)

boolean VelocityFlag = true; // Velocity ON (true) or OFF (false)

//*******************************************************************************************************************
// Internal Use Variables
//*******************************************************************************************************************

boolean activePad[6] = {0,0,0,0,0,0}; // Array of flags of pad currently playing
int PinPlayTime[6] = {0,0,0,0,0,0}; // Counter since pad started to play

unsigned char status;

int pin = 0;
int hitavg = 0;

//*******************************************************************************************************************
// Setup
//*******************************************************************************************************************

void setup()
{
Serial.begin(57600); // connect to the serial port 115200
}

//*******************************************************************************************************************
// Main Program
//*******************************************************************************************************************

void loop()
{
for(int pin=0; pin < 6; pin++)
{
hitavg = analogRead(pin); // read the input pin

if((hitavg > PadCutOff[pin]))
{
if((activePad[pin] == false))
{
if(VelocityFlag == true)
{
// hitavg = 127 / ((1023 – PadCutOff[pin]) / (hitavg – PadCutOff[pin])); // With full range (Too sensitive ?)
hitavg = (hitavg /  -1 ; // Upper range
}
else
{
hitavg = 127;
}

MIDI_TX(144,PadNote[pin],hitavg);
PinPlayTime[pin] = 0;
activePad[pin] = true;
}
else
{
PinPlayTime[pin] = PinPlayTime[pin] + 1;
}
}
else if((activePad[pin] == true))
{
PinPlayTime[pin] = PinPlayTime[pin] + 1;

if(PinPlayTime[pin] > MaxPlayTime[pin])
{
activePad[pin] = false;
MIDI_TX(128,PadNote[pin],127);
}
}
}
}

//*******************************************************************************************************************
// Transmit MIDI Message
//*******************************************************************************************************************
void MIDI_TX(unsigned char MESSAGE, unsigned char PITCH, unsigned char VELOCITY)
{
status = MESSAGE + midichannel;
Serial.print(status);
Serial.print(PITCH);
Serial.print(VELOCITY);
}


}
}

Thanks again

PS: some newly learned teams: GPIO, i2c, wire.h, Mask (computing)...

The very first thing you should do, before writing the code, is to make sure your hardware setup is correct. Wiring a piezo sensor directly to the Arduino pins may work, but it's a hack. It may not work with the MCP23017; piezos can produce high voltage pulses and it could easily damage the MCP23017 inputs. One possible way to prevent damage would be a 5V Zener diode connected between the piezo outputs and ground. This would hopefully limit the voltage to 5V and eliminate the risk of damage.

The piezos each have a zener dieode and resistor. and are connected to the mux-sheild NOT physically to the i2c MCP23017 12c port expander. The mux shield handles the inputs i.e. Piezo and the 23017 handles the outputs i.e. LEDs


http://www.thebox.myzen.co.uk/Hardware/MIDI_Footsteps.html


http://todbot.com/blog/2006/10/29/spooky-arduino-projects-4-and-musical-arduino/

Adafruit (from whom I got the chip) has a library. I posted it and the related question Here: [Updated forum post- fewer typos] Help using MCP23017 & Adafruit-MCP23017-Arduino-Library - LEDs and Multiplexing - Arduino Forum. It helps or at this point it's a start.

This part has been already setup and tested
My Inputs (mux shield) and midi shield for midi output

My senors

Cheers!

Excerpt from midi-footspets: Using 23016

// Defines
// I2C registers
#define I2CregisterInput 0
#define I2CregisterOutput 2
#define I2CregisterPolarity 4
#define I2CregisterConfig 6
#define I2CregisterInterrupt 8
#define I2CregisterExpander 10
// I2C device addresses
#define ledAddress   (0x20 | 0x0)     // address of trigger LED indicators output
// Control Switch device bit masks
#define ddrTrigger 0x00000     // data direction register for trigger indictor LEDs

// Arduino pin assignments

#define midiChannel (byte)0


// Variable definations
int currentState[16]; // current state of sensors
int lastState[16];    // the last state of the sensors
int threshold = 0x90;  // sets the threshold value in deciding if a sensor is pressd.
int lastLedVal;
char control[16] = { 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
#include <Wire.h>
#include <avr/pgmspace.h>

lastLedVal = 0;

// Setup I2C devices
Wire.begin(); // start the I2C interface
// Initilise registers 
gpio_write(ledAddress, ddrTrigger, I2CregisterConfig); // Make into outputs
gpio_write(ledAddress, 0, I2CregisterInput); // turn them all off
doSensorScan(); // get initial states

// the value of threshold determins the on / off point
void lookForChange(){
int ledVal = 0;
int ledMask = 1;
for(int i=0; i<16; i++){
if(currentState[i] < threshold) ledVal |= ledMask; // add a 1 in the position of sensors under threshold
ledMask = ledMask << 1;
}
if(lastLedVal != ledVal) { // something has changed
ledMask = 1;
for(int i=0; i<16; i++){
if((ledMask & ledVal) != (ledMask & lastLedVal)){
if((ledMask & ledVal) == 0) {
// note off
controlSend(0x80, control[i], 0x00); // turn off control message
//noTone(8);
 
}
else{
// note on
controlSend(0x90, control[i], currentState[i]>>3); // turn on control message
//tone(8, notes[i], 20);

}
}
ledMask = ledMask << 1;
}
// Update the trigger LEDs
gpio_writeByteInverse(ledAddress, ledVal, I2CregisterInput);
}
lastLedVal = ledVal; // record current state of LEDs and MIDI notes / messages

}
void gpio_write(int address, int data, int reg) {
// Send output register address
Wire.beginTransmission(address);
Wire.send(reg);
// Connect to device and send two bytes
Wire.send(0xff & data); // low byte
Wire.send(data >> 8); // high byte
Wire.endTransmission();
}

void gpio_writeByteInverse(int address, int data, int reg) {
// Send output register address
Wire.beginTransmission(address);
Wire.send(reg);
// Connect to device and send two bytes
Wire.send(data >> 8); // high byte
Wire.send(0xff & data); // low byte
Wire.endTransmission();
}

int gpio_read(int address) {
int data = 0;
// Send input register address
Wire.beginTransmission(address);
Wire.send(I2CregisterInput);
Wire.endTransmission();
// Connect to device and request two bytes
// Wire.beginTransmission(address);
Wire.requestFrom(address, 2);
if (!Wire.available()) { } // do nothing until data arrives
data = Wire.receive();

if (!Wire.available()) { } // do nothing until data arrives
data |= Wire.receive() << 8;
Wire.endTransmission();
return data;
}?

http://www.arduino.cc/en/Reference/Bitwise

A simple way to state this is "one or the other but not both."
Put differently, exclusive disjunction is a logical operation on two logical values, typically the values of two propositions, that produces a value of true only in cases where the truth value of the operands differ.
The opposite of XOR is logical biconditional, where the output of two compared values is true only if both A and B are the same.

//logical values
//propositions
//truth value
or
//logical disjunction
//operands
//true

====
I also found this very helpful:

A left arithmetic shift of a binary number by 1. The empty position in the least significant bit is filled with a zero. Note that arithmetic left shift may cause an overflow; this is the only way it differs from logical left shift.

A right arithmetic shift of a binary number by 1. The empty position in the most significant bit is filled with a copy of the original MSB.

Source: Arithmetic shift - Wikipedia

=====
:smiley:

Alternative conversion process
A shortcut to manually convert a binary number into its two's complement is to start at the least significant bit (LSB), and copy all the zeros (working from LSB toward the most significant bit) until the first 1 is reached; then copy that 1, and flip all the remaining bits. This shortcut allows a person to convert a number to its two's complement without first forming its ones' complement. For example: the two's complement of "0011 1100" is "1100 0100", where the underlined digits were unchanged by the copying operation (while the rest of the digits were flipped).
In computer circuitry, this method is no faster than the "complement and add one" method; both methods require working sequentially from right to left, propagating logic changes. The method of complementing and adding one can be sped up by a standard carry look-ahead adder circuit; the alternative method can be sped up by a similar logic transformation.

Source: Two's complement - Wikipedia

========
correct me if I'm wrong.

The logical operation exclusive disjunction, also called exclusive or (symbolized by the prefix operator J, or by the infix operators XOR, EOR, EXOR, ? or ?, /??ks ??r/ or /?z?r/), is a type of logical disjunction on two operands that results in a value of true if exactly one of the operands has a value of true.[1] A simple way to state this is "one or the other but not both."
Put differently, exclusive disjunction is a logical operation on two logical values, typically the values of two propositions, that produces a value of true only in cases where the truth value of the operands differ.