Forum: Mikrocontroller und Digitale Elektronik Programmierung eines ADC mit Arduino


von Moffo M. (Firma: HAWK Göttingen) (marcel2)


Lesenswert?

Hallo,

ich arbeite gerade an einem Projekt, bei dem es darum geht, ein analoges 
Signal von einem ADC in ein digitales umwandeln zu lassen. Ich habe mir 
hier auf dem Forum ähnliche Projekte angeguckt, leider habe ich bis 
jetzt keine Lösung zu meinem Problem gefunden.

Ich habe als Mikrokontroller das Arduino Due zur Steuerung des 
AD7911/AD7921. Ich habe leider keine Erfahrung mit 
Arduino-Programmierung und möchte jetzt lernen, wie das ganze läuft.

hier ist das Datenblatt für mein 
Bauteil:http://www.analog.com/static/imported-files/data_sheets/AD7911_7921.pdf

ich möchte gern wissen, wie die SPI Kommunikation funktioniert, das 
heißt wie ich den ADC mit dem Arduino anspreche.  anschließend möchte 
ich das Ergebnis der  Umwandlung an den Arduino schicken und in ein 
Register speichern.

Ich habe erstmals den Code nur für einen Channel geschrieben, aber es 
läuft gar nichts.

über eine Antwort würde ich mich sehr freuen.
1
  #include<SPI.h>
2
 
3
 const int cs = 4;
4
 unsigned int adcValue;
5
 unsigned int adcValue1;
6
 unsigned int config1;
7
 int j=0;
8
9
void setup()
10
11
{
12
  pinMode(cs, OUTPUT);
13
  digitalWrite(cs, HIGH);
14
  SPI.begin();
15
  SPI.setBitOrder(MSBFIRST);
16
  SPI.setClockDivider(cs,21);
17
  SPI.setDataMode(SPI_MODE0);
18
  Serial.begin(9600);
19
20
}
21
22
23
void loop()
24
{
25
  //Analog Digital Umwandlung 
26
  for (int i=0; i<16; i++)
27
  {
28
    digitalWrite(cs, LOW);
29
    setAdc(1);
30
  }
31
  digitalWrite(cs, HIGH);
32
  delayMicroseconds(10);
33
}  
34
 
35
36
//Analog Digital Funktion
37
void setAdc(int channel)
38
{
39
  int c=16;
40
 int feld1[c];
41
     config1=0010000000000000;
42
43
   byte adcValueLSB = SPI.transfer(cs,0x00);        // niederwertiges Byte zuerst, D15...D8
44
  byte adcValueMSB = SPI.transfer(cs,0x00);        // höherwertiges Byte zum Schluss, D7...D0
45
  adcValue = adcValueMSB << 8;
46
  adcValue = adcValue | adcValueLSB;
47
  adcValue1= adcValue | config1; 
48
  
49
     feld1[j] = adcValue1;
50
    Serial.print("analog value = ");
51
    Serial.println(feld1[j]);
52
    Serial.print('\n');
53
54
      j++;
55
  
56
  delayMicroseconds(0.25);//convertion time
57
 
58
      
59
}

: Bearbeitet durch User
von Hafax (Gast)


Lesenswert?

Hi,

Erst einaml eine Grundlegende Frage: Ist ein externer ADC notwendig? 
Dein Arduino Due hat zwei ADC integriert die sich bequemer Auslesen 
lassen...

Nach einem kurzen Blick ins Datenblatt des ADCs bin ich, auf Seite 21, 
auf diesen Satzt gestoßen "Sixteen serial clock cycles
are required to perform the conversion process and to access
data from the AD7921". Wenn ich mir deinen Code ansehen könnte ich mir 
Vorstellen das der CS Pin nach jedem Byte wieder High wird und keine ADC 
Wandlung zustande kommt.
Versuch einmal die Chip Select Leitung "von Hand" zu setzen.
1
 CS PIn low setzten
