Conexiones realizadas
Como se ha comentado en el epígrafe anterior, este sensor se va a conectar mediante el protocolo SPI. Las conexiones que se han realizado entre dicho sensor y nuestro sistema de desarrollo han sido las siguientes:
- Pines de tierra de ambos conectados
- Alimentación del sensor al pin de 3,3 de Arduino
- Pines MISO y MOSI del protocolo SPI a los pines 50 y 51 de Arduino respectivamente
- La señal de reloj, SCK, se ha conectado pin 52 de Arduino
- Los pines de indicación de dato listo (DRDY) y de selección del chip (CSB) se han conectado a los pines 30 y 31 de Arduino respectivamente
Código implementado
El código está estructurado de la siguiente forma:
- En el apartado de setupo(), se configuran los registros del sensor
- En el bucle principal se configura el sensor para que lea en alta resolución, es decir, devolverá 19 bits para la presión y 16 bits para la temperatura. Para obtener la temperatura en grados centígrados, bastará con dividir los 16 bits entre 20
- A continuación se lee la temperatura en 2 bytes
- Finalmente, se lee la presión en dos partes: primero se leen los 3 bits más altos, y seguidamente los 16 bits más bajos. Estas dos partes se combinan en un long entero desplazando los bits más altos y realizando una OR bit a bit para combinarlos con los 16 más bajos. La humedad en pascales es el resultado de 19 bits dividido entre 4.
El código completo se muestra a continuación. Se han dejado los comentarios para simplificar la comprensión del mismo:
// Incluimos la librería SPI #include <SPI.h> //Direcciones de los registros de la memoria del sensor const int PRESSURE = 0x1F; //3 bits mas significativos de la presion const int PRESSURE_LSB = 0x20; //16 bits menos significativos de la presion const int TEMPERATURE = 0x21; //16 bits de la lectura de temperatura const byte READ = 0b11111100; // Instruccion de lectura del SCP1000 const byte WRITE = 0b00000010; // Instruccion de escritura del SCP1000 // Pines usados para la conexion con el sensor // El resto ya estan definidos en la libreria SPI const int dataReadyPin = 30; const int chipSelectPin = 31; void setup() { Serial.begin(9600); // Inicializamos la libreria SPI SPI.begin(); // Inicializamos pines dataReady y chipSelect pinMode(dataReadyPin, INPUT); pinMode(chipSelectPin, OUTPUT); //Configuramos el SCP1000 en config. de bajo ruido writeRegister(0x02, 0x2D); writeRegister(0x01, 0x03); writeRegister(0x03, 0x02); // Y le damos tiempo al sensor para que se prepare delay(100); } void loop() { //Seleccionamos el modo de alta resolucion writeRegister(0x03, 0x0A); // No hacemos nada hasta que el pin dataReady este alto if (digitalRead(dataReadyPin) == HIGH) { //Leemos la temperatura int tempData = readRegister(0x21, 2); // Convertimos la temp. a Celcius y la mostramos float realTemp = (float)tempData / 20.0; Serial.print("Temp[C]="); Serial.print(realTemp); // Leemos los 3 bits mas altos de la presion byte pressure_data_high = readRegister(0x1F, 1); pressure_data_high &= 0b00000111; // Solo hacen falta los bits del 2 al 0 //Se leen los 16 bits mas bajos de la presion unsigned int pressure_data_low = readRegister(0x20, 2); // Se combinan las dos partes en un solo numero de 19 bits: long pressure = ((pressure_data_high << 16) | pressure_data_low)/4; // Mostramos la presion: Serial.println("\tPressure [Pa]=" + String(pressure)); } } //Lecturas desde o escrituras hacia los registros del SCP1000 unsigned int readRegister(byte thisRegister, int bytesToRead ) { byte inByte = 0; // Byte entrante del SPI unsigned int result = 0; // Resultado a devolver Serial.print(thisRegister, BIN); Serial.print("\t"); // SCP1000 espera el nombre del registro en los 6 bits mas altos // del byte. Asi que desplazamos los bits hacia la izq. 2 posiciones thisRegister = thisRegister << 2; // Combinamos la direccion y la instruccion en un byte byte dataToSend = thisRegister & READ; Serial.println(thisRegister, BIN); // Bajamos el ChipSelct para seleccionar el dispositivo digitalWrite(chipSelectPin, LOW); // Mandamos al dispositivo el registro que queremos leer: SPI.transfer(dataToSend); // Mandamos un valor de 0 para leer el primer byte devuelto result = SPI.transfer(0x00); // Reducimos en uno el numero de bytes restantes por leer bytesToRead--; // Si quedan bytes por leer if (bytesToRead > 0) { // Desplazamos el primer byte hacia la izquierda, y obtenemos el 2º byte: result = result << 8; inByte = SPI.transfer(0x00); // Combinamos el byte que acabamos de obtener con el anterior: result = result | inByte; // Nos queda un byte menos por leer: bytesToRead--; } // Levantamos el chip-select digitalWrite(chipSelectPin, HIGH); // Devolvemos el resultado return(result); } //Mandamos ahora una escritura el dispositivo void writeRegister(byte thisRegister, byte thisValue) { // SCP1000 espera la direccion del registo en los 6 bits mas altos // del byte. Asi que desplazamos en 2 posiciones hacia la izquierda thisRegister = thisRegister << 2; // Combinamos el registro de direccion y la instruccion en un solo byte: byte dataToSend = thisRegister | WRITE; // Bajamos el chip-select para seleccionar el sensor: digitalWrite(chipSelectPin, LOW); SPI.transfer(dataToSend); //Mandamos la localizacion del registro SPI.transfer(thisValue); //Mandamos el valor a almacenar en el registro // Levantamos el chip-select digitalWrite(chipSelectPin, HIGH); } |
Aquí os dejo una captura de la salida de datos, en la que se ve la presión en grados, la temperatura en pascales y el contenido de los registros leídos en bianrio (simplemente los he dejado como traza, para ver que todo se hace correctamente):
---------------------------------
Referencias:
- Sensor SCP1000: http://www.bricogeek.com/shop/150-sensor-de-presion-barometrica-scp1000.html