Sensoren am I2C-slave über eigene adresse erreichbar machen

hallo, ich habe vor mehrere sensoren(3x OneWireBUS(Ja 3x der BUS) mit DS18B20 sensoren,3x DHT11,2x PIR und 4x Reed-kontakte) an einen Arduino Mega 2560 R3 zu betreiben welcher über I2C als Slave angesprochen wird, jetzt habe ich mir überlegt bzw mich gefragt ob es nicht möglich ist jeden dieser sensoren bzw quasi jeden "Input" pin eine eigene I2C adresse zu zuweisen und über diese abzufragen.
ich hab bisher keine ahnung wie ich das bewerkstäligen könnte, für die OneWireBus hab ich zwar eine mögliche libary gefunden (OneWireHub Wenn ich mich nicht irre) aber viel weiter hat mich das bisher nicht gebracht.
ich hoffe ihr könnt mir tipps geben.
mfg OW

So ganz verstehe ich dein Problem nicht.
Deine Sensoren sind keine I2C-Sensoren, also wofü brauchst die Adressen.
Die Slave-Adresse für deinen Mega kannst du selbst vergeben.

Bitte deine Beschreibung nochmal etwas genauer schreiben.

du könntest

a) in deinem Slave Sketch auf verschiedene Slave Adressen reagieren.
b) imho sauberer wäre wenn du für jeden deiner Sensoren ein separates "Register" machst und damit gezielt den Sensor abfragst - aber unter der gleichen Slave Adresse. Das ist auch eher das was du bei anderen I2C Komponenten hast: 1 Adresse - verschiedene Register.

Die Vergabe ganzer Adressbereiche wird von der Mega Hardware unterstützt.
Allerdings nicht von Wire.
Der Weg ist also verdorben. (es sei denn ....)

Ja!

nun ja ich würde gerne adressen "emulieren" das somit jeder sensor bzw eigentlich würde es reichen wenn nur die werte von den sensoren über eine eigene adresse abfragbar sind.

ok möglichkeit "b)" hört sich nach dem an was ich suche. jetzt ist die frage wie bewerkstellige ich das ? ich bin anfänger in dem gebiet,möchte zwar so schnell wie nur möglich die codes schreiben aber ich möchte es am besten auch verstehen.

Das musst du nur manuell umsetzen. Also über I2C 0x01, 0x02, oder andere Adressen senden, darauf abfragen und ein Einlesen des jeweiligen OneWire Sensors daraus machen.

Ok, das muss dann ja keine I2C-Adresse sein.
Das kann ja jeder beliebige Wert sein, der dann gezielt angesprochen wird.

schnell geht gar nix. Aber ich kann dir zeigen was ich (vor 4 Jahren!) gemacht habe:
Abfrage von 5 Ultraschallsensoren.
So nebenbei gibts auch Register für Analog-Eingänge und Digitaleingänge.

Die Register stehen oben im Kommentar.

Im Prinzip brauchst nur am Ende die paar neuen Register für deine Temperatursensoren ergänzen...

/*
  ARDUINO UNO/NANO as I2C port expander for ultrasonic sensors
  by noiasca

  inspired by http://forum.arduino.cc/index.php?topic=77310.0

  5 ultrasonic proximity sensors

  send Digital IN (GPIO) over I2C        (register  0 - 31) 00 - 13 used
  send Analog IN over I2C                (register 31 - 63) 31 - 39 Used
  send proximity sensor values over I2C  (register 63 - 94) 63 - 72 5 ultrasonic proximity sensors on D2-D11

  in detail, the registers are as following:

  Register   GPIO/usage       comment
  -----------------------------------
  0          Digital 0        RX                        --> PIN's 0 + 1 could be ocopied by Serial - if debug messages are used
  1          Digital 1        TX
  2          Digital 2        Trigger Sensor A          --> PIN's 2 - 11 are used for the 5 proximity sensors
  3          Digital 3        Echo
  4          Digital 4        Trigger Sensor B
  5          Digital 5        Echo
  6          Digital 6        Trigger Sensor C
  7          Digital 7        Echo
  8          Digital 8        Trigger Sensor D
  9          Digital 9        Echo
  10         Digital 10       Trigger Sensor E
  11         Digital 11       Echo
  12         Digital 12       free (could be used for a switch or any other digital sensor)
  13         Digital 13       occupied by built in LED
  14..30     reserved         for future use
  31         Analog 0 LSB     Analog values are 0..1023 - you need two bytes for each value!
  32         Analog 0 MSB
  33         Analog 1 LSB
  34         Analog 1 MSB
  35         Analog 2 LSB
  36         Analog 2 MSB
  37         Analog 3 LSB
  38         Analog 3 MSB
  39         reserved          Analog 4 is occupied by I2C on UNO/NANO
  40         reserved          Analog 5 is occupied by I2C on UNO/NANO
  41         -                 could be used for Analog 6 on a NANO - not implemented
  42         -                 could be used for Analog 7 on a NANO - not implemented
  43..62     reserved
  63         Distance 0 LSB   Proximity sensors: all calculated values are in cm are and splitted in LSB and MSB
  64         Distance 0 MSB
  65         Distance 1 LSB
  66         Distance 1 MSB
  67         Distance 2 LSB
  68         Distance 2 MSB
  69         Distance 3 LSB
  70         Distance 3 MSB
  71         Distance 4 LSB
  72         Distance 4 MSB
  73..94     reserved         for future use
  FE         Manufacturer ID Register Description
  FF         Device ID Register Description

  Set #define NO_ECHO 65535 in NewPing.h !!!
  28500/57 = 500
  31635/57 = 555
  32767/57 = 574
  56943/57 = 999
  65535/57 = 1149 <-- each time you receive 1149 cm, you know the sensor has exceeded the limit
*/

