SPI - A/D Wandler AD7124 Kommunikation

Wie Kalibriere ich die Kanäle denn am besten? Der Chip bietet ja schon eine OnBoard Kalibration. Oder ich kalibriere die jeweiligen Eingänge mit einem Kalibrator der Fa. Burster.
 
Hmmm...
Ich wuerde zuerst den internen benutzen, damit man eine mehr oder weniger stabile ausgangslage hat.
Anschliessend den externen um zu sehen, wie weit die zuerst ermittelte ausgangslage davon abweicht und dann das ergebnis in die weitere berechnung einfliesen lassen
Addi
 
Das muß dann jedesmal nach einem Powerup neu gemacht werden (da da ja mit Gain=1 gestartet, und die entsprechende Fabrikkalibration geladen wird)?
Bei der System-Kalibration muß man ja die Referenzen extern auf den verwendeten Eingang (der dann den entsprechenden Setup-Weg nutzt) verbinden, bei der internen schaltet der IC das intern selbst.
Wenn ich Dich richtig verstehe (addi), würde man in der fertigen Schaltung dann nach dem Startup nur noch'ne interne Kalibration nach dem Startup (und dem Setup) anstoßen, und die eventuelle Abweichung zur einmaligen Systemkalibration beim Aufbau... in Software berücksichtigen?
 
So habe ich mir das vorgestellt. Bei den nicht ausbleibenden Alterungsprozessen kann man das ganze wiederholen und es in der jeweiligen software beruecksichtigen
Addi
 
So ganz habe ich das Datenblatt in Bezug auf die Kalibration nicht verstanden.

Ich darf während der Kalibration nur einen Kanal aktiv schalten, dann die Internal Zero Scal Calibration aktivieren und solange warten bis das Ready Bit im Status Register auf 0 geht.

Danach lese ich im Offset Register (Welches davon?) den Offset Wert ab und rechne den gegen den aktuellen AD Wert?
 
Du konfigurierst eines der Setups. Danach mußt/willst Du es intern kalibrieren. Du aktivierst einen einzigen Channel, der dieses Setup verwendet.
Die interne(!) ZeroScaleCalibration wird durch setzen der entsprechenden Mode-Bits im ADC-Control Register initiiert, das Ready-Bit im Statusregister singnaliesiert den Abschluß. Der Offset steht hinterher im Offset-Register des Setups, und kann dort auch ausgelesen werden...
Die interne FullScaleCalibration ist nicht im FullPowerMode durchführbar. Ansonsten sinngemäß wie beim ZeroScale. Das Ergebnis steht am Ende im Gain-Register des verwendeten Setups, und kann dort ausgelesen werden.
Üblicherweise calibriert man beides, dann muß (->intern) der FullScale vor dem ZeroScale calibriert werden, und dazu wiederum muß das Offsetregister vorher mit 0x800000 beschrieben werden.
Also:
ADC in Idle oder Standby, MidPower
Einen Channel aktivieren mit dem zu kalibrierenden Setup.
Configuration- und Filter-Register des zu kalibrierenden Setups beschreiben
Offsetregister mit 0x800000 beschreiben
interne FullScaleCalibration auslösen
auf Ready warten
interne ZeroScaleCalibration auslösen
auf Ready warten
Offset und Gainregister des Setups auslesen.

Bei der System...Calibration müssen die Referenzen extern (je) an den verwendeten Eingang gelegt werden, außerdem wird hier erst der Offset (SystemZeroScale), danach der Gain(SystemFullScale) calibriert (damit entfällt das 0x800000-setzen).
 
Werde ich machen...
 
Zuletzt bearbeitet:
Es kommt bei der Kalibration als Offset (umgerechnet) 1,25V raus.
Das kann doch nicht sein?



CodeBox C
void AD7124_CalibrateCh(ad7124_t *AD_ptr, [I]uint8_t[/I] Ch)

