Go Down

Topic: Arduinos finden sich nicht über I2C (Read 4036 times) previous topic - next topic

schUk0

Hi,

ich möchte Messwerte von einem Nano auf einen Mega senden der diese dann auf einem Display darstellen soll.
An BEIDEN habe ich bereits erfolgreich ein I2C OLED Display betrieben.
Und mit einem Testsketch finden sie auch BEIDE das Display auf dem Bus aber ums Verrecken nicht den jeweils anderen
Arduino.

Da der Bus ja offensichtlich richtig verdrahtet ist und beide Geräte fähig sind darüber zu kommunizieren, bin ich jetzt
etwas Ratlos.
Würde auch nur ungern anders kommunizieren, da später wahrscheinlich mehr I2C Geräte dazu kommen.

Hoffe jemand anders hat noch eine schlaue Idee.

Gruß

schUk0

HotSystems

Da wir deinen Sketch nicht kennen, wissen wir nicht, was du falsch machst.

Wichtig ist, du solltest mit einem Master und einem Slave anfangen.
Das ist für den Anfang am einfachsten.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

schUk0

#2
Feb 18, 2017, 12:41 pm Last Edit: Feb 18, 2017, 12:46 pm by schUk0
Da wir deinen Sketch nicht kennen, wissen wir nicht, was du falsch machst.
Dachte das hatte ich schon...

Und mit einem Testsketch finden sie auch BEIDE das Display auf dem Bus aber ums Verrecken nicht den jeweils anderen
Arduino.

Aber dann nochmal ganz förmlich.

Code: [Select]
   
// --------------------------------------
    // i2c_scanner
    //
    // Version 1
    //    This program (or code that looks like it)
    //    can be found in many places.
    //    For example on the Arduino.cc forum.
    //    The original author is not know.
    // Version 2, Juni 2012, Using Arduino 1.0.1
    //     Adapted to be as simple as possible by Arduino.cc user Krodal
    // Version 3, Feb 26  2013
    //    V3 by louarnold
    // Version 4, March 3, 2013, Using Arduino 1.0.3
    //    by Arduino.cc user Krodal.
    //    Changes by louarnold removed.
    //    Scanning addresses changed from 0...127 to 1...119,
    //    according to the i2c scanner by Nick Gammon
    //    http://www.gammon.com.au/forum/?id=10896
    // Version 5, March 28, 2013
    //    As version 4, but address scans now to 127.
    //    A sensor seems to use address 120.
    // Version 6, November 27, 2015.
    //    Added waiting for the Leonardo serial communication.
    //
    //
    // This sketch tests the standard 7-bit addresses
    // Devices with higher bit address might not be seen properly.
    //
     
    #include <Wire.h>
     
     
    void setup()
    {
      Wire.begin();
     
      Serial.begin(9600);
      while (!Serial);             // Leonardo: wait for serial monitor
      Serial.println("\nI2C Scanner");
    }
     
     
    void loop()
    {
      byte error, address;
      int nDevices;
     
      Serial.println("Scanning...");
     
      nDevices = 0;
      for(address = 1; address < 127; address++ )
      {
        // The i2c_scanner uses the return value of
        // the Write.endTransmisstion to see if
        // a device did acknowledge to the address.
        Wire.beginTransmission(address);
        error = Wire.endTransmission();
     
        if (error == 0)
        {
          Serial.print("I2C device found at address 0x");
          if (address<16)
            Serial.print("0");
          Serial.print(address,HEX);
          Serial.println("  !");
     
          nDevices++;
        }
        else if (error==4)
        {
          Serial.print("Unknow error at address 0x");
          if (address<16)
            Serial.print("0");
          Serial.println(address,HEX);
        }   
      }
      if (nDevices == 0)
        Serial.println("No I2C devices found\n");
      else
        Serial.println("done\n");
     
      delay(5000);           // wait 5 seconds for next scan
    }


Und mit jedem anderen Sketch aus irgendwelchen Tutorials klappt es genauso gut...nämlich gar nicht.
Nur das Display funktioniert tadellos.

