Which arduino to use for reading out 25 (!) APDS 9960 sensors

Hi there,

as the header says I'd like to read out 25 APDS 9960 colour sensors (via 4 TCA9548A – I2C multiplexers) and I don't have any idea how to go about deciding which Arduino to use.

Can anyone give some pointers? What would I need to look at in order to find out which Arduino can do the necessary computations? (and is one I2C bus sufficient or do I need more?)

Many thanks in advance!

Can you tell what the project is for ?

Manufacturer's page of the SPDS-9960: https://www.broadcom.com/products/optical-sensors/integrated-ambient-light-and-proximity-sensors/apds-9960.
It is a 3.3V sensor, with a 400 kHz I2C bus plus a interrupt signal, no SPI.

Modules are avaiable from Sparkfun and from Adafruit.

Do you have modules with the APDS-9960 ? Can you give a link to them ?
The Arduino 5V pin can not power all of them, if the internal led is used.
How long are the distances ?

The data sheet says

Which means you would need 25 I2C busses to use 25 devices, so clearly that is not an option as you need 2 pins per I2C bus and 50 pins is more than any Arduino has.

So what you have to use is an analogue multiplexer to switch data and clock from the one real I2C bus to each of your sensors. You can do this on any Arduino it will take five additional pins if you design your multiplexer correctly.

Hi @Grumpy_Mike

Thanks for getting back about this.

As I wrote in the original post, I'm using 4 multiplexers... so that's not the problem. May question is how I find out if the Arduino can do the necessary computations for input from 25 sensors... and as for looking at the data sheet, I am asking because I precisely don't know what to look for.

@Koepel I am trying to get colour sensor readouts for an rgb LED flashlight moving across a 5x5 matrix of sensors. This will then be forwarded to MaxMSP for further processing.

I am using these sensors.
https://www.alibaba.com/product-detail/GY-9960-3-3-APDS-9960_1600164271328.html?spm=a2700.galleryofferlist.normal_offer.d_title.757f6a9c3IJ6x4
Tested originally with the Adafruit version but I can't afford 25 of them so these gave me the same readouts and seemed to work well when I tried three of them hooked up to a TCA9548A multiplexer.

This is exactly my question, because I am new to Arduino and don't know what I have to look at. So power is an issue... how do I calculate that? Is computation as well? Will an Uno be able to process all the information coming in?

Distances are quite short, I'm distributing them in a 5x5 matrix across a 40x40cm surface.

Short distances :white_check_mark:
Modules without level shifter (25 level shifters could be a problem) :white_check_mark:
Modules that can disable pullup resistors :white_check_mark:

How fast do you want to collect data ? Once per second ?

The power usage depends if you are going to use the internal led.

Manufacturer's page of the TCA9548A : https://www.ti.com/product/TCA9548A

Do you use this TCA9548A module ? https://www.adafruit.com/product/2717.
The TCA9548A can do level shifting as well, so you can use a 5V Arduino board (which has a 5V I2C bus).
The I2C bus to the APDS-9960 must be a 3.3V I2C bus.

You need pullup resistors for every I2C bus. For the main I2C bus at the Arduino and for all the 25 (sub) I2C busses. I think the 10k pullup on the module is just fine.

When you wire everything, don't use a flat ribbon cable with SDA and SCL next to each other. The I2C bus can not handle crosstalk between SDA and SCL. Just a bunch of lose wires is better.

Which Arduino board do you want to use ?
Do you have a number of boards lying around to choose from ?

The software is another hurdle to take.

[ADDED] The /RESET pin of the multiplexers disables all channels. I think you need to use that. If you use one main I2C bus at the Arduino board, then you need to select one channel from one multiplexer and disable the other multiplexers.
So the Arduino needs 2 pins for the I2C bus and 4 extra pins for the /RESET signals of the multiplexers.

[EDIT] No need to use the /RESET, use I2C command.

Ideally I'd like to measure it much faster. Currently my sketch is outputting serial data at 115200 Baud rate, but honestly I haven't yet thought about how that relates to data collection or how I could set that. Ideally, data collection/forwarding should happen in as close to real time as possible, because it's meant to be a gestural instrument, and as such I can't have any latency.

The way it looks atm I'm not using the LED because I'm receiving data from the rgb diodes only. Do I need to/can I switch it off?

yep. I'm currently testing on an Arduino Uno, running the Analog 4 and 5 pins into the TCA9548A and from there into the sensors. Appears to be working fine at six sensors right now.

