Forum: Mikrocontroller und Digitale Elektronik AD7793 Single Conversion Mode


von Bergie B. (bergie)


Lesenswert?

Hallo,

ich schlage mich gerade mit dem Externen AD7793 [[ 
http://www.analog.com/static/imported-files/data_sheets/AD7792_7793.pdf 
]] rum (und meinem MSP230F248)

Für meine Messung möchte ich den SingelConvert Modus benutzen.

Ich habe aber einen Bedienfehler drin den ich nicht erkenne.

Könntet ihr mir helfen?

Also ich gehe wie folg vor:

Ich habe die Kommunikation aufgebaut und kann alle Register auslesen nur 
mit den Messungen habe ich meine Probleme.

Zu erst Resette ich den ADC:

FF,FF,FF,FF

Dann beschreibe ich das:
- IO Register
28,02
- Mode Register
08,20,07

Dann möchte ich die Messungen Starten erst Ch1 dann Ch2:

- Config Register
10,11,90
lese Data(C0 sende ich um einen Takt zu erzeugen)
58,
while(RDY); //Warten bis der ADC sagt der er gemessen hat
C0,C0,C0


- Config Register
10,11,92
lese Data(C0 sende ich um einen Takt zu erzeugen)
58,
while(RDY); //Warten bis der ADC sagt der er gemessen hat
C0,C0,C0


Das Problem was ich habe stellt sich so da das ich genau EINE Messung 
nach dem RESET machen kann. Beim 2. beschreiben des Config registers 
signalisiert mir der ADC nicht das er fertig mit der Messung sein.

Muss ich ihm bevor er mit der Messung startet noch andere Sachen 
bereitstellen?

Wenn ich nun nur einen durchlauf machen lasse, und ihn danach RESETe um 
dann den anderen Ch zu messen bekomme ich ein Ergebnisse. Aber ich muss 
doch nicht für jede Messung einen reset ausführen oder?

LG und danke für jede Hilfe

von Bergie B. (bergie)


Lesenswert?

MM keiner da der sowas schonmal gemacht hat ?

Welche Register muss ich alle beschreiben um eine neue Messung zu 
starten?


Oder muss ich den ADC nach JEDER Messung in den RESET bringen?


LG

von Bergie B. (bergie)


Lesenswert?

schubs

zum Feier abend

von Michael H. (morph1)


Lesenswert?

hier ist mal 7792 im single conversion :)
1
void tempInit(void)
2
{
3
  tempReset();
4
  Delay10KTCYx(50);            // Pause
5
6
  tempSetRegister16(ADCCONFREG, 0x1200);  // Select buffered mode / chanel 1 / unipolar / gain 4
7
  tempSetRegister8(ADCIOREG, 0x02);
8
  tempSetRegister16(ADCMODEREG, 0x0009);  // 50Hz 80dB rejection
9
  Delay10KTCYx(50);            // Pause
10
}
11
12
void tempReset(void)
13
{
14
  TEMP_CS = 0;
15
  SPIWrite8(0xFF);
16
  SPIWrite8(0xFF);
17
  SPIWrite8(0xFF);
18
  SPIWrite8(0xFF);
19
  TEMP_CS = 1;
20
}
21
22
double tempRead(void)
23
{
24
  double temp;
25
  
26
  tempSetRegister16(ADCMODEREG, 0x2009);  // 50Hz 80dB rejection and start conversion
27
28
  TEMP_CS = 0;
29
  while(SDI);                // wait for conversion to finish
30
  TEMP_CS = 1;
31
    
32
  temp = tempConvert(tempReadRegister16(ADCDATAREG)); // read last conversion result and convert
33
34
  return temp;
35
}

wie unschwer zu erkennen messe ich damit eine temperatur :D

hoffe es hilft, die 2 ICs sind ja doch eng verwandt

von Michael H. (morph1)


Lesenswert?

Weil man mich gefragt hat, hier der restliche Code:
1
void tempSetRegister16(unsigned char reg, unsigned int data)
2
{
3
  reg = reg << 3;
4
  TEMP_CS = 0;
5
  softSPIWrite8(0x00 | reg);    // write to status reg
6
  softSPIWrite16(data);
7
  TEMP_CS = 1;
8
}
9
10
void tempSetRegister8(unsigned char reg, unsigned char data)
11
{
12
  reg = reg << 3;
13
  TEMP_CS = 0;
14
  softSPIWrite8(0x00 | reg);    // write to status reg
15
  softSPIWrite8(data);
16
  TEMP_CS = 1;
17
}
18
19
unsigned char tempReadRegister8(unsigned char reg)
20
{
21
  unsigned char data;
22
23
  reg = reg << 3;
24
  TEMP_CS = 0;
25
  softSPIWrite8(0x40 | reg);    // write to status reg
26
  data = softSPIRead8();
27
  TEMP_CS = 1;
28
29
  return data;
30
}
31
32
unsigned int tempReadRegister16(unsigned char reg)
33
{
34
  unsigned int data;
35
36
  reg = reg << 3;
37
  TEMP_CS = 0;
38
  softSPIWrite8(0x40 | reg);    // write to status reg
39
  data = softSPIRead16();
40
  TEMP_CS = 1;
41
42
  return data;
43
}