Dachte ja auch, dass es an dem eigentlich Sketch liegt, in dem es laufen soll.
Ab er momentan bekomme ich es ja nicht mal hin die Geräte im Bus zu finden. 


Trotzdem erstmal danke für die schnelle Antwort  :)

Gruß

schUk0

Edith sagt:

Serial Monitor auf dem Nano
Code: [Select]

Scanning...
I2C device found at address 0x3C  !
done


Und auf dem Mega

Code: [Select]

Scanning...
I2C device found at address 0x3C  !
done

Rabenauge

Das ist ein stinknormaler I2C-Scanner.
Der findet _nur_ I2C-Geräte.

Wenn du aber zwei Arduinos so miteinander verbinden willst, wird auf dem zweiten irgendwas laufen müssen, was überhaupt I2C bietet??
Du könntest also mal noch das Programm des Slaves hinzufügen.

Einfach so geht das natürlich nicht!
------------
Grüssle, Sly

HotSystems

#4
Feb 18, 2017, 12:50 pm Last Edit: Feb 18, 2017, 12:53 pm by HotSystems
Wir brauchen nicht den I2C-Scanner-Sketch, sondern deinen Sketch.

Und lies bitte meine letzte Antwort.
Du musst einen Arduino zum Master (ohne I2C-Adresse) machen und den zweiten zum Slave (mit I2C-Adresse) machen.
Dann kannst du vom Master Daten senden und der Slave antwortet drauf.
Es geht auch als Multi-Master-System, ist aber recht kritisch, da ja beide senden können und sich dabei evtl. in die Quere kommen.
Master-Slave

Edit:

Und mit gleichen Adressen im Bus wird das auch nichts.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

schUk0

Ok.. dann war das mit dem Testsketch nicht so eine pralle Idee...

Dann werde ich jetzt zum 500. mal die Master-Slave Sketche raufspielen und hoffen, dass es endlich geht.

Vielleicht hatte ich ja gestern Abend schon ein bisschen Tomaten auf den Augen.

Und mit gleichen Adressen im Bus wird das auch nichts.

Das ist die Adresse vom Display, das beide ja finden.


Und ich will meinen Sketch nicht verheimlichen, aber weil ich aus mehreren anderen Zwischenschritten  schlau geworden bin,
wollte ich erst mal die Kommunikation alleine bewerkstelligen und eventuell auch etwas herum probieren und dann in den "großen" Sketch einbinden.  


Trotzdem, wie gesagt, erstmal danke für die schnelle Hilfe.


Gruß

schUk0

HotSystems

#6
Feb 18, 2017, 01:22 pm Last Edit: Feb 18, 2017, 01:29 pm by HotSystems
Dann werde ich jetzt zum 500. mal die Master-Slave Sketche raufspielen und hoffen, dass es endlich geht.

Vielleicht hatte ich ja gestern Abend schon ein bisschen Tomaten auf den Augen.

Das ist die Adresse vom Display, das beide ja finden.
Dann hast du bei dem Aufbau etwas falsch gemacht.
Das funktioniert bei mir prima.
Wichtig ist, der Slave muss eine eigene Adresse haben, die der Master ansprechen muss.


Also die Displays müssen in einem Netz verschiedene Adressen haben.

Und in einem I2C-NetzWerk darf eine I2C-Adresse nur einmal vorhanden sein, sonst gibt es Probleme.

Edit:
Hier noch eine schöne Beschreibung, nach der man das sehr gut nachvollziehen kann:

I2C-Beschreibung
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

schUk0



Und natürlich gehts jetzt...

muss ich irgendwas beachten, wenn ich eine 5-stellige Zahl (z.B. 10350) senden möchte?


Gruß

schUk0

HotSystems

Ok, wunderbar.
Was war das Problem ?

Die Übertragung von Daten ist in dem oben verlinkten Beitrag auch beschrieben.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

schUk0