#include <Wire.h>
#include <NewPing.h>                  // Ultrasonic Sensors

/* *******************************************************************
         the different boards / die Einstellungen der verschiedenen Boards
 * ******************************************************************/

const uint8_t slaveAdress = 8;         // I2C adress of this slave

/* *******************************************************************
         Globals
 * ******************************************************************/

byte registerPointer = 0;              // requested register from master
unsigned long previousMillis = 0;      // will store last time ADC was read
const long adcInterval = 10;           // interval at which to read ADC (milliseconds)
int adc[4];                            // will store analog value form analog inputs
byte analog[8];                        // i2c output byte: 4 analog values 0..1023 need 8 bytes
byte digital[14];                      // i2c output byte: 14 digital PINs but some are occupied
byte proximity[10];                    // i2c output byte: proxmity sensors could return more than 255cm, 5 sensors each 2 byte = 10 bytes used
// byte buffer[32];                    // MISSING: not shure if I should use a generic buffer or separate buffers for digital/analog/proximity
const byte SONAR_NUM = 5;              // count of ultrasonic proximity sensors
const byte SONAR_FRONT = 2;            // Number of ultrasonic sensor facing north/front/12 o'clock
const uint16_t MAX_DISTANCE = 350;     // Maximum distance (in cm) to ping
unsigned long previousSonarMillis = 0; // will store last time Sonar was called
const long SONAR_INTERVAL = 30;        // interval at which to read ADC (milliseconds)
byte sonarActual = 0;                  // the actual Sonar sensor to read
uint16_t distance[SONAR_NUM];          // measured distance for each sensor
NewPing sonar[SONAR_NUM] = {           // Sensor object array. 5 Sensors
  NewPing(2,  3,  MAX_DISTANCE),        // Each sensor needs one trigger pin, one echo pin, and a max distance to ping.
  NewPing(4,  5,  MAX_DISTANCE),
  NewPing(6,  7,  MAX_DISTANCE),
  NewPing(8,  9,  MAX_DISTANCE),
  NewPing(10, 11, MAX_DISTANCE)
};

#include "blink.cpp"      // on separte tab
BlinkLed led(13);         // a status LED (PIN 13) will blink according to the measured distance of proximity sensor 2 (in my case the sensor pointing forwards)


/* *******************************************************************
         D E B U G            activate to get more serial data
 ********************************************************************/

#define DEBUG 0              // set to 1 to activate debug messages on serial


/* *******************************************************************
         S E T U P
 ********************************************************************/
void setup()
{
  Serial.begin(115200);
  Serial.println(F("\nUNO as I2C port expander ultrasonic"));
  led.setup();
  Wire.begin(slaveAdress);                            // set slave adress
  Wire.onRequest(requestEvent);                       // add event
  Wire.onReceive(receiveEvent);                       // the master must anounce a starting register before he can read
}


/* *******************************************************************
         M A I N L O O P
 ********************************************************************/
