davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

hey,
how long will 2x MCP23017 readings last (min, max) to read or write all 2x16 =32 bits (2x2=4 bytes) via i2c repeatedly (endless loop, given only these 2 devices on that i2c bus) ?
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

davenull wrote:hey,
how long will 2x MCP23017 readings last (min, max) to read or write all 2x16 =32 bits (2x2=4 bytes) via i2c repeatedly (endless loop, given only these 2 devices on that i2c bus) ?
It depends on how you write them... wiringPi writes one bit at a time, but if you directly access the registers, then it's 3 bytes over the I2C bus per 8-bit write - or 30 bits. So 30 bits at 100Kbits/sec is 0.3mS - so to write to 16-bits is 0.6mS, so 1.2mS for double that (2 devices) - given ideal conditions.

This: https://www.youtube.com/watch?v=g5cSvVGCX_A uses 2 x mcp23017's to drive 128 LEDs multiplexed, one LED at a time using wiringPi's digitalWrite() function. Not the most efficient, but usable.

-Gordon
--
Gordons projects: https://projects.drogon.net/

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

thank you Gordon!

can you please give me a hint for (edit) reading and writing bytes to registers?

In Arduino Wiring Sketch it's

Code: Select all

``````  Wire.beginTransmission(addr);
Wire.write(databyte);
Wire.endTransmission();``````
(not knowing by heart now how to address the write register for devices).

How would it look like for Raspi to do something like

Code: Select all

``````i2cwrite(int devaddr, int regaddr, int ndatabytes, char *data)
? (edited)

and 2nd question:
would it be possible to drive the bus at 400kb/s for the MCPs?
Last edited by davenull on Mon Feb 29, 2016 7:19 pm, edited 1 time in total.
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

davenull wrote:thank you Gordon!

can you please give me a hint for writing bytes to registers?
You read my source code for mcp23017.c in wiringPi ...

The code there is:

Code: Select all

``    wiringPiI2CWriteReg8 (node->fd, MCP23x17_GPIOA, old) ;``
where node->fd is the fd returned from wiringPiI2CSetup() and 'old' here is the value you're writing. Get the register definitions from the header file mcp23x0817.h.

I plan on expanding the digitalWriteByte & digitalReadByte calls soon, but that'll break binary compatibility, so not sure what to do about that one. (just need re-linking)

-Gordon
--
Gordons projects: https://projects.drogon.net/

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

Code: Select all

``````/*
* q2w.c:
*      Using the Quick 2 wire board for its mcp23017
*
* Copyright (c) 2012-2013 Gordon Henderson. <projects@drogon.net>
***********************************************************************
*/

#include <stdio.h>
#include <wiringPi.h>
#include <mcp23017.h>

int main (void)
{
int i, bit ;

wiringPiSetup () ;
mcp23017Setup (100, 0x20) ;

printf ("Raspberry Pi - MCP23017 Test\n") ;

for (i = 0 ; i < 10 ; ++i)
pinMode (100 + i, OUTPUT) ;

pinMode         (100 + 15, INPUT) ;
pullUpDnControl (100 + 15, PUD_UP) ;

for (;;)
{
for (i = 0 ; i < 1024 ; ++i)
{
for (bit = 0 ; bit < 10 ; ++bit)
digitalWrite (100 + bit, i & (1 << bit)) ;
delay (5) ;
while (digitalRead (100 + 15) == 0)
delay (1) ;
}
}
return 0 ;
}``````
but I must admit: I don't understand how to read/write a byte at a certain MCP23017 dev addr and reg address containing a bit pattern...

moreover, there is a different initialization:

Code: Select all

``````   wiringPiSetup () ;
mcp23017Setup (100, 0x20) ;
``````
and no node->fd which is the fd returned from wiringPiI2CSetup()

I know how to set or read single bits in a byte, I just want to know how to address the reg to read or write to it...

OTOH, that would be very easy to use instead:

Code: Select all

``````i2cwrite(char * i2cport, int devaddr, int regaddr, int ndatabytes, char *data)
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

Not that code.

~/wiringPi/wiringPi/mcp23017.c

You can use my code to get the basic setup done, then get the fd with:

Code: Select all

``````mcp23017Setup (100, 0x20) ;
struct wiringPiNodeStruct *node ;

node = wiringPiFindNode (100) ;
fd = node->fd ;
``````
Then you can write to GPIO portA on that device (with a pin base of 100 inside wiringPi) with

Code: Select all

