New I2C library for Teensy3

Thanks for that info.

On my MCP I only need to detect button presses and then send out keyboard short cut keys or send mouse x,y and then click. All software stuff for the MCP.

My Teensy 3.2 will have to drive an LCD display and I have not yet looked into that to know if it needs 3.3 or 5.

So that I am clear on the LC power pin, that's the 3rd pin down on the right side (USB plug facing top) where on the LC card it says "3.3V (100 mA max)"? That's where I plug a wire into and then into the power strip on the breadboard. So that's an Output power pin to provide 3.3v of power to the entire board?

The 5v pin (pin 1) is power Input only? "Vin (3.7 to 5.5 volts". So pin1 is power in and pin3 is 3.3v power out?
 
Mostly. The normal case is you either apply power via the USB socket, or you apply 3.7-5.5v to the VIN pin. In this case, the 3.3v pins are output only. There is a second 3.3v pin on the very back (3rd pin on the right, if you have the Teensy facing up and the USB socket pointing down).

However, if you don't provide power to either the USB socket or the VIN pin, you can feed regulated 3.3v to one of the 2 3.3v pins. You might want to do this if the devices you attach to the Teensy requires more than 100mA of power.

If you provide power to either the VIN pin or the 3.3v pins, you probably want to cut the solder trace underneath the LC that connects the VUSB pin to the VIN pin (i.e. providing 5v power from USB). This would allow you to program the Teensy without having to deal with 2 separate power inputs.
 
Excellent description...I have not seen that explained that way anywhere else!! Thank you very much!!

My project will use the USB plug for input power as I need to send keyboard and mouse commands to the PC.

So, using my Teensy 3.2 or my LC, I only have 3.3v output to the breadboard power line. My project will use push buttons and some dual rotary encoders so I guess 3.3v will be fine for them. The only other device I have yet to work with is my LCD device which is a 4 line, 20 char serial display. I'm guessing that will work with 3.3v but I have yet to get a breadboard worked for for that.
 
I checked and the LCD I have does in fact require 5v: Blue Serial IIC/I2C/TWI 2004 204 20X4 Character LCD Module Display For Arduino

It was only $7.00 so I will get a 3.3v LCD and will look at your links...thanks.
 
Note, many of the 20x4 LCD displays are 5v only, so you might need to do level shifting with these displays.

You might want to consider instead getting the i2c 128x64 or 128x32 OLED displays. Most of these run at 3.3v. Here is one of the adafruit models: https://www.adafruit.com/products/326.

Alternatively, the PJRC store sells a color display that uses the SPI pins (pins 10-13): http://www.pjrc.com/store/display_ili9341.html.

I need a screen larger than 0.96 lol so I will buy the PJRC Color 320x240 TFT Display, ILI9341...thank you for the tip.

I just saw the touch screen version...I'm going to order that one.
 
Last edited:
I don't want to interrupt your discussion, but please move it to a new thread if it is unrelated to I2C.

Regarding your original question, your chip is this one correct?
mcp23017-pinout1.jpg

That chip needs an INPUT supply voltage on pin9 (VDD). Your photo does not indicate that it is getting power, the red bus on your breadboard is not connected (there is nothing driving it).
 
@nox771

Damn, that was it...i missed adding a wire to that one power line.

Now your code runs...thanks for the help...
 
rfresh737,

You need to get your voltage levels correct.
Quick background. Most logic used to be 5v , its now mainly 3v3 , and its dropping to 1v8.
you can 'sometimes' plug 5v into 3v3 , and other times you can not.
easiest to pick one voltage and check all your gear can cope with the.

having said that, the Teensy 3.2, all the diital IO pins are 3v3, but 5v tolerant,
so its a great hacking board. suggest you get one.
or if you in the states or Canada, look up rugged uno, just about impossible to blow up.

Strong suggestion that you draw out what you have, a schematic , even if its on paper, and let us see.
you need to get the voltages correct , and as Michael says you might need translates to stop board going pop.

Speaking from experience, randomly plugging things into different voltages will kill something, and make debugging even harder.
 
rfresh737,

You need to get your voltage levels correct.
Quick background. Most logic used to be 5v , its now mainly 3v3 , and its dropping to 1v8.
you can 'sometimes' plug 5v into 3v3 , and other times you can not.
easiest to pick one voltage and check all your gear can cope with the.

having said that, the Teensy 3.2, all the diital IO pins are 3v3, but 5v tolerant,
so its a great hacking board. suggest you get one.
or if you in the states or Canada, look up rugged uno, just about impossible to blow up.

Strong suggestion that you draw out what you have, a schematic , even if its on paper, and let us see.
you need to get the voltages correct , and as Michael says you might need translates to stop board going pop.

Speaking from experience, randomly plugging things into different voltages will kill something, and make debugging even harder.

Thanks for the tips. I do have a 3.2 but I also bought several LC's to test my circuits and code on breadboards. So the pics I've been showing in this thread are of the LC.

