Tecnología > Electricidad y Electrónica

Voltímetro digital de precisión con LTC2400

(1/2) > >>

Carlos:
Voltímetro con Arduino basado en el conversor Analógico/Digital de 24 bits LTC2400 de Linear Technology



Carlos:
Programa de Arduino


--- Código: (Arduino) ---/*
   TEST PROGRAM:
   LTC2400 Sigma-Delta 24bit ADC converter
   DATASHEET: http://cds.linear.com/docs/en/datasheet/2400fa.pdf
   WEBPAGE:   http://www.linear.com/product/LTC2400

   ARDUINO ->  LTC2400
   --------------------
    GND    ->  (4) GND
    D2     ->  (7) SCK
    D3     ->  (6) SDO
    D4     ->  (5) /CS
   --------------------

   ARDUINO -> I2C-LCD
   --------------------
    GND    ->   GND
    5V     ->   VCC
    A4     ->   SDA
    A5     ->   SCL
   --------------------

  Web page: https://www.picuino.com/foro/index.php?topic=9.0
  License: GPLv3 http://www.gnu.org/licenses/gpl-3.0.txt
  Creation date: 2/05/2015
  Revision 09/05/2015:
     Added Arduino -> I2C-LCD conexion explanation.
*/


#include <Wire.h>  // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h>


// Setup LCD 16x2 chars
LiquidCrystal_I2C lcd(0x27,16,2);


// ADC Pin definition
const int ADC_SCK = 2;   // Serial ClocK
const int ADC_SDO = 3;   // Serial Digital Output
const int ADC_CS  = 4;   // Chip Select
const int sampling_time = 500;  // Sampling time in milliseconds


/*
   Init LTC2400 signals
*/
void adc_init(void) {
   pinMode(ADC_SCK, OUTPUT);
   digitalWrite(ADC_SCK, HIGH);

   pinMode(ADC_CS, OUTPUT);
   digitalWrite(ADC_CS, LOW);

   pinMode(ADC_SDO, INPUT);
}


/*
   Read 32 raw data bits from LTC2400
*/
unsigned long adc_read32(void) {
   unsigned long int count;

   digitalWrite(ADC_CS, LOW);  // ADC Chip Select
   count = 0;
   // Read 32 bits from serial ADC
   for(char i=32; i; i--) {
      count <<= 1;
      digitalWrite(ADC_SCK, LOW);   // Send Clock Signal
      digitalWrite(ADC_SCK, HIGH);
      if (digitalRead(ADC_SDO)) {
         count |= 1;
      }
   }
   digitalWrite(ADC_SCK, LOW);  // Init next conversion
   return count;
}


/*
   Read voltage from LTC2400
   Return 0x80000000 if not conversion available
   Return values from negative 0xFF... to positive 0x1F...
*/
long int adc_read(void) {
  signed long count;
  char stat;

  count = adc_read32();

  // Get status
  stat = count >> 28;
  count &= 0x0FFFFFFF;

  // Test end of conversion
  if (stat & 8) {
     return 0x80000000;
  }

  // Positive Extended Range
  if (stat == 3)
     count += 0x0FFFFFFF;

  // Negative Extended Range
  if (stat == 1)
     count += 0xF0000000;

   return count;
}


/*
   Return 1 if ADC End Of Conversion bit is Enable
*/
int adc_eoc(void)  {
   digitalWrite(ADC_CS, LOW);
   return(!digitalRead(ADC_SDO));
}


/******************************************************
    MAIN PROGRAM
 *****************************************************/

// Init program

unsigned long sample_time;

void setup() {
   // Initialize serial communications
   Serial.begin(115200);

   // Initialize ADC
   adc_init();
   sample_time = millis() + 200;

   // Initialize LCD
   lcd.init();
   lcd.backlight();
   lcd.print("System OK       ");
}


