Forum: Mikrocontroller und Digitale Elektronik AD5272 mit Arduino über I2C verbinden


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Petr t. (vicon)


Lesenswert?

Hallo Leute,

ich habe folgendes Problem,

ich möchte meinen Arduino Uno mit dem AD5272 Digitalpotentiometer über 
I2C verbinden. Über den Arduino I2C Portscanner sketsch hat das schon 
funktioniert, und somit kenne ich die Adresse: 0x2c
jetzt komme ich aber irgendwie nicht weiter
1
#include <Wire.h>
2
3
void setup()
4
{
5
  Wire.begin(); // join i2c bus (address optional for master)
6
  Serial.begin(9600);  // start serial for output
7
}
8
9
byte val = 0;
10
void loop()
11
{
12
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
13
  Wire.write(byte(val));      
14
  Wire.endTransmission();      // stop transmitting
15
   Wire.requestFrom(44, 6);
16
17
  while(Wire.available())    // slave may send less than requested
18
  { 
19
    char c = Wire.read();    // receive a byte as character
20
    Serial.print(c);         // print the character
21
  }
22
  
23
  val++;        // increment value
24
  if (val == 100) 
25
  {
26
    val = 0;    // start over from lowest value
27
  }
28
   delay(10);
29
}

Das ist der Programmcode, ich möchte erstmal das der Widerstand vom Poti 
erhöht wird, und das ich diesen dann über den Seriellen Monitor von der 
Arduino IDE auslese, welcher Wert gerade eingestellt ist.

