DAC liefert falsches Ausgangssignal

Hallo,
ich habe ein Problem: Mein Ziel ist es, digitale Signal vom Arduino in ein analoges Signal durch meinen DAC umzuwandeln. Jedoch erscheint bei mir am Ausgang nicht das gewünschte Signal. Wenn ich beispielsweise eine Sinussignal vom Funktionsgenerator einspeise, erscheint am Ausgang eine ''Treppenfunktion'. Beim Rechtecksignal hingegen, erscheint auch am Ausgang ein Rechtecksignal.

Ich benutze einen ArduinoMega2560. Als Eingang verwende ich den Pin A0.

Als DAC wird der AD557 verwendet. Dabei ist wichtig zu beachten, dass die Pins 1-8 vom DAC mit dem PortL(42-49) verbunden sind. Das CS hat den Pin 9 und das CE hat den Pin 10. CS ist mit dem Pin 40 des Arduino verbunden und CE mit den Pin 41.

Bitte um Hilfe, bin schon am verzweifeln!

Hier ist der Programmcode:
ps: Alles mit dem Display ignorieren, da es in meinem Fall irrelevant ist. Messe das Signal mit einem Oszilloskop.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <LiquidCrystal.h>
#include <stdio.h>
#include "AODEF.h"


volatile static int i = 0;
volatile static uint8_t feld1[4999];

volatile static uint8_t j;
char x[100];


void setup() 
{ 
   cli();
  Serial.begin(9600);
  
//  
  /////////////////////////////DAC/////////////////////////////
  pinMode(40,OUTPUT);
  pinMode(41,OUTPUT);

  digitalWrite(40, LOW);
  digitalWrite(41, LOW);


  DDRL =0xFF;  //OUTPUT
  
  ///////////////////////ADC///////////////// //
  pinMode(A0,INPUT);
  
   ADCSRA=0;
   ADMUX=0;
   ADCSRB=0; // ADTS auf Null free running mit ADate

   ADMUX =  B01100000;
   ADCSRA = B11101110;
  
  sei();   // Enable Global Interrupts
  i=0;
}

ISR(ADC_vect)
{ 
  j=ADCH;
  feld1[i]=j;
  
  digitalWrite(40, LOW);
  
  PORTL = j;  //Ausgabe Wert
  
  digitalWrite(40, HIGH);
 
  i++;
  if(i>4998)

  { 
    i=0;
  }
}

void loop() {
}

Und was bitte soll der DOPPELPOST ?
Damit wird dein Problem auch nicht besser !

Weil es ja im letzten Post Probleme gab mit dem Code.

besart123:
Weil es ja im letzten Post Probleme gab mit dem Code.

Das ist doch kein Grund, dann kann man den Sketch nochmal posten.

Meist ist aber der Fehler an anderer Stelle zu suchen.

Ja tut mir Leid. Bin sehr neu in diesem Forum.

Hallo,

da der Code wild kopiert ist, einmal klassisch C und dann wieder Arduino Style und wirre cli / sei dabei sind, muss ich mal nach dem Ablaufplan fragen. Was soll der Code eigentlich konkret machen? Analogwert einlesen und den Wert zum externen DAC ausgeben. Dabei noch Displayausgaben?

Tip. Du musst das sauber untergliedern. Analog einlesen mit analogRead, dann fällt für dich die ISR weg, verarbeiten, Ausgabe an DAC und nebenbei wenn Zeit ist Ausgabe auf das Display. Den eingelesenen analogen Wert mußte durch 4 teilen, falls du mehr als 1,25V anlegst, dein DAC kann nur 8 Bit verarbeiten.

@Doc_Arduino du hast es erfasst, nur ist im diesem das Display irrelevant(habe es nur zum Überprüfen benötigt).
Ich messe das Ausgangssignal vom DAC mit einem Oszilloskop.

Hallo,

was macht die AODEF.h Lib?

Diese library habe ich von meinem Professor, da laut ihm sonst das Programm nicht korrekt wäre.

Hier der Code vom Aodef.h

// Ein Zeilenumbruch, abhängig davon, was die Gegenstelle haben will 
// Windows: "rn" 
// Linux  : "n" 
// MacOS  : "r" 
#define CR "\r\n"

// Set und Clear bit als Macro
#define SETBIT1(ADRESS,BIT) (ADRESS |= (1<<BIT))
#define SETBIT0(ADRESS,BIT) (ADRESS &= ~(1<<BIT))
#define SETBITT(ADRESS,BIT) (ADRESS ^= (1<<BIT))

//Macro zur BIT-Abfrage
#define CHECKBIT1(ADRESS,BIT) (ADRESS & (1<<BIT))
#define CHECKBIT0(ADRESS,BIT) ( !(ADRESS & (1<<BIT)) )

Hallo,

die Makros nutzt du aber nicht, also brauchst du sie auch nicht. Wer weiß wofür das dein Prof verwendet hat.
Dafür gibts eigentlich cbi und sbi.

Werf mal alles aus dem Code raus was du nicht brauchst. Zum Bsp. das Display.
Was macht Pin 40 und 41.
Port.L ist mir klar, komplett 8 Bit für DAC.
An A0 wird analog eingelesen.
Dann versuche ich den Code zu gliedern ...