The next time I run into problems I will Fritz a drawing and upload it with my post. Good idea...thanks.
 
So I've finally got my MCP23017 code running. I have another question. Recall I have 4 buttons on my breadboard. When I press one of the buttons, one of the LEDs light up. Fritzing image file attached.

My serial window shows the bit when I press a button but the other bits seem to randomly get set high or low. In other words, even when I don't have a button pressed, I see 00000000's scrolling by in the serial window but then I'll see other values such as 11111100 or 11110011 etc. scroll by and then all 0's again.

What causes the random values and can I suppress them so that only 00000000's are detected until I actually press a button?

My goal is to connect 12 buttons and then detect each one and call an appropriate software action etc. For this setup, I'm only lighting up one LED per button press. Once I can get this working the way I want, I will then add 4 more buttons for 8 total. I will keep the same 4 LEDs. Once buttons 5-8 are working then I will add the last 4 buttons (9-12) and see how it works with all 12 buttons. I know I'll have to switch over to the B bank for the last 4 buttons (8-12) and will have re-use the 4 LEDs since I won't have room for 12 buttons and 12 LEDs on one MCP chip.

I'm running an LC board BTW.

Code:
#include <i2c_t3.h>

const byte  mcp_address=0x20;      // I2C Address of MCP23017 Chip
const byte  GPIOA=0x12;            // Register Address of Port A
const byte  GPIOB=0x13;            // Register Address of Port B

byte c;

void setup()
{
  //Send settings to MCP device
  Serial.begin(9600);
  Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_400);
  
  Wire.beginTransmission(0x20);
  Wire.write(0x00); // IODIRA register
  Wire.write(0xFF); // set all of port A to input
  Wire.endTransmission();

  Wire.beginTransmission(0x20);
  Wire.write(0x01); // IODIRB register
  Wire.write(0x00); // set all of port B to outputs
  Wire.endTransmission();
}

void loop()
{
  Wire.beginTransmission(mcp_address);

  Wire.write(GPIOA);
  Wire.endTransmission();
  Wire.requestFrom(mcp_address, 1);
  while(Wire.available())    // slave may send less than requested
  { 
    c = Wire.read();    // receive a byte as character         
  }
  printByteBits(c);

  Wire.beginTransmission(mcp_address);
  Wire.write(GPIOB);      // address bank B
  Wire.write((byte)c);  // value to send - equiavl input from buttons
  Wire.endTransmission();
  //Serial.println(c);

  delay(200);
  
  Wire.beginTransmission(mcp_address);
  Wire.write(GPIOB);
  Wire.write((byte)0x00);  // value to send - all LOW
  Wire.endTransmission();
 
  delay(200);
}

void printByteBits(byte myByte)
{
 String strByte = "";  
 for(byte mask = 0x80; mask; mask >>= 1)
 {
   if(mask  & myByte)
   {
       strByte = strByte + "1";
   }
   else
   {
       strByte = strByte + "0";
   }
 }
   Serial.print(strByte);
   Serial.print(" ");
   Serial.println(myByte);   
}

MCP23017 Fritz Ver 2.jpg
 
I would try first changing the baud rate to 100kHz and see if anything changes. Then I would add bypass caps across supply/gnd on the MCP chip. Breadboards can be capacitive and ringy - I've seen before where insufficient bypass can cause corruption. If you had a scope you could diagnose directly (logic analyzer could help also).
 
Your schematic is a little bit confusing (black for 5V and red for AGND)

From all what I read on this Forum, you should use AGND only for ADC work (here poti)
and GND for all digital work. That is, you should connect GND of LED and Microprocessor to Teensy GND (pin number 0) and not to AGND
 
Your schematic is a little bit confusing (black for 5V and red for AGND)

From all what I read on this Forum, you should use AGND only for ADC work (here poti)
and GND for all digital work. That is, you should connect GND of LED and Microprocessor to Teensy GND (pin number 0) and not to AGND

AGND is the pin next to 3.3v out pin?

And the G pin next to Digital pin 0 is the Digital Ground pin?
 
I would try first changing the baud rate to 100kHz and see if anything changes. Then I would add bypass caps across supply/gnd on the MCP chip. Breadboards can be capacitive and ringy - I've seen before where insufficient bypass can cause corruption. If you had a scope you could diagnose directly (logic analyzer could help also).

>Then I would add bypass caps across supply/gnd on the MCP chip.

I'm pretty new to this...what is a bypass cap? Capacitor? what size and how would I wire that?
 
An explanation of bypass caps: http://www.seattlerobotics.org/encoder/jun97/basics.html

You can find many more via google on "bypass caps" or "decoupling caps". Typical values are 0.1uF, 0.01uF ceramic caps.

