Wie mit analog Poti => Digital Poti ansteuern ?

Doc_Arduino:
Wobei ich mir aktuell wegen der Datenübertragung nicht ganz sicher bin ob der wirklich nur 11 Bits haben möchte oder doch volle 16 also 2 Bytes.
Einmal wird im Datenblatt immer von 11 Bit geschrieben und dann wieder von einem Word Format, was 2 Bytes sind.
Keine vollen Bytes wäre unüblich, dann ginge nie Hardware SPI.

Ich denke auch dass SPI nicht funktionieren kann.

Der Kode von "nur 11 Bits" sollte funktionieren, ich würde aber (außer wie hier zum Test) andere Pins nehmen,
Software SPI auf den Hardware SPI Pins ist wirklich nur zum Testen sinnvoll.

Hallo,

dann bin ich erstmal nicht alleine wegen den 11 Bits. :slight_smile:
Andere Pins zuverwenden ist auch eine gute Idee für Software SPI.
Dann kommt sich nichts in die Quere. Dann ist man auch gezwungen nochmal mitzudenken.

Ich würde den IC aufbauen und am Poti mit dem Multimeter keine Widerstände sondern Spannungen messen. A1 an 5V und B1 an Masse. Mit dem Multimeter zwischen W1 und Masse die Spannung messen.
Tja und dann eben in einer Schleife Daten rüberschicken und schauen was passiert. Dann kannste noch beide Varianten der Übertragung ausprobieren. Falls eine nicht das tut was sie soll.

Der Spannungsteiler ist nur aktiv wenn du /PR auf low schaltest. Dann schaltet er sich intern auf halben Wert, also 128. Kannst auch 128 übertragen, hat den gleichen Effekt.

Doc_Arduino:
Der Spannungsteiler ist nur aktiv wenn du /PR auf low schaltest. Dann schaltet er sich intern auf halben Wert, also 128. Kannst auch 128 übertragen, hat den gleichen Effekt.

Ist es nicht einfach nur der Poti-Registerwert der durch /PR auf 0x80 gesetzt wird?

Wenn man die 0x80 selbst schreibt, muss man das für alle Register einzeln machen,
/PR erledigt das in einem Aufwasch.

Völlig korrekt. Auf das /PR Signal reagieren alle Potis zeitgleich. :wink:

Whandall:
Ich denke auch dass SPI nicht funktionieren kann.

Der Kode von "nur 11 Bits" sollte funktionieren, ich würde aber (außer wie hier zum Test) andere Pins nehmen,
Software SPI auf den Hardware SPI Pins ist wirklich nur zum Testen sinnvoll.

Beim Uno R3 sind die HardwareSPI PIN`s doch D10 - D13 ?

Könnte ich, um bei Euren Tipps zu bleiben, dann zB einfach dafür die PIN`s D6 - D9 verwenden, und diese dann per pinMode als Output definieren ?
Oder sind dafür noch weitere Schritte nötig ?

Grüsse

Hallo,

klar kannste machen. Wenn du im Sketch kein Hardware SPI verwendest, also SPI.h nicht einbindest, dann kannste auch bei den bsiherigen Pins bleiben. Musst nur alle mit pinMode einstellen. Und denke dran den CS Pin default auf High zu setzen.

Doc_Arduino:
Hallo,

Zum testen ohne Hardware SPI. Der /CS Pin muss in Idle, also schon im setup auf HIGH.

nur 11 Bits

void softSPItransfer( const uint8_t address, const uint8_t value ) 

{ // rausschieben, MSB first
 uint16_t data = 0;
 data = (data|address)<<8;
 data |= value;                    // beide Bytes verodern
 
 data = data<<5;                   // Bit 7 bis 3 rauswerfen

for(uint8_t i=0; i<11; i++) {
   if (data & 0x8000) {            // nur oberstes Bit betrachten
     digitalWrite(MOSI, HIGH);     // und Datenleitung entsprechend setzen
   }
   else {
     digitalWrite(MOSI, LOW);
     
   }
   digitalWrite(CLK, HIGH);        // Takt erzeugen
   data = data<<1;                 // nächstes Bit links schieben
   digitalWrite(CLK, LOW);
 }

digitalWrite(CS, HIGH);
}

Habe gerade versucht den obigen Code zu compilieren:

zuerst kommt 'CLK' was not declared in this scope, füge ich die mit int CLK ein
kommt 'CS' was not declared in this scope...
Wenn beide eingefügt sind erhalte ich:

Arduino: 1.8.6 (Windows 10), TD: 1.45, Board: "Arduino/Genuino Uno"
Arduino: 1.8.6 (Windows 10), TD: 1.45, Board: "Arduino/Genuino Uno"

