alternative zu MCP4921

Hallo,
ich habe ein großes Problem. Ich habe einen MCP4921 als DAC für meinen Arduino Mega 2560. Dieser funktioniert alleine auch super. Wenn ich aber die SD Karte mit an den SPI schlisse und den DAC ebenfalls gibt es Probleme. Mit dem Oszi betrachtet sieht man deutlich, dass die Sende Protokolle sich unterscheiden :frowning:

Habt ihr einen anderen DAC der ebenfalls so einfach ist wie dir MCP4921 zb. einen für I2C?

Vielen Dank im Voraus

(link zum MCP4921)

Hallo,
ich habe den MCP4716 schon mal eingesetzt, funktioniert über i2c problemlos, gibt es auch als MCP4726 als 12Bit Variante.
Wie sind deine Anforderungen an Geschwindigkeit? SPI ist da sicher schneller.
Gruß
Reinhard

Hallo Reinhard ,
vielen Dank für deine Antwort.
Gibt es für dieses IC auch eine Lib? Oder wie kann ich ihm sagen was es zu tun hat? :blush:
Geschwindigkeit ist recht langsam, ca. alle 60Sek wird der Wert Geändert.

Viele Grüße

Hallo Masterboy,

nein, eine Library habe ich dafür nicht benutzt. Die Basisfunktion "Analog Wert einstellen" kann man sich aus dem Datenblatt herleiten.
Hier mal ein Beispielprogramm mit einem Sweep, aus dem die Programmierung ersichtlich ist.

#include <Wire.h>
#define DAC_ADD 0x60
unsigned int volts=0;  // 10 Bit = Vcc

void setup() {
  Serial.begin (115200);
  Serial.println ();
  Serial.println ("MC4716 Test ...");
  byte count = 0;
  
  Wire.begin();
    Wire.beginTransmission (DAC_ADD);
    if (Wire.endTransmission () == 0)
      {
      Serial.print ("Found address: ");
      Serial.print (DAC_ADD, DEC);
      Serial.print (" (0x");
      Serial.print (DAC_ADD, HEX);
      Serial.print (" ");
      Serial.print (DAC_ADD, BIN);
      Serial.println (")");
      delay (1);  // maybe unneeded?
      } // end of good response
}  // end of setup

void loop() {
  byte byte0 = (volts >> 6);
  byte byte1 = (volts << 2) & 0xFF;
  unsigned int volt_w = map(volts,0,1023,0,4810);
      Serial.print(volt_w);
      Serial.print(" mv ");
      Serial.print (volts);
      Serial.print(" ");
      Serial.print(byte0, BIN);
      Serial.print(" ");
      Serial.print(byte1, BIN);
      Serial.print(" ");
      Serial.print (byte0);
      Serial.print(" ");
      Serial.println(byte1);
 
    Wire.beginTransmission(DAC_ADD);
    Wire.write(byte0);
    Wire.write(byte1);
    Wire.endTransmission();   
    delay(1000);
  volts++;
  if (volts==1024) volts=0;
}

Gruß
Reinhard

Hallo Masterboy,

Du brauchst keinen anderen D/A-Wandler!

Das gleiche Problem hatte ich auch.
Man muss 'nur' den Inhalt der SPI-Register sichern, dann die SPI-Kommunikation starten, nach Beendigung der SPI-Kommunikation das die SPI-Register wieder herstellen und schon funktioniert die SD-Card wieder:

saved_spcr = SPCR;
saved_spsr = SPSR;

Jetzt wird die SPI-Kommunikation gestartet
Ist die SPI-Kommunikation fertig, geht das ganze andersherum, d.h. die SPI-Register werden wieder auf den ursprünglichen Wert gesetzt:

SPCR = saved_spcr;
SPSR = saved_spsr;

Diesen Trick hat mir ein freundlicher Kollege hier aus dem Forum verraten.

Gruß

Martin

Hallo Martin,

das klingt ja noch einer super einfachen Lösung.
Allerdings habe ich jetzt ein anderes Problem. :fearful:

Wenn ich folgendes mache:

       saved_spcr = SPCR;
       saved_spsr = SPSR;
       
       AnalogOutput1.setValue(2000);
       
       SPCR = saved_spcr;
       SPSR = saved_spsr;

kommt eine Fehlermeldung:
saved_spcr was not declared in this scope....

Könnt ihr mir das weiter Helfen? Die SPI und Wire Hex habe ich includet

Viele Grüße

Hallo,

Du musst halt ehe Du die beiden Variablen benutzt diese auch definieren:

int saved_spcr;
int saved_spsr;

Gruß,
Ralf

Danke für die schnelle Antwort.