2
 adcValue_high_byte = SPI.transfer(0x00)
3
 adcValue_low_byte = SPI.transfer(0x00)
4
CS Pin high setzten

Grüße

Hafax

von Moffo M. (Firma: HAWK Göttingen) (marcel2)


Lesenswert?

Hey Hafax,
 Danke erstmal für deine schnelle Reaktion. Ich verstehe die Frage mit 
externem ADC, aber der Projektleiter will, dass ich die Umwandlung mit 
einem externen ADC  mache.

Ich versuche es und melde mich nochmal zurück.
Vielen Dank.

Marcel

von Cyblord -. (cyblord)


Lesenswert?

Apropos HAWK: Fällt jetzt dein völlig talentloses Arduino rumgefrickel 
unter Wissenschaft oder Kunst?

von Moffo M. (Firma: HAWK Göttingen) (marcel2)


Lesenswert?

hey ,

meintest du das?
1
 #include<SPI.h>
2
3
 const int cs = 4;
4
 unsigned int adcValue;
5
 unsigned int adcValue1;
6
 unsigned int config1;
7
 int j=0;
8
9
void setup()
10
11
{
12
  pinMode(cs, OUTPUT);
13
  digitalWrite(cs, HIGH);
14
  SPI.begin();
15
  SPI.setBitOrder(MSBFIRST);
16
  SPI.setClockDivider(cs,21);
17
  SPI.setDataMode(SPI_MODE0);
18
  Serial.begin(9600);
19
20
}
21
22
23
void loop()
24
{
25
  //Analog Digital Umwandlung
26
  for (int i=0; i<16; i++)
27
  {
28
    setAdc(1);
29
  }
30
  delayMicroseconds(10);
31
}
32
33
34
35
//Analog Digital Funktion
36
void setAdc(int channel)
37
{
38
  int c=16;
39
 int feld1[c];
40
     config1=0010000000000000;
41
 digitalWrite(cs, LOW);
42
SPI.transfer(cs,config1);
43
   byte adcValueLSB = SPI.transfer(cs,0x00);        // niederwertiges 
44
Byte zuerst, D15...D8
45
  byte adcValueMSB = SPI.transfer(cs,0x00);        // höherwertiges Byte 
46
zum Schluss, D7...D0
47
 digitalWrite(cs, HIGH);
48
  adcValue = adcValueMSB << 8;
49
  adcValue = adcValue | adcValueLSB;
50
  adcValue1= adcValue | config1;
51
52
     feld1[j] = adcValue1;
53
    Serial.print("analog value = ");
54
    Serial.println(feld1[j]);
55
    Serial.print('\n');
56
57
      j++;
58
59
  delayMicroseconds(0.25);//convertion time
60
61
62
}

: Bearbeitet durch User
von Moffo M. (Firma: HAWK Göttingen) (marcel2)


Lesenswert?

Unter Wissenschaft und Kunst:)

von Hafax (Gast)


Lesenswert?

Ok nachdem ich etwas mehr Zeit hatte mir das ganze Anzusehen mal eine 
etwas Detailiertere Antwort...

1: Du übergibst den Wert Channel machst dann aber nichts damit.

2: Du Deklarierst eine Varible
1
 int c=16;
 nur im die Größe des
1
 int feld1[c];
 Arrays zu Definieren. Das ging mit einem
1
#define buffer_gr 16
 schöner.

3: Die Werte in deinem Array feld1 sind nach dem Rücksprung aus der 
Funktion nicht mehr Vorhanden.

4: Versuch einheitlich einzurücken

5: Es besteht ein Unterschied zwischen
1
 SPI.transfer(cs,0x00);
 und
1
 SPI.transfer(0x00);

6: Du setzt deine Index Variable j nie zurück => Das ganze läuft einmal 
dann erst nach dem Überlauf von j. Das Aber noch viel größere Problem 
ist das du mit j auf eine Stelle im Array feld1 zugreifst. Dieses ist 
aber nur 16*Sizeof(int) lang. Ist j > 16 greifst du auf einen 
Speicherbereich zu der nicht im Array liegt. Gratuliere du hast einen 
Bufferoverflow Programmiert ;D