void loop()
{
  // read out analog inputs
  if (millis() - previousMillis >= adcInterval) {            // to avoid to fast reading of adc, we only measure once each adcIntervall and only one ADC
    byte adcActual = millis() % 3;
    analogRead(adcActual);
    adc[adcActual] = analogRead(adcActual);
  }
  // read out proximity sensors
  if (millis() - previousSonarMillis >= SONAR_INTERVAL)      // wait some time between reading of the ultrasonic sensors
  {
    sonarActual++;                                           // only read one sensor. define which one to read
    if (sonarActual >= SONAR_NUM)
    {
      sonarActual = 0;
#if DEBUG
      Serial.println();
#endif
    }
    distance[sonarActual] = sonar[sonarActual].ping_cm();
#if DEBUG
    //Serial.print(sonarActual);
    //Serial.print("=");
    Serial.print(sonar[sonarActual].ping_cm());
    Serial.print(F("  "));
    //Serial.print("cm ");
#endif
    if (sonarActual == SONAR_FRONT)                                         // set blinkfrequency according to forward facing proximity sensor
    {
      uint16_t blinktime = map(distance[SONAR_FRONT], 0, 1149, 20, 1000);   // calculate a blinktime based to the front distance. The sensor out is 0-1149. The Blinkfrequency should be between 20-1000ms
      //uint16_t blinktime = distance[SONAR_FRONT] + 100;                   // calculate a blinktime based to the front distance
      led.set(blinktime, 1149 + 100 - blinktime);                           // ontime = blinktime, offtime = somehow reversed value
    }
  }
  // do other stuff
  led.loop();                                                               // update blink led
}

/* *******************************************************************
         F U N C T I O N S
 ********************************************************************/

// function that executes whenever data is requested by master
// this function is added as an event in setup()
// maximum of 32 bytes can be sent
// according to
// https://forum.arduino.cc/index.php?topic=517096.0
// no chance to get the requested bytes from the master (as of 2018-06-19)
// therefore: this slave answeres n bytes according to the requested register block
// in other words: this slave sends the n remaining bytes till end of this regigster block
//
void requestEvent()
{
  if (registerPointer <= 13)                                                            // handle registers for DIGITAL Inputs
  {
    for (byte i = 0; i <= 13; i++)
    {
      digital[i] = digitalRead(i);
    }
    // Wire.write(data, quantity)
    Wire.write(digital + registerPointer, sizeof(digital) - registerPointer);
  }
  else if (registerPointer >= 31 && registerPointer <= 31 + 8)                          // handle registers for ANALOG Inputs
  {
    byte registerStart = 31;  // this register group starts at adress 31
    analog[0] = adc[0];
    analog[1] = adc[0] >> 8;
    analog[2] = adc[1];
    analog[3] = adc[1] >> 8;
    analog[4] = adc[2];
    analog[5] = adc[2] >> 8;
    analog[6] = adc[3];
    analog[7] = adc[3] >> 8;
    Wire.write(analog + registerPointer - registerStart, sizeof(analog) - (registerStart - registerPointer));
  }
  else if (registerPointer >= 63 && registerPointer <= 63 + 10)                         // handle registers for PROXIMITY Sensors
  {
    byte registerStart = 63;
    proximity[0] = distance[0];
    proximity[1] = distance[0] >> 8;
    proximity[2] = distance[1];
    proximity[3] = distance[1] >> 8;
    proximity[4] = distance[2];
    proximity[5] = distance[2] >> 8;
    proximity[6] = distance[3];
    proximity[7] = distance[3] >> 8;
    proximity[8] = distance[4];
    proximity[9] = distance[4] >> 8;
    Wire.write(proximity + registerPointer - registerStart, sizeof(proximity) - (registerStart - registerPointer));
  }
  else if (registerPointer == 0xFE)                         // Manufacturer ID Register Description (0xFE)
  {
    Wire.write(8);                                          // "my" Manufacturer ID is 0x0815
    Wire.write(15);
  }
  else if (registerPointer == 0xFF)                         // Device ID Register Description
  {
    Wire.write(5);                                          // my device is able to send 5 proximity sensors,
    Wire.write(8);                                          // this values can be set to any value
  }
}


void receiveEvent(int howMany)
{
  // Read the requested register
  registerPointer = Wire.read();
}

und die blink.cpp habe ich offenbar in einem anderen Tab:

#include <Arduino.h>                   // include Arduino specifica - needed for .cpp in separate tabs if not included with an separate .h
class BlinkLed {
    uint8_t state = 1;                 // 0 off, 1 blink
    unsigned long previousMillis;      // last blink timestamp
    uint16_t on = 180;
    uint16_t off = 320;                // 180/320 is according ECE
    const int ledPin;                  // a GPIO for the LED