Noch die notwendigen Defines:
1
// ext. ADC
2
#define ADCSTATREG      0x00    // 8bit
3
#define ADCMODEREG      0x01    // 16bit
4
#define ADCCONFREG      0x02    // 16bit
5
#define ADCDATAREG      0x03    // 16bit
6
#define ADCIDREG        0x04    // 8bit
7
#define ADCIOREG        0x05    // 8bit
8
#define ADCOFFREG       0x06    // 16bit
9
#define ADCFSREG        0x07    // 16bit

Hoffe damit ist alles klar :)

von Martin A. (bitzel)


Lesenswert?

Hallo,

ich hab gerade das Datenblatt des AD7792/3 durchforstet und bin auf die 
Temeperatur-Messschaltung gestoßen. Diese arbeitet als 3-Leiter Messung. 
Ist mit diesem Baustein auch eine 4-Leiter Messung möglich?

Danke!
Martin

von bitzel (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich haben den oben gennanten Code verwendet, krieg es aber ums verrecken 
nicht gebacken das er einigermaßen nachvollziehbare Werte anzeigt. 
Aktuell wechselt er willkürlich von 0 und 65535 hin und her.
Verdrahtet ist das ganze wie im Bild zu sehen. Controller ist ein 
Atmega8 mit Standardgrunbechaltung.
Hat jemand einen Idee wo der Fehler liegt, bin leider noch Anfänger!

von Bergie B. (bergie)


Lesenswert?

Hi !

Du schreibst du hast einen 7793 eingesetzt und deine Werte liegen 
zwischen 0x0000 und 0xFFFF. Der 7793 hat aber kein 16Bit register 
sondern ein 24Bit Register. Also 0xFFFFFF = 16.777.216. Also ist die 
Frage:

1) liest due vielicht nur die 16 der 24 Bits  aus?

2) Wenn du 24Bits ausliest aber im untersten berecht mist, könnte es 
dann sein das dein ADC die Werte nicht erfassen kann da er (überlegt) 
Spannungen nur Messen kann die Größer als 0,5V sind.

3) für welchen MODE hast du dich endschieden. Wenn du sehr schnell 
Messen must ist der ADC nicht die Optimale wahl. Ich habe gute 
erfahrungen bei eriner Messzeit von ca 120ms gemacht. Bei Temperaturn 
änmdern sich normalerweise nicht so schnell ;)

4) Funktiniert den die Kommunikation? Kannst du die beschriebenen 
Register wieder auslesen ?

5) Gibst du den Strom auch auf dem Richtigen Ausgang ? (Mit Multimeter 
die Spannung am RTD Prüfen)

-------------
Oh ich habe gerade erst deinen Code gesehen. Versuch dochmal alle 24 
Bits ab zu holen ;)



SPDR = 0x00;                /* Start transmission */
while(!(SPSR & (1<<SPIF)));  /* Wait for transmission complete */
twobytes |= (SPDR << 8);

SPDR = 0x00;                /* Start transmission */
while(!(SPSR & (1<<SPIF)));          /* Wait for transmission complete 
*/
twobytes |= SPDR;

SPDR = 0x00;                /* Start transmission */
while(!(SPSR & (1<<SPIF)));          /* Wait for transmission complete

------

LG

von bitzel (Gast)


Lesenswert?

Fehler von mir, ich verwende natürlich den AD7792.
Daher auch nur 16Bit.
Geschwindigkeit liegt bei t(settle) = 120ms, müsste also passen.
Ausgang der Stromquelle habe ich mit dem IO-Register auf 210uA auf IEXC1 
to Pin iout1 gestellt. Den RTD hab ich mal mit einem poti simuliert das 
auf 200 Ohm steht. Dadurch müsste ich einen Spannungsabfall von 0,042V 
messen. Da tut sich aber rein gar nix!

von bitzel (Gast)


Lesenswert?

Hab jetzt mal folgendes versucht:
1
int main (void) {
2
3
        uint8_t data = 0x00;
4
  char text2[8];
5
  spi_init();
6
7
  PORTB &= ~_BV(PB2);
8
  SPIWrite8(0x60);
9
  PORTB |= _BV(PB2);
10
  
11
  PORTB &= ~_BV(PB2);
12
  data = SPIRead8();
13
  PORTB |= _BV(PB2);
14
  
15
  
16
  lcd_init();
17
  lcd_clear();
18
  utoa(data,text2,10);
19
  lcd_string(text2); }

Dies müsste eigentlich das ID-Register auslesen. Gibt aber wieder nur 
lauter Müll!

von bitzel (Gast)


Lesenswert?

Hab jetzt nochmal folgendes probiert:
Ich schreibe zuerst 4x 0xFF um den AD7792 zu resetten. Anschließend 
schreibe ich in das CommunicationRegister das die nächste Operation eine 
Schreiboperatoin in das IO-register ist. Dann schreibe ich einfach 0xFF 
in da IO-Register. Anschließend dann wieder in das 
Communications-Register das der nächste Befehl ein Lesezugriff auf das 
IO-Register ist. Dann sende ich 0x00 als Dummybyte um das Register zu 
lesen.
Theoretisch müsste der vorherige Wert von 0xFF zurückkommen, es kommt 
aber nur 0.

Hier noch der Code:
1
#include <avr/io.h>
2
#include "lcd-routines.h"
3
#include <stdlib.h>
4
#include <util/delay.h>
5
6
7
void master_init (void);
8
uint8_t master_transmit (uint8_t cdata);
9
10
11
void master_init (void) {
12
  /* Set MOSI and SCK output, all others input */