Sind auf die Schnelle die Gröbsten Schnitzer in der Programmierung.

Nun zum Funktionstechnischen...

Lies dich in SPI ein und wie es Funktioniert. Kleiner Tipp es werden 
bidirektional die Daten geschrieben und gelesen. SPI ist eigentlich ein 
Schieberegister...

Es müsste in etwa so aussehen.
1
 CS auf Low
2
adcValue_low_byte = SPI.transfer(config1);
3
adcValue_high_byte = SPI.transfer(0x00);
4
CS auf High

von Hafax (Gast)


Lesenswert?

Ok um so länger ich hier schreib um so mehr fällt mir auf und ein... 
Aber ich geh jetzt erst mal Glühwein trinken :P Dir noch viel spaß beim 
Progen... Btw. ein Tutorial lesen schadet selten.

von Moffo M. (Firma: HAWK Göttingen) (marcel2)


Lesenswert?

hey ,

vielen Dank nochmal für deine Hilfe.ich hoffe dein Glühwein hat gut 
geschmeckt.ich werde morgen mein Programm noch besser strukturieren.

von Moffo M. (Firma: HAWK Göttingen) (marcel2)


Lesenswert?

hallo,

ich habe mich heute nochmal mit dem Projekt beschäftigt, aber dabei kam 
nichts befriedigendes raus. Trotzdem glaube ich, dass das Programm schon 
besser aussieht :) ich hätte aber gern noch Hilfe und ein Paar Fragen.

hier ist mein Code, aber ich bin noch total unsicher.

  #include<SPI.h>
  #define BUFFER_SIZE1    16


 const int cs = 4;
 unsigned int adcValue;
 unsigned int config1;
 unsigned int feld1[BUFFER_SIZE1];


void setup()

{
  pinMode(cs, OUTPUT);
  digitalWrite(cs, HIGH);
  SPI.begin(cs);
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(cs,21);
  SPI.setDataMode(cs,SPI_MODE0);
  Serial.begin(9600);

}


void loop()
{
 for(int i=0;i<16;i++)
 {
    feld1[i] =  setAdc();                              // damit will ich 
das ergebnis in einem Array speichern ,, ist dieser Befehl richtig?
    Serial.print("analog value = ");
    Serial.println(feld1[i]);
    Serial.print('\n');
    delayMicroseconds(10);
  }
}


//Analog Digital Funktion
int setAdc()
{
  config1=00100000;
  digitalWrite(cs, LOW);
  byte adcValueLSB = SPI.transfer(cs,config1);         // niederwertiges 
Byte zuerst, D15...D8
  byte adcValueMSB = SPI.transfer(cs,0x00);         // höherwertiges 
Byte zum Schluss, D7...D0
  adcValue = adcValueMSB << 8;
  adcValue = adcValue | adcValueLSB;                //wird sommit das 
umgewandelte Signal an adcValue zugewiesen?
  delayMicroseconds(4);                           //cycle time
  digitalWrite(cs, HIGH);
  return adcValue;

}




 1) wie kann ich das Ergebnis der Umwandlung in ein Array speichern
2) wie kann ich auf das Ergebnis ohne die ersten 4 Bits 
zugreifen(convertion result).

von Moffo M. (Firma: HAWK Göttingen) (marcel2)


Lesenswert?

sorry nochmal wenn ich blöde Fragen stelle...ich lerne gerade Arduino 
und SPI:)

von Cyblord -. (cyblord)


Lesenswert?

Moffo Marcel schrieb:
> sorry nochmal wenn ich blöde Fragen stelle...ich lerne gerade Arduino
> und SPI:)

Werd doch lieber Gärtner. Da lernst du Bäume und Blumen. Evt. liegt dir 
das besser?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.