es geht trotzdem nicht, bzw. ich habe das gleiche Problem wie vorher. Der DAC will einfach nicht :frowning:

       saved_spcr = SPCR;
       saved_spsr = SPSR;
       
       AnalogOutput1.setValue(200);
       
       delay (100);
       
       AnalogOutput1.setValue(4000);
       
       SPCR = saved_spcr;
       SPSR = saved_spsr;

So steuer ich ihn an, aber leider tut sich nichts :cold_sweat:

grüße

Masterboy:
Danke für die schnelle Antwort.

es geht trotzdem nicht, bzw. ich habe das gleiche Problem wie vorher. Der DAC will einfach nicht :frowning:

       saved_spcr = SPCR;

saved_spsr = SPSR;
       
       AnalogOutput1.setValue(200);
       
       delay (100);
       
       AnalogOutput1.setValue(4000);
       
       SPCR = saved_spcr;
       SPSR = saved_spsr;





So steuer ich ihn an, aber leider tut sich nichts :cold_sweat:

grüße

besser so:

       int saved_spcr = SPCR;
       int saved_spsr = SPSR;
       
       AnalogOutput1.setValue(200);
       
       delay (100);
       
       AnalogOutput1.setValue(4000);
       
       SPCR = saved_spcr;
       SPSR = saved_spsr;

Hallo,

die Deklaration der Variablen macht man doch am Anfang oder nicht?

Viele Grüße

deklarieren musst du sie, wenn du sie brauchst. Wenn du sie nur einmal in einer Subroutine brauchst, musst du sie nicht global deklarieren.

Ich brauch diese Funktion bzw. den DAC in vielen Unterprogrammen.
Kann man den nicht die SPI Konfig wie beschrieben speichern und dann den SPI neu initialisieren?

Viele Grüße

Hallo Masterboy,

mit diesem Codefragment habe ich für mein derzeit in Arbeit befindliches Projekt die SPI-Kommunikation erfolgreich getestet:

void SPI_Senden(int Value)
{
  Hoch = highByte(Value);
  Nieder = lowByte(Value);
  Serial.println(Hoch);
  Serial.println(Nieder);
  SPI.transfer(Hoch+112);
  SPI.transfer(Nieder);
}


void SPI_Empfangen()
{
  R_Hoch = SPI.transfer(0);
  R_Nieder = SPI.transfer(0);
  Serial.println(R_Hoch);
  Serial.println(R_Nieder);
  Rueck = (R_Hoch & 31);
  Serial.print("1 ");
  Serial.println(Rueck);
  Rueck = Rueck*256;
  Serial.print("2 ");
  Serial.println(Rueck);
  Rueck = Rueck + R_Nieder;
  Serial.print("3 ");
  Serial.println(Rueck);
  Rueck = (Rueck >> 1);
  Serial.print(Rueck);
}

void SPI_Lesen()
{
// save the SPI registers
saved_spcr = SPCR;
saved_spsr = SPSR;  
SPI.begin();
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV4); 
digitalWrite(Test_Select, LOW);
SPI_Senden(UA_Soll);
delay(200);
digitalWrite(Test_Select, HIGH);
delay(200);
digitalWrite(Test_Select_2, LOW);
SPI_Empfangen();
delay(200);
digitalWrite(Test_Select_2, HIGH);
SPI.setBitOrder(LSBFIRST);
//SPI.setClockDivider(SPI_CLOCK_DIV);
SPI.end();
// restore the SPI registers
SPCR = saved_spcr;
SPSR = saved_spsr;
}

Ob die eingetragenen delays überhaupt erforderlich sind, habe ich noch nicht ausprobiert, die habe ich nur eingebaut, damit ich an den mit Leuchtdioden bestückten Chip-Select-Ausgängen sehen kann, ob die reagieren.

Ich gebe hier eine Spannung mit einem MCP4921 aus und lese sie über einen MCP3201 wieder zurück (zu Testzwecken).

Nach dem schliessen der SPI-Kommunikation und dem wiederherstellen der SPI-Register funktioniert dann auch wieder der SD-Card-Zugriff.

Gruß

Martin

Hast Du einen eigenen Enable-Pin (SS) für den MCP4921 benutzt? Die SD-Karte benuzt meist pin 4 oder seltener Pin 10.
Grüße Uwe

Hallo,

ja ich habe getrennte SS PINS in verwerndung.
Habe mir das ganze auch mit dem Oszi angeschaut und in der Theorie Funkt es auch.
Nur das sobald die SD Karte mit in dem programm ist, werden die Daten die an den DAC geschickt werden quasi invertiert.

Das ganze Läuft an einem Mega2560 evl hilft diese Info weiter :smiley:

Viele Grüße