Ehrlich gesagt, ich weiß es noch nicht.
Wahrscheinlich hab ich dann irgendwo doch schon was anpassen wollen, was dann nicht so cool war.
Bei reinem C&P habe ich immer die Befürchtung den Sinn der Sache nicht zu verstehen.

Dein Link war echt gut... hat mir auch geholfen mit der Übertragung der großen Zahlen.
Hab was das angeht auch schon mit irgendwelchen dubiosen Libs rumgespielt die am Ende doch alles nur total überladen hätten und sooo einfach dann auch wieder nicht zu bedienen sind. Meiner Meinung nach.
Aber für meine 2 Werte, die ich übertragen will reicht die Wire.h scheinbar vollkommen.

hab mir daraus selber nen Testsketch zusammengefriemelt und der ging auch super.

Im eigentlichen Sketch geht es jetzt wieder nicht -.-

Obwohl ich es extra schon im kleinen genauso getestet habe wie ich es später brauche (Bezeichnung der Variablen, ohne delay, etc.).

Naja... werde noch ein paar Minuten rum probieren und wenn es dann nicht klappt melde ich mich nochmal.

Gruß

schUk0

HotSystems

hab mir daraus selber nen Testsketch zusammengefriemelt und der ging auch super.

Im eigentlichen Sketch geht es jetzt wieder nicht -.-

Obwohl ich es extra schon im kleinen genauso getestet habe wie ich es später brauche (Bezeichnung der Variablen, ohne delay, etc.).

Naja... werde noch ein paar Minuten rum probieren und wenn es dann nicht klappt melde ich mich nochmal.
Ok, dann aber mit deinem bisherigen Sketch, damit wir sehen woran es hakt.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

schUk0

So... dann jetzt Butter bei de Fische.

Hatte das alles schon zusammen auf einem Nano laufen.
Da hat der Picture-Loop aber die Messungen versaut.

Außerdem war er da Speicher-mäßig schon dicht an der Grenze.

Es gibt auch noch einen dritten im Bunde.
Ein Nano, der sie Impulse erzeugt.
Der ist aber nur an den Interrupt Eingängen des Sensors dran.

Der physische Aufbau wurde während des Testens nicht geändert, sollte also nicht als Ursache in Betracht kommen.
Wenn sich aber im Code nichts finden lässt, kann ich davon auch ein Foto posten.


Muss es leider aufteilen  ::)

HotSystems

Sketch niemals als Foto posten, das liest keiner durch.
Gruß Dieter

I2C = weniger ist mehr: weniger Kabel, mehr Probleme. 8)

schUk0

Der Code vom Sensor-Nano:

Code: [Select]
//Bordcomputer Slave (Sensor)
//with 74HC595 LED-Bargraph

//I2C Master


//library for I2C
#include <Wire.h>
//library for EEPROM access
#include <EEPROM.h>

//I2C slave address
int slaveAddress = 2;


//Pin connected to ST_CP of 74HC595
int latchPin = 8;
//Pin connected to SH_CP of 74HC595
int clockPin = 9;
////Pin connected to DS of 74HC595
int dataPin = 10;


//
//RPM
//
volatile int ignitionCount;
//ignition pickup input | Interrupt-Pin
int interPin1 = 2;
unsigned long t;
//period between 2 ignitions
float period = 0.0;
//variable to store the RPM
unsigned long rpm = 20;
float fCrank = 0.0;


//
//Speed
//
//EEPROM address for the wheel circumference value.
//Don't change this if you don't EXAKTLY know what you're doing !
int wheelCircAddress = 1;
//wheel-circumference in mm
int wheelCirc;
volatile int wheelRevolutions;
unsigned long t1;
float fWheel = 0.0;
int interPin2 = 3;
const float pi = 3.142;
int vel;
int numberOfWheelsensors=1;
int numberOfWheelsensorsAddress=2;





//Byte-Array for the LED-Bargraph
byte data[9] {B00000000, B00000001, B00000011, B00000111, B00001111, B00011111, B00111111, B01111111, B11111111};
int val;


