Go Down

Topic: i2c and A/D (Read 4 times) previous topic - next topic

Joegi

Mar 17, 2012, 08:34 pm Last Edit: Mar 18, 2012, 01:04 pm by Joegi Reason: 1
Hi,
I use the attached code to realise a VU-Meter with 11 LEDs connected to a TLC59116 LED-driver.
The TLC59116 is connected to the ARDUINO via i2c. I switched the i2c bus to 400kHz frquency (by replacing "#define TWI_FREQ 100000L" with "#define TWI_FREQ 400000L" in "twi.h").
The strange thing is that the higher the values are that i choose for "BRIGHTNESS" (which sets the PWM-brightness of the LEDs and is sent via i2c) the worse are the analog-values ("sample") that I get!
If I activate the "delay(10);" (it has to be at least a 10ms delay) after "Set_LED_NUM_PWM(s, BRIGHTNESS);" this behaviour is gone (and the A/D-values are good)! So it seems that the i2c bus transfer affects the a/d-converter although the Atmega doc says that i2c transfer should not affect the a/d-values!?
Code: [Select]

#define BRIGHTNESS 50
#define ZERO 500
#define MAXAVG 250
#define NUMSAM 100
.
.
int i, s, sample;
unsigned long sum;
.
.
void loop()
{
 sum = 0;
 for (i = 0; i < NUMSAM; i++)
 {
   sample = analogRead(A0);
   if (sample > ZERO) sample -= ZERO;
   else sample = ZERO - sample;
   sum += sample;
 }
 s = sum / NUMSAM * 11 / MAXAVG;
 if (s > 11) s = 11;
 Set_LED_NUM_PWM(s, BRIGHTNESS);//delay(10);
}
//--------------------------------------------------------------
void Set_LED_NUM_PWM(byte LED, byte PWM)
{
 Wire.begin();      // I2C-Start
 Wire.beginTransmission(B1100000);    // TLC59116 Slave Adress ->C0 hex
 Wire.write((byte)0x82);     // Startregister 02h
 for (i = 1; i <= LED; i++) Wire.write(PWM);    //set LEDs 1 to x to BRIGHTNESS
 for (; i < 12; i++) Wire.write((byte)0);    //switch off LEDs x+1 to 11
 Wire.endTransmission();    // I2C-Stop
}
.
.

Nick Gammon


Please edit your post, select the code, and put it between [code] ... [/code] tags.

You can do that by hitting the # button above the posting area.




To change the speed all you have to do is this:

Code: [Select]
Wire.begin ();
TWBR = 12;





Just do Wire.begin once (in setup), not like this:

Code: [Select]
void Set_LED_NUM_PWM(byte LED, byte PWM)
{
  Wire.begin();      // I2C-Start





Quote
I switched the i2c bus to 400kHz frquency ...


Doesn't seem to be much point if you have to throw in a 10 mS delay. But I suppose that's what the question is about.

In any case, isn't that over-egging the pudding? For a VU-meter, your eyes don't need the extra speed do they?




Quote
So it seems that the i2c bus transfer affects the a/d-converter although the Atmega doc says that i2c transfer should not affect the a/d-values!?


Well, it's not is it? You are really saying that if you send one number it works, and if you send a different number it doesn't? This sounds electrical to me. Like, the higher brightness is consuming too much power, and reducing the operation of something else.
http://www.gammon.com.au/electronics

Joegi

Quote

Doesn't seem to be much point if you have to throw in a 10 mS delay. But I suppose that's what the question is about.

In any case, isn't that over-egging the pudding? For a VU-meter, your eyes don't need the extra speed do they?


You are right, but I'm just interested why I/one need(s) the delay!

Quote
Well, it's not is it? You are really saying that if you send one number it works, and if you send a different number it doesn't? This sounds electrical to me. Like, the higher brightness is consuming too much power, and reducing the operation of something else.


You might be right, I will check this!

-Thanks!

Joegi

Quote

...You are really saying that if you send one number it works, and if you send a different number it doesn't? This sounds electrical to me. Like, the higher brightness is consuming too much power, and reducing the operation of something else.


You are right! I previously connected the complete electronics (TLC59116 + lm386 as main components) to the USB-Powered ARDUINO. Now I connected the ARDUINO to a 2,2A power supply and everything works fine, even without delay! Should have come to the reason for the problems by myself!

kzxm300

hey someone can helpme please?

i dont understand in this line
Wire.write((byte)0);

especify why add "((byte) 0)" 
what does when i add "(byte)"?

Nick Gammon

The compiler gets confused by the number 0, which might be a pointer or it might be a number. Putting (byte) there is a typecast which tells it which "version" of zero to use.
http://www.gammon.com.au/electronics

kzxm300


The compiler gets confused by the number 0, which might be a pointer or it might be a number. Putting (byte) there is a typecast which tells it which "version" of zero to use.

i see
thanks a lot.
greetings.

cappy2112

Quote from: Nick Gammon

To change the speed all you have to do is this:

Code: [Select]
Wire.begin ();
TWBR = 12;




Nick- where is this documented?
I've recently posted a question in another forum about how to change the I2C bus speed.

Nick Gammon

Here:

http://www.gammon.com.au/i2c

But I suppose you mean the "real" documentation?

Datasheet, page 241:

Quote
TWBR - TWI Bit Rate Register

TWBR selects the division factor for the bit rate generator. The bit rate generator is a frequency divider which generates the SCL clock frequency in the Master modes.


In twi.c is this:

Code: [Select]
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;


Where in twi.h is:

Code: [Select]
  #define TWI_FREQ 100000L

Now normally for a CPU speed of 16000000 that will give:

Code: [Select]
TWBR =  ((16000000 / 100000) - 16) / 2 = 72

And from the datasheet:

Quote
SCL frequency = CPU_FREQUENCY / (16 + 2(TWBR) * (PrescalerValue))


Where the prescaler happens to be 1 in this case.

So substituting, we get the SCL frequency:

Code: [Select]
16000000 / (16 + 2 * 72) = 100000

But if we change TWBR to 12 we get:

Code: [Select]
16000000 / (16 + 2 * 12) = 400000

Thus,  TWBR of 12 gives a clock four times as fast (400000 / 100000) compared to the default.
http://www.gammon.com.au/electronics

cappy2112


Here:

http://www.gammon.com.au/i2c

But I suppose you mean the "real" documentation?

Datasheet, page 241:

Quote
TWBR - TWI Bit Rate Register

TWBR selects the division factor for the bit rate generator. The bit rate generator is a frequency divider which generates the SCL clock frequency in the Master modes.


In twi.c is this:

Code: [Select]
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;


Where in twi.h is:

Code: [Select]
  #define TWI_FREQ 100000L

Now normally for a CPU speed of 16000000 that will give:

Code: [Select]
TWBR =  ((16000000 / 100000) - 16) / 2 = 72

And from the datasheet:

Quote
SCL frequency = CPU_FREQUENCY / (16 + 2(TWBR) * (PrescalerValue))


Where the prescaler happens to be 1 in this case.

So substituting, we get the SCL frequency:

Code: [Select]
16000000 / (16 + 2 * 72) = 100000

But if we change TWBR to 12 we get:

Code: [Select]
16000000 / (16 + 2 * 12) = 400000

Thus,  TWBR of 12 gives a clock four times as fast (400000 / 100000) compared to the default.


Thank you for all of that info.

What I am looking for is- what values need to be written to TBR to select the three I2C transfer modes.
You've answered that.

I wonder why the Wire library wasn't written with a simple method to select the transfer mode.
If I wanted to modify Wire to add such a method, where would I go to find out what the procedure is,
such that my changes will be evaluated to be included on upcoming releases?

Who is/are the maintainer(s) of Wire?


Nick Gammon

Wire is a core module - I suppose the Arduino team at GitHub would do that. However you might want to check out:

http://dsscircuits.com/articles/arduino-i2c-master-library.html

I haven't used it, but I believe it adds extra features.
http://www.gammon.com.au/electronics

jp11

Hi,

I found something interesting when using the TLC59116. In the code above (1st post), the following line is given:

Code: [Select]
Wire.beginTransmission(B1100000);    // TLC59116 Slave Adress ->C0 hex

However, the B1100000 is only 7 bits. If we make it 8 bits (B11000000), the TLC does not respond. Why is this?

Nick Gammon

What do you mean "make it 8 bits?"

The address is shifted left one by the Wire library.

http://www.gammon.com.au/i2c
http://www.gammon.com.au/electronics

Graynomad

I2C doesn't use the LSB for addressing, it's the R/W bit. Therefore the wire library takes your supplied address and left shifts it 1 bit, eg

address_used = your_addr << 1;

So B1100000 becomes B11000000 or B11000001 depending of it it's a read or write operation.

Similarly your B11000000 becomes B10000000 or B10000001 and you lose the upper bit.

______
Rob
Rob Gray aka the GRAYnomad www.robgray.com

jp11

@Graynomad, @Nick Gammon - Thanks! That clears things up.

Go Up