Go Down

Topic: Addressing 23017/4051 using I2C Serial Interface & PROGMEM (Read 11 times) previous topic - next topic

Nick Gammon

Code: [Select]
#include "Defines.h"
#include <Wire.h>
//Give convenient names to the control pins
#define CONTROL0 5   
#define CONTROL1 4
#define CONTROL2 3
#define CONTROL3 2

//Create arrays for data from the the MUXs
//See the Arduino Array Reference: http://www.arduino.cc/en/Reference/Array
int mux0array[16];
int mux1array[16];
int mux2array[16];

void setup()
{
    w = 0;


Well, where is this file?

Code: [Select]
sketch_may08b.cpp:11:21: error: Defines.h: No such file or directory





Code: [Select]
sketch_may08b.cpp: In function 'void setup()':
sketch_may08b:28: error: 'w' was not declared in this scope


You don't have "w" declared.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

marco_c

#16
May 08, 2012, 01:58 pm Last Edit: May 08, 2012, 02:00 pm by marco_c Reason: 1
I made a few changes, mainly to make the mux array a 2 dimensional array that allows you to use loops (always easier).

Good job so far. Remember to compile often to work out mistakes more easily.

Arduino libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com

Grumpy_Mike

Basically the MCP23017 and the MCP23016 are not the same chip. The clue is in the fact that they have different numbers.
While they have roughly similar features there are a number of major differences that stop one being a direct replacement for the other:-
1) The pinout of the two chips is different therefore any schematic or PCB will have to be changed to accomidate this.
2) The MCP23017 has an external reset pin that needs driving or at least biasing.
3) The MCP23016 has an external RC to determine the internal clock frequency, this affects things like time to respond to an interrupt.
4) Most importantly the registers are at different addresses in the two devices so any software will have to take this into account.
5) There are also more registers in the MCP23017 giving it more options than the MCP23016.

Pitchoilcan

#18
May 08, 2012, 04:50 pm Last Edit: May 08, 2012, 06:04 pm by Pitchoilcan Reason: 1
This is what I have now, but this comes from Grumpy_Mike's project using MCP23016, unmodified.
Code: [Select]
// 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

Quote
1) The pinout of the two chips is different therefore any schematic or PCB will have to be changed to accomidate this.
2) The MCP23017 has an external reset pin that needs driving or at least biasing.
3) The MCP23016 has an external RC to determine the internal clock frequency, this affects things like time to respond to an interrupt.
4) Most importantly the registers are at different addresses in the two devices so any software will have to take this into account.
5) There are also more registers in the MCP23017 giving it more options than the MCP23016.


thanks for your reply and post Grumpy_Mike, To start off I couldn't find the mcp23016 online for sale. I wired the 23017 as described in example on the tronixstuff website. And was able to test the LEDS going in sequence a.k.a knightrider scanner (centipede shield library and sketch) so I've had atleast the basic wiring changes for the mcp23017 to work. I haven't gotten the mx shield yet as I wanted to try it with just one maybe two mcp23017's first.  Not sure how to bias the external reset pin and most importantly I don't know how to edit the code to accommodate for the register being at different addresses. I hope I don't make you feel as overwhelmed as I do, but my I'm really up against a deadline. marco_c has been a great help in rewriting my sketch but it'll be wrong if I don't provide the right information. And based on what you've said I might have provided some erroneous info. Can you help me at least with points #2 and  #4 of your reply. Your 5th point about the MCP23017 having more options makes it some complicated (for me) to use at this point :(    

This is what I used to test the mcp23017 chip knightrider style (no human interaction) http://docs.macetech.com/doku.php/centipede_shield

This is the chip I have and am attempting to use
http://ww1.microchip.com/downloads/en/devicedoc/21952b.pdf

This is the one uesed by Grumpy_Mike in the midifootsteps project ( from where I get the I2C setup we are discussing)
http://ww1.microchip.com/downloads/en/DeviceDoc/20090C.pdf
so parts dealing with the latter should be make to suite the former.....
================================
http://twit.tv/floss61
Think different
Think UbuntuStudio
============================

Pitchoilcan

#19
May 08, 2012, 06:05 pm Last Edit: May 08, 2012, 09:21 pm by Pitchoilcan Reason: 1
Example of the MCP23017 using centipede library and sketch. KnightRider style. No Human interaction. The mus shield is wired up to my inputs i.e. Piezo sensors. thought not in use here the midi shield is used to output midi note data (again not used here). Stay tuned.
PS adafru.it has a library for the mcp23017 however Grumpy_mike uses an MCP23016 with just the wire library. Please note that in all cases the wire library in being used
http://www.youtube.com/watch?v=_vzjLqWoXIk
The centipede shield was NOT used in this demo!
My i2c bus wiring
in the above photo I'm using the mega 2560 but in my project and in the test I'm using the duemilanove. The only resistor used are on the 16 attached to the LED pins. Arduino pins 4 and 5 have no resistors at this point.

