i2c adresse changes by itself ?

Hello everyone,
I have a to deal with a big Problem and i can't find a solution for it ...
I want to contorle an digital led strip ( ws2811), with the Raspberry,
but it's direktly not possible, so i have to use an Arduino for it.
My idea was to send 4 Variables ( Red, Green, Blue,Mode) to it over i2c.
At first it worked pretty well, but now the slave dissapers, get's an other adress
and then get's back to it's old adress.
Because of that there is now way to send the data stable to the Arduino.
both are running at 400khz.

here is the python script on the Raspberry i'm using :

#!/usr/bin/python

import smbus
import time
bus = smbus.SMBus(1)
address = 0x47




def writeNumber(r,g,b,m):

    
    bus.write_byte(address, m)
    
    bus.write_byte(address, r)
    
    bus.write_byte(address, g)
    
    bus.write_byte(address, b)
    time.sleep(0.05)
    #bus.write_byte(address, m)
    # bus.write_byte_data(address, 0, value)
    return -2
    
    
    
    
mode = int(input("Modus:" ))
red = int(input("Rotwert:"))    
green = int(input("Gruenwert:"))
blue = int(input("Blauwert:"))

writeNumber(red,green,blue,mode)

and here the arduino code

#include <Wire.h>
#define SLAVE_ADDRESS 0x47
#define lengtharray 4
#include <FastLED.h>
#define NUM_LEDS 100
#define DATA_PIN 8
#define TWI_FREQ_SETTING         400000L 
#define CPU_FREQ                 16000000L
 CRGB leds[NUM_LEDS];





int ledscontrole[lengtharray]; // laenge der Modi array ( rot gruen blau modus )
int i = 0;  // zaehlervariable fuer das array  
int red = 0;  // rgbwert fuer rot 0-255
int blue = 0;  // rgbwert fuer blau 0-255
int green = 0;  // rgbwert fuer gruen 0-255
int mode = 0;  // modus

/////////// Metoershower ///////////
uint8_t hue = 32;
byte idex = 255;
byte meteorLength = 29;
//////////////////////

//////////Rainbow///////////
uint8_t max_bright = 128;
uint8_t thisdelay = 1;
uint8_t thishue; 
uint8_t deltahue = 10; 
///////////////////////






void setup() {
   
    Serial.begin(9600);       // print output  
    TWBR = ((CPU_FREQ / TWI_FREQ_SETTING) - 16) / 2;
    Wire.begin(SLAVE_ADDRESS);  // adruino slvae adress
    Wire.onReceive(receiveData);  // baudraht "oeffnen"
    FastLED.addLeds<WS2811, DATA_PIN>(leds, NUM_LEDS); // definieren der leds
  
   

}


void receiveData(int byteCount){

  while(Wire.available()) { 
         
       ledscontrole[i++]=Wire.read();
     }
    
  }
     
void loop() {
  
  
  red = ledscontrole[1];
  green = ledscontrole[2];
  blue = ledscontrole[3];
  mode = ledscontrole[0];
  Serial.println(mode);
  
   i =0;
 
  delay(5);
  
  switch (mode){
    case 0:
    ledstriptest();
    
    break;
    case 1:
    meteorShower(); 
    
    break;
    case 2:
    rainbow_march();
    delay_at_max_brightness_for_power(2.5*thisdelay);
  
    break;
    case 3:
    strobe();
    
    break;
    case 4:
    test();
    break;
    case 5:
    backnforth();
    break;
    case 6:
    hinherrandom();
    break;
    case 7:
    hinherschwarz();
    break;
    default:
    test();
    break;
    
   
  }
  
  


  
}

void ledstriptest(){
  
  for (int i = 0; i < NUM_LEDS;i++){
 leds[i] = CRGB (green,red,blue);
  FastLED.show();
  }
  
}

void test(){
LEDS.showColor(CRGB (green,red,blue));
}






