Recibir datos slave SPI Arduino

Buenas, necesito realizar un programa con Arduino que me lea el valor de un ADC conectado vía SPI. Por internet he encontrado numeros ejemplos de dicha comunicación pero todas son órdenes mandadas del Arduino al slave y no se como realizarlo. Les agradecería mucho la ayuda. ...
 
Es que lo que necesitas es eso.
El esclavo es el ADC y el master el arduino
 
Si eso lo sé, pero lo que me pasa es que no se como hacer para que el arduino obtenga los datos del ADC externo. He probado multitud de programas haciendole modificaciones y los resultados me dan 255 (porque es un ADC de 8 bits) aunque no tenga una tensión de entrada, o no me da ningún resultado. No se si tengo que emplear un comando en concreto o algo para obtener la información.
 
Mira a ver si algo de esto te despeja la mente es lo que siempre les digo a mis estudiantes:LOL: y al momento tiene la solución por su propia cuenta:unsure:
 

Adjuntos

  • arduino-lab-10.pdf
    1.1 MB · Visitas: 28
Última edición:
En primera saber que ADC estas usando, debes leer la hoja de datos para ver los comandos y crear una API para usarlo, es relativamente fácil.
 
Sigo teniendo problemas con el resultado que obtengo del ADC, siempre recibo el valor de 255. Da igual que conecte tensión en el cable de entrada. Lo único que cambia es cuando le quito la VA al ADC y me da un valor nulo, pero a 3,3 V y 5V me sigue dando ese valor. El ADC que estoy utilizando es el 082s021 de TI, pero en el datasheet no viene información sobre como configurar el dispositivo.
 
¿Revisaste le diagrama de tiempos? Seria util ver tu código, pero nota que el comando solo es un bit para determinar el canal y que la respuesta comienza inmediatamente, si "apagas" el ADC, la primer conversion al activarlo es en In1, luego puedes indicar cual canal en la siguiente, nota que usas 16 ciclos en cada conversión y que deberás recorrer los bits para poder pasarlos a un byte ya que el resultado se divide entre los 2bytes de la comunicación.
 
El programa que tengo es el siguiente que lo he creado a partir del pdf que adjuntaron en un mensaje anterior. El programa que adjunto es para un adc de 4 canales y 12 bits mientras que mi ADC es de 2 canales y 8 bits.He modificado los valores de multitud de formas y no consigo nada. Lo único que varía es si desconecto la tensión de refencia que me sale un valor 0 y si la pongo ya sea en 3,3V o 5V me da un valor de 255.


Código:
#include <SPI.h>
const int CS=10;// Chip Selector pin 10

void setup() 
{
  Serial.begin(9600);
  pinMode(CS, OUTPUT);
  digitalWrite(CS, HIGH);//Valor alto para comunicacion inactiva
  SPI.begin();
  SPI.setClockDivider(SPI_CLOCK_DIV4);//4MHz de reloj
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);
}

int readADC(int channel)
{
  digitalWrite(CS, LOW);//Comienza el dispositivo a operar
  int adval=0;
  SPI.transfer(0b00000110 + ((channel>>2)& 1));
  adval = (((unsigned char)SPI.transfer(channel<<6) )& 0b00001111)<<8;
  adval |= ((unsigned char)SPI.transfer(0));
  digitalWrite(CS,HIGH);
  return adval;  
}


void loop()
{
  Serial.println(readADC(0));
  delay(250);

}
 
SPI.transfer() no se usa como sea, se envía el comando y devuelve el dato recibido, pero esos valores 0bxxxxxx que pone son los comandos específicos para su circuito, en tu caso envías solo el canal en el bit 3, el dato es o bien 0x00 (canal 1) o 0x08 (canal 2), inmediatamente el ADC responde, en el ejemplo que te dieron se ignora el primer byte, pero aquí tienes que leer desde el primer byte, luego envías un byte basura para continuar la transmisión y recibir la siguiente parte. O puedes probar usar SPI.transfer16(val16) y enviar como val16 0x0000 o 0x0800 directamente, la lectura es el valor de 16bits donde el dato del ADC esta en medio, a eso tienes que correrlo 4 puestos luego para eliminar los 0's que sobran.

Lo otro, debes ver los gráficos de tiempo, creo que usas el SPI_MODE3 y otro detalle, la frecuencia máxima del ADC es 3,2Mhz, para configurarlo intenta SPI.beginTransaction(SPISettings(3200000, MSBFIRST, SPI_MODE3));
 
Por ejemplo si tenemos...:rolleyes:

SPI.transfer(B00000110);
byte msb = SPI.transfer(channelBits);
byte lsb = SPI.transfer(0x00);