Aber raus bekomme ich nur das:
(((000888@@@HHHPPPXXX```hhhpppx x x 
€"€"€"ˆ$ˆ$ˆ$�&�&�&˜(˜(˜( * * *¨,¨,¨,°.°.°.¸0¸0¸0À2À2À2È4È4È4Ð6Ð6Ð6Ø8Ø8Ø8 
à:à:à:è<è<è<ð>ð>ð>ø@ø@ø@

(In einer Zeile)
Aber wie bekomme ich die Werte in Zahlen ?

Danke

von Klaus (Gast)


Lesenswert?

Wire.endTransmission() liefert einen Status, den würd ich mir mal 
ansehen.

> Returns
>
> byte, which indicates the status of the transmission:
>
>    0:success
>    1:data too long to fit in transmit buffer
>    2:received NACK on transmit of address
>    3:received NACK on transmit of data
>    4:other error

MfG Klaus

von Petr t. (vicon)


Lesenswert?

Klaus schrieb:
> Wire.endTransmission() liefert einen Status, den würd ich mir mal
> ansehen.

Wie kann ich den bekommen ?
1
byte result;
2
byte val = 0;
3
void loop()
4
{
5
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
6
  Wire.write(byte(val));      
7
  Wire.endTransmission();      // stop transmitting
8
   Wire.requestFrom(44, 6);
9
10
  while(Wire.available())    // slave may send less than requested
11
  { 
12
    char c = Wire.read();    // receive a byte as character
13
    Serial.print(c);         // print the character
14
  }
15
  
16
  val++;        // increment value
17
  if (val == 100) 
18
  {
19
    val = 0;    // start over from lowest value
20
  }
21
   delay(100);
22
23
     result = Wire.endTransmission();
24
  Serial.print(result); 
25
}
Ich habe den Code hier erweitert um
byte result;
...
result = Wire.endTransmission();
Serial.print(result);

Aber ich bekomme immer noch seltsame Zeichen angezeigt :(

von Karl (Gast)


Lesenswert?

Du bekommst von dem Digitalpotentiometer byte-Werte deklarierst sie aber 
als char. Mit Serial.print() schreibst du diese dann. Die Komischen 
Zeichen sind "Steuerzeichen" die den Werten entsprechen. Du musst die 
byte-Werte erstmal in ein sinnvolles Datenformat umwandeln und dann 
ausgeben.

von Petr t. (vicon)


Angehängte Dateien:

Lesenswert?

Karl schrieb:
> Du bekommst von dem Digitalpotentiometer byte-Werte deklarierst sie aber
> als char. Mit Serial.print() schreibst du diese dann. Die Komischen
> Zeichen sind "Steuerzeichen" die den Werten entsprechen. Du musst die
> byte-Werte erstmal in ein sinnvolles Datenformat umwandeln und dann
> ausgeben.

Das bekomme ich heraus, wenn ich byte anstatt char wähle.
Wie wandle ich denn die Werte um :( ?

von Petr t. (vicon)


Lesenswert?

Ich bekomme zwar die Meldung, dass das Digital Poti mit dem I2C 
Portscanner Sketsch gefunden wurde, also liegt es nicht an der 
Testschaltung.
Kann mir jemand einen Code zeigen, der Daten vom Arduino an das Poti 
sendet und diese von dem Poti wieder beim Arduino empfangen werden und 
dargestellt werden ?
Danke

von Mathias (Gast)


Lesenswert?

Hast du mal ins Datenblatt geguckt? So wie ich das lese, kannst du nicht 
einfach ein Byte schreiben und erwarten, dass passiert was du wolltest.

Probier mal:
1
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
2
  Wire.write(1<<2 | val>> 8)  //Write contents of serial register data to RDAC.
3
  Wire.write(val & 0xff);  
4
  Wire.endTransmission();      // stop transmitting
5
6
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
7
  Wire.write(1<<3)            //Read contents of RDAC wiper register.
8
  Wire.write(0);  
9
  Wire.endTransmission();      // stop transmitting
10
11
  Wire.requestFrom(44, 2);
12
  while(Wire.available())    // slave may send less than requested
13
  { 
14
    byte c = Wire.read();    // receive a byte as character
15
    Serial.print(c);         // print the character
16
  }

und du hast 10 Bit zur Verfügung oder? Dann sollte val auch nicht byte, 
sondern größer sein...

von Petr t. (vicon)


Lesenswert?

Ok, danke Mathias,

jetzt bekomme ich zumindest zahlen ;)
Aber was sind das für werte und wie bekomme ich diese ?
Am wiper kann ich mit dem Multimeter nichts messen, weder Widerstand 
noch Spannungsänderung (Wiper Pin messe ich 4,8V gegen Masse)

von Mathias (Gast)


Lesenswert?

Was meinst du, das hier:
1
  Wire.write(1<<2 | val>> 8)  //Write contents of serial register data to RDAC.
2
  Wire.write(val & 0xff);
? Das steht (quasi) im Datenblatt:
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5272_5274.pdf
Tabelle 12, Seite 21. Da ist das in Binärdarstellung angegeben.
Das Protokoll ist in binär:
1
xxccccdd dddddddd
Die ersten zwei Bits werden ignoriert (x), dann kommen 4 command Bits 
(c), dann 10 Daten bits (d). Macht zusammen 16 Bits, das sind 2 Bytes.
Allgemein kannst du dann folgendes nutzen:
1
  Wire.write(0bcccc<<2 | ((val>> 8)&0b11))  //Write contents of serial register data to RDAC.
2
  Wire.write(val & 0xff);
Das "<<2" shiftet die Bits um zwei nach links. Also aus 0bcccc wird 
0bcccc00. Das "(val>> 8)&0b11" gibt dir Bit 9&10 von val. "|" fügt dann 
beide teile zusammen. "val & 0xff" schneidet das untere Byte von val ab. 
Gibt dir also die letzten 8 Bits von val.

Wenn man noch nie mit Binärdaten gearbeitet hat, dann guck dir mal die 
"Bitwise Operators" auf arduino.cc an.

von Petr t. (vicon)


Lesenswert?

Mathias schrieb:
> Wire.write(0bcccc<<2 | ((val>> 8)&0b11))  //Write contents of serial
> register data to RDAC.
>   Wire.write(val & 0xff);

Die Arduino IDE nimmt den code nicht an

error: invalid suffix "bcccc" on integer constant
invalid suffix "bcccc" on integer constant

Und wie sorgt das nun dafür das sich der Widerstand ändert?
Ich messe mit meinem Multimeter an dem Wiper Pin keine Änderung :(

von Mathias (Gast)


Lesenswert?

http://playground.arduino.cc/Code/BitMath
https://www.arduino.cc/en/Reference/BitwiseAnd
https://www.arduino.cc/en/Reference/Bitshift
http://www.analog.com/media/en/technical-documentation/data-sheets/AD5272_5274.pdf

In der Reihenfolge durcharbeiten. Den letzten Link nur überfliegen, da 
sind aber die relevanten Infos drin, Tabelle 12 Seite 21.

"0bcccc" die "c"s musst du durch einen passenden Binärwert ersetzen, 
also je 0 oder 1:
0b0001: Write contents of serial register data to RDAC.
0b0010: Read contents of RDAC wiper register.

usw, Tabelle 12, Seite 21.

Zum testen kannst du ja mal probieren:
1
void loop()
2
{
3
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
4
  Wire.write(0b00000111);
5
  Wire.write(0b11111111);
6
  Wire.endTransmission();      // stop transmitting
7
  delay(1000);
8
9
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
10
  Wire.write(0b00000100);
11
  Wire.write(0b00000000);
12
  Wire.endTransmission();      // stop transmitting
13
  delay(1000);
14
}

Sollte im Sekundentakt zwischen 0% und 100% schalten

von Mathias (Gast)


Lesenswert?

Oh und vielleicht noch in der Setup:
1
Wire.beginTransmission(44); // transmit to device #44 (0x2c)
2
Wire.write(0x1c);
3
Wire.write(0x02);
4
Wire.endTransmission();      // stop transmitting
Das kommt davon, wenn man das Datenblatt nicht richtig liest, dann 
übersieht man (ich in dem Fall) sowas.

von Petr t. (vicon)


Lesenswert?

Danke für deine große Hilfe,

ich werde mir die links später anschauen, habe erstmal deinen Code rein 
kopiert und sieht so aus
1
#include <Wire.h>
2
3
void setup()
4
{
5
  Wire.begin(); // join i2c bus (address optional for master)
6
}
7
8
void loop()
9
{
10
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
11
  Wire.write(0b00000111);
12
  Wire.write(0b11111111);
13
  Wire.endTransmission();      // stop transmitting
14
  delay(2000);
15
16
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
17
  Wire.write(0b00000100);
18
  Wire.write(0b00000000);
19
  Wire.endTransmission();      // stop transmitting
20
  delay(2000);
21
}

Aber mit dem Multimeter messe ich am Wiper nichts.

von Mathias (Gast)


Lesenswert?

Wie gesagt:
1
void setup()
2
{
3
  Wire.begin(); // join i2c bus (address optional for master)
4
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
5
  Wire.write(0x1c);
6
  Wire.write(0x02);
7
  Wire.endTransmission();      // stop transmitting
8
}

von Petr t. (vicon)


Lesenswert?

Mathias schrieb:
> Oh und vielleicht noch in der Setup:
>
1
> Wire.beginTransmission(44); // transmit to device #44 (0x2c)
2
> Wire.write(0x1c);
3
> Wire.write(0x02);
4
> Wire.endTransmission();      // stop transmitting
5
>


ok, danke ^^ das hat gefehlt.

Mein Code sieht nun so aus:
1
#include <Wire.h>
2
3
void setup()
4
{
5
  Wire.begin(); // join i2c bus (address optional for master)
6
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
7
  Wire.write(0x1c);
8
  Wire.write(0x02);
9
  Wire.endTransmission();      // stop transmitting
10
11
}
12
13
void loop()
14
{
15
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
16
  Wire.write(0b00000111);
17
  Wire.write(0b11111111);
18
  Wire.endTransmission();      // stop transmitting
19
  delay(5000);
20
21
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
22
  Wire.write(0b00000100);
23
  Wire.write(0b00000000);
24
  Wire.endTransmission();      // stop transmitting
25
  delay(5000);
26
}

Ich kann mit dem Multimeter sehen, wie der Widerstand immer hin und her 
schaltet 0 und max.
Aber wenn er bei 0 ist, dann blinkt das Multimeter in dem abstand wie 
lang der delay dauert (5 sekunden, 5c blinken)
Kannst du mir das erklären ?

von Mathias (Gast)


Lesenswert?

Ähh nö, was blinkt da?

Mit der obigen setup, könnte übrigens auch wieder mein erster Code 
funktionieren
Beitrag "Re: AD5272 mit Arduino über I2C verbinden"

(Ich bin dann übrigens auch gleich weg, mit Glück gucke ich morgen 
nochmal rein.)

von Malte S. (maltest)


Lesenswert?

Petr t. schrieb:
> Über den Arduino I2C Portscanner sketsch hat das schon funktioniert, und
> somit kenne ich die Adresse: 0x2c

Du verwendest einen "Portscanner", um die Adresse zu raten, die du mit 
einem halben Blick ins Datenblatt gefunden hättest? Vorgehensweisen 
gibt's.
Die Lektüre des DB hätte dir überhaupt diesen ganzen Thread ersparen 
können.

Petr t. schrieb:
> Wire.beginTransmission(44); // transmit to device #44 (0x2c)

Wenn du dokumentieren möchtest, dass die so mühsam ermittelte Adresse 
0x2c ist, warum schreibst du dann nicht 0x2c in den Code statt das als 
44 reinzuklimpern und einen ansonsten überflüssigen Kommentar zu 
bemühen?

von Petr t. (vicon)


Lesenswert?

Malte S. schrieb:
> Wenn du dokumentieren möchtest, dass die so mühsam ermittelte Adresse
> 0x2c ist, warum schreibst du dann nicht 0x2c in den Code statt das als
> 44 reinzuklimpern und einen ansonsten überflüssigen Kommentar zu
> bemühen?

Ich war mir, zum Anfang als ich den Code genommen habe nicht sicher ob 
das geht, jetzt weiß ich es ;)

Mathias schrieb:
> Ähh nö, was blinkt da?

Beim anlegen des Messklemmen des Multimeters an den Wiper und den Masse 
Pin des Digi Potis ist er hochohmig (für 5 sekunden, siehe Programmcode) 
und dann fällt der Wert sofort auf 0 Ohm, blinkt dann 5x kurz auf und 
wird dann wieder hochohmig.

Mathias schrieb:
> Mit der obigen setup, könnte übrigens auch wieder mein erster Code
> funktionieren
> Beitrag "Re: AD5272 mit Arduino über I2C verbinden"

Das Probiere ich morgen, der Arduino liegt auf der Arbeit ;)

Malte S. schrieb:
> Du verwendest einen "Portscanner", um die Adresse zu raten, die du mit
> einem halben Blick ins Datenblatt gefunden hättest? Vorgehensweisen
> gibt's.

Na im Datenblatt habe ich ja die Tabelle mit den jeweiligen Pin 
belegungen gefunden. Je nachdem welcher der Pin´s an Masse oder Vdd ist, 
gibt es dementsprechend eine andere Adresse.
Den Portscanner habe ich nur benutzt um zu prüfen, das die I2C 
Verbindung funktioniert, der Arduino das Digi Poti am Bus erkennt und 
mit der Adresse des Datenblatts übereinstimmt.
Das ganze Datenblatt zu lesen hätte ich machen können, aber wenn nicht 
ich, dann wäre irgendwann jemand anderes gekommen um diese Fragen zu 
stellen :)

Morgen werde ich weiter daran arbeiten und schauen wie weit ich mit dem 
Teil komme.

von Mathias (Gast)


Lesenswert?

Auch wenn ich dir wahrscheinlich eh nicht helfen kann, aber kannst du 
"blinkt kurz" anders erklären als "blinkt kurz"? Wird das immer kurz 
hochohmig oder was?
Vielleicht ist "das Multimeter blinkt" auch ein normaler 
elektrodingens-Begriff, den ich einfach nicht kenne...

von Petr t. (vicon)


Lesenswert?

Mathias schrieb:
> "blinkt kurz" anders erklären als "blinkt kurz"? Wird das immer kurz
> hochohmig oder was?

Also man muss sich das wie ein Impuls vorstellen, es zeigt, wenn bei 0 
Ohm, daurend die 0 Ohm an, aber immer wenn eine Sekunde vergangen ist, 
gibt es sowas wie ein impuls und es wird für paar milisekunden 0 KOhm 
angezeigt und dann wieder 0 Ohm und dann geht das wieder von vorne los.
1
{
2
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
3
  Wire.write(0b00000111);   // Teil1
4
  Wire.write(0b11111111);
5
  Wire.endTransmission();      // stop transmitting
6
  delay(5000);
7
8
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
9
  Wire.write(0b00000100);   // Teil2
10
  Wire.write(0b00000000);
11
  Wire.endTransmission();      // stop transmitting
12
  delay(5000);
13
}
Bei dem Code habe ich mich jetzt soweit eingelesen und auch verstanden 
warum es so getrennt ist.
Aber warum machst du "0b" dann kommen die 2 bits die ignoriert werden 
(warum eigentlich?), dann die 4 Kommando bits und dann die Datenbits.
Aber warum kann ich den Wert, in Teil2 nicht ändern, ich möchte ja in 
binär mir den Widerstandswert einstellen.
Also müsste es doch so aussehen:

  Wire.write(0b00000100);
  Wire.write(0b00010000); // Wert wäre 16 (Von rechts 1,2,4,8,16)

Aber das geht bei mir nicht, was habe ich falsch gemacht ?

von Mathias (Gast)


Lesenswert?

"...Aber das geht bei mir nicht.." heißt was konkret? Was misst du dann 
mit dem Multimeter? Probier mal
1
  Wire.write(0b00000110);
2
  Wire.write(0b00000000);
Das sollte dann 50% sein.


"0b" sagt dem compiler, hier kommt jetzt eine Binärzahl. Die zwei 
ignorierten Bits kommen daher, weil das so im Datenblatt steht. Das 
Protokoll braucht nur 14 Bits, weil man aber mit dem uC nur ganze Bytes 
(=8Bit) senden kann, müssen irgendwo 2 Müll-Bits sein.

Und die 0kOhm kommen nicht vom Multimeter? Was misst du, wenn du die 
Prüfspitzen einfach zusammenhältst? Hast du ansonsten ein Oszilloskop 
zur Hand? Oder nimm mal ein anderes Multimeter? Keine Ahnung, ich bin 
kein Elektronikfachmann.

von Petr t. (vicon)


Lesenswert?

Mathias schrieb:
> "...Aber das geht bei mir nicht.." heißt was konkret? Was misst du dann
> mit dem Multimeter? Probier mal  Wire.write(0b00000110);
>   Wire.write(0b00000000);
> Das sollte dann 50% sein.

Ich habe das probiert, aber ich bekomme keinen Wert, es blinkt nur 
wieder :(
Ich habe schon das beste Multimeter in der Firma ;) , denke nicht das es 
daran liegen kann.
Ok, das mit den Bits habe ich verstanden.

Aber warum funktioniert das nicht, hast du das bei dir probiert ?

von Mathias (Gast)


Lesenswert?

Nö, schick mir nen AD5272 und ich probier das mal aus...

Ich glaube ich kann hier nicht mehr helfen, frag den Rest in deinem 
anderen Thread:
https://ez.analog.com/thread/69278

von Petr t. (vicon)


Lesenswert?

Mathias schrieb:
> Nö, schick mir nen AD5272 und ich probier das mal aus...
>
> Ich glaube ich kann hier nicht mehr helfen, frag den Rest in deinem
> anderen Thread:
> https://ez.analog.com/thread/69278

Ok, trotzdem danke für deine Hilfe, hast mir viel geholfen.
^^

von Petr t. (vicon)


Lesenswert?

Hallo,

hat noch jemand anderes weitere lösungsvorschläge ?

Danke

von Mathias (Gast)


Lesenswert?

Schick doch mal ein Foto/Schaltplan von deinem Aufbau. Vielleicht ist ja 
was kaputt.

Probier mal:
1
  Wire.beginTransmission(44); // transmit to device #44 (0x2c)
2
3
  Wire.write(0b00000110);  //Write RDAC 50%
4
  Wire.write(0b00000000);
5
6
  Wire.write(0b00001000);  //Read RDAC
7
  Wire.write(0b00000000);
8
9
  Wire.endTransmission();      // stop transmitting (evtl. erst später senden?)
10
  
11
12
  Wire.requestFrom(44, 2);
13
14
  while(Wire.available())    // slave may send less than requested
15
  { 
16
    byte c = Wire.read();    // receive a byte as character
17
    Serial.print(c);         // print the character
18
    Serial.print(" ");
19
  }
20
  Serial.println("");

von Petr t. (vicon)


Angehängte Dateien:

Lesenswert?

Mathias schrieb:
> Wire.beginTransmission(44); // transmit to device #44 (0x2c)
>
>   Wire.write(0b00000110);  //Write RDAC 50%
>   Wire.write(0b00000000);
>
>   Wire.write(0b00001000);  //Read RDAC
>   Wire.write(0b00000000);
>
>   Wire.endTransmission();      // stop transmitting (evtl. erst später
> senden?)
>
>
>   Wire.requestFrom(44, 2);
>
>   while(Wire.available())    // slave may send less than requested
>   {
>     byte c = Wire.read();    // receive a byte as character
>     Serial.print(c);         // print the character
>     Serial.print(" ");
>   }
>   Serial.println("");

Mathias, vielen vielen dank :)
jetzt läuft das Digital Poti, der Widerstand lässt sich vom minimalen 
Wert 28,8 Ohm bis 20kOhm einstellen.

Das Problem lag wohl das der Kommando Code 0b00001000 zum auslesen des 
RDAC nicht vorhanden war.

Nochmals vielen dank.

Ps. Hier das Foto

von Mathias (Gast)


Lesenswert?

Wat? Das soll geholfen haben? Also du hast das ja schon mit nem 
Multimeter gemessen, das sollte dann doch nichts mehr ändern... 
merkwürdig.
Na was solls, man muss ja nicht immer verstehen warum etwas geht oder 
nicht geht, so lange es geht...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.