There is also the concept of "star-wiring" versus "daisy-chain" on supply and ground connections. Looking at your breadboard, the IC is getting it's power from the "end" of the supply line, and it further has high-current sinks that it is driving (4 LEDs). When all LEDs light it might be pulling ~30mA or so, given the R values. This may be dragging the supply line down.

As a first step, unconnect the MCP chip from the red bus, and run a supply wire directly from its VDD (pin 9), over to the Teensy supply (3.3V), as close as you can get it. If you do add a bypass cap, it would be at the MCP chip, across VDD (pin 9) and VSS (pin 10).

There is another thing you can do to isolate if it is a supply or ground problem at the MCP chip - pull 3 of the 4 LEDs off, see if there is any difference in data reliability. Also try to run the SDA/SCL wires away from any other parallel wire that may be switching (this is to prevent cross-coupling in the signals).
 
Last edited:
You can also try adding a more robust failure mode like this:

Code:
#include <i2c_t3.h>

const byte  mcp_address=0x20;      // I2C Address of MCP23017 Chip
const byte  GPIOA=0x12;            // Register Address of Port A
const byte  GPIOB=0x13;            // Register Address of Port B

byte c;
uint8_t err;

void setup()
{
  //Send settings to MCP device
  Serial.begin(9600);
  Wire.begin(I2C_MASTER, 0x00, I2C_PINS_18_19, I2C_PULLUP_EXT, I2C_RATE_400);
  
  Wire.beginTransmission(mcp_address);
  Wire.write(0x00); // IODIRA register
  Wire.write(0xFF); // set all of port A to input
  Wire.endTransmission();

  Wire.beginTransmission(mcp_address);
  Wire.write(0x01); // IODIRB register
  Wire.write(0x00); // set all of port B to outputs
  Wire.endTransmission();
}

void loop()
{
  Wire.beginTransmission(mcp_address);
  Wire.write(GPIOA);
  err = Wire.endTransmission();
  if(!err)
  {
    Wire.requestFrom(mcp_address, 1);
    if(Wire.available())    // slave may send less than requested
    {
      c = Wire.read();    // receive a byte as character        
      printByteBits(c);
  
      Wire.beginTransmission(mcp_address);
      Wire.write(GPIOB);      // address bank B
      Wire.write((byte)c);  // value to send - equiavl input from buttons
      Wire.endTransmission();
      //Serial.println(c);

      delay(200);
  
      Wire.beginTransmission(mcp_address);
      Wire.write(GPIOB);
      Wire.write((byte)0x00);  // value to send - all LOW
      Wire.endTransmission();    
    }
  }
  delay(200);
}

void printByteBits(byte myByte)
{
 String strByte = "";  
 for(byte mask = 0x80; mask; mask >>= 1)
 {
   if(mask  & myByte)
   {
       strByte = strByte + "1";
   }
   else
   {
       strByte = strByte + "0";
   }
 }
   Serial.print(strByte);
   Serial.print(" ");
   Serial.println(myByte);   
}

What this is doing is gating the subsequent I2C commands on the success of the prior one.
 
Your schematic is a little bit confusing (black for 5V and red for AGND)

From all what I read on this Forum, you should use AGND only for ADC work (here poti)
and GND for all digital work. That is, you should connect GND of LED and Microprocessor to Teensy GND (pin number 0) and not to AGND

I have corrected that...thanks for catching it.
 
Do you happen to know if there is a tutorial on how to use this LCD display?

Thanks...

Well the page at the pjrc store looks it has instructions on how to use it. Note, I haven't used this display, so I can't comment on it. You might search to see if there are articles about it. Or ask in a new thread (since it is no longer i2c related) about it.
 
I finally got my MCP23017 working with 12 buttons with my Teensy 3.2. Yahoo. I have another grouping of buttons (12 of them) that I'd like to add to a second MCP23017 chip.

I read about how to set the address of each MCP (A0 A1 A2 pins) so I'll set my second MCP address to 0x21.

My question is: how do I wire the second MCP into first MCP? I don't mean the I/O pins that the buttons will pin into, I mean the 'daisy chain' wiring? How to I connect the second MCP to the first MCP?

I know I will call each MCP via their address (0x20 and 0x21) and use the same code to read the pins (in my case since there are only buttons). So I think I know how to set up the second MCP except I'm not clear in my mind how it connects to the first MCP?

I googled around but only found single MCP examples...I was hoping to find a Fritzing drawing showing multiple MCPs but I didn't.

Thanks...
 
I know I will call each MCP via their address (0x20 and 0x21) and use the same code to read the pins (in my case since there are only buttons). So I think I know how to set up the second MCP except I'm not clear in my mind how it connects to the first MCP?

As long as the two MCP chips have different addresses, then you just connect them to the same SDA/SCL lines (eg. Teensy SDA to both MCP SDA, Teensy SCL to both MCP SCL). That is the whole advantage of I2C, you wire all the Slave chips to the same two bus lines (which is why it is a "bus" and not point-to-point connection).
 
Back
Top