Ich wiederhole meinen Text aus dem anderen Thread:

In einer ISR darfst du nicht Serial verwenden. Sondern nur ein Flag setzten und die Ausgabe in loop() machen. Dabei Variablen die innerhalb und außerhalb von ISRs verwenden werden volatile machen und den Zugriff atomar.

Außerdem solltest du die Baudrate auf Maximum setzen! Und nicht mit mickrigen 9600 Baud arbeiten wo ein Zeichen 1ms dauert

itoa() ist überflüssig. Das kann auch print() erledigen. Das ist wahrscheinlich weil der Code aus einem nicht-Arduino Programm ist.

Habe nun alles was ich nicht brauche(Display-Befehle) entfernt.

Der Pin 40 ist mit dem CS(Chip-Select) und der Pin 41 mit dem Chip CE(Chip-Enable) vom DAC verbunden.

Hallo,

sieht schon viel einfacher aus, mal sehen ob das klappt ...

/* 
 *   für Arduino Mega2560
 */

const byte CS = 40;
const byte CE = 41; 
const byte aIN = A0;

byte value;

void setup()
{
  digitalWrite(CS, LOW); 
  digitalWrite(CE, LOW); 
  pinMode(CS, OUTPUT);
  pinMode(CE, OUTPUT);
  DDRL =0xFF;     // 8 Bit Ausgang zum DAC AD557
  pinMode(aIN, INPUT);
  
}

void loop() {

  value = analog_einlesen();
  
  send_to_DAC(value);
  
}


// ****** Funktionen ****** //

byte analog_einlesen ()
{
  byte data = analogRead(aIN)/4;
  return data;
}


void send_to_DAC (byte data)
{
  digitalWrite(CS, LOW);
  PORTL = data;          // 8Bit parallel zum DAC
  digitalWrite(CS, HIGH);
}

Doc_Arduino:
die Makros nutzt du aber nicht, also brauchst du sie auch nicht. Wer weiß wofür das dein Prof verwendet hat.
Dafür gibts eigentlich cbi und sbi.

Das sind die Assember Primitiven, die Macros sind doch eher vergleichbar mit

bitRead()
bitWrite()
bitSet()
bitClear()
bit()

Vielen Danke für deine Hilfe und deinen Zeitaufwand! Werde es Morgen, wenn möglich in der Schule testen.

Hallo,

@ Serenifly,
die serielle wurde nicht genutzt, die ISR ist erstmal weg, damit kommt er erst gar nicht in Versuchung was falsch zu machen. Falls das Display wieder rein soll, kann er das mit einer zusatzlichen Funktion machen die den Ablauf nicht stört.

@ Whandall,
ja passt besser, :wink: so genau kenne ich mich mit den Unterschieden nicht aus. Nutzt man sehr selten.

@Doc_Arduino habe noch paar Fragen:

Brauche ich das ADCSRA und ADMUX nicht mehr? oder hast du es übersehen?
Wieso brauch in den Befehl PORTL = ADCH nicht mehr?

besart123:
Wenn ich beispielsweise eine Sinussignal vom Funktionsgenerator einspeise, erscheint am Ausgang eine ''Treppenfunktion'.

Was erwartest du bei 8 bit?
Man kann zwar mit einem RC Glied noch etwas die Flanken verschleifen, aber das funktioniert nur in einem bestimmten Frequenzbereich befriedingend, für den das RC Glied ausgelegt ist.

@Doc_Arduino

Würde es mit den Registern so passen? Oder ist das ADCH in dem Fall falsch?

/* 
 *   für Arduino Mega2560
 */

const byte CS = 40;
const byte CE = 41; 
const byte aIN = A0;

byte value;

void setup()
{
////////////////DAC//////////////////////
  digitalWrite(CS, LOW); 
  digitalWrite(CE, LOW); 
  pinMode(CS, OUTPUT);
  pinMode(CE, OUTPUT);
  DDRL =0xFF;     // 8 Bit Ausgang zum DAC AD557
  
//////////////ADC//////////////////////////
  pinMode(aIN, INPUT);

   ADCSRA=0;
   ADMUX=0;
   ADCSRB=0; // ADTS auf Null free running mit ADate

   ADMUX =  B01100000;
   ADCSRA = B11101110;
}

void loop() {

  value = analog_einlesen();
  
  send_to_DAC(value);
  
}


// ****** Funktionen ****** //

byte analog_einlesen ()
{
  byte data = ADCH;
  return data;
}


void send_to_DAC (byte data)
{
  digitalWrite(CS, LOW);
  PORTL = data;          // 8Bit parallel zum DAC
  digitalWrite(CS, HIGH);
}

Hallo,

die Register habe ich jetzt nicht im Kopf, müßte ich erst nachschauen, frühestens morgen wieder.
Im Datenblatt sollten jedoch Bsp. stehen.
Zum probieren Einlesewert serial ausgeben lassen, wenn alles passt, der DAC Funktion übergeben.
Ohne Debugging wird wohl niemand auskommen.

@ all: so viel ich nun weiß soll er zumindestens für das analoge einlesen klassisch mit Registern arbeiten