exit status 1
Fehler beim Kompilieren für das Board Arduino/Genuino Uno...

Grüsse

Hallo,

sagmal, willst du mich jetzt verarschen? :wink: Ist das dein gesamter Sketch?

Doc_Arduino:
Und denke dran den CS Pin default auf High zu setzen.

Wenn man kein SPI benutzen will ist das irrelevant.

@stingray05 poste bitte den aktuellen Sketch und die vollständige Fehlermeldung.

Hallo,

das ist nicht irrelevant. Ob man Hardware- oder Software SPI verwendet ist erstmal irrelevant. Die Signale an den Pins müssen dennoch stimmen. Aber das weißt du doch. :wink:

Quatsch.

Ob der doofe Chip die ganze Zeit selektiert ist oder nicht spielt keine Rolle.

Hauptsache er ist selektiert wenn man mit ihm reden will. :wink:

Niemand anders benutzt diese seriellen Verbindungen zwischen dem Arduino und dem Chip.

Die Ähnlichkeit mit SPI heisst nicht dass man alles genauso,
oder es irgendjemandem Recht machen muss, wie Output Pin abschalten oder so.

Hallo,

da muss ich leider nochmal widersprechen. :wink: Der CS benötigt den sauberen Pegelwechsel. Ich kenne das nicht anders. Ich erwähnte das mit dem CS auf High, weil es vor paar Tagen hier einen Fall gab wo das vergessen wurde. Nach der Korrektur funktionierte es. Standardmäßig setze ich CS immer auf HIGH. Dann kann nichts schief gehen.

Ich habe das nochmal mit meinem EA Display und einem MAX7221 einzeln getestet ob es vielleicht Ausnahmen gibt. Mit denen nicht. Lasse ich CS dauerhaft auf Low macht der MAX7221 gar nichts und das Display zeigt Müll an.

Natürlich muss man den CS Pin benutzen wie im Datenblatt beschrieben.

Bedarf das einer besonderen Erwähnung?
Nur weil es mal jemanden gab der das nicht machte?

Egal.

Andere Pins als die normalen SPI Pins benutzen, diese richtig konfigurieren,
dann kann man (datenblattgemäß) 11 Bit Nachrichten senden.

Ein Blick ins Datenblatt kann viele Unklarheiten beseitigen :slight_smile:

CS wird benötigt, um die Daten in die internen Register zu übernehmen, ein statisches Signal nützt da garnichts. Zudem kann man dann 16 Bit mit SPI schicken, wobei die ersten 5 Bits egal sind - die fallen einfach hinten raus.

Hallo,

dann haben wir aneinander vorbei geredet. Egal.

@ Doktor:
Wenn ich mir das recht überlege sollte das klappen mit 2 Bytes rein und die 5 nicht benötigten Bits gehen ordnungsgemäß verloren.

Kann er ja alles testen wenn er mitbekommen hat was er vergessen hat zu programmieren oder zu ändern. Ich sehe es schon vor meinem Auge bei der gezeigten Fehlermeldung. :slight_smile:

Doc_Arduino:
Hallo,

sagmal, willst du mich jetzt verarschen? :wink: Ist das dein gesamter Sketch?

sorry Fehler von mir !
aktueller compilierter Sketch mit der 11 bit Variante:

/* verwendet wird der Arduino Uno R3, IDE 1.86
  
    Das AD5204 soll von einem analog Poti angesteuert werden und 
    dessen Werte ausgeben.

    Verdrahtung:
    AD5204 PIN  3 (GND)=>         Arduino GND
    AD5204 PIN  4 (CS) =>         Arduino PIN D10
    AD5204 PIN  5 (PR) =>         Arduino +5 V
    AD5204 PIN  6 (VDO) =>        Arduino +5 V
    AD5204 PIN  7 (SHDN) =>       Arduino +5 V
    AD5204 PIN  8 (SDI / MOSI) => Arduino D11
    AD5204 PIN  9 (CLK/SCK) =>    Arduino D13
    AD5204 PIN 10 (SDO /MISO) =>  Arduino D12
*/ 

const byte analogPotiPin = A0;  // Globale Variable, legt A0 als PIN für das Analog Poti fest
int analogPotiWert = analogRead(analogPotiPin)/4;
int CS;
int CLK;


 void setup()
{
  pinMode(CS,OUTPUT); // definiert CS (PIN D10) als Output
  digitalWrite(CS,HIGH); // setzt CS (PIN D10) auf High  
  //SPI.begin(); // startet den SPI bus. 
  //SPI.setBitOrder(MSBFIRST); 
}

