Forum: Mikrocontroller und Digitale Elektronik Arduino: Soft-I2C-Lib - Datenpin on the fly umdefinieren?


von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Ich muss an einem Arduino Nano 5 I2C-Sensoren auslesen, die leider keine 
Adresscodierung auf ihren Breakout-Boards anbieten, also eine feste 
Adresse haben.

Als Lösung dacht ich mir, mithilfe der Library Soft-I2C einfach die 
Datenleitungen der Sensoren an 5 verschiedene Arduino-Pins anzuschießen 
und den jeweiligen Pin vor jedem Auslesen on-the-fly umzudefinieren bzw. 
umzuschalten.

Das Auslesen muss nicht besonders schnell erfolgen, so dass das sicher 
kein Zeitproblem darstellt, sofern es überhaupt funktioniert.

Die entscheidende Zeile ist:
1
SoftWire i2c(sdaPin, sclPin);

Dumme Frage: Kann das beliebig of neu ausgeführt werden, oder klappt das 
nur einmal im Setup-Bereich?

von Joachim B. (jar)


Lesenswert?

Frank E. schrieb:
> SoftWire i2c(sdaPin, sclPin);
> Dumme Frage: Kann das beliebig of neu ausgeführt werden

dumme Frage, warum schaltest du nicht DDR manuell out auf in und 
umgekehrt?

DDR In lesen PORT ist high, Out Bit senden Port ist low
das ganze mit Bitbanging

von Stefan F. (Gast)


Lesenswert?

Frank E. schrieb:
> Kann das beliebig of neu ausgeführt werden, oder klappt das
> nur einmal im Setup-Bereich?

Ich habe es nicht ausprobiert aber ich ich denke, das sollte gehen. 
Dabei wird aber jedesmal eine neue Instanz von dem Objekt erzeugt, was 
je nach Konstellation den Speicher fragmentieren könnte.

Wenn du das Objekt nicht global deklarierst, sondern nur innerhalb der 
Funktion wo es benutzt wird, reduzierst du die Gefahr, den Heap zu 
fragmentieren.

von John P. (brushlesspower)


Lesenswert?

Kannst du die sensoren nicht an 5 GPIO's hängen und die Spannung der 
Sensoren an/abschalten?
Oder noch besser Enable Eingänge falls vorhanden.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

Stefanus F. schrieb:
> Frank E. schrieb:
>> Kann das beliebig of neu ausgeführt werden, oder klappt das
>> nur einmal im Setup-Bereich?
>
> Ich habe es nicht ausprobiert aber ich ich denke, das sollte gehen.
> Dabei wird aber jedesmal eine neue Instanz von dem Objekt erzeugt, was
> je nach Konstellation den Speicher fragmentieren könnte.
>
> Wenn du das Objekt nicht global deklarierst, sondern nur innerhalb der
> Funktion wo es benutzt wird, reduzierst du die Gefahr, den Heap zu
> fragmentieren.

Ja, danke, das ist Plan A: Instantiierung und Abfrage in einer Funktion, 
Sensorauswahl als Parameter. Ich werde berichten ...

: Bearbeitet durch User
von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

John P. schrieb:
> Kannst du die sensoren nicht an 5 GPIO's hängen und die Spannung
> der
> Sensoren an/abschalten?
> Oder noch besser Enable Eingänge falls vorhanden.

Ja danke, das ist Plan B: Pins als Spannungsquelle ... genialer Trick!

von Max D. (max_d)


Lesenswert?

Die Versorgung abzuschalten wird nicht funktionieren. Die Sensoren haben 
intern pull-ups die entweder den Bus lahmlegen oder die Sensoren 
parasitär weiterversorgen.
Entweder fertigen i2c multiplexer kaufen oder selber bauen mit 
analogschaltern.

von Jim M. (turboj)


Lesenswert?

Frank E. schrieb:
> Dumme Frage: Kann das beliebig of neu ausgeführt werden, oder klappt das
> nur einmal im Setup-Bereich?

Nur einmal, denn das sieht für mich schwerstens nach einem C++ 
Konstruktor aus.

Wie gut ist Dein C++? Ich hätte mir die Lib mal kurz im Source 
angeschaut -

falls https://github.com/stevemarple/SoftWire/tree/master/src kompatibel 
ist,
könnte man einfach die setSda(), setScl() und begin() Methode benutzen.

von Johannes S. (Gast)


Lesenswert?


von Peter D. (peda)


Lesenswert?

Frank E. schrieb:
> Dumme Frage: Kann das beliebig of neu ausgeführt werden

Ja, das sollte gehen. Es reicht, nur den SDA umzuschalten, der SCL kann 
für alle gemeinsam verwendet werden. Man kann den SDA aber auch über 
einen 74HC4051 umschalten. Jeder SDA-Pin braucht natürlich seinen 
eigenen Pullup.

von Frank E. (Firma: Q3) (qualidat)


Lesenswert?

So, ich hab mal experimentiert!

Mit der Lib "SoftwareI2C" von Sparkfun (hab noch 3 andere ausprobiert, 
die alle "zickig" waren!) klappt es, quasi beliebig viele (soweit Pins 
vorhanden), I2C-Devices mit der gleichen Adresse zu benutzen. Hier ein 
Beispiel mit dem Magnetsensor HCM5883L.

Der Code läuft auf einem UNO seit einigen Stunden problemlos, dürfte 
also auch keine Mem-Leaks produzieren.
1
#include <SoftwareI2C.h>
2
3
int  hmc_adr = 0x1E;
4
byte hmc_mode = 0x02;
5
byte hmc_cont = 0x00;
6
byte hmc_out = 0x03;
7
8
void setup()
9
{
10
  Serial.begin(9600);
11
}
12
13
void loop()
14
{
15
  Serial.println(get_mag(A0));
16
  Serial.println(get_mag(A1));
17
  Serial.println(get_mag(A2));
18
  Serial.println(get_mag(A3));
19
  Serial.println(get_mag(A4));
20
  Serial.println("-----------");
21
  delay(500);
22
}
23
24
int get_mag(int sda_pin)
25
{
26
  int x,y,z; // 3 Achsen
27
  SoftwareI2C s;
28
  s.begin(sda_pin,A5); //SCL unverändert
29
  s.beginTransmission(hmc_adr); // Verbindung öffnen mit dem HMC5883
30
  s.write(hmc_mode); // Mode Register
31
  s.write(hmc_cont);   // Kontinuierliche Messung
32
  s.endTransmission();
33
34
  s.beginTransmission(hmc_adr);
35
  s.write(hmc_out); // Register 3, X MSB Register
36
  s.endTransmission();
37
  
38
  s.requestFrom(hmc_adr, 6);
39
  x = s.read()<<8;  x |= s.read();
40
  z = s.read()<<8;  z |= s.read();
41
  y = s.read()<<8;  y |= s.read();
42
  s.endTransmission();
43
 
44
  float w = atan2(-y , x) / M_PI * 180.0;
45
  if(w < 0){w = w + 360.0;}
46
  return w; 
47
}

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.