  public:
    BlinkLed(byte attachTo, uint16_t _on = 180, uint16_t _off = 320):
      ledPin(attachTo),
      on (_on),
      off (_off)
    {}
    void setup() {
      pinMode(ledPin, OUTPUT);
    }
    void set(uint16_t _on, uint16_t _off) { // modify on/off times during runtime
      on = _on;
      off = _off;
    }
    void setState(byte _state) {           // 1 Switch on blinking; 0 switch off blinking
      state = _state;
    }
    void loop() {
      if (state) {
        uint32_t currentMillis = millis();
        if (digitalRead(ledPin) && currentMillis - previousMillis >= on) {
          previousMillis = currentMillis;            // save the last time you blinked the LED
          digitalWrite(ledPin, LOW);
        }
        else if (!digitalRead(ledPin) && currentMillis - previousMillis >= off) {
          previousMillis = currentMillis;           // save the last time you blinked the LED
          digitalWrite(ledPin, HIGH);
        }
      }
    }
};

Für DS18B20 nimm

die Werte danach per I2C senden.

ich wollte mit der gesamten aussage auch aussagen das mir bewusst ist das sowas nicht schnell geht :smiley:

Wie weit ist die Strecke ? Bei mehr als 0,5m fangen Probleme an, außer dem Schaft der Mega alles selbst, je nach dem was an dem Master alles noch hängt, interessant ist auch wer ist der Master

Also Du hast einen Arduino MEGA mit mehreren Sensoren und willst einzeln jeden Sensor per Slave Abfrage über I2C abfragen.

Du hast die I2C Adresse des MEGA und sendest zusätzlich ein Byte für den Sensor der ausgelesen werden soll.
Der Mega gibt als Antwort den angesprochenen Sensor.

Grüeß Uwe

gut zu wissen aber ich habe mir mehrere lochrasterplatinen gekauft auf einen von denen hatte ich vor stiftleisten zu löten um den mega2560 dort aufstecken zu können wie ein prototypshield quasi nur das ich noch die buchsenleisten vom mega2560 nach unten hin versetze.eine andere platine dient als Master"shield" wo ich das selbe mit einem ESP32 oder eine pfostenbuchse für ein Raspberry pi mache oder beides (ein raspberry pi finde ich zumindest für fehler suche und testzwecke "einfacher" oder angenehmer zuhand haben was für den dauerbetrieb als master aber für mich eher ein kompromiss wäre) und das selbe noch mit einer anderen ich nenne es mal "slave" platine diese platinen werde ich wie weiß ich noch nicht genau über einander stappel eventuell einfach mit M2,5/M3 gewindestangen und je nach abstand mit wahrscheinlich cat oder Modularkabeln mit einander verbinden. also wird es ich denke nicht mal 25cm betragen.

Und warum machst das nicht alles auf einem ESP32 ?

vielen dank ich glaube fürs erste hat mir das schon weiter geholfen. ich werde wahrscheinlich heute nicht mehr groß was tun aber vielleicht schaffe ich es das wochenende noch und melde mich dann mit dem ergebnis.

achso mal nebenbei ein anderer Slave in dem projekt soll ein 4-kanal-ac dimmer werden,was aber erst später ein thema wird, wenn ich es richtig verstanden habe kann ich diese methode auch darauf hin über tragen das ich mit den registern auch die jeweiligen kanäle ansprechen kann oder ?
gruß OW

ESP 32 wie auch RasPI arbeiten mit 3,3V Mega mit 5V also noch an Pegelwandler denken

Du weißt schon daß I2C ein Bus für kurze Kabellängen ist. Max im besten Fall 2m.
Grüße Uwe

3,3V pins.. die kabel längen der sensoren werden in den meisten fällen weit über 1m lang sein,teilweise 3-5m.
davon mal ab möchte ich bei dem esp32 sowenig "last" ziehen wie nur möglich da ich die erfahrung gemacht habe das dieser auch bei guter strom versorgung nur sehr "schwaches" oder "instabiles" wlan liefert wenn zu viele pins belegt sind.
dieses projekt ist derzeit nur ein "prototyp" projekt später möchte ich es vernünftig mit bedruckten leiterplatten selbst bestücken.

ich hab einen bidirektionalen 4-kanal-level-converter hier für dieses projekt.