void loop()
{
   analogPotiWert = analogRead(analogPotiPin); 
}

//----[Functions]--------------------

   // POT value: 0 -> 3
   // LEVEL value: 0 -> 255 (8 bits)

void setPot(int POT, int LEVEL){ 
//     digitalWrite(CS, LOW);
//     SPI.transfer(POT);
//     SPI.transfer(LEVEL);
//     digitalWrite(CS, HIGH);
}

// nur 11 Bits !
void softSPItransfer( const uint8_t address, const uint8_t value )
{ // rausschieben, MSB first
  uint16_t data = 0;
  data = (data|address)<<8;
  data |= value;                    // beide Bytes verodern
  
  data = data<<5;                   // Bit 7 bis 3 rauswerfen
 
  for(uint8_t i=0; i<11; i++) {
    if (data & 0x8000) {            // nur oberstes Bit betrachten
      digitalWrite(MOSI, HIGH);     // und Datenleitung entsprechend setzen
    }
    else {
      digitalWrite(MOSI, LOW);
      
    }
    digitalWrite(CLK, HIGH);        // Takt erzeugen
    data = data<<1;                 // nächstes Bit links schieben
    digitalWrite(CLK, LOW);
  }

  digitalWrite(CS, HIGH);
}

Der Code wird zwar Fehlerfrei compiliert, Drehbewegungen am Poti ändern aber nicht die nachstehenden Messwerte. Ich geh mal davon aus das im Sketch sicher noch einiges fehlt oder falsch ist...

Messung zwischen PIN 18 (A1) und PIN 16 (B1) bei offenem PR / SHDN PIN = schwankende Werte zwischen 95 K und etwa 105 KOhm.
Wenn PR auf + 5V liegt zeigt der Wert etwa 115 KOhm.
Sobald SHDN zusätzlich auf +5 V gelegt wird pendelt sich der Messwert bei etwa 73 KOhm ein.

Messung A1 / W1 bei offenem PR / SHDN PIN = etwa 75 KOhm. Mit +5V an PR pendelt der Wert um 75 KOhm. Wird zusätzlich an SHDN +5V angelegt, werden 36 kOhm angezeigt.

Messung B1 / W1 bei offenem PR / SHDN PIN = etwa 5KOhm. Dies Werte ändern sich fast bis auf 0 wenn man nur mit den Fingern in die Nähe der Drähte kommt...
Mit +5V an PR und SHDN liegt der Wert bei etwa 34 kOhm, berühre man die Drähte halbiert sich der Wert...

Grüsse

Hallo,

was machst du denn? Bin etwas verärgert. Deine loop macht nichts weiter wie den analogen Pin einlesen. Das wars.

Du hättest nur die benötigten Pins definieren, analog einlesen, vier teilen und meiner Funktion übergeben müssen.

Pin 13 lasse ich gern frei für "Debuginformationen". Kann jeder machen wie er möchte.
Beachte die Pinnummern oder ändere sie passend ab.
SDO/MISO benötigen wir hier nicht.

Mach was daraus und lerne bitte die Grundlagen, wenn es noch an den Pins scheitert.

Nochwas. Pin 6 vom AD5204 heißt VDD bzw. Vdd und nicht VD0. Sonst kann es mal schnell rauchen.
VDD ... +5V
VSS ..... Masse in dem Fall
GND ... Masse

/* verwendet wird der Arduino Uno R3, IDE 1.8.6
  
    Das AD5204 soll von einem analog Poti angesteuert werden und
    dessen Werte ausgeben.

    Verdrahtung:
    AD5204 PIN  3 (GND)=>         Arduino GND
    AD5204 PIN  4 (CS) =>         Arduino Pin D10
    AD5204 PIN  5 (PR) =>         Arduino +5 V
    AD5204 PIN  6 (VDO) =>        Arduino +5 V
    AD5204 PIN  7 (SHDN) =>       Arduino +5 V
    AD5204 PIN  8 (SDI / MOSI) => Arduino Pin D11
    AD5204 PIN  9 (CLK/SCK) =>    Arduino Pin D12
*/

const byte pin_A0   = A0;  // Globale Variable, legt A0 als PIN für das Analog Poti fest
const byte pin_CS   = 10;
const byte pin_MOSI = 11;
const byte pin_CLK  = 12;

byte analogPotiWert;


 void setup()
{
  digitalWrite(pin_CS,HIGH); 
  pinMode(pin_CS,OUTPUT); 
  pinMode(pin_MOSI,OUTPUT); 
  pinMode(pin_CLK,OUTPUT); 
}