// Main Loop
void loop() {
   long count;
   static float volt1, volt2;

   // Wait for next adquisition
   if (millis() > sample_time) {
      sample_time += sampling_time;

      // Read ADC
      count = adc_read();
      delay(165);

      // Convert ADC to voltage
      volt1 = volt2;
      volt2 = ((float)count) * (5.000000/(256.0*1024.0*1024.0));
      count = ((volt2 - volt1)*1000000.0);

      // Print voltage to serial port
      if (volt2 >= 0) Serial.print(" ");
      Serial.print(volt2, 6);
      Serial.print("\t");
      if (count >= 0) Serial.print(" ");
      Serial.println(count);

      // Print voltage to LCD
      lcd.setCursor(0, 0);
      lcd.print("V=");
      if (volt2 >= 0)
         lcd.print(" ");
      lcd.print(volt2, 6);
      lcd.print("  ");

      // Print voltage difference to LCD second line
      lcd.setCursor(0, 1);

      char sign;
      if (count<0) {
         count = -count;
         sign = -1;
      }
      else {
         sign = 1;
      }

      // Right justified number
      lcd.print("   ");
      if (count<1000000) lcd.print(" ");
      if (count<100000) lcd.print(" ");
      if (count<10000) lcd.print(" ");
      if (count<1000) lcd.print(" ");
      if (count<100) lcd.print(" ");
      if (count<10) lcd.print(" ");
      if (sign == -1)
         lcd.print("-");
      else
         lcd.print(" ");
      lcd.print(count);
      lcd.print("  ");
   }
}

--- Fin del código ---

Carlos:
Componentes utilizados:
   * LTC2400 Conversor Analógico/Digital Sigma-Delta de 24 bits
      Linear Technology Samples
   * ADR4550ARZ Referencia de tensión de precisión de 5v
     Samples de Analog Devices
   * Conversor I2C - LCD
   * Arduino Nano compatible
   * Display LCD de 16 columnas x 2 filas

Librerías Arduino:
   LiquidCrystal_I2C (copia local)
 

Carlos:
En este video se puede ver al voltímetro en acción midiendo la salida de tensión de un regulador LM78L05.
En el video, se calienta al regulador para comprobar cómo cambia la tensión de salida con la temperatura.

    [youtube]fU3rQj6sFgk[/youtube]


Medida de varias referencias de tensión (más precisas y estables) y de varios reguladores de tensión:

    [youtube]ERDTHneD4Ak[/youtube]

Saludos.

Manuel:
Fantástica idea, la de un voltímetro digital con arduino.

Muchas gracias por regalarme el ADC de microchip. Lo he probado nada más llegar a casa, y funciona fantásticamente. Hace unos meses compré en ebay una referencia de voltaje ADR421, de 2.5 voltios, con muy bajo ruido y una precisión inicial de 400ppm que sabía que acabaría usando, así que la incorporé al breadboard. El resultado es este voltímetro/arduino, midiendo la caída de voltaje en un 1N4148:



y la salida por pantalla:



prácticamente los clásicos 0.6 voltios que se esperan en este caso. Basta tocar el diodo para apreciar la variación exponencial del voltaje con la temperatura  ;D . También he probado con un diodo de germanio, y con una división de voltaje, para calibrar. Todo perfecto, con muchos decimales.

El código fuente que he usado, bastante crudo todavía, es:


--- Código: (Arduino) ---#include <SPI.h>
/* D13 -> SCK
 * D12 -> MISO
 * D11 -> MOSI (UNUSED)
 * D9  -> SS
 */
#define SCKPIN 13
#define MISOPIN 12
#define MOSIPIN 11
#define SSPIN 9

SPISettings settingsA(100000, MSBFIRST, SPI_MODE3);

void setup() {
  pinMode (SSPIN, OUTPUT);
 
  SPI.begin();
  Serial.begin(9600);
}


void loop() {
  long ret;
  double vout;
 
  SPI.beginTransaction(settingsA);
  digitalWrite (SSPIN, LOW);
  // while(1) {
  while (digitalRead(MISOPIN) != LOW); // Wait for ADC ready.
  ret = SPI.transfer(0);
  ret <<= 8;
  ret |= SPI.transfer(0);
  ret <<= 8;
  ret |= SPI.transfer(0);
  delay(1);
  digitalWrite (SSPIN, HIGH);
  vout = 2.5 * ((double) ret) / (2097152.0);
  Serial.println(vout,8);
  //}
  SPI.endTransaction();
  delay(500);
}

--- Fin del código ---


En cuanto tenga tiempo, voy a hacer un programa en python que lea los datos del ADC y los procese con ScyPy, para dar gráficas y demás.

¡Gracias por el chip y por la idea! Si te parece que éste no es lugar correcto para el post, muévelo a otro lado con toda libertad.

Navegación

[0] Índice de Mensajes

[#] Página Siguiente

Ir a la versión completa