Ejercicio con Arduino, compás HMC5883L, Display I2C y servo con librerías servoTimer2

Con este tutorial estrenamos nuestra nueva sección de Ejercicios, donde vamos a incluir tutoriales orientados a la utilización práctica de diferentes sensores, controladores y arquitectura.

Muchas veces un sensor que funciona correctamente en nuestras pruebas, al avanzar en el proyecto y añadir nuevos sensores y librerías, todo se empieza a complicar y algunos de ellos dejan de funcionar debido a incompatibilidades entre las diferentes librerías.

Esta nueva sección está dedicada precisamente a eso, a enseñar soluciones prácticas para evitar los problemas que surgen cuando utilizamos diferentes sensores y shields en un proyecto.


Por comodidad, la rapidez y la facilidad de uso, todos estos Ejercicios los desarrollamos con la Shield de la plataforma Grove como base, esto nos permite hacer prototipos complejos sin necesidad de Breadboard o soldaduras.

Uno de los problemas típicos que nos encontramos, es cuando queremos utilizar la librería estandar servo y además necesitamos utilizar el Timer1 para controlar otro proceso mediante una interrupción.

La librería servo utiliza internamente el Timer1, lo que impide que se utilice para cualquier otro proceso.

En este ejercicio vamos a utilizar algunos componentes que son prácticamente estándares en todos los proyectos, un servo, un Display y un relay,  junto con un compás magnético  HMC5883L que lea la posición.
El proceso que vamos a realizar es: Primero leemos del bus I2c el valor en grados mediante el Compás HMC5883L, lo imprimimos en el Display, también conectado al bus I2C y movemos el medidor de distancia ultrasónica a la posición indicada por el compás.

Además tenemos una interrupción que utiliza el Timer1 de Arduino para encender y apagar un Relay cada segundo.

Como la librería servo estándar utiliza el temporizador Timer1 de Arduino, utilizamos la librería servoTimer2, que nos permite utilizar hasta 10 servos, dejando libre el Timer1 para nuestros uso.

 

Las librerías servoTimer2 modificadas y corregidas para que funcionen con la nueva IDE de Arduino las puedes encontrar aquí: ServoTimer2

//
// Example sketch for integration with an HMC5883L triple axis magnetomer.
// servoTimer2 for servos
// I2C Display
// I2C comunication
//
// Reference the I2C Library
#include
// Reference the HMC5883L Compass Library
#include
#include <LiquidCrystal_I2C.h> #include

#define STEPTIME 10 // Centesimas de segundo para la interrupcion

int debug = true;
int posiTion = 0;
volatile boolean toggle1 = 0;
// Store our compass as a variable.
HMC5883L compass;
// Record any errors that may occur in the compass.
LiquidCrystal_I2C lcd(0x20,16,2); // set the LCD address to 0x20 for a 16 chars and 2 line display
Servo myservo; // create servo object to control a servo
// a maximum of eight servo objects can be created

int pos = 0; // variable to store the servo position

int error = 0;
// Out setup routine, here we will configure the microcontroller and compass.
void setup()
{
configureInt();
pinMode(13, OUTPUT);
// Initialize the serial port.
Serial.begin(9600);

Serial.println(“Starting the I2C interface.”);
Wire.begin(); // Start the I2C interface.

Serial.println(“Constructing new HMC5883L”);
compass = HMC5883L(); // Construct a new HMC5883 compass.

Serial.println(“Setting scale to +/- 1.3 Ga”);
error = compass.SetScale(8.100); // Set the scale of the compass.
if(error != 0) // If there is an error, print it out.
Serial.println(compass.GetErrorText(error));

Serial.println(“Setting measurement mode to continous.”);
error = compass.SetMeasurementMode(Measurement_Continuous); // Set the measurement mode to Continuous
if(error != 0) // If there is an error, print it out.
Serial.println(compass.GetErrorText(error));

myservo.attach(9); // attaches the servo on pin 9 to the servo object

lcd.init(); // initialize the lcd
lcd.backlight();
lcd.print(“KM82 robot”);
lcd.setCursor(0,1);
lcd.print(“Kool Mechatronics”);
delay(1000);
lcd.clear();
}

float compassRead(){
// Mide los grados actuales del compass
// Retrived the scaled values from the compass (scaled to the configured scale).
MagnetometerScaled scaled = compass.ReadScaledAxis();

// Values are accessed like so:
float MilliGauss_OnThe_XAxis = scaled.XAxis;// (or YAxis, or ZAxis)
float MilliGauss_OnThe_ZAxis = scaled.ZAxis;
// return MilliGauss_OnThe_XAxis;
Serial.print(“Eje Z : “);
Serial.println(MilliGauss_OnThe_ZAxis/10);
/**/
// Calculate heading when the magnetometer is level, then correct for signs of axis.
float heading = atan2(scaled.YAxis, scaled.XAxis);

// Correct for when signs are reversed.
if(heading < 0) heading += 2*PI; // Check for wrap due to addition of declination. if(heading > 2*PI)
heading -= 2*PI;
// Convert radians to degrees for readability.
float headingDegrees = heading * 180/M_PI;
/* */

// Output the data via the serial port.
// Output(raw, scaled, heading, headingDegrees);
return headingDegrees;
}

// Our main program loop.
void loop()
{
posiTion=compassRead();
myservo.write(posiTion); // tell servo to go to position in variable ‘pos’
printPos(posiTion) ;
delay(100); // waits ms for the servo to reach the position

}
void printPos(){
lcd.setCursor(0, 0);
lcd.print(“Pos:”);
lcd.print(compassRead());
lcd.print(” “);
delay(500);
}

void printPos(int Pos){
lcd.setCursor(0, 0);
lcd.print(“Angle: “);
lcd.print(Pos);
lcd.print(” “);
delay(50);
}
void configureInt()
{
//set timer1 interrupt at STEPTIME times x second
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1 = 0;//initialize counter value to 0
// set compare match register for 1hz increments
// OCR1A = 15624 * 2 ;// = (16*10^6) / (1*1024) – 1 (must be <65536)
// set compare match register for STEPTIME increments
OCR1A = 312 * STEPTIME ; // 312 x centesimas de segundo.
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12 and CS10 bits for 1024 prescaler
TCCR1B |= (1 << CS12) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
TCNT2 = 100; //start timer
}

ISR(TIMER1_COMPA_vect){//timer1 interrupt STEPTIME times x second toggles pin 13 (LED)
// read rpmCounter and restert to 0
if (toggle1){
digitalWrite(13,HIGH);
toggle1 = 0;
}
else{
digitalWrite(13,LOW);
toggle1 = 1;
}
}

2 pensamientos en “Ejercicio con Arduino, compás HMC5883L, Display I2C y servo con librerías servoTimer2”

  1. Que tal!, hace algún tiempo compre un Leonardo en su empresa, muy buena la atención tanto como el producto, en general Arduino es muy practico, y este blog ayuda mucho para quienes deseamos realizar proyectos cada vez mas complejos, gracias, lo pondré en practica.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Eres humano? pon el resultado * Time limit is exhausted. Please reload CAPTCHA.