Lo ideal sera....:unsure:

digitalWrite(CS, LOW);

SPI.transfer((commandBytes>>8) & 0xff);

msb = SPI.transfer((byte)commandBytes & 0xff) & b00001111;
lsb = SPI.transfer(0x00);

digitalWrite(CS, HIGH);


Ahí te dejo ese trozo para que lo meditéis:unsure:
 
Última edición:
Sigo intentado el programa pero igualmente el valor que recibo es el de la tensión de alimentación, no de la tensión a convertir y no sé si tiene que ver con la programación o no.

El valor siempre es 255 porque es la referencia.

¿Puede que sea porque no tengo conectado en el circuito los condensadores que me vienen indicado en el datasheet?
 
Última edición:
Yo digo que aparte de corregir la configuración, seria cosa de
Código:
#define CH1 0x0000
#define CH2 0x0800
digitalWrite(CS, LOW);//Comienza el dispositivo a operar
int ADC16CH1=SPI.transfer16(CH2); //la primer lectura siempre es CH1
int ADC16CH2=SPI.transfer16(CH1); //La segunda es la que se le ordeno en el comando anterior
digitalWrite(CS, HIGH);
unsigned char ADCCH1 = 0xFF & (ADC16CH1>>4);
unsigned char ADCCH2 = 0xFF & (ADC16CH2>>4);
 
Última edición:
El código me ha quedado así, pero sigo teniendo el problema que los resultados son 0 si no hay tensión de alimentación y 255 si hay tensión de alimentación.

Código:
#include <SPI.h>
#define CH1 0x0000
#define CH2 0x0800
const int CS=10;

void setup() 
{
  Serial.begin(9600);
  pinMode(CS, OUTPUT);
  digitalWrite(CS, HIGH);
  SPI.beginTransaction (SPISettings (3200000, MSBFIRST, SPI_MODE3));
}

int readADC(int channel)
{

  digitalWrite(CS, LOW);
  int ADC16CH1=SPI.transfer16(CH2); 
  int ADC16CH2=SPI.transfer16(CH1); 
  digitalWrite(CS, HIGH);
  unsigned char ADCCH1 = 0xFF & (ADC16CH1>>4);
  unsigned char ADCCH2 = 0xFF & (ADC16CH2>>4);
  return ADCCH1; 
}


void loop()
{
  Serial.println(readADC(0));
  delay(250);

}
 
Ahora solo tengo la duda en si el modo era el correcto (me costo entender lo del diagrama de tiempos) o la conexiones, tendría que conseguir el ADC y experimentarlo por mi cuenta.

Prueba enviando el valor directo en hexadecimal para que veamos que transmite el ADC, la primer lectura siempre es en la entrada 1 así que no importa lo que reciba de comando, debe retornar el valor, solo usa:

Código:
#include <SPI.h>
#define CH1 0x0000
#define CH2 0x0800
const int CS=10;

void setup() 
{
  Serial.begin(9600);
  pinMode(CS, OUTPUT);
  digitalWrite(CS, HIGH);
  SPI.beginTransaction (SPISettings (3200000, MSBFIRST, SPI_MODE3));
}

void loop()
{
  digitalWrite(CS, LOW);
  int ADC16=SPI.transfer16(0x0000);
  digitalWrite(CS, HIGH);
  Serial.println(ADC16, HEX);
  delay(250);
}
 
Cuando esta alimentado me da siempre este valor:
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
Y cuando le quito la alimentación me da valor 0
 
Por lo que veo tienes es un problema en el ADC082S021CIMMX, si no esta bien acoplado el SMD te puede dar ese error, sube fotos de como tienes armado el circuito.
 
El ADC esta soldado en una PCB, tengo dos modelos de este ADC y otros dos ADC que van por I2C. Los que van por I2C me han funcionado a la perfección los dos, pero los que quiero utiizar ahora los dos pasa lo mismo y están soldados de la misma manera. Lo que me queda por probar es utilizar una placa de arduino original a ver si el fallo reside en eso y si no me tendré que buscar otro ADC por SPI para mi Proyecto de Fin de Grado.
 
El problema es más de Hardware que software, elegiste un ADC con muy poca información sobre este mismo, si cambias el ADC te aseguro que te va mejor http://playground.arduino.cc/Code/MCP3208.

sspiss2.jpg


http://tronixstuff.com/2011/05/13/tutorial-arduino-and-the-spi-bus/

La mejor información tanto escrita como visual la mas completa esta en ingles, no busques en español estará muy incompleta.
 
Última edición:
Atrás
Arriba