////////////// Rainbow //////////
void rainbow_march() { // The fill_rainbow call doesn't support brightness levels
thishue++; // Increment the starting hue.
fill_rainbow(leds, NUM_LEDS, thishue, deltahue); // Use FastLED's fill_rainbow routine.
} 
///////////////////////////////






///////// meteorShower///////////

void meteorShower(){
  
  
  memmove8( &leds[1], &leds[0], (NUM_LEDS - 1) * 3 );
 
  
  idex++;
  
  if ( idex > meteorLength ) {
    idex = 0;
   
    hue += 32;  
  
  }
 

  switch ( idex ) {
  case 0:
    leds[0] = CRGB(200,200,200);
    break;
  case 1:
    leds[0] = CHSV((hue - 20), 255, 210);
    break;
  case 2:
    leds[0] = CHSV((hue - 22), 255, 180);
    break;
  case 3:
    leds[0] = CHSV((hue - 23), 255, 150);
    break;
  case 4:
    leds[0] = CHSV((hue - 24), 255, 110);
    break;
  case 5:
    leds[0] = CHSV((hue - 25), 255, 90);
    break;
  case 6:
    leds[0] = CHSV((hue - 26), 160, 60);
    break;
  case 7:
    leds[0] = CHSV((hue - 27), 140, 40);
    break;
  case 8:
    leds[0] = CHSV((hue - 28), 120, 20);
    break;
  case 9:
    leds[0] = CHSV((hue - 29), 100, 20);
    break;
  default:
    leds[0] = CRGB::Black;
  }
 
 
  FastLED.show();  
  
  delay(50);
  
  
}
///////////////////// Metorshower ende ////////////////////////


//////////STrobe////////
void strobe() {


LEDS.showColor(CRGB (green,red,blue));
delay(20);


LEDS.showColor(CRGB::Black);
delay(20);


}


//////////////////////////Hin und her//////////
void backnforth(){
int de =10;




for(int k =0; k < NUM_LEDS-5; k++){
leds[k] =  CRGB (green,red,blue);
delay(de);
leds[k+1] = CRGB (green,red,blue);
delay(de);
leds[k+2] = CRGB (green,red,blue);
delay(de);
leds[k+3] =  CRGB (green,red,blue);
delay(de);
leds[k+4] = CRGB (green,red,blue);
delay(de);
leds[k+5] = CRGB (green,red,blue);

FastLED.show();
  
  
}
delay(200);
for(int k =NUM_LEDS-1; k >0; k--){

leds[k] =  CRGB ::Black;
delay(de);
leds[k-1] = CRGB ::Black;
delay(de);
leds[k-2] = CRGB ::Black;
delay(de);
leds[k-3] =  CRGB ::Black;
delay(de);
leds[k-4] = CRGB ::Black;
delay(de);
leds[k-5] = CRGB ::Black;
delay(de);
FastLED.show();

}
delay(200);
}
//////////////////////////////////////////////////

///////////////Hin her random//////////////
void hinherrandom(){
int rndr = random(255);
int rndb = random(255);
int rndg = random(255);
for(int i =0; i < NUM_LEDS; i+=5){
leds[i] =  CRGB (rndr,rndb,rndg);
delay(10);
leds[i+1] = CRGB (rndr,rndb,rndg);
delay(10);
leds[i+2] = CRGB (rndr,rndb,rndg);
delay(10);
leds[i+3] = CRGB (rndr,rndb,rndg);
delay(10);
leds[i+4] = CRGB (rndr,rndb,rndg);

FastLED.show();

delay(200);
  
  
  
  
}
rndr = random(255);
rndb = random(255);
rndg = random(255);
for(int k =NUM_LEDS-1; k > 0 ; k-=5){
leds[k] =  CRGB (rndr,rndb,rndg);
delay(10);
leds[k-1] = CRGB (rndr,rndb,rndg);
delay(10);
leds[k-2] = CRGB (rndr,rndb,rndg);
delay(10);
leds[k-3] = CRGB (rndr,rndb,rndg);
delay(10);
leds[k-4] = CRGB (rndr,rndb,rndg);

FastLED.show();
Serial.println(k);
delay(200);

}

  
  
}
//////////////////////////////////////////