void setup() {
  // put your setup code here, to run once:
 
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);

  t = millis();
  t1=millis();

 
  attachInterrupt(digitalPinToInterrupt(interPin1),isIgnition,RISING);
  ignitionCount;
  attachInterrupt(digitalPinToInterrupt(interPin2),isRev,RISING);
  wheelRevolutions=0;
 
  Serial.begin(9600);
  Wire.begin();

  EEPROM.get(wheelCircAddress,wheelCirc);
  //EEPROM.get(numberOfWheelsensorsAddress,numberOfWheelsensors); 


}


//ISR for the Speed
void isIgnition() {
  ignitionCount++;
}


//ISR for the Speed
void isRev() {
  wheelRevolutions++;
}

//2 bytes
void sendRPM(int x){
  Wire.beginTransmission(slaveAddress);  // begin transmission to slave device
  Wire.write(x & 0xff);       // send first byte
  Wire.write(x >> 8);         // send second byte shiftet by 8 bits
  Wire.endTransmission();     // stop transmitting
}

//1 byte
void sendSpeed(int x){
  Wire.beginTransmission(slaveAddress); 
  Wire.write(x);
  Wire.endTransmission();     
}


void loop() {

 

  //calculate the RPM
  if (ignitionCount > 20){
       
    detachInterrupt(digitalPinToInterrupt(interPin1));//Disable interrupt when calculating
   
    fCrank = (1/(((millis()-t)/ignitionCount)/1000.0));
    rpm = fCrank * 60;
    ignitionCount = 0;
   
    Serial.print("Crank frequency  ");
    Serial.println(fCrank);
    Serial.print("RPM  ");
    Serial.println(rpm);
    Serial.println("-------------");
   
    sendRPM(rpm);
 

    //drive the LED-Bar
    val = map(rpm, 0, 12000, 0, 8);
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, data[val]);
    digitalWrite(latchPin, HIGH);

       
    attachInterrupt(digitalPinToInterrupt(interPin1),isIgnition,RISING);
    t=millis();
  }


 

 

  //calculate the Speed
  if (wheelRevolutions > 0){
       
    detachInterrupt(digitalPinToInterrupt(interPin2));//Disable interrupt when calculating
   
    fWheel = (1/(((millis()-t1)/wheelRevolutions)/1000.0));
    vel=(((wheelCirc*pi*(fWheel*60))/1000)*60)/1000;
    vel=vel/numberOfWheelsensors;
    wheelRevolutions=0;
   
    Serial.print("Wheel frequency  ");
    Serial.println(fWheel);
    Serial.print("Speed  ");
    Serial.println(vel);
    Serial.println("-----------------");

    //sendSpeed(vel);
   
    attachInterrupt(digitalPinToInterrupt(interPin2),isRev,RISING);
    t1=millis();
  }

 
}



Der Code vom Pulsgeber-Nano

Code: [Select]

int rpm;
int vel;
unsigned long t1;
unsigned long t2;


#define rpmIn   A0  //rpm input pin 100k Pot
#define rpmOut  13
#define velIn   A1  //speed input pin 10k Pot
#define velOut  11

void setup() {
  // put your setup code here, to run once:
pinMode(rpmIn,INPUT);
pinMode(rpmOut,OUTPUT);
pinMode(velIn,INPUT);
pinMode(velOut,OUTPUT);
Serial.begin(9600);

}

void rpmPulse(int rpmIn, int pin, int onTime){

  //rpm=map(analogRead(rpmIn),0,1024,150,1);
  rpm=map(analogRead(rpmIn),0,1024,6,300);
 
  if (t1 + rpm < millis()){
      digitalWrite(pin,HIGH);
      t1=millis();     
    }
 
  if (t1 + onTime < millis()){
      digitalWrite(pin,LOW);   
    }
}

void velPulse(int rpmIn, int pin, int onTime){

  rpm=map(analogRead(rpmIn),0,1024,1500,100);
 
  if (t2 + rpm - onTime < millis()){
      digitalWrite(pin,HIGH);
      t2=millis();   
    }
 
  if (t2 + onTime < millis()){
      digitalWrite(pin,LOW);
    }
}