13
DDRB |= (1<<PB2) | (1<<PB3) | (1<<PB5);
14
15
/* Enable SPI, Master, set clock rate fck/32 */
16
SPCR = (1<<SPE) | (1<<MSTR) | (1<<SPR1);
17
  //Aktivierung des SPI, Master, Taktrate fck/16
18
}
19
20
uint8_t master_transmit (uint8_t cdata) {
21
  uint8_t daten;
22
  PORTB &= ~_BV(PB2);
23
    _delay_ms(1);            //SS am Slave Low --> Beginn der Übertragung
24
  SPDR = cdata;                //Schreiben der Daten
25
  while (!(SPSR & (1<<SPIF)));
26
  daten = SPDR; 
27
  _delay_ms(1);
28
  PORTB |= _BV(PB2);              //SS High --> Ende der Übertragung
29
  return daten;
30
}
31
32
int main (void) {
33
34
  master_init ();
35
  lcd_init();
36
  uint8_t data;
37
  
38
  
39
  _delay_ms(100);
40
  master_transmit(0xFF);
41
  _delay_ms(100);
42
  master_transmit(0xFF);
43
  _delay_ms(100);
44
  master_transmit(0xFF);
45
  _delay_ms(100);
46
  master_transmit(0xFF);
47
  
48
  _delay_ms(100);
49
  master_transmit(0x28);
50
  _delay_ms(100);
51
  master_transmit(0xFF);
52
  
53
  _delay_ms(100);
54
  master_transmit(0x68);
55
  _delay_ms(100);
56
  data = master_transmit(0x00);
57
  char text2;
58
  
59
  
60
  lcd_clear();
61
  utoa(data,text2,10);
62
  lcd_string(text2); 
63
  
64
}


Hat jemand eine Idee an was es liegen kann. Benötige echt drigend Hilfe!

von Bergie B. (bergie)


Lesenswert?

Was Passiert den wenn du das Status register ausliest ?

Evt. erzeugt dein µC ja keinen Tackt zum Auslesen oder der kommt nicht 
am IC an. Oder du hast einen dreher in der Leitung (Hatte ich auch schon 
:( )

von bitzel (Gast)


Lesenswert?

Habs endlich zum Laufen gebracht. Du hattest recht mit dem Takt. Ich 
hatte einfach eine Leitung falsch gesetzt.
Aktuell hab ich aber noch ein Problem was er misst. Ich hab als 
Temperaturwiderstand aktuell einen Festwiderstand von 1k dran. Eine 
kleine Routine rechnet mir laut Datenblatt (siehe Seite 24) den 
gelieferten Code erst in die Eingangsspannung um und anschließend durch 
den Strom von 210µA, das ergibt dann den Widerstandswert.

Bei 1k wird aber nur 554 Ohm angezeigt. Also mehr oder weniger genau die 
Hälfte. An was kann das liegen?
Gain habe ich auf 8 geändert da ADC Input Spannung bei rund 210mV liegt.

von Bergie B. (bergie)


Lesenswert?

MM Spanntan hatte ich gesagt du hast nicht 210µA sonndern 420µA drauf 
gegeben :) aber dann wüde deine Messung ja nicht stimmen.

Ich würde erstmal Andere Wiederstände messen  500Ohm 2k 4k ... damit 
könntest du dann schonmal sagen ob es ein Offset Fehler oder ein 
Fachktor Fehler ist.

Welche Formel hast du den genommen?

Habe gerade mal ins DB geschaut, und da stehen immerhin 2 ! Du must da 
bachten on du Unipolar/Bipolar Messen möchtest. Wenn du keine Negativen 
Spannungen erwartet würde ich immer UNI vorziehen! Mal davon abgesehen 
das du ein Bit mehr auflösung hast must du keine Fallunterscheidung im 
µC machen.

LG Bergie

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.