//////////// Hin und her mit schwarz /////////
void hinherschwarz(){
int de = 5;



for(int i =0; i < NUM_LEDS-5; i++){
leds[i] =  CRGB (green,red,blue);
delay(de);
leds[i+1] = CRGB (green,red,blue);
delay(de);
leds[i+2] = CRGB (green,red,blue);
delay(de);
leds[i+3] =  CRGB (green,red,blue);
delay(de);
leds[i+4] = CRGB (green,red,blue);
delay(de);
leds[i+5] = CRGB (green,red,blue);

FastLED.show();
leds[i] =  CRGB ::Black;
delay(de);
leds[i+1] = CRGB ::Black;
delay(de);
leds[i+2] = CRGB ::Black;
delay(de);
leds[i+3] =  CRGB ::Black;
delay(de);
leds[i+4] = CRGB ::Black;
delay(de);
leds[i+5] = CRGB ::Black;
delay(de);


  
  
  
  
}

for(int i =NUM_LEDS-5; i >0; i--){
delay(de);
leds[i] =  CRGB (green,red,blue) ;
delay(de);
leds[i-1] = CRGB (green,red,blue);
delay(de);
leds[i-2] = CRGB (green,red,blue);
delay(de);
leds[i-3] =  CRGB (green,red,blue);
delay(de);
leds[i-4] = CRGB (green,red,blue);
delay(de);
leds[i-5] = CRGB (green,red,blue);

FastLED.show();
leds[i] =  CRGB ::Black;
delay(de);
leds[i-1] = CRGB ::Black;
delay(de);
leds[i-2] = CRGB ::Black;
delay(de);
leds[i-3] =  CRGB ::Black;
delay(de);
leds[i-4] = CRGB ::Black;
delay(de);
leds[i-5] = CRGB ::Black;
delay(de);


}
}





/////////////////////////////////////

I hope you guys can help me, i count on you !

thank you :slight_smile:

give it a try at 100KHz?

Same problem :confused:

Please provide a wiring diagram or a (sharp) photograph of your setup.

My guess are either wrong pullups, missing GND connection or too long signal lines. If you don't use a level converter, 400kHz is probably out of reach, I would recommend one even with 100kHz.

Have you seen this about direct control of WS2811 from RPi

my Setup :

I don't see any pullup resistors on the SDA and SCL lines.
.

Do i realy need pullup resistors or a levelshifter ?
the arudino is just running as slave.

Use a o-scope or voltmeter to check. Most schematics that interface I2C on RPi to Arduino show two pullup resistors for each side of the logic level converter, one for the SDA and one for SCL, like this circuit.

edit: Some logic level converters have the pullup resistors onboard, like this one.

I don't see a level converter. This means that the internal (weak) pull-up of the Arduino may be active which pulls the I2C signals of the Raspberry Pi to 5V. That may damage the Raspberry Pi circuits. You should use a level converter or at least pull the signals up to 3V3 with a 2k2 resistor.

So I bought the level shifter :

and wired everything up but i still have the same problem...
so i played a little bit with the code.
If just have wire on read and save everything to one variable it's works fine...
Is it possible to send an array to the arduino and not 4 numbers one after the other ?

If just have wire on read and save everything to one variable it's works fine...

Can you please post the code that now works, so that we can compare?

bus.write_byte(address, m)
bus.write_byte(address, r)
bus.write_byte(address, g)
bus.write_byte(address, b)

I am not familiar with the Python library you are using, but I wonder if each of these statements sends an I2C stop condition after each byte of data? The Arduino receive handler would then be triggered for each byte individually, and therefore write each byte into the first array element.

Just did a quick search on SMBUS I2C for the Pi.

Have a look at the section "I2C Access Functions" and the code example on this page:

http://www.raspberry-projects.com/pi/programming-in-python/i2c-programming-in-python/using-the-i2c-interface-2

#Write an array of registers
ledout_values = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
bus.write_i2c_block_data(DEVICE_ADDRESS, DEVICE_REG_LEDOUT0, ledout_values)

I think this will write one I2C message to the device at DEVICE_ADDRESS. First data byte will be the value specified as DEVICE_REG_LEDOUT0 - in your program, this would be m. Then the rest of the data is the values in the array - you would need to change this to be just your r, g,b values.

If you decide to test this out, try adding more print statements to your Arduino program to check all the values that you receive, not just mode.

Thank you !
so i kicked some leds modes out of the code and it work, idk why but it works.
i only have the problem, i can only send the array one time and then i get an input/output error until i typ the command : "i2cdetect -y 1 ". After that it works for just 1 try...
i there any way to solve this problem ?

Please post the latest versions of your Arduino and Python code.

Arduino :

#include <Wire.h>
#define SLAVE_ADDRESS 0x47
#define lengtharray 4
#include <FastLED.h>
#define NUM_LEDS 100
#define DATA_PIN 8

 CRGB leds[NUM_LEDS];
 CRGB ledstritt[NUM_LEDS];




int ledscontrole[lengtharray]; // laenge der Modi array ( rot gruen blau modus )
int i = 0;  // zaehlervariable fuer das array  
int red = 0;  // rgbwert fuer rot 0-255
int blue = 0;  // rgbwert fuer blau 0-255
int green = 0;  // rgbwert fuer gruen 0-255
int mode = 0;  // modus
int trittred = 0;
int trittblue = 0;
int trittgreen = 0;


/////////// Metoershower ///////////
uint8_t hue = 32;
byte idex = 255;
byte meteorLength = 29;
//////////////////////

//////////Rainbow///////////
uint8_t max_bright = 128;
uint8_t thisdelay = 1;
uint8_t thishue; 
uint8_t deltahue = 10; 
///////////////////////






void setup() {
   
    Serial.begin(9600);       // print output  
    Wire.begin(SLAVE_ADDRESS);  // adruino slvae adress
    Wire.onReceive(receiveData);  // baudraht "oeffnen"
    FastLED.addLeds<WS2811, DATA_PIN>(leds, NUM_LEDS); // definieren der leds
    FastLED.addLeds<WS2811, 9>(ledstritt, NUM_LEDS); // definieren der ledstritt
  
   

}




void receiveData(int byteCount){

  while(Wire.available()) {               
       ledscontrole[i++]=Wire.read();
     }
    
  }
     
void loop() {
  
  mode = ledscontrole[0];
  red = ledscontrole[1];
  green = ledscontrole[2];
  blue = ledscontrole[3];
  trittred = ledscontrole[4];
  trittblue = ledscontrole[5];
  trittgreen = ledscontrole[6];
  
  
  
  Serial.println(mode);
  
   i =0;
 
  delay(10);
  
  
  
  switch (mode){
    case 0:
    ledstriptest();
    
    break;
    case 1:
  
    meteorShower(); 
    
    break;
    
    case 2:
    
    rainbow_march();
    delay_at_max_brightness_for_power(2.5*thisdelay);
  
     break;
    
     case 3:
    
      strobe();
     break;
  
    case 4:
    test();
    break;
    default:
    //ledstriptest();
    break;
    
   
  }
  
  


  
}

void ledstriptest(){
  
  for (int i = 0; i < NUM_LEDS;i++){
 leds[i] = CRGB (green,red,blue);
  FastLED.show();
  }
  
}

void test(){
LEDS.showColor(CRGB (green,red,blue));
}






////////////// Rainbow //////////
void rainbow_march() { // The fill_rainbow call doesn't support brightness levels
thishue++; // Increment the starting hue.
fill_rainbow(leds, NUM_LEDS, thishue, deltahue); // Use FastLED's fill_rainbow routine.
} 
///////////////////////////////