I'm using the onboard pullups on the sensors, but so far not on the main bus. Why do I need it? (I'm generally a little lost when it comes to pullup resistors, I think I understand the concept in theory but honestly unsure about application in practice)

:white_check_mark:

I currently have an Uno lying around as well as this one: Adafruit ItsyBitsy M0 Express - for CircuitPython & Arduino IDE : ID 3727 : $11.95 : Adafruit Industries, Unique & fun DIY electronics and kits but I'm happy to purchase whichever I need for the task.

Software so far is no problem. I'm using mostly modified sketches from Adafruit + their libraries, which are very useful. On the MaxMSP side of things everything seems to be working nicely as well... whether my programming the most efficient is an entirely different matter alltogether. :wink: I can't know that unless I scale up.

Ah, here I'm clueless. Why do I need to disable the other multiplexers? (Adafruit website says something similar but I'm not quite there yet)

Thanks for the in-depth reply and the help. I greatly appreciate it!

Turn led off

I don't know if your module has something for that. Can you reverse-engineer the module and make a schematic ?

One out of 25

Where ? I would like to read that.
When you have four I2C multiplexers connected and you want just one sensor, how can you do that ? You need to turn off three multiplexers. [EDIT] There is no problem, a I2C command can turn it off.

Warning: Do not put too many level shifters and multiplexers in the SDA and SCL signal path. You could put a multiplexer after a multiplexer, but everything you do makes the signals weaker.

Speed

Adafruit library: https://github.com/adafruit/Adafruit_APDS9960.
Suppose the sensor is ready and getColorData() takes about 24 * 10 bytes.
At 100kHz, that is 2.4 ms. Plus overhead makes 5ms. Plus switching the mux makes 7ms.
That means you might read the whole array at 5 times per second on a fast Arduino board.
Disclaimer: this is purely theory.

Pullup

A sensor and a Arduino board can make SDA and SCL low. That's about it.
No one makes the SDA and SCL signals high. They are just floating, flapping in the breeze. Only a resistor to 5V or 3.3V makes the SDA and SCL slowly go towards that voltage.
Very nice pictures here: http://www.gammon.com.au/forum/?id=10896&reply=5#reply5

The I2C bus is idle high. When there is no communication, then SDA and SCL should be high. That means you have to keep the unused sub-I2C buses high, or else a sensor gets confused.

You have one main I2C bus and 25 sub-I2C buses. Everyone of those 26 I2C busses needs pullup resistors.

The modules have them. The Arduino board has (weak) internal pullup. If you add extra 10k pullup resistors at the Arduino board, then it should be alright.

Itchy Bitchy

Question: I have a problem with my Itchy Bitchy, what shall I do ?
Answer from Arduino aficionados: That is not an Arduino board, try zinc oxide ointment.

So you're pretty much talking this:


One set of pullups for the Arduino side of the muxes, each sensor with its own pullups, and then 2 address lines to select which mux you are talking to, and select channel 0 to 7 in that mux to connect to a sensor, or select no sensor.

1 Like

Thank you @CrossRoads. So all channels can be turned off by a I2C command.
@gabechan, you can forget what I wrote about the /RESET.

What you look for is how fast the I2C bus can run. The standard is 100KHz but there are chips that can run at 400KHz and even 1MHz. Each byte of data sent or received takes 10 clock cycles. So you count up how many bytes of data you can get from each sensor with one command, and add one for sending the address. Then you can calculate how long it will take to transfer one frame of data from one sensor. Then you multiply by 25 to find your fastest transfer rate.

That is not going to happen so if this is a hard requirement then the project can never work. There will always be latency, what you have to consider is how much you can accept for a useful system.

The more gestures you have the longer it takes to recognise which one you have just received. This requires a lot of processing. Basically you have to take what set of data you have received and compare this to all the data sets you have stored and see which one is the closest. This is given as a match probability for each possible gesture you have stored. The gesture with the biggest probability is then subject to a threshold test to see if it is big enough to say if the data received is close enough to say that this is one of your gestures or whether it was not one at all.

This sort of thing is called pattern matching and it takes a lot of processing time. The best you can do to get a flavor of what is needed is to run some of the examples that come with the Arduino port of the Tensor Flow package.
https://www.arduino.cc/reference/en/libraries/arduino_tensorflowlite/
To run these examples you will need a Nano 33 BLE sense Arduino. I must say I was not too impressed with the gesture recognition example they have, but I didn't play about it for too long. This sort of thing is not exactly a beginners project but gives you a big step up into what sorts of things need to be done.