void loop()
{
   analogPotiWert = analogRead(pin_A0)/4;

   setPoti(0, analogPotiWert);    // 1. Kanal und Wert
   setPoti(1, analogPotiWert);    // 2. Kanal und Wert
   setPoti(2, analogPotiWert);    // 3. Kanal und Wert
   setPoti(3, analogPotiWert);    // 4. Kanal und Wert

  
   /*
   for (byte i=0; i<4; i++) {     // oder so für alle
     setPoti(i, analogPotiWert);
   }
   */
}

//----[Functions]--------------------


// nur 11 Bits !
void setPoti( const uint8_t address, const uint8_t value )
{ // rausschieben, MSB first
  uint16_t data = 0;
  data = (data|address)<<8;
  data |= value;                    // beide Bytes verodern
  
  data = data<<5;                   // Bit 16 bis 12 rauswerfen

  digitalWrite(pin_CS, LOW);
   
  for(uint8_t i=0; i<11; i++) {
    if (data & 0x8000) {            // nur oberstes Bit betrachten
      digitalWrite(pin_MOSI, HIGH); // und Datenleitung entsprechend setzen
    }
    else {
      digitalWrite(pin_MOSI, LOW);
    }
    digitalWrite(pin_CLK, HIGH);    // Takt erzeugen
    data = data<<1;                 // nächstes Bit links schieben
    digitalWrite(pin_CLK, LOW);
  }
  digitalWrite(pin_CS, HIGH);
}

Doc_Arduino:
Hallo,

was machst du denn? Bin etwas verärgert. Deine loop macht nichts weiter wie den analogen Pin einlesen. Das wars.

Du hättest nur die benötigten Pins definieren, analog einlesen, vier teilen und meiner Funktion übergeben müssen.

Pin 13 lasse ich gern frei für "Debuginformationen". Kann jeder machen wie er möchte.
Beachte die Pinnummern oder ändere sie passend ab.
SDO/MISO benötigen wir hier nicht.

Mach was daraus und lerne bitte die Grundlagen, wenn es noch an den Pins scheitert.

Nochwas. Pin 6 vom AD5204 heißt VDD bzw. Vdd und nicht VD0. Sonst kann es mal schnell rauchen.
VDD ... +5V
VSS ..... Masse in dem Fall
GND ... Masse

Hallo Doc_Arduino,

großen Dank für Deine Tipps ! - Habe die PIN`s entsprechend angepasst. Es funktioniert jetzt (nach einem Drahtbruch an VSS...) - zumindest teilweise...

Ich kann tatsächlich Änderungen am AD 5204 messen:
Gesamtwiderstand Zwischen A3 / B3 rund 110 kOhm.

Zwischen A3/W3 etwa 50 - 100 KOhm wenn ich an meinem Analog Poti drehe, - unter 50 K geht allerdings nicht.
Zwischen B3/W3 messe ich etwa 0 - 8 KOhm... Mehr als 8 kOhm geht nicht...
Die selben Ergebnisse auch zwischen A1/W1, A2/W2, A4/W4, und auch bei einem zweiten neuen AD5204.

Bei allen Messungen war PR und SHDN offen (nicht beschaltet).
Die gemessenen Werte schwanken ziemlich stark (mindestens +- 20%), und ändern sehr gerne die Werte je näher man den Anschlussdrähten kommt...

Ein Potiknopf aus Kunststoff bracht da schonmal die erste leichte Besserung.

Ich habe dann mal mit externen Pullup / Pulldown, sowohl am Eingang A0 als auch an den Ausgängen
D 10 - D12 getestet:
Leider ohne den gewünschten Erfolg - Da ändert sich nix. Die Werte schwanken nach wie vor.
Auch der Tausch des Analog Potis gegen 10 k, 50 k oder 250 K brachte keine Änderung.

Fragen:
Was muss noch wo geändert werden um den Widerstand am AD 5204 nun durchgängig von 0 - 100 k regelbar zu machen ?
Wie lassen sich die stark schwankenden Werte in den Griff bekommen ?

Grüsse

Hallo,

na wenigstens etwas.

/PR und /SHDN offen zulassen wurde nicht gesagt.

Zum Schwankungsproblem. Messe bitte keine Widerstände sondern Spannungen.
Ansonsten zeichne bitte einen ordentlichen Schaltplan.
Das heißt, nichts mit Fritzing! Jedenfalls für mich.

Für die Widerstandsmessung wird eine Spannung angelegt, und wenn die die falsche Polarität hat, kann beliebiger Murks herauskommen. Also wie bereits erwähnt eine vorschriftsmäßige Spannung anlegen und dann die Ausgangsspannung messen.