/* vorerst für channel 0 */
AD7124_write_uint16(AD7124_CFG0_REG + Ch,REF_SEL_INT_REF | REF_BUFP | REF_BUFM | BURNOUT_OFF | PGA_GAIN_1);
AD7124_write_uint16(AD7124_ADC_CTRL_REG, REF_EN | POWER_MODE_ME | MODE_INTERNAL_ZERO_SCALE_CAL | CLK_SEL_INT_614kHz_WITH_OUT);
AD7124_write_uint16(AD7124_Channel_0,ENABLE_CH | SETUP | AINP0 | DGND_M);
AD7124_write_uint24(AD7124_OFFS0_REG, 0x800000);
while ((AD7124_read_uint8(AD7124_STATUS_REG) & 0x80) != 0){};
AD7124_write_uint16(AD7124_ADC_CTRL_REG, REF_EN | POWER_MODE_ME | MODE_INTERNAL_FULL_SCALE_CAL | CLK_SEL_INT_614kHz_WITH_OUT);
while ((AD7124_read_uint8(AD7124_STATUS_REG) & 0x80) != 0){};
AD_ptr->Offset[Ch] = AD7124_read_uint24(AD7124_OFFS0_REG + Ch);
AD_ptr->Gain[Ch] = AD7124_read_uint24(AD7124_GAIN0_REG + Ch);


 
Muss ich eigentlich noch die Formel benutzen?



CodeBox C
Data = 0.75 * VIN / VREF ....(Seite 52)
 
Halli Hallo :)

Wie sieht das eigentlich mit dem shiften in Bezug auf Makros aus?


CodeBox C
#define SETUP(x)      (x) << 12 // Bit 14 - 12


Klappt das auch ohne Literale ? Wenn ich ein "U" dahinter hänge meckert er sofort?!
 
Wenn du das Makro aufrufst hängst du an die Konstante U.
Wenn es sich um eine Variable handelt, muss die entweder beim Aufruf den passenden Typ haben oder du castest implizit.
 
nabend,

@LotadaC
Habe meine Kalibrationsroutine angepasst. Nur glaube ich, dass dort noch ein Fehler drinn ist (was die Rechnung betrifft)

Hier der Aufruf (damit will ich alle Channels abfragen) ->


CodeBox C
 uint8_t ReadChannel = 13;
 for ( ; ReadChannel > 0 ; ReadChannel--)
 {
  AD7124_CalibrateCh(&AD,ReadChannel,0); 
 }




