Forum: Mikrocontroller und Digitale Elektronik Mal wieder XMEGA ADC über shunt widerstand


von Felix H. (masterq)


Lesenswert?

Hallo zusammen,
ich hänge fest...
Folgendes:
Ich möchte mit dem atxmega16a4 den Spannungsabfall über ein 
Shunt-Widerstand messen, und mir den Strom auf einem Display ausgeben, 
außerdem möchte ich mir die Möglichkeit vorbehalten, die 
Versorgungsspannung zu unterbrechen, wenn ein bestimmter Strom 
überschritten wird.
Der Shunt Widerstand liegt am gleichen ground wie der uC. Dennoch wollte 
ich gerne den Differenz-Modus mit Gain benutzen um die Referenzen DIREKT 
am Widerstand zu messen.
Der Widerstand ist nicht sooo klein: 1/3 Ohm, und ich möchte damit 
Spannungen bis 700mA messen können.
Spannungsquelle ist ein PC Netzteil. Versorgung für den uC GND -> 3,3 V.
Zu messender Strom GND -> 5V.
Beide Spannung sind geglättet durch Kondensatoren verschiedener Größe, 
wobei ich mit dem Oszilloskop auch keine Spannungsschwankungen 
feststellen konnte.
Der Aufbau des Ganzen ist auf einem Steckbrett. Deshalb sind gewisse 
Schwankungen sicher nicht ungewöhnlich. Jedoch schwanken die 
Messergebnisse mit mehr als 20%. Das finde ich viel.

Hier der relevante Code:
1
#include "main.h"
2
#include "bla/iox16a4.h"
3
#include <inttypes.h>
4
5
#include <stdio.h>
6
#include <stdint.h>
7
8
#include <stddef.h>
9
10
11
#include "includes/lcd.c"
12
#include "includes/uart/uart.c"
13
#include "includes/out.c"
14
#include "includes/adc.c"
15
#include "includes/osc.c"
16
17
18
void init_uart(void);
19
20
21
int16_t Result = 234;
22
23
float ResultVolts;
24
25
int main(void)
26
{
27
  PORTD.DIR = 0xff;
28
  PORTD.OUT = 0x00;
29
  
30
31
  ext_osc_init();
32
  uart_init();
33
  adc_init();
34
  
35
  printf_init();
36
37
  lcd_init();
38
  
39
    // *** Interruptcontroller: Highlevelinterrupts aktivieren ***
40
  PMIC.CTRL |= PMIC_HILVLEN_bm;
41
    //************************************************************
42
  sei();
43
44
  while(1)
45
  {
46
    Result = adc_read();
47
    _delay_ms(200);
48
    if(Result >= 60000)
49
      Result = 0;
50
51
    ResultVolts = (float) (Result*1.75)/4096;
52
    printf("ADC Ch. 0: %1.3f   \n", ResultVolts);
53
    printf("ADC Ch. 0: %u   \n", Result);
54
  }
55
}

adc.c:
1
#include "includes/adc.h"
2
#include <bla/iox16a4.h>
3
4
5
void adc_init(void)
6
{
7
  PORTA.DIR = 0;
8
  ADCA.CTRLA |= ADC_ENABLE_bm;        // enable adc
9
  ADCA.CTRLB = ADC_CONMODE_bm | ADC_RESOLUTION_12BIT_gc;    // 12 bit signed conversion (pos 11bits)
10
  ADCA.REFCTRL = ADC_REFSEL_INT1V_gc | 0x02;           // internal 1V bandgap reference
11
  ADCA.PRESCALER = ADC_PRESCALER_DIV512_gc;             // peripheral clk/16 (2MHz/16=125kHz)
12
  ADCA.CH0.CTRL = ADC_CH_INPUTMODE_DIFFWGAIN_gc | ADC_CH_GAIN_16X_gc;     // differential, 4x front end gain
13
  ADCA.CH0.MUXCTRL = ADC_CH_MUXPOS_PIN2_gc | ADC_CH_MUXNEG_PIN4_gc;      // PORTA:2 wrt PORTA:4
14
  ADCA.CH0.INTCTRL = ADC_CH_INTLVL_HI_gc;              // hi level interrupt
15
  ADCA.EVCTRL = ADC_EVSEL_0123_gc | ADC_EVACT_CH0_gc;  // trigger ch0 conversion on event0
16
17
  ADCA.CALL = adc_read_calibration_byte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0));