the library and the code can be found here http://docs.macetech.com/doku.php/centipede_shield
================================
http://twit.tv/floss61
Think different
Think UbuntuStudio
============================

Grumpy_Mike

So why do you not use the centipede library with your own project? Then you would not have to rewrite anything.
As for the reset pin I connect it to an arduino output and toggle it on start up.

Grumpy_Mike

Code: [Select]
if(w != x)
  {   // something has changed
// write the value of x to your LED port expander interface here
    y = 1;


Quote
some have resistors on pins 4 and 5 other don't,

The ones without pull up resistors on pins 4 & 5 are wrong, no debate about it, it is just wrong.


Grumpy_Mike

OK lets spell it out. Use the Centipede library and change your code to write out all 16 bits at once to light your LEDs:-
Code: [Select]
if(w != x)
 {   // something has changed
// write the value of x to your LED port expander interface here
  myInstance.portWrite(0, x);
   y = 1;

Having first made an instance ( I called it myInstance ) like you did in the knightrider program, and setting all the bits to outputs  like you did in the knightrider program.

Pitchoilcan

#23
May 09, 2012, 12:32 am Last Edit: May 20, 2012, 04:22 pm by Pitchoilcan Reason: 1
add
Code: [Select]
#include <Centipede.h>
and change
Code: [Select]
if(w != x)
 {   // something has changed
// write the value of x to your LED port expander interface here
   y = 1;

to
Code: [Select]
if(w != x)
 {   // something has changed
// write the value of x to your LED port expander interface here
  myInstance.portWrite(0, x);
   y = 1;
================================
http://twit.tv/floss61
Think different
Think UbuntuStudio
============================

Grumpy_Mike

Add:-
Code: [Select]
#include <Centipede.h>
Centipede myInstance; // create Centipede object


Then inside the setup() function add:-
Code: [Select]
  myInstance.initialize(); // set all registers to default
  myInstance.portMode(0, 0); // set all pins on chip 0 to output


then what I said before:-
Code: [Select]
if(w != x)
  {   // something has changed
// write the value of x to your LED port expander interface here
   myInstance.portWrite(0, x);
    y = 1;

Grumpy_Mike

But this is totally different code to what you posted earlier. I can't even see the variable x mentioned in this code you have just posted. Do you understand what you are trying to do?
You need to send to the LEDs a 16 bit value, an integer. Each bit in the integer represents an LED that will turn on or off. When you scan through all the sensors that other code was putting a bit in an integer that represented the state of that sensor.
What is that code you posted? Have you missed things out of it?

Pitchoilcan

#26
May 10, 2012, 08:15 am Last Edit: May 11, 2012, 06:02 am by Pitchoilcan Reason: 1
Mike Thanks for the info I checked and now my running v1.0. So I'll Try to leave the whole thing intact including the qtrSensors, and see how far I get. I understand what I'm trying to do but not how to do it.  And marco_c I've made note of your update to the mux section.  So my focus is still on the LEDs

and trying to turn them on/off based on whats happening here
Code: [Select]
void checkSensors(int analogPin){

 for(int pin=0; pin < 16; pin++){
   //hitavg = analogRead(pin);                              // read the input pin
   //hitavg = muxArray[pin];    // read the input pin
   if(analogPin==0){
     hitavg = mux0array[pin];
     pad=pin;
   }
   else if(analogPin==1){
     hitavg = mux1array[pin];
     pad=pin+16;
   }
   else if(analogPin==2){
     hitavg = mux2array[pin];
     pad=pin+32;
   }

   if((hitavg > PadCutOff[pin])){

       //Serial.write("hitavg > PadCutOff[pin])");
       //Serial.write(' ');
     if((activePad[pad] == false)){
       if(VelocityFlag == true){
         //hitavg = 127 / ((1023 - PadCutOff[pin]) / (hitavg - PadCutOff[pin]));    // With full range (Too sensitive ?)
         hitavg = (hitavg / 8) -1 ;                                                 // Upper range
       }
       else{
         hitavg = 127;
       }
       if (analogPin==0 && PadNote[pad]==42){ //  array position = 7 , Hihat is handeld in a special way
   
         qtra.readCalibrated(sensorValues);
       
         unsigned char i;

         for (i = 0; i < NUM_SENSORS; i++){
           //Serial.write(sensorValues[i] * 10 / 1001);
           //Serial.write(' ');
           hihatPos = sensorValues[i] * 10 / 1001;
           if (hihatPos==0){
             MIDI_TX(144,42,hitavg);
             PinPlayTime[7] = 0;
             activePad[7] = true;
            // hihatWasTriggered=false;
           }
           else if (hihatPos >0 && hihatPos <= 6){
             MIDI_TX(144,44,hitavg);
             PinPlayTime[9] = 0;
             activePad[9] = true;
            // hihatWasTriggered = true;
           }
           else{

             MIDI_TX(144,46,hitavg);
             PinPlayTime[11] = 0;
             activePad[11] = true;
            // hihatWasTriggered = true;
           }
         }
       }

       else{

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

     if(PinPlayTime[pad] > MaxPlayTime[pad]){
       activePad[pad] = false;
       MIDI_TX(128,PadNote[pad],127);
     }
   }
 }
 
}
================================
http://twit.tv/floss61
Think different
Think UbuntuStudio
============================

marco_c

#27
May 10, 2012, 10:37 am Last Edit: May 10, 2012, 10:42 am by marco_c Reason: 1
You really need to understand what you are trying to achieve rather than just copying code, because your data mapping may/will be different from what others have done. Discipline is required!

Here's what I suggest as an approach:
1. Understand the commands you need to send to the MCP chip and how tio interact with it. As you had your knightrider thing going I am going to assume that you have some idea on how this needs to be done. Add the code to initialise the MCP thru the I2C in the setup function.

2. You need to work out how the data in your arrays (activePad?) maps to the bits for the MCP. Actually do this on a bit of paper - which element goes to which output bit - if is not clear. Hopefully you have a design that is linear and all the bits are consecutive which makes it easier as you can use loops.

3. Once the mapping is done, you then construct the 16 bit words using the ORing function we discussed at the start of this thread.

4. Then send those bytes to the MCP using the right address on the I2C interface.
Arduino libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com

Pitchoilcan

#28
May 10, 2012, 10:49 am Last Edit: May 11, 2012, 03:15 pm by Pitchoilcan Reason: 1
Thanks for the suggestion!
[font=Verdana]working on the steps.........[/font]
#include <Wire.h>
#include <Centipede.h>


/* Available commands
 .digitalWrite([0...127], [LOW...HIGH]) - Acts like normal digitalWrite
 .digitalRead([0...127]) - Acts like normal digitalRead
 .pinMode([0...127], [INPUT...OUTPUT]) - Acts like normal pinMode
[font=Verdana]  .portWrite([0...7], [0...65535]) - Writes 16-bit value to one port (chip)[/font]
 .portRead([0...7]) - Reads 16-bit value from one port (chip)
[font=Verdana] .portMode([0...7], [0...65535]) - Write I/O mask to one port (chip)[/font]
 .pinPullup([0...127], [LOW...HIGH]) - Sets pullup on input pin
 .portPullup([0...7], [0...65535]) - Sets pullups on one port (chip)
 .init() - Sets all registers to initial values

 Examples
 CS.init();
 CS.pinMode(0,OUTPUT);
 CS.digitalWrite(0, HIGH);
 int recpin = CS.digitalRead(0);
 CS.portMode(0, 0b0111111001111110); // 0 = output, 1 = input
 CS.portWrite(0, 0b1000000110000001); // 0 = LOW, 1 = HIGH

 int recport = CS.portRead(0);
 CS.pinPullup(1,HIGH);
[font=Verdana][font=Verdana]  CS.portPullup(0, 0b0111111001111110); // 0 = no pullup, 1 = pullup[/font][/font]
*/
================================
http://twit.tv/floss61
Think different
Think UbuntuStudio
============================

Pitchoilcan

#29
May 10, 2012, 05:24 pm Last Edit: May 12, 2012, 06:58 am by Pitchoilcan Reason: 1
[font=Verdana][ Two's complement ][/font][/b][/u]
[font=Verdana][font=Verdana]doing the steps[/font][/font][/color]
TABLE 1-2:
REGISTER ADDRESSES
Quote
Address
IOCON.BANK = 1
00h 10h 01h 11h 02h 12h 03h 13h 04h 14h 05h 15h 06h 16h 07h 17h 08h 18h 09h 19h 0Ah 1Ah
Address
IOCON.BANK = 0
00h 01h 02h 03h 04h 05h 06h 07h 08h 09h 0Ah 0Bh 0Ch 0Dh 0Eh 0Fh 10h 11h 12h 13h 14h 15h

Access to:
IODIRA  IPOLA  GPINTENA  DEFVALA  INTCONA  IOCON GPPUA  INTFA  INTCAPA  [font=Verdana]GPIOA[/font]  [font=Verdana]OLATA[/font]
IODIRB IPOLB  GPINTENB  DEFVALB  INTCONB  IOCON GPPUB INTFB  INTCAPB  [font=Verdana]GPIOB[/font]  [font=Verdana]OLATB[/font]

my muX bits

LSB                                                       MSB
    0 1  2 4 5 6 7 8 9 10 11 12 13 14 15

http://ww1.microchip.com/downloads/en/devicedoc/21952b.pdf

The default mode of the mcp2317 is the sequential mode which is more like the knightrider example, however what I need is BYTE mode....
================================
http://twit.tv/floss61
Think different
Think UbuntuStudio
============================

Go Up