CodeBox C
void AD7124_CalibrateCh(ad7124_t *AD_ptr, uint8_t Ch, uint8_t Setup)
{
 uint8_t  ChannelRegister = 0;
 uint16_t ChannelSelect  = 0;
 /* select channel */
 switch(Ch)
 {
  case 0:  {ChannelRegister = AD7124_Channel_0; ChannelSelect = AINPx(AIN0);} break;
  case 1:  {ChannelRegister = AD7124_Channel_1; ChannelSelect = AINPx(AIN1);} break; 
  case 2:  {ChannelRegister = AD7124_Channel_2; ChannelSelect = AINPx(AIN2);} break;
  case 3:  {ChannelRegister = AD7124_Channel_3; ChannelSelect = AINPx(AIN3);} break;
  case 4:  {ChannelRegister = AD7124_Channel_4; ChannelSelect = AINPx(AIN4);} break;
  case 5:  {ChannelRegister = AD7124_Channel_5; ChannelSelect = AINPx(AIN5);} break;
  case 6:  {ChannelRegister = AD7124_Channel_6; ChannelSelect = AINPx(AIN6);} break;
  case 7:  {ChannelRegister = AD7124_Channel_7; ChannelSelect = AINPx(AIN7);} break;
  case 8:  {ChannelRegister = AD7124_Channel_8; ChannelSelect = AINPx(AIN8);} break;
  case 9:  {ChannelRegister = AD7124_Channel_9; ChannelSelect = AINPx(AIN9);} break;
  case 10: {ChannelRegister = AD7124_Channel_10; ChannelSelect = AINPx(AIN10);}break;
  case 11: {ChannelRegister = AD7124_Channel_11; ChannelSelect = AINPx(AIN11);}break;
  case 12: {ChannelRegister = AD7124_Channel_12; ChannelSelect = AINPx(AIN12);}break;
  case 13: {ChannelRegister = AD7124_Channel_13; ChannelSelect = AINPx(AIN13);}break;
  case 14: {ChannelRegister = AD7124_Channel_14; ChannelSelect = AINPx(AIN14);}break;
  case 15: {ChannelRegister = AD7124_Channel_15; ChannelSelect = AINPx(AIN15);}break;
 
  default: {ChannelRegister = AD7124_Channel_0; ChannelSelect = AINPx(AIN0);};
 }
 /* select setup */
 switch(Setup)
 {
  case 0:  {AD7124_write_uint16(AD7124_Config_0, (REF_SEL(INT_REF) | REF_BUFP | REF_BUFM | BURNOUT_OFF  |  PGA_GAIN(GAIN_1)));  }break;// setup "0"
  case 1:  {AD7124_write_uint16(AD7124_Config_1, (REF_SEL(INT_REF) | REF_BUFP | REF_BUFM | BURNOUT_OFF  |  PGA_GAIN(GAIN_2)));  }break;// setup "1"
  case 2:  {AD7124_write_uint16(AD7124_Config_2, (REF_SEL(INT_REF) | REF_BUFP | REF_BUFM | BURNOUT_OFF  |  PGA_GAIN(GAIN_4)));  }break;// setup "2"
  case 3:  {AD7124_write_uint16(AD7124_Config_3, (REF_SEL(INT_REF) | REF_BUFP | REF_BUFM | BURNOUT_OFF  |  PGA_GAIN(GAIN_8)));  }break;// setup "3"
  case 4:  {AD7124_write_uint16(AD7124_Config_4, (REF_SEL(INT_REF) | REF_BUFP | REF_BUFM | BURNOUT_OFF  |  PGA_GAIN(GAIN_16))); }break;// setup "4"
  case 5:  {AD7124_write_uint16(AD7124_Config_5, (REF_SEL(INT_REF) | REF_BUFP | REF_BUFM | BURNOUT_05uA |  PGA_GAIN(GAIN_32))); }break;// setup "5"
  case 6:  {AD7124_write_uint16(AD7124_Config_6, (REF_SEL(INT_REF) | REF_BUFP | REF_BUFM | BURNOUT_2uA  |  PGA_GAIN(GAIN_64))); }break;// setup "6"
  case 7:  {AD7124_write_uint16(AD7124_Config_7, (REF_SEL(INT_REF) | REF_BUFP | REF_BUFM | BURNOUT_4uA  |  PGA_GAIN(GAIN_128)));}break;// setup "7"
 
  default: {AD7124_write_uint16(AD7124_Config_0, (REF_SEL(INT_REF) | REF_BUFP | REF_BUFM | BURNOUT_OFF |  PGA_GAIN(GAIN_1)));}
 }
 /* config adc control register */
 AD7124_write_uint16(AD7124_ADC_CTRL_REG,(REF_EN | PWR_MDE(PWR_ME) | ADC_MDE(INT_ZERO_SCALE_CAL) | CLK_SEL(CLK_INT_614kHz_WITH_OUT)));
 /* config channel register */
 AD7124_write_uint16(ChannelRegister,(ENABLE_CH(Ch) | SETUP(Setup) | ChannelSelect  | AINMx(DGND)));
 /* wait for ready */
 while ((AD7124_read_uint8(AD7124_STATUS_REG) & 0x80) != 0){};
 AD7124_write_uint16(AD7124_ADC_CTRL_REG,(REF_EN | PWR_MDE(PWR_ME) | ADC_MDE(INT_FULL_SCALE_CAL) | CLK_SEL(CLK_INT_614kHz_WITH_OUT)));
 /* wait for ready */
 while ((AD7124_read_uint8(AD7124_STATUS_REG) & 0x80) != 0){};
 /* read offset */
 AD_ptr->Offset[Ch] = AD7124_read_uint24(AD7124_OFFS0_REG + Setup);
 /* calculate offset */
 AD_ptr->Offset[Ch] = 0x800000 - AD_ptr->Offset[Ch];
 /* read gain */
 AD_ptr->Gain[Ch] = AD7124_read_uint24(AD7124_GAIN0_REG + Setup); 
}


Was das Gain Register betrifft, muss ich mir noch überlegen ob ich das mit einbeziehe?!
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)