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?
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
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.
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 ...
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!
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.
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.
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.
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