Changing a Slave Arduino's Address

I know that having an arduino with multiple slave addresses is impossible, however i wish to have an arduino that starts out at address A, and if a condition is met switch to address B instead. So not multiple slave addresses, since they'd be one at a time. I simply wish to change it in code.

How would i do this?

(if you are curious as to what this is for, im trying to make an arduino act like another slave device, and said slave device changes its address after receiving an "activation" byte)

What are you talking about?

Sadly, absolutely no context.
Read the sticky at the top of the forum "Read this before posting a programming question".

probablyhuman:
I know that having an arduino with multiple slave addresses is impossible

Almost true. Arduino does not accept the broadcast address, but that can be turned on. Then it has two Slave addresses.
A ATtiny with its flexible USI can do about anything.

probablyhuman:
How would i do this?

Wire.end() stops everything, and a new Wire.begin(address) with a new Slave address starts all over with the new address. You can do that as often as you want. External pullup resistor should keep the SDA and SCL high, so no I2C device will ever notice it. Things can go wrong when calling Wire.end() while the Arduino is busy with I2C.

I think that some arduino users use a new Wire.begin(address) and forget to call Wire.end(). Don't do that. Perhaps the Wire library will be changed in a way that it no longer works.

probablyhuman:
im trying to make an arduino act like another slave device

You are in for a rough ride. It may never work.

[Update] Oops, the link was to Wire.endTransmission(), but I changed it to Wire.end() in the source code.

Koepel:
Wire.end() stops everything, and a new Wire.begin(address) with a new Slave address starts all over with the new address.

That sounds exactly like what id need! But i think that the link you referred me to (Wire.endTransmission) is for master devices that want to ends a transmission started by beginTransmission(). As quoted from the docs;

Ends a transmission to a slave device that was begun by beginTransmission() and transmits the bytes that were queued by write().

SteveMann:
Sadly, absolutely no context.
Read the sticky at the top of the forum "Read this before posting a programming question".

Does this really need context? Koepel seemed to understand it. I only included that explanation at the bottom to explain why id need it (eg a scenario so you're not confused), its not supposed to be an interpretation of my code. I can give you the code if you feel as though you need it, but its 1200+ lines.

Unless you have an arduino nano 33 BLE, a custom wiimote adapter (and wiimote), and all 5 non-arduino dependencies, i fail to see what you would attempt to gain from other than what i provided in the question.

So you are talking about I2C - do you not think that would be a detail you should of included in your original post?

Changing I2C address is trivial, I have a board that uses the 328, and is programmed here, when it is deployed, the master sends a command to set the next available address, this way the client does not have to worry about the nodes being 'setup' as they are plug and play.

Unless you have an arduino nano 33 BLE, a custom wiimote adapter (and wiimote), and all 5 non-arduino dependencies, i fail to see what you would attempt to gain from other than what i provided in the question.

This does not change the fact that you need to post code here!

probablyhuman:
But i think that the link you referred me to (Wire.endTransmission) is for master devices that want to ends a transmission started by beginTransmission().

Oops, that was a mistake.

I meant Wire.end() which releases the SDA and SCL pins and stops the Wire library.

Hmmm, that is weird, it is not in the documentation: Wire - Arduino Reference. I thought it would be considered as a normal function by now.

However, it is in the Wire.h for AVR boards and in the source code.

Arduino Nano 33 BLE has a nRF52840 processor.
I think it uses the "ArduinoCore-mbed" branch. That has also a Wire.end(): ArduinoCore-mbed/libraries/Wire/Wire.cpp at main · arduino/ArduinoCore-mbed · GitHub.

I see, after a call to Wire.end(), would i have to also re-apply the onRecieve(), onRequest(), and setClock() functions as well?

Yes.

After calling Wire.end(), the SDA and SCL pins have returned to normal pins and the Wire library is no longer active.
Then calling Wire.begin() starts the Wire library with the default settings. So you have set everything again.

probablyhuman:
Does this really need context? Koepel seemed to understand it.

Koepel made a guess, should it have been necessary to guess ?

I meant Wire.end() which releases the SDA and SCL pins and stops the Wire library.

I2CBusFormationPart.png
Figure-1:

Refer to Fig-1:
1. There are no SDA and SCL pins. These are I2C signals of the I2C Interface Module of the MCU, which become active when I2C Module is enabled.

2. Wire.begin() instruction opens switch K2 and closes switch K1; as a result, SDA and SCL signals of the I2C Module get connected with the A4 and A5 pins of the UNO Board. Now, A4 and A5 form the I2C Bus. K1 and K2 are switches at conceptual level.

3. Wire.end() instructions disables I2C Module, opens K1, and closes K2; as a result PC4 and PC5 digital IO signals P0rt-C are available on A4 and A5 pins of UNO Board. Now, A4 and A5 can exchange digital IO signals with external devices.

I2CBusFormationPart.png

Koepel:
After calling Wire.end(), the SDA and SCL pins have returned to normal pins and the Wire library is no longer active.
Then calling Wire.begin() starts the Wire library with the default settings. So you have set everything again.

So, if im correct, implemented in my ARM board it would look like this

// Begins I2C communication at address 1
Wire.begin(address1);
Wire.setClock(...);
Wire.onReceive(...);
Wire.onRequest(...);

Wire.end();

// Begins I2C communication at address 2
Wire.begin(address2);
Wire.setClock(...);
Wire.onReceive(...);
Wire.onRequest(...);

Correct.

And last thing just to make sure, i need to tie both sda and scl to ground with a 4.7k ohm resistor? My power source is 3.3v but id think the current is the same for the resistors.

A pullup resistor is to 5V or to 3.3V. Hence the name pull UP :wink:
I assume that there are already pullup resistors somewhere in the circuit.
When the I2C bus is idle, the level is high.

The I2C bus is pulled high with a resistor. The Master and Slave put data on the bus by sinking the SDA and SCL to GND. They never output a voltage to the bus. They have an open-drain output (or open-collector as it was called in the past). For a high level, they release the SDA or SCL, and then the signal flutters slowly to a high level by the resistor.
Nice pictures here: Gammon Forum : Electronics : Microprocessors : I2C - Two-Wire Peripheral Interface - for Arduino.

Ah, i see, so connect the 4.7k ohm resistors from sda/scl to 3.3v and the i2c communication will be uninterrupted. Thank you!

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.