///////// meteorShower///////////

void meteorShower(){
  
  
  memmove8( &leds[1], &leds[0], (NUM_LEDS - 1) * 3 );
 
  
  idex++;
  
  if ( idex > meteorLength ) {
    idex = 0;
   
    hue += 32;  
  
  }
 

  switch ( idex ) {
  case 0:
    leds[0] = CRGB(200,200,200);
    break;
  case 1:
    leds[0] = CHSV((hue - 20), 255, 210);
    break;
  case 2:
    leds[0] = CHSV((hue - 22), 255, 180);
    break;
  case 3:
    leds[0] = CHSV((hue - 23), 255, 150);
    break;
  case 4:
    leds[0] = CHSV((hue - 24), 255, 110);
    break;
  case 5:
    leds[0] = CHSV((hue - 25), 255, 90);
    break;
  case 6:
    leds[0] = CHSV((hue - 26), 160, 60);
    break;
  case 7:
    leds[0] = CHSV((hue - 27), 140, 40);
    break;
  case 8:
    leds[0] = CHSV((hue - 28), 120, 20);
    break;
  case 9:
    leds[0] = CHSV((hue - 29), 100, 20);
    break;
  default:
    leds[0] = CRGB::Black;
  }
 
 
  FastLED.show();  
  
  delay(50);
  
  
}
///////////////////// Metorshower ende ////////////////////////


//////////STrobe////////
void strobe() {


LEDS.showColor(CRGB (green,red,blue));
delay(20);


LEDS.showColor(CRGB::Black);
delay(20);


}

Raspberry:

#!/usr/bin/python

import smbus
import time
bus = smbus.SMBus(1)
address = 0x47




def writeNumber(r,g,b,m,tr,tb,tg):

    a = [r,g,b,tr,tb,tg]
    bus.write_i2c_block_data(address, m , a)
    return -2
    
    
    
    
mode = int(input("Modus:" ))
red = int(input("Rotwert:"))    
green = int(input("Gruenwert:"))
blue = int(input("Blauwert:"))
tr = int(input("Rotwerttritt:"))    
tb = int(input("Gruenwerttritt:"))
tg = int(input("Blauwerttirtt:"))

writeNumber(red,green,blue,mode,tr,tb,t
#define lengtharray 4
int ledscontrole[lengtharray];
mode = ledscontrole[0];
red = ledscontrole[1];
green = ledscontrole[2];
blue = ledscontrole[3];
trittred = ledscontrole[4];
trittblue = ledscontrole[5];
trittgreen = ledscontrole[6];
a = [r,g,b,tr,tb,tg]
bus.write_i2c_block_data(address, m , a)

Writing beyond end of array!

Also, safer to declare your variable i as byte and make it volatile, since it is updated in the interrupt service routine and the main program:

volatile byte i = 0;  // zaehlervariable fuer das array

okay i changed my mistakes, but look a this:

how can this be explaind ? :confused:

is there an alternativ way to write data on the bus?
I mean without python ?

edit :
okay i finally made it...
i just made a while loop with an errorexception and with the "i2cdetect -y 1" call

and now it works

here the code

#!/usr/bin/python

import smbus
import time
import subprocess
import sys
bus = smbus.SMBus(1)
address = 0x47
flag = 0

def writeNumber(m,a):


    try:
        bus.write_i2c_block_data(address, m , a)
        flag = 0
    except IOError:
        subprocess.call(['i2cdetect', '-y', '1'])
        flag = 1
    return flag




m = int(input("Modus:" ))
r = int(input("Rotwert:"))    
g = int(input("Gruenwert:"))
b = int(input("Blauwert:"))


a = [r,g,b]

while writeNumber(m,a) == 1:
    print("fehler")

I was about to post a link to the same fix :slight_smile:

Looks like it may be due to a known issue related to clock stretching - see last post on this thread: Bulletproof I2C - Raspberry Pi Forums