void loop() {
  // put your main code here, to run repeatedly:

 
  rpmPulse(rpmIn,rpmOut,2);
  velPulse(velIn,velOut,1);

 //Serial.println (rpm);
   
   
}



Und noch die funktionierenden Master-Slave Sketche

Code: [Select]
   // Wire Master Writer
// by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates use of the Wire library
// Writes data to an I2C/TWI slave device
// Refer to the "Wire Slave Receiver" example for use with this

// Created 29 March 2006

// This example code is in the public domain.


#include <Wire.h>

int slaveAddress=2;

void sendRPM(int x){
  Wire.beginTransmission(slaveAddress); // transmit to device #8
  Wire.write(x & 0xff);        // sends five bytes
  Wire.write(x >> 8);              // sends one byte
  Wire.endTransmission();    // stop transmitting

}

void setup() {
  Serial.begin(9600);
  Wire.begin(); // join i2c bus (address optional for master)
}



void loop() {
  unsigned long t = millis();
  int x = random(0,12000) ;
  sendRPM(x);
  //delay(10);
  Serial.println(millis() - t);
}


Code: [Select]
// Wire Slave Receiver
// by Nicholas Zambetti <http://www.zambetti.com>

// Demonstrates use of the Wire library
// Receives data as an I2C/TWI slave device
// Refer to the "Wire Master Writer" example for use with this

// Created 29 March 2006

// This example code is in the public domain.


#include <Wire.h>

int rpm;

void setup() {
  Wire.begin(2);                // join i2c bus with address #8
  Wire.onReceive(receiveEvent); // register event
  Serial.begin(9600);           // start serial for output
}

void loop() {
  Serial.print("Drehzahl: ");
  Serial.print(rpm);
  Serial.println(" RPM");
}

// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany) {
  if (Wire.available()){
    rpm = Wire.read();
      if(Wire.available()){
        rpm = rpm + (Wire.read()<<8);
      }
  }
}

schUk0

Der Code vom Mega:

Code: [Select]
//Bordcomputer Master (Display)

//I2C Slave


//library for the Display
#include <U8glib.h>
//library for I2C
#include <Wire.h>
//library for EEPROM access
#include <EEPROM.h>

//constructor for display
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NO_ACK);



//Buttons. Change "Adress"-values in isr-funktion (whichBt();) if needed!

int btVal = A0;
volatile boolean btA=false;
volatile boolean btB=false;
volatile boolean btC=false;
volatile boolean btD=false;
int interPin1 = 2;

//important for Intro-Screen
boolean state;

//GUI
int index=0;
boolean S1=true;
boolean S2=true;
boolean S3=true;
int wheelCirc;
int wheelCircTemp;
int rpm;
int vel;

//Logo Array
#define logo_width 80
#define logo_height 60
PROGMEM const unsigned char logo_bits[] = {

//Das denken wir uns hier mal

};

void drawMenu1(void){
  u8g.setFont(u8g_font_7x14B);
  u8g.setFontPosTop();
  u8g.setPrintPos(0, 0);
  u8g.print("Hauptmenue");

  u8g.setFontPosTop();
  u8g.setPrintPos(0, index + 20);
  u8g.print(">");

  u8g.setFontPosTop();
  u8g.setPrintPos(10, 20);
  u8g.print("Radumfang");
  //u8g.print(" ");
  u8g.print("(");
  u8g.print(wheelCirc);
  u8g.print(")");
  
  u8g.setFontPosTop();
  u8g.setPrintPos(10, 35);
  u8g.print("Fahrzeug");
  //u8g.print(" ");
  u8g.print("(");
  u8g.print("S51");
  u8g.print(")");
  
  u8g.setFontPosTop();
  u8g.setPrintPos(10, 50);
  u8g.print("Erweitert");
  
}

void drawMenuWheel(void){
  u8g.setFont(u8g_font_7x14B);
  u8g.setFontPosTop();
  u8g.setPrintPos(0, 0);
  u8g.print("Radumfang in mm");

  u8g.setFontPosTop();
  u8g.setPrintPos(0, 20);
  u8g.print("-");
  u8g.print(wheelCircTemp);
  u8g.print("+");
  
}