18
  ADCA.CALH = adc_read_calibration_byte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1));
19
}
20
21
int16_t adc_read(void)
22
{
23
  int16_t result;
24
  ADCA.CH0.CTRL |= ADC_CH_START_bm;
25
  while(!ADCA.CH0.INTFLAGS);
26
  result = ADCA.CH0RES;
27
  return result;
28
}
29
30
31
32
33
uint8_t adc_read_calibration_byte(uint8_t index)
34
{
35
  uint8_t result;
36
37
  /* Load the NVM Command register to read the calibration row. */
38
  NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc;
39
  result = pgm_read_byte(index);
40
41
  /* Clean up NVM Command register. */
42
  NVM_CMD = NVM_CMD_NO_OPERATION_gc;
43
44
  return(result);
45
}

An alle die sich diesen Roman durchlesen um mir zu helfen:

Vielen Lieben Dank!

von Jutta (Gast)


Lesenswert?

Hast du die Erratas über die ADCs der XMEGAs und die vernichtenden 
Kritiken im Internet darüber gelesen?

von XMEGA (Gast)


Lesenswert?

Hallo,

Jutta schrieb:
> Kritiken im Internet darüber gelesen?

wieder jemand der hier Schauermärchen verbreitet.

Du findest keinen Punkt in diesem Code der nur annähernd ein Problem mit 
der Errata hat.

Das Übliche bei einem ADC: (und das hat fast jeder in dieser 
Preisklasse)

6LSB for sample rates above 1Msps, and up to 8 LSB for 2Msps sample 
rate.

Zu 90% ist es der Hardwareaufbau. Messen in solch rauer Umgebung wie ein 
Netzteil führt zwangsweise zu Störungen (hier Netzteil). Steckboards 
sind für AD-Wandler nicht zu empfehlen!

ADC_CH_GAIN_16X_gc verstärkt das Problem natürlich auch.

Teste deine Schaltung mal an einen kleinen Akku/Battarie mit Poti

Gruß XMEGA

von total error (Gast)


Lesenswert?

>wieder jemand der hier Schauermärchen verbreitet.

Eine Integral Non-Linearity (INL) von +/-5LSB und ein Gain Error von 
+/-14LSB bei einer 3V Referenz und 500ksps findest du normal?? Das ist 
ja nicht mal 10bit-Genauigkeit.

Legt man eine 1V Referenz zugrunde, sind es sogar +/-41 LSB Gain 
Error...

von Felix H. (masterq)


Lesenswert?

Danke für die Antworten,

ich werde es testen.
Allerdings ist noch zu sagen das es ziemlich egal ist ob Verstärkung 
drin ist oder nicht, aber meine Messgenauigkeit hatte ich ja auch in % 
angegeben...

Ich hatte irgendwo gelesen das es einen Haufen XMegas mit sehr 
schlechten adc gibt,

ich habe einen:
atxmega16a4
Produktionswoche:
1041

soweit ich es mitbekommen habe, wurden die Fehler im adc irgendwann 
behoben, weiß irgendjemand zu welcher Kategorie dieser gehört?

Grüße

Felix

von total error (Gast)


Lesenswert?

>soweit ich es mitbekommen habe, wurden die Fehler im adc irgendwann
>behoben,

Ich glaube das ehrlich gesagt nicht. Auch sind die spezifizierten 
+/-5LSB INL für sich ja schon ein Hammer. Gut, der ADC ist sehr schnell, 
aber sehr genau scheint er nicht zu sein. Schade, ich wollte ihn auch 
schon einsetzen...

Ein guter 12bit ADC hat ein maximalen INL von +/-1LSB. Ein PIC18F2423 
bringt es schon auf +/-2LSB und der ATXMEGA auf +/-5LSB.

Ein weiterer Schwachpunkt dieses ATXMEGA ADCs ist, daß ich nirgends 
Angaben über die Monotonie finden kann. Monotonie ist aber für bestimmte 
Regelaufgaben Grundvoraussetzung!

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.