``````  wiringPiI2CWriteReg8 (fd, MCP23x17_GPIOA, data) ;
``````
You need to do the same for the 2nd mcp23017 you have.

-Gordon
--
Gordons projects: https://projects.drogon.net/

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

sorry, I don't find the ressource link, and I am obviously too dump fo this extremely sophisticated i2c protocol
I really can't understand and handle that
(Arduino wiring Sketch programming level ist the upper most level for my programming skills )
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

davenull wrote:sorry, I don't find the ressource link, and I am obviously too dump fo this extremely sophisticated i2c protocol
I really can't understand and handle that
(Arduino wiring Sketch programming level ist the upper most level for my programming skills )
You need to get the wiringPi source:

Code: Select all

``````cd ; git clone git://git.drogon.net/wiringPi
``````
-Gordon
--
Gordons projects: https://projects.drogon.net/

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

for a cmps11 I am already using this:

Code: Select all

``````int cmps11 = wiringPiI2CSetupInterface("/dev/i2c-1", 0x60);

unsigned char  angle8;
signed char    pitch, roll;

angle8    = wiringPiI2CReadReg8 (cmps11, 1 ) ;
pitch     = wiringPiI2CReadReg8 (cmps11, 4 ) ;
roll      = wiringPiI2CReadReg8 (cmps11, 5 ) ;``````

I assumed I could do it that way for a mcp23017:

Code: Select all

``````int mcp23017_0= wiringPiI2CSetupInterface("/dev/i2c-1", 0x20);

``````

edit: how to write a byte to a register?
wiringPiI2CWriteReg8 (mcp23017_0, 0x12, databyte) ; // bank A
Last edited by davenull on Tue Mar 01, 2016 10:14 pm, edited 1 time in total.
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

ps,
just found an Arduino Wiring Sketch ressource for

Code: Select all

``````bool i2cwrite(byte devaddr, int regaddr, byte ndatabytes, char *data){
Wire.write(HIGH(regaddr)); // this assumes the device expects MSB,LSB
if(ndatabytes>29) ndatabytes=29; // Wire's internal transmit buffer is 32 bytes
for(byte i=0;i<ndatabytes;i++){
Wire.write(data[i]);
}
return (Wire.endTransmission(true)==0);
}  ``````

and for the MCP23017 especially

Code: Select all

`````` // ref.: Nick Gammon,  http://www.gammon.com.au/forum/?id=10940

// address dev and reg and set bank and mode, and read or write
Wire.beginTransmission (0x20);  // expander has I2C address 0x20
Wire.send (0x00);   // register 0 is the I/O direction register for Port A ("B" == 0x01)
Wire.send (0x00);   //  0x00 for all pins to output mode, 0xFF for all pins to input mode
Wire.endTransmission ();

// (write)
Wire.beginTransmission (0x20);  // expander has I2C address 0x20
Wire.send (0x12);   // register 0x12 is the I/O port "A" ("B" == 0x13)
Wire.send (0x56);   //  what to put on that port
Wire.endTransmission ();

Wire.requestFrom (0x20, (byte) 1);
``````
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

now from Nick Gammon's Arduino MCP23017 code the basic logic is a little bit more clear to me:

get device handle:

Code: Select all

``int mcp23017_0= wiringPiI2CSetupInterface("/dev/i2c-1", 0x20); ``
read 1 byte from register 0x12:

Code: Select all

``````unsigned char data  = wiringPiI2CReadReg8 (mcp23017_0, 0x12) ;   // read bank A data register (0x12)
unsigned char data  = wiringPiI2CReadReg8 (mcp23017_0, 0x13) ;   // read bank B data register (0x13)
``````

but which command is the right one to write to a register?

1st, to set bank A or B to input or output: write 0x00 or 0xff to register 0x00 (A) or register 0x01 (B) ?

Code: Select all

``````wiringPiI2CWriteReg8 (mcp23017_0, 0x00, 0x00) ;  bank A:= output?
wiringPiI2CWriteReg8 (mcp23017_0, 0x00, 0xff) ;  bank A:= input?
wiringPiI2CWriteReg8 (mcp23017_0, 0x01, 0x00) ;  bank B:= output?
wiringPiI2CWriteReg8 (mcp23017_0, 0x01, 0xff) ;  bank B:= input?
``````
2nd, to write a certain data byte to register 0x12 (A) or 0x13 (B) ?

Code: Select all