void draw(void) {

  u8g.setFont(u8g_font_fub20);
  u8g.setFontPosTop();
  u8g.setPrintPos(0, 19);
  u8g.print(rpm);
  u8g.setFont(u8g_font_7x14B);
  u8g.setFontPosTop();
  u8g.print("RPM");
  u8g.setFont(u8g_font_fub20);
  u8g.setFontPosTop();
  u8g.setPrintPos(0, 40);
  u8g.print(vel);
  u8g.setFont(u8g_font_7x14B);
  u8g.setFontPosTop();
  u8g.print("km/h");
}

void drawLogo(int x, int y) {
  u8g.drawXBMP( x, y, logo_width, logo_height, logo_bits);
}


void setup() {
  // put your setup code here, to run once:
  state = true;
  
  pinMode(btVal, INPUT);
  attachInterrupt(digitalPinToInterrupt(interPin1),whichBt,RISING);
  
  
  Wire.begin(2);              
  Wire.onReceive(receiveEvent);
  Serial.begin(9600);
  //EEPROM.get(wheelCircAddress,wheelCirc);
  //EEPROM.get(numberOfWheelsensorsAddress,numberOfWheelsensors);  

}

void receiveEvent(int howMany) {
  if (Wire.available()){
    rpm = Wire.read();
      if(Wire.available()){
        rpm = rpm + (Wire.read()<<8);
      }
  }
}

//ISR for the buttons
void whichBt(){
  
  //Serial.println(analogRead(btVal));
  
  if (analogRead(btVal) > 100 && analogRead(btVal) < 200){
    btA=true;
  }
  else if (analogRead(btVal) > 200 && analogRead(btVal) < 400){
    btB=true;
  }
  else if (analogRead(btVal) > 400 && analogRead(btVal) < 800){
    btC=true;
  }
  else if (analogRead(btVal) > 800){
    btD=true;
  }
  
  //Serial.println("fired");  
}



void loop() {

 Serial.println(rpm);

  // picture loop
  //display Logo
  if (state == true) {
    u8g.firstPage();
      do {
        drawLogo(20, 10);
         }
    while ( u8g.nextPage() );
    delay(2000);
    //scroll the logo down
    for (int i = 10; i < 70; i = i + 5) {
      u8g.firstPage();
      do {
        drawLogo(20, i);
        }
      while ( u8g.nextPage() );
      }
    //set the status false to go to normal mode
    state = false;
  }


  //Menu loop
  while (btC || S1 == false){
    S1=false;
    btC=false;
    
    u8g.firstPage();
    do {
     drawMenu1();

      if (btA){
        index=index-15;
        btA=false;
      }
      else if (btB){
        index=index+15;
        btB=false;
      }

          while (index == 0 && btC || S2 == false){
            S2 = false;
            btC=false;
            u8g.firstPage();
            do {
            drawMenuWheel();
            

                if(btA){
                  wheelCircTemp = wheelCircTemp - 10;
                  btA = false;
                }

                if(btB){
                  wheelCircTemp = wheelCircTemp + 10;
                  btB = false;
                }

                if (wheelCircTemp < 0){
                  wheelCircTemp=0;
                }

                if (btC){
                  wheelCirc = wheelCircTemp;
                  //EEPROM.put(wheelCircAddress,wheelCirc);
                  
                  btC=false;
                  S2=true;
                }

                if(btD){
                  S2=true;
                }
            }
            while ( u8g.nextPage() );
          }
          wheelCircTemp = wheelCirc;
      
      if (index < 0){
        index=0;
      }
      if (index > 30){
        index=30;
      }

       if (btD){
      S1=true;
      btD=false;
      
      }
    
    }
  while ( u8g.nextPage() );  
  }
    
  if (state == false) {
  u8g.firstPage();
    do {
     draw();        
    }
  while ( u8g.nextPage() );      
  }
    
    

}

Go Up