One musician I know (to talk to) is called Kris Halpin, he uses Mi.Mu Gloves donated to him by Imogen Heap. He is disabled and increasingly unable to use conventional instruments. These gloves cost about £25K, and are fitted with sensors. This allows him to make gestures that are translated into sound for his performances, much like you want to do. Here is a video of him performing some music.
https://www.youtube.com/watch?v=WNU7JGUwB98

This is a video of where it all worked and there is a tremendous effort required to set up his gestures that can change what instruments they trigger throughout the song. So even when you have the basic data acquisition system working it is a big step integrating them into this level of performance.

1 Like

Sorry for the delayed reply, it was a lot to process and I only had time the last few days.

first off, thanks for the in-depth replies! I found them really helpful.

I found my module has some contacts you need to bridge to enable it, so that should make it easy.

yep, like that. I've wired the circuit, and ran into some other problem (below) but I think I got it.

A question that came up was what is the difference between I2C clock speed and baud rate? I couldn't find anything useful on the topic online. Do I need to observe anything in terms of synchronization?

Also, timing in general, how do the clocks synchronize on the I2C bus? I imagine there's a lot of traffic and I'm not quite have a mental image yet how to optimize the reading, if that makes sense.

sorry about that, I phrased it wrong. didn't mean 'gestures' in that sense, more like direction, speed and light intensity. no need for an algorithm to recognise me drawing a circle on the thing. I'm using optical flow measurements in MaxMSP and hope it will do the trick. so far it seems promising, provided I can get the latency low enough.

I adapted some sketches that I found online and tried to test it with two TCA multiplexers (two APDS9960 sensors on each multiplexer), but getting no signal from three of the four sensors.

I know remote-diagnosing this is a bit of an impossibility, but wondering if anyone could have a look at this and find any obvious mistakes I'm not seeing? been looking at this for too long.

#include <Wire.h>
#include "Adafruit_APDS9960.h" /*include wire + sensor library*/
Adafruit_APDS9960 apds;

byte tcaI2CAddress[] = {0x70, 0x71}; /*define array containing all the addresses*/
byte numberOfTCAs = 2; /* define number of TCAs used */
byte numberOfDevicesPerTCA = 2; /* define number of Sensors per TCA */
const int numberOfDevices = 4; /* define number of total devices */

void setup(void) 
{
  Serial.begin(115200);
  Serial.println("I2C Scanner ready.");
  Serial.println();
  
  pinMode(2, OUTPUT); /* sets pin 2 as output for changing the TCAs address */
  
  for(int i=0; i<numberOfDevices; i++){ /* run sensor setup function for each sensor */
    setupSensor(i);
  }

}

void loop(void){
  
digitalWrite(2, HIGH); /* sets pin 2 to HIGH for changing one of the TCAs address */
  
scanI2C(100000); /* run scanner at normal I2C speed */

  Serial.println("****************************");
  Serial.println();

for(int i=0; i<numberOfDevices; i++){ /* loop for # of devices */

  byte tca = setTCAAndChannel(i); /* call function that sets the right TCA and channel */

  uint16_t r[i], g[i], b[i], c[i]; /* define variables to be filled with rgbc values */
  
  /*wait for color data to be ready*/
  while(!apds.colorDataReady()){ 
    delay(5);
  }

  /*get the data and print the different channels*/
  apds.getColorData(&r[i], &g[i], &b[i], &c[i]);
  Serial.print("red.");
  Serial.print(i);
  Serial.print(": ");
  Serial.print(r[i]);
  
  Serial.print(" green.");
  Serial.print(i);
  Serial.print(": ");
  Serial.print(g[i]);
  
  Serial.print(" blue.");
  Serial.print(i);
  Serial.print(": ");
  Serial.print(b[i]);
  
  Serial.print(" clear.");
  Serial.print(i);
  Serial.print(": ");
  Serial.println(c[i]);
  Serial.println();

  disableTCA(tca); /* disable TCA again */
  
}
  Serial.println("****************************"); 
  Serial.println();
  delay(500);
}


/*********************************************************************************/
/*********************************************************************************/


byte setTCAAndChannel(byte i){ /* define function for setting TCA and sensor */
  byte tca = i/numberOfTCAs; /* divide i (total # of devices) by # of TCAs, that way because it's int, 1,5 will still be 1, thereby selecting the correct TCA */
  byte channel = i%numberOfDevicesPerTCA; /* modulo... divide i (the total number of devices) by the # of devices per TCA and give the rest, e.g. 2%4 = 0*/
  
  Wire.beginTransmission(tcaI2CAddress[tca]); /* choose TCA by its address */
  Wire.write(1 << channel); /* channel = sensor to talk to */
  Wire.endTransmission();
  return tca; 
}

void disableTCA(byte tca){ /* define function for disabling the TCA */
  Wire.beginTransmission(tcaI2CAddress[tca]);
  Wire.write(0);
  Wire.endTransmission();  
}

void setupSensor(byte i){ /* define sensor setup function */
  byte tca = setTCAAndChannel(i); /* set TCA and channel (see above) */
  
  if(!apds.begin()){ /* if initialization fails */
    Serial.print("Failed to initialize device ");
    Serial.print(i);
    Serial.println("! Please check your wiring.");
    Serial.println();
  }
  else Serial.print("Device "); /* if initialization successful */
  Serial.print(i);
  Serial.println(" initialized!");
  Serial.println();

  /*enable color sensing mode*/
  apds.enableColor(true);

  disableTCA(tca); /* disable TCA again */
}

void scanI2C(long frequency){ /* define I2C scanner function */
  String normal = "standard mode (100 kHz):";
  String fast = "fast mode (400 kHz):";
  String fastPlus = "fast mode plus (1 MHz):";
  String highSpeed = "high speed mode (3.4 MHz):";
  String ultraSpeed = "ultra fast mode (5.0 MHz):";
  String defaultStr = " !!!!! Invalid Frequency !!!!!";
  bool error = true;
  bool addressFound = false;
      
  Serial.print("Scanning in ");
  switch(frequency){
    case 100000:
      Serial.println(normal);
      break;
    case 400000:
      Serial.println(fast);
      break;
    case 1000000:
      Serial.println(fastPlus);
      break;
    case 3400000:
      Serial.println(highSpeed);
      break;
    case 5000000:
      Serial.println(ultraSpeed);
      break;
    default:
      Serial.println(defaultStr);
      break;
  }
  
  Wire.setClock(frequency);
  for(int i=1; i<128; i++){ /* go through addresses to see if current one can be found */
    Wire.beginTransmission(i);
    error = Wire.endTransmission();
    if(error == 0){
      addressFound = true;
      Serial.print("0x");
      Serial.println(i,HEX);
    }
  }
  if(!addressFound){
    Serial.println("no address found");
  }
  Serial.println();
}

The multiplexers have three address selection pins and you only have four multiplexers. What is pin 2 used for ?

You need a object for each sensor. Each sensor has to be initialized with its own object.

Adafruit_APDS9960 apds[25];  // all 25 of them !
...
apds[i].begin()   // all 25 of them !

You could make a function that selects one channel and turns off the other multiplexers. That would result into turning off multiplexers that are already turned off, but the using that function will be easier in the rest of the sketch.

The clock speed is measured in Hz, it used to be called cycles per second, in the context of I2C the term Baud rate is meaningless, but then you measure it in an oscilloscope it is exactly the same as the clock rate. Why are you bringing the term Baud rate into your thinking? A Baud is a bit of information per second, which is why we talk of Baud rate and not Baud speed. Baud implies per second.

There is a difference between the two in that Baud rate also takes into account the modulation of the data where one clock cycle can impart more than one bit of information. For example if your incoming data signal could change in phase or amplitude or normally both, then the baud rate would change to be much higher but the data clock frequency would not. But in simple asynchronous serial date the two are the same, where as date encoded for a satellite TV picture, or tones sent down a telephone line in a modem, they are not. This is an advanced topic and not one likely to be encountered when programming an Arduino.

In I2C it takes 10 clocks to transfer a byte, most transactions involve you sending an address to talk to, one byte, an internal register to address, an other byte, and then the date byte you want to send or read. This is a bit simplified but good enough to do some ball park calculations.

No

The master device on the I2C bus generates the clock and sends it to all the other slave addresses on the bus. The master is the only device that can initiate contact. It sends the address of what device it wants to contact and engages with data transfer with that. All the other devices who are not address do nothing until an address is sent again.
So there is no way of optimising the readings, you can only read one device at a time. There is no need to synchronise anything because there is nothing to synchronise.
Most bus formats only allow one thing at once to interact with it.

Ironically (in the proper English use of the word) the USB is not actually a Bus despite its name.

Mh, not sure if I understand the question right. The standard address of the multiplexers is 0x70, so I use pin 2 on the Arduino to send a HIGH to one of the address pins (A0 in this case) of one multiplexer to change the address of one multiplexer to 0x71. For four, I'd need to adjust the code, but I'm currently testing with two.

Do you mean combine my setTCAAndChannel and disableTCA functions into one?


On a different note, I'm running the updated code but it's still throwing errors:

****************************

Failed to initialize device 0! Please check your wiring.

0 initialized!

Device 1 initialized!

Device 2 initialized!

Device 3 initialized!

Scanning in standard mode (100 kHz):
0x70

****************************

red.0: 0 green.0: 4 blue.0: 1 clear.0: 4

red.1: 0 green.1: 4 blue.1: 1 clear.1: 4

red.2: 5 green.2: 4 blue.2: 3 clear.2: 12

red.3: 15110 green.3: 15110 blue.3: 15110 clear.3: 15110

****************************

Scanning in standard mode (100 kHz):
0x70
0x71

****************************

red.0: 10 green.0: 8 blue.0: 6 clear.0: 24

red.1: 10 green.1: 8 blue.1: 7 clear.1: 24

red.2: 11 green.2: 8 blue.2: 7 clear.2: 24

red.3: 11 green.3: 8 blue.3: 9 clear.3: 24

****************************

Scanning in standard mode (100 kHz):
0x39
0x70

****************************

red.0: 8 green.0: 7 blue.0: 6 clear.0: 21

red.1: 0 green.1: 0 blue.1: 0 clear.1: 0

this is weird on many levels ...

  • the initialisation prompt says device0 can't be initialized and then in the next line says it was initialized.
  • the values for rgbc3 are way above what they should be (4097 is max when you test the sensors by themselves).
  • sometimes it says it's scanning 0x70 and sometimes it's scanning 0x39 (the sensor) AND 0x70 (the multiplexer) and sometimes it's apparently scanning both multiplexers at the same time (0x70 AND 0x71)
  • it just stops after a few rounds of scanning and freezes the serial monitor

Imma double check my wiring and code for the third time ... :confused:

Because I'm using serial.begin() as well as Wire.setClock(). I know what Wire.setClock() does and I see serial.begin() used in all the code examples so I realised I don't understand the difference or, more specifically, what they affect.

ah, how come?

Please don't do that. Can you keep all the multiplexers available all the time with different I2C addresses ?
That trick works with some I2C devices, but don't make it harder for yourself to finish this project, make it easier :relaxed:
Just plain straightforward without tricks is better in the end. See also the KISS principle.

Yes, it will take more time with unnecessary disabling already disabled multiplexers, but the sketch will be easier to test everything. It is just a suggestion. Stay with you code if you feel more comfortable with that.

If you only change a comma in the sketch, then I would like to have a look at the new sketch :microscope:

Because no two USB devices can connect to the same wires leading back to the same USB socket. To be able to connect two USB devices to the same socket, you need to use a USB hub. The hub acts as a kind of multiplexer/demultiplexer circuit (a little like your TCA multiplexers). It is not a dumb circuit where the USB wires are simply connected together inside the USB hub. Once the hub is connected, then, as always, only one usb device is connected to one usb socket.

But i2c is a bus, because many devices are connected to the same two wires. In your circuit, you might think that is not happening, as each sensor is connected to separate pins on the multiplexers. But the 4 multiplexers are connected to the same 2 pins on the Arduino.

Unfortunately not... I have one Adafruit where you can bridge some contact at the bottom to permanently change the address, but the other three are different models that need to permanently receive a HIGH to set the address. Might have to buy three more Adafruits if that makes things more straightforward :money_mouth_face:

ok this is me testing it with one multiplexer and two sensors only, just to see if the code throws errors. but it works fine. problems seem to start when there's more than one multiplexer involved.

#include <Wire.h>
#include "Adafruit_APDS9960.h" /*include wire + sensor library*/
Adafruit_APDS9960 apds[2];

byte tcaI2CAddress[] = {0x70}; /*define array containing all the addresses*/
byte numberOfTCAs = 1; /* define number of TCAs used */
byte numberOfDevicesPerTCA = 2; /* define number of Sensors per TCA */
const int numberOfDevices = 2; /* define number of total devices */

void setup(void) 
{
  Serial.begin(115200);
  Serial.println("I2C Scanner ready.");
  Serial.println();
  
  pinMode(2, OUTPUT); /* sets pin 2 as output for changing the TCAs address */
  
  for(int i=0; i<numberOfDevices; i++){ /* run sensor setup function for each sensor */
    setupSensor(i);
  }

}

void loop(void){
  
digitalWrite(2, HIGH); /* sets pin 2 to HIGH for changing one of the TCAs address */
  
scanI2C(100000); /* run scanner at normal I2C speed */

  Serial.println("****************************");
  Serial.println();

for(int i=0; i<numberOfDevices; i++){ /* loop for # of devices */

  byte tca = setTCAAndChannel(i); /* call function that sets the right TCA and channel */

  uint16_t r[i], g[i], b[i], c[i]; /* define variables to be filled with rgbc values */
  
  /*wait for color data to be ready*/
  while(!apds[i].colorDataReady()){ 
    delay(5);
  }

  /*get the data and print the different channels*/
  apds[i].getColorData(&r[i], &g[i], &b[i], &c[i]);
  Serial.print("red.");
  Serial.print(i);
  Serial.print(": ");
  Serial.print(r[i]);
  
  Serial.print(" green.");
  Serial.print(i);
  Serial.print(": ");
  Serial.print(g[i]);
  
  Serial.print(" blue.");
  Serial.print(i);
  Serial.print(": ");
  Serial.print(b[i]);
  
  Serial.print(" clear.");
  Serial.print(i);
  Serial.print(": ");
  Serial.println(c[i]);
  Serial.println();

  disableTCA(tca); /* disable TCA again */
  
}
  Serial.println("****************************"); 
  Serial.println();
  delay(500);
}


/*********************************************************************************/
/*********************************************************************************/


byte setTCAAndChannel(byte i){ /* define function for setting TCA and sensor */
  byte tca = i/numberOfTCAs; /* divide i (total # of devices) by # of TCAs, that way because it's int, 1,5 will still be 1, thereby selecting the correct TCA */
  byte channel = i%numberOfDevicesPerTCA; /* modulo... divide i (the total number of devices) by the # of devices per TCA and give the rest, e.g. 2%4 = 0*/
  
  Wire.beginTransmission(tcaI2CAddress[tca]); /* choose TCA by its address */
  Wire.write(1 << channel); /* channel = sensor to talk to */
  Wire.endTransmission();
  return tca; 
}

void disableTCA(byte tca){ /* define function for disabling the TCA */
  Wire.beginTransmission(tcaI2CAddress[tca]);
  Wire.write(0);
  Wire.endTransmission();  
}

void setupSensor(byte i){ /* define sensor setup function */
  byte tca = setTCAAndChannel(i); /* set TCA and channel (see above) */
  
  if(!apds[i].begin()){ /* if initialization fails */
    Serial.print("Failed to initialize device ");
    Serial.print(i);
    Serial.println("! Please check your wiring.");
    Serial.println();
  }
  else Serial.print("Device "); /* if initialization successful */
  Serial.print(i);
  Serial.println(" initialized!");
  Serial.println();

  /*enable color sensing mode*/
  apds[i].enableColor(true);

  disableTCA(tca); /* disable TCA again */
}

void scanI2C(long frequency){ /* define I2C scanner function */
  String normal = "standard mode (100 kHz):";
  String fast = "fast mode (400 kHz):";
  String fastPlus = "fast mode plus (1 MHz):";
  String highSpeed = "high speed mode (3.4 MHz):";
  String ultraSpeed = "ultra fast mode (5.0 MHz):";
  String defaultStr = " !!!!! Invalid Frequency !!!!!";
  bool error = true;
  bool addressFound = false;
      
  Serial.print("Scanning in ");
  switch(frequency){
    case 100000:
      Serial.println(normal);
      break;
    case 400000:
      Serial.println(fast);
      break;
    case 1000000:
      Serial.println(fastPlus);
      break;
    case 3400000:
      Serial.println(highSpeed);
      break;
    case 5000000:
      Serial.println(ultraSpeed);
      break;
    default:
      Serial.println(defaultStr);
      break;
  }
  
  Wire.setClock(frequency);
  for(int i=1; i<128; i++){ /* go through addresses to see if current one can be found */
    Wire.beginTransmission(i);
    error = Wire.endTransmission();
    if(error == 0){
      addressFound = true;
      Serial.print("0x");
      Serial.println(i,HEX);
    }
  }
  if(!addressFound){
    Serial.println("no address found");
  }
  Serial.println();
}

That makes perfect sense, thank you!