Arduino (IoT): Tutorial de Sensores Avanzados

Arduino Honduras Santiapps Marcio Valenzuela

Tutorial Sensores Avanzados

Ok es cierto, ya sabemos leer datos de un sensor de Temperatura y Humedad.  Estos son datos que podemos obtener fácilmente de muchas fuentes.  Pero si quisiéramos datos mas específicos como para hacer una estación ambiental?

Requisitos:

  1. Computadora (mac)
  2. Arduino UNO.  Aqui utilizamos la UNO por el pinout que es identico al del Grove Shield.  El pinout (osea las conexiones) de la MEGA son ligeramente distintas.
  3. Sensores CO2 & Polvo (Dust) tipo Grove
  4. Breadboard
  5. Grove Shield
  6. Arduino IDE (https://www.arduino.cc/en/Main/Software)

La tarjeta Grove Shield es una shield y como tal se ensambla sobre la UNO.

Arduino Grove Tutorial Santiapps Marcio Valenzuela
Arduino Grove Shield

Esta shield tiene 4 puertos para sensores análogos, 8 puertos para sensores digitales y 4 puertos para sensores con conexión tipo I2C que es un protocolo de conexión digital avanzada.

Nosotros estaremos usando 2 sensores; (1) de CO2 y (2) de Dust o Polvo.  Iniciemos con el sensor de polvo:

Arduino Grove Dust Sensor de Polvo Tutorial Santiapps Marcio Valenzuela
Arduino Grove Dust Sensor de Polvo

Es tan sencillo como conectarlo a uno de los puertos digitales marcados con una “D” en la Grove shield y luego ensamblar la Grove Shield sobre la UNO de la siguiente manera:

Arduino Dust Sensor Tutorial Santiapps Marcio Valenzuela
Arduino Dust Sensor Tutorial

El código es aun mas sencillo:

int pin = 2;
unsigned long duration;
unsigned long starttime;
unsigned long sampletime_ms = 30000;//sampe 30s ;
unsigned long lowpulseoccupancy = 0;
float ratio = 0;
float concentration = 0;
void setup() {
Serial.begin(9600);
pinMode(8,INPUT);
starttime = millis();//get the current time;
}
void loop() {
duration = pulseIn(pin, LOW);
lowpulseoccupancy = lowpulseoccupancy+duration;
if ((millis()-starttime) > sampletime_ms)//if the sampel time == 30s
{
ratio = lowpulseoccupancy/(sampletime_ms*10.0); // Integer percentage 0=>100
concentration = 1.1*pow(ratio,3)-3.8*pow(ratio,2)+520*ratio+0.62; // using spec sheet curve
Serial.print(lowpulseoccupancy);
Serial.print(",");
Serial.print(ratio);
Serial.print(",");
Serial.println(concentration);
lowpulseoccupancy = 0;
starttime = millis();
}
}

De donde sale el código para saber que el dato que genera el sensor, aqui leido como pulseIn, es lo que es y que significa?  Facil!  El fabricante de los sensores suele proveer la documentación que define los datos:

http://www.seeedstudio.com/wiki/Grove_-_Dust_Sensor

En este caso el fabricante de la Grove Shield da la información necesaria pero los fabricantes de los módulos también.

Subamos el código a la UNO.

El resultado de este proyecto se puede ver aquí:

Arduino Dust Sensor Grove Tutorial Santiapps Marcio Valenzuela
Arduino Dust Sensor Grove

 

También tenemos a disposición un sensor de CO2.  En este caso conectas el sensor al D8 de la Grove Shield (D8 usa los pines 7 & 8).  El sensor es este:

Arduino Tutorial Grove CO2 Sensor Santiapps Marcio Valenzuela
Arduino Tutorial Grove CO2 Sensor

El código es un poco mas complejo pero repasémoslo brevemente:

#include <SoftwareSerial.h>
#define DEBUG 0
const int pinRx = 8;
const int pinTx = 7;
SoftwareSerial sensor(pinTx,pinRx); //Definimos los pines Rx/Tx
const unsigned char cmd_get_sensor[] = {
0xff, 0x01, 0x86, 0x00, 0x00,
0x00, 0x00, 0x00, 0x79
};
unsigned char dataReceive[9]; //Creamos un array de data
int temperature;
int CO2PPM; //Creamos un par de variables
void setup() {
sensor.begin(9600);
Serial.begin(115200);
Serial.println("get a 'g', begin to read from sensor!");
Serial.println("********************************************************");
Serial.println(); // iniciamos el monitor serial
}
void loop() {
if(dataReceive()) {
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.print(" CO2: ");
Serial.print(CO2PPM);
Serial.println(""); //Si recibimos data, la imprimimos
}
delay(1000);
}
bool dataReceive(void) { //la data la pedimos al sensor
byte data[9];
int i = 0;
//transmit command data
for(i=0; i<sizeof(cmd_get_sensor); i++) {
sensor.write(cmd_get_sensor[i]);
}
delay(10);
//begin reveiceing data
if(sensor.available()) { //Si el sensor esta disponible...
while(sensor.available()) {
for(int i=0;i<9; i++) {
data[i] = sensor.read(); //Leemos la data
}
}
}
#if DEBUG
for(int j=0; j<9; j++) {
Serial.print(data[j]);
Serial.print(" ");
}
Serial.println("");
#endif
if((i != 9) || (1 + (0xFF ^ (byte)(data[1] + data[2] + data[3]
+ data[4] + data[5] + data[6] + data[7]))) != data[8]) {
return false; //Verificamos que la data es valida
}
CO2PPM = (int)data[2] * 256 + (int)data[3];
temperature = (int)data[4] - 40;
return true; //Si es valida, la almacenamos en las variables creadas
}

Los resultados son así:

Arduino Sensor CO2 Grove Tutorial Santiapps Marcio Valenzuela
Arduino Sensor CO2 Grove Tutorial

Ok ya sabemos utilizar varios sensores para crear una estación de datos (en este caso ambiental) que genere los datos.  Que tal si:

  • Pudiéramos comunicar esos datos a otros dispositivos?
  • Y si esos dispositivos estuvieran conectados al internet?
  • Quizás podríamos crear un web service que provea datos al publico!

Que interesante!  Veamos como podemos ahora conectar una MEGA al internet 🙂

Arduino (IoT) Video Serie: Kit de Carro Parte 7 (Guante)

Arduino Honduras Santiapps Marcio Valenzuela

Arduino (IoT): MPU6050 Accelerometro para Carro 4×4 Parte 7 (Control de Carro via Guante)

En un tutorial anterior vimos como crear un carro 4×4 y controlarlo via instrucciones:

  • Pre-cargadas en el codigo
  • Via IR
  • Via Bluetooth
  • Via Sensor Ultrasonico

En otro tutorial anterior vimos como usar un accelerometer MPU6050 para visualizar movimiento (aceleración) en cualquiera de los 3 ejes de las 3 dimensiones espaciales.  Usamos los datos del sensor para mover una gráfica de una ‘aeroplano’ en un programa llamado Processing y así visualizar el movimiento de nuestro sensor en una pantalla:

Ahora veremos como combinar los datos de aceleración espacial para controlar un carro 4×4:

Arduino (IoT): Video Serie Smart Car 4WD Kit Auto-dirigido by Santiapps Marcio Valenzuela
Arduino (IoT): Video Serie Smart Car 4WD Kit Auto-dirigido

Las conexiones serian las mismas que las del ultimo carro, el 4×4, pero desconectamos el servo que gira el ultrasonido y usamos la conexión al pin 2 como la data que entrará del sensor IR.

La idea es conectar una nano (la cual debido a su tamaño puede ser montada en un guante) y adjuntarle un sensor MPU6050 y un modulo Tx de IR para enviar la aceleración del MPU6050 al receptor Rx.  Del lado del Rx estara nuestra UNO con la L293D shield que teníamos en el carro 4×4 ultrasonido.

El Jumper

Este jumper cuando esta interrumpido significa que la L293D usará la potencia de la fuente externa (las 4xAA) para los motores y debemos suplir una fuente alterna para la Arduino UNO.  Anteriormente solo usábamos 2 motores por lo cual no era necesario mas potencia pero ahora que usaremos 4 motores si es necesario.  Es decir, los 4 motores se usaran de manera mas continua debido a que el Arduino se continuara moviendo en distintas direcciones mientras decide cual es el mejor camino para avanzar.

Una vez removido el jumper, podemos conectar ambas fuentes de poder y listo!

Analicemos el código final para el transmisor:

#include <IR.h>
#include <SPI.h>
#include "Wire.h" //For communicate
#include "I2Cdev.h" //For communicate with MPU6050
#include "MPU6050.h" //The main library of the MPU6050
MPU6050 mpu;

int data[2];
void setup() {
Serial.begin(9600);
mpu.initialize(); //Initialize the MPU object
}
void loop() {
delay(2000); // Delay so DHT-22 sensor can stabalize

data[0] = map(350, -17000, 17000, 300, 400 ); //Send aX axis data
data[1] = map(155, -17000, 17000, 100, 200); //Send aY axis data
Serial.println(data[0]);
Serial.println(data[1]);
}

y para el codigo receptor:

// Include dependant SPI Library 
#include  
#include 
//Define packet for the direction (X axis and Y axis)
int data[2];

AF_DCMotor motor1(1, MOTOR12_64KHZ); // create motor #1, 64KHz pwm
AF_DCMotor motor2(2, MOTOR12_64KHZ); // create motor #2, 64KHz pwm
AF_DCMotor motor3(3, MOTOR12_64KHZ); // create motor #3, 64KHz pwm
AF_DCMotor motor4(4, MOTOR12_64KHZ); // create motor #4, 64KHz pwm

String str_out;

void setup() {
  Serial.begin(9600);
}

void loop() {
// Set buffer to size of expected message
    int receivedData[3] = {0};
    uint8_t buflen = sizeof(receivedData);
    if (rf_driver.recv((uint8_t*)receivedData, &buflen)) {
       for (byte i = 0; i < 3; i++) { Serial.print(receivedData[i]); Serial.println("..."); //Serial.print('\t');} if(receivedData[0] > 380){left(); Serial.println("LEFT"); //motor back left}
    if(receivedData[0] < 310){ right(); Serial.println("RIGHT"); //motor back right } if(receivedData[1] > 180){ forward(); Serial.println("FORWARD"); //motor bl and br direction 1}
    if(receivedData[1] < 110){ backward(); Serial.println("BACKWARD"); //motor bl and br direction 2 } if(receivedData[0] > 330 && receivedData[0] < 360 && receivedData[1] > 130 && receivedData[1] < 160);
      //brake();
      stopCar();
      Serial.println("STOP");
    }
  }
}

void forward(){
  Serial.println("running forward");
  motor1.run(FORWARD);   
  motor2.run(FORWARD);
  motor3.run(FORWARD);   
  motor4.run(FORWARD);     

}
void backward(){
  Serial.println("running backward");
  motor1.run(BACKWARD);   
  motor2.run(BACKWARD);
  motor3.run(BACKWARD);    
  motor4.run(BACKWARD);    
}

void left(){
  motor3.run(FORWARD);   
  //motor3.run(BACKWARD);   
}
void right(){
  motor4.run(FORWARD);    
  //motor3.run(FORWARD);     
}

void brake(){
  motor1.run(RELEASE);    
  motor2.run(RELEASE);    
  motor3.run(RELEASE);    
  motor4.run(RELEASE);      
}

void stopCar(){
  motor1.run(RELEASE);    
  motor2.run(RELEASE);    
  motor3.run(RELEASE);    
  motor4.run(RELEASE);     
}

Aquí esta el video: