My first question is: If the chips are locked on the 0x20s won't there be any conflict IF any another i2c device uses the same schemes?
Correct. Another slave device which uses address
0x20 - 0x27 would conflict with an existing MCP23017 device using the same address within that address range, if they were connected on the same I2C bus. Each I2C slave needs a unique address on an I2C bus.
Two ways to mitigate a slave address conflict would be either spreading the devices across multiple I2C buses on the I2C master (e.g. the Raspberry Pi), or using an I2C multiplexer device on a single I2C bus (which effectively creates multiple I2C buses itself). [See below for another approach.]
Secondly: Is there a way to modify the basic addressing scheme (0x3*, 0x4*, 0x5*) to maximize all these potential addresses. Or are they permanently set for each device?
This depends on the device (i.e. read their datasheet) but typically the I2C address, or the range of selectable I2C addresses, is fixed for each model of slave device.
One exception is where a slave device is totally programmable (e.g. some I2C slaves are actually PIC devices running firmware to make them into permanent I2C slaves) and in those cases, I have seen more flexibility about which addresses they can be programmed to use.
Edited to add: Another approach to avoid I2C bus address conflict, as kindly commented by @DoxyLover, is to use the Linear Technologies I2C address translators - LTC4316, LTC4317, LTC4318. These devices re-write the I2C addresses "on-the-fly" between their input and output "channels". Effectively, they create new I2C bus segments, with a configurable pattern of (in theory, transparent) I2C address translation between the original and new I2C bus segments.
From their datasheets, they also add other features e.g. built-in "stuck bus" detection and voltage level translation. However, while they support common I2C features, there are a few which they don't support e.g. 10-bit addressing and Device ID. As always, read the datasheets.
In the context of the original question, an LTC4316 looks like it would be able to create a new I2C bus segment, where another set of (up to) eight MCP23017 devices could be connected. Let's assume that I2C addresses
0x30 - 0x37 are free on the I2C bus directly connected to the master, but the new set of MCP23017 devices need to use their fixed addresses
0x20 - 0x27. The LTC4316 would be configured with a "translation byte" value of
On the LTC4316 "output" I2C bus segment, the new set of eight MCP23017 devices "see" their usual
0x20 - 0x27 I2C addresses, as they require. However on the "input" I2C bus segment where the I2C master is connected, the I2C master would address them using I2C addresses
0x30 - 0x37, with the LTC4316 translating an address of
0x3n on the "input" (master side) bus segment, to
0x2n on the "output" (slave side) bus segment [where
0 - 7].