``````wiringPiI2CWriteReg8 (mcp23017_0, data, 0x12 ; write data to bank A?
wiringPiI2CWriteReg8 (mcp23017_0, data, 0x13 ; write data to bank B?
``````
I'm still not sure about that... :-/
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

The code is all written for you - I typed some in in my last post and the sources to wiringPi are all online with many examples of using mcp23017's.

I suggest you read the data sheets too. I also suggest you use my header file (or someone elses) that has all the register definitions in it to save guessing register numbers.

All you need will be in ~/wiringPi/wiringPi/mcp23017.c if you get the wiringPi source.

-Gordon
--
Gordons projects: https://projects.drogon.net/

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

I already found your MCP23017 ressource, and I also saw what you wrote above -
my issue is: to understand, how writing and reading from / to device registers work with your wiringPi API in general to be capable to use either i2c device in future.

wiringPiI2CWriteReg8 (node->fd, MCP23x17_GPIOA, old) ;
where node->fd is the fd returned from wiringPiI2CSetup() and 'old' here is the value you're writing. Get the register definitions from the header file mcp23x0817.h.
I don't understand at all because I have no clue what node->fd means ( looks weird....: a pointer? or a class?),
and instead of wiringPiI2CSetup() I want to use
wiringPiI2CSetupInterface("/dev/i2c-1", 0x20);
because of the additional "/dev/i2c-0" option, but this also will return a i2c device handle, won't it?

Of course I will use then later
for the first MCP device if the code will work.

Data sheets are an abomination to me (they are obviously written by technicians for technicians, not for hobby programming noobs),
but if I understood the logic of the device and the logic of your wiringPi API functions correctly, the following code should work (please CMIIW):
set bank A to output (read),
set bank B to input (write),
then read 1 byte from A ,
then write 1 byte to B:

Code: Select all

``````uint8_t data;

wiringPiI2CWriteReg8 (mcp23017_0, 0x00, 0x00) ;  // bank A:= output (read)
wiringPiI2CWriteReg8 (mcp23017_0, 0x01, 0xff) ;  // bank B:= input (write)

data  = wiringPiI2CReadReg8 (mcp23017_0, 0x12) ;   // read bank A data register (0x12)
//...
wiringPiI2CWriteReg8 (mcp23017_0, data, 0x13);   // write data to bank B (0x13)

``````
Am I right or wrong?
(hell, how confusing! - but I MUST understand that!)
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

davenull wrote: Am I right or wrong?
(hell, how confusing! - but I MUST understand that!)
I think you might want to stop and learn some more C before you do much more ... (sorry. but it has to be done!)

-Gordon
--
Gordons projects: https://projects.drogon.net/

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

I'm learning by doing.
(BTW, that's why I loved to have Wiring for Raspi like I have it for Arduino Sketch, suitable for beginners:
it took me 1 day to write my first C programs for Arduino, but meanwhile I struggling 6 months for writing C programs for Raspi!)

but what is faulty now in my code?

Code: Select all

``````uint8_t data;

wiringPiI2CWriteReg8 (mcp23017_0, 0x00, 0x00) ;  // bank A:= output (read)
wiringPiI2CWriteReg8 (mcp23017_0, 0x01, 0xff) ;  // bank B:= input (write)

data  = wiringPiI2CReadReg8 (mcp23017_0, 0x12) ;   // read bank A data register (0x12)
//...
wiringPiI2CWriteReg8 (mcp23017_0, data, 0x13);   // write data to bank B (0x13)
``````
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

davenull wrote:I'm learning by doing.
(BTW, that's why I loved to have Wiring for Raspi like I have it for Arduino Sketch, suitable for beginners:
it took me 1 day to write my first C programs for Arduino, but meanwhile I struggling 6 months for writing C programs for Raspi!)

but what is faulty now in my code?

Code: Select all

``````uint8_t data;

wiringPiI2CWriteReg8 (mcp23017_0, 0x00, 0x00) ;  // bank A:= output (read)
wiringPiI2CWriteReg8 (mcp23017_0, 0x01, 0xff) ;  // bank B:= input (write)

data  = wiringPiI2CReadReg8 (mcp23017_0, 0x12) ;   // read bank A data register (0x12)
//...
wiringPiI2CWriteReg8 (mcp23017_0, data, 0x13);   // write data to bank B (0x13)
``````
Assuming your register assignments are correct then it doesn't look too bad - what doesn't happen?

Always a good idea to check return codes from functions that return error codes though - make sure the fd (mcp23017_0 in your case) is >= 0.

-Gordon
--
Gordons projects: https://projects.drogon.net/

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

I have no MCP23017 yet, but I will order 2 of 'em, and I will have to be sure that I'll be capable of using the right code to control it once I've finally got it.
Although my Arduino Due works.... but it's interface is too slow for 8x encoder motor control :-/

3 PCF8591 will be the next challenge then, at the 2nd i2c bus.
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

davenull wrote:I have no MCP23017 yet, but I will order 2 of 'em, and I will have to be sure that I'll be capable of using the right code to control it once I've finally got it.
Although my Arduino Due works.... but it's interface is too slow for 8x encoder motor control :-/

3 PCF8591 will be the next challenge then, at the 2nd i2c bus.
when you do get it, before writing a single line of code, you can test it -

Code: Select all

``````gpio -xmcp23017:100:0x20 mode 100 out
gpio -xmcp23017:100:0x20 write 100 1``````
that will set the first bit of port A high - connect an LED to check or use a multimeter.

The gpio command can't use the "other" I2C bus (but programs can). Not sure why you want to, however I'm sure you have your reasons.

-Gordon
--
Gordons projects: https://projects.drogon.net/

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

yes, sure, thanks, I will do so!

what exactly do these 2 lines test? Just if it's defective or not?

and which wires do I have to plug to the mcp chip for this test?
just +5V(9), GND(10), SCL(12), SDA(13),
and pin21( line A) -> LED 470Ohm -> GND ?

Code: Select all

``````gpio -xmcp23017:100:0x20 mode 100 out
gpio -xmcp23017:100:0x20 write 100 1``````
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

Massi
Posts: 1691
Joined: Fri May 02, 2014 1:52 pm
Location: Italy

why don't you read the datasheet of the chip? (as suggested above)
in the datasheet it's clearly stated what you need to connect to have the chip working reliably
Sometimes (not always, in your case would be enough SOME TIME) you can try to do some homework instead of waiting for prepared bread from others.

Obviously wrong connections to mcp23017 chips have been discussed a lot of times on the forum.

gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

davenull wrote:yes, sure, thanks, I will do so!

what exactly do these 2 lines test? Just if it's defective or not?
They don't test anything really - more confidence to make sure its wired up correctly. I see too many people diving into code after connecting hardware without even doing basic tests that I get fed-up replying to their email... Just saving you some bother.
and which wires do I have to plug to the mcp chip for this test?
just +5V(9), GND(10), SCL(12), SDA(13),
and pin21( line A) -> LED 470Ohm -> GND ?
You need to read the fine manual, however I'd start off with using the 3.3v power from the Pi rather than the 5v supply.

Code: Select all

``````gpio -xmcp23017:100:0x20 mode 100 out
gpio -xmcp23017:100:0x20 write 100 1``````
Read the manual/datasheet to find out what to do with the A0, A1 and A2 pins. Also the reset pin. The picture here:

http://wiringpi.com/examples/testing-wiringpi-v2/

might give you some hints too if you study it closely. (although its not that high resolution, but still might be handy)

-Gordon
--
Gordons projects: https://projects.drogon.net/

davenull
Posts: 1159
Joined: Thu Oct 22, 2015 7:22 am
Location: a small planet close to Betelgeuze

I see too many people diving into code after connecting hardware without even doing basic tests that I get fed-up replying to their email... Just saving you some bother....however I'd start off with using the 3.3v power from the Pi rather than the 5v supply.
yap !
#define S sqrt(t+2*i*i)<2
#define F(a,b) for(a=0;a<b;++a)
float x,y,r,i,s,j,t,n;int main(){F(y,64){F(x,99){r=i=t=0;s=x/33-2;j=y/32-1;F(n,50&S){t=r*r-i*i;i=2*r*i+j;r=t+s;}if(S){PointOut(x,y);}}}for(;;);}

Sonny_Jim
Posts: 45
Joined: Tue Oct 23, 2012 4:15 pm

Just curious, why the recommendation to run the mcp23017 at 3.3v rather than 5v? I run mine at 5V with seemingly no problems.

gordon@drogon.net
Posts: 2020
Joined: Tue Feb 07, 2012 2:14 pm
Location: Devon, UK
Contact: Website

Sonny_Jim wrote:Just curious, why the recommendation to run the mcp23017 at 3.3v rather than 5v? I run mine at 5V with seemingly no problems.
Less chance of doing something silly and blowing up a Pi...

-Gordon
--
Gordons projects: https://projects.drogon.net/

joan
Posts: 13998
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK