changing I2C bus speed

Hello
I was trying to look at the I2C bus. I downloaded the master and slave sketches from the tutorials and adapted a "poor man's person's oscilloscope" Processing sketch I found on the internet to have two traces. The arduino part is:

#define ANALOG_IN_1 A4
#define ANALOG_IN_2 A5

void setup() {
  Serial.begin(115200); 
}

void loop() {
  int val1 = analogRead(ANALOG_IN_1);
  int val2 = analogRead(ANALOG_IN_2);
  Serial.write( 0xff);
  Serial.write( (val1 >> 8) & 0xff);
  Serial.write( val1 & 0xff);
  Serial.write( (val2 >> 8) & 0xff);
  Serial.write( val2 & 0xff);
}

The Processing part just graphs it.

Although the "scope" does appear to draw what is finds on the bus it seems to be way too slow to get the I2C signals or it is losing messages. I am not sure which. The signals are both just permanently high with an occasional (extremely) brief dip.

I tried to slow down the bus by changing

  #define TWI_FREQ 100L
//  #define TWI_FREQ 100000L

but this does not seem to have done it. I am not even sure if it worked.

Please help.

P.S. I want to look at the bus out of curiosity not for some application.
Thanks for taking the time to look
Mrs Z

I thought the I2C choices were 100KHz and 400KHz.

You don't seem to be doing any I2C transfers. What are you monitoring? The I2C clock and data line will only be active during a transfer.

Hi Crossraods
Thanks for the reply. I am running the master writer slave reader sketches on two Arduinos from

I have my Arduino no1 with the above sketch connected to the I2C bus along with them. The slave reader is receiving the information as it is printing it on a serial monitor on another serial port so the bus is definitely active.

As regards your comment about 100kHz or 400Khz does that mean I cannot slow it down by setting TWI_FREQ to 100L?

I have a setup like that on my table.
The maximum data transfer I get is about 8kbyte/s via the I2C bus.
So I tried to increase the I2C speed, but it was still 8kbyte/s.

The 100kHz and 400kHz are 'official' speeds. The Arduino should be able to set any value for the clock.

Thanks for this Erdin.

Am I changing the correct variable to bring the speed down?

To capture I2C a logic analyser would be better. Here is my simple attempt at a single channel device using an UNO & processing. I was thinking of updating it to 2 channels but lack of interest means it's not a priority ATM.

You could try the Arduino SUMP code Arduino Forum

Thanks Riva

Your sketch looks very useful. It seems to approach the problem in a dfferent way, reporting changes rather than using samples so there are less messages. I may update what I have to do a similar thing (once I have worked out how). I have never used interrupts so it will be a good learning experience.
I had seem the SUMP thread but it is way beyond my current level of knowledge as I am just a beginner.

Thanks again
Mrs Z.

From the datasheet:
22.5.2 Bit Rate Generator Unit
This unit controls the period of SCL when operating in a Master mode. The SCL period is controlled by settings in
the TWI Bit Rate Register (TWBR) and the Prescaler bits in the TWI Status Register (TWSR). Slave operation
does not depend on Bit Rate or Prescaler settings, but the CPU clock frequency in the Slave must be at least 16
times higher than the SCL frequency. Note that slaves may prolong the SCL low period, thereby reducing the average
TWI bus clock period. The SCL frequency is generated according to the following equation:

SCL frequency = (CPU Clock frequency)/(16 + 2 x (TWBR) PrescalerValue))

• TWBR = Value of the TWI Bit Rate Register.
• PrescalerValue = Value of the prescaler, see Table 22-7 on page 236."

I don't IDE access here, so I don't know how any of that meshes with:

#define TWI_FREQ 100L

This little tool is great for looking at this kind of thing:

Shows you the signals, can make fine time measurements, and it also decodes the bursts of data to show the byte being transmitted with every burst.
Save yourself up some money and pick one up if you can.
I used mine recently to fine tune some SPI.transfer code & confirm my code was able to spit out data really fast!
SPI can send data out with 8 MHz clock. 8 bits, 2 clock cycles/bit = 1uS per byte - I had 41 bytes going in 46uS, so pretty close to as fast as possible.

Zaplady:
I had seem the SUMP thread but it is way beyond my current level of knowledge as I am just a beginner.

I'm also new to processing and only just over a year old on arduino.
I just found this that may be helpful.

Thank you both for your help and suggestions.

CrossRoads:
This little tool is great for looking at this kind of thing:
Logic Analyzers from Saleae - #1 with Professional Engineers

:smiley: Crossroads, I can see that you are the person to ask when I need an excuse to buy myself a new toy ... :smiley:

Riva:
I'm also new to processing and only just over a year old on arduino.
I just found this that may be helpful.

This looks good. I can't work out how to port it to Arduino though. It is a bunch of C files and headers.
Over a year on Arduino! You are an oldie compared to me, Riva.

Thanks again both of you.
Mrs Z.

I can't work out how to port it to Arduino though. It is a bunch of C files and headers.

the idea is as follows (code not tested, and is definitely not a 1 to 1 translation of the other code)

int lastValue;

void setup()
{
  Serial.begin(115200);  // send data as fast as possible;
  DDRD = B00000010;     // sets Arduino pins  2 to 7 as inputs  ( 0 and 1 are serial port they are input and output )
  lastValue = PORTD & B11111100;     // read pins 2 to 7 , mask of bit 0, 1 (they are the serial port)
}

void loop()
{
  int x = PORTD & B11111100;
  if (x != lastValue)  // if a new value found for the pins 2 to 7
  {
    lastValue = x;   // remember it and 
    Serial.println(x, DEC);   // send it to the PC.
  }
}

DDRD is DataDirectionRegister D which handles the pinMode() of pins 0..7
PORTD is a register (8 bits) which reflects the values of pin 0..7

More about the PORTD and DDRD can be read on - Arduino Reference - Arduino Reference -

Thanks for this, robtillaart.
I think it would be much quicker to do it this way and use the two relevant bits in the port C register as I do not really care about having an analogue reading. I had not thought of that. This only leaves taking care of the time axis ...
Maybe I could use a timestamp in some way on the Arduino or Processing as I won't have a regular supply of samples?
Thanks again
Mrs Z.

I did some tests with the I2C bus speed.

The speed of 100kHz is fixed in the Wire library, and it is used in the Wire.begin() function. It is passed to the twi.c file which sets the TWBR register.

The TWBR register can be set faster and slower.
It is a 8-bits register and it is default 72.
The value of 72 makes it easy to change the speed without the need to change the prescaler.
A value of 255 makes it three and a half times slower.
A value of 18 makes it four times faster.

void setup()
{
  Serial.begin(9600);

  Serial.print( "1, TWBR = ");
  Serial.println( TWBR);  
  
  Wire.begin();

  Serial.print( "2, TWBR = ");
  Serial.println( TWBR);  

  TWBR = 18;

  Serial.print( "3, TWBR = ");
  Serial.println( TWBR);  
}

I don't have a logic analyzer, so I used a audio-attenuator to my PC line-in with Audacity at 96kHz.
Attached is a picture for the i2c scanner at normal speed, and with TWBR at 255 and at 18.

i2c-twbr.png

excuse to buy myself a new toy ...

Not toy - Tool, tell yourself, your spouse, your kids, your coworkers, its a tool 8)
And you can never have too many tools :wink:

Thank you everyone for the help.
After much experimentation using ports and all sorts, I now think I see the problem. My processing sketch refreshes the screen at 60Hz. The I2C bus runs at 100kHz. Even at one third of the speed (thanks for this Erdin - I was using the wrong variable) there is no chance of monitoring the bus in real time and being able to see what is going on. The best I could hope for would be to capture some data for half a second and plot it later.

Crossroads, how do I turn this into an excuse to buy a Due?

Thanks again
Mrs Z

How does having a Due change your screen refresh?
I think this shows the need for having a Saleae analyzer!
Real time monitoring - fast streaming numbers will not really tell you much.
Really need something that can process the data as it comes in and break it up or out so you can look at the relevant parts - like ignore everything but the data from the I2C device for example.