Introducción
Como seguro ya sabéis la placa mCore de nuestro mBot es una placa basada en Arduino y por tanto podemos programarla sin problemas desde el propio IDE de Arduino como si fuera un Arduino UNO.
MakeBlock proporciona librerías que nos permiten interactuar de un modo sencillo con cada uno de los componentes que componen la placa (driver para los motores, buzzer, sensor de luz, LEDs RGB, etc) y también con los módulos adicionales (seguidor de líneas, sensor de sonido, sensor PIR, ultrasonidos ,etc).
Si instalamos las librerías de Arduino podemos ver ejemplos de utilización de cada una de ellas.
En este tutorial veremos cómo podemos programar nuestra placa mCore tanto con las librerías de Makeblock como sin ellas e incluso utilizando librerías de terceros.
La ventaja que tiene la placa mCore es que ya tenemos muchos componentes integrados dentro de la propia placa por el contrario esto hace que no tengamos disponibles todos los pines que podríamos tener en una placa Arduino UNO ya que han sido reservados para dichos componentes.
Mapeo de puertos
El mapeo de puertos, es decir, la relación entre un puerto y los pines asociados a éste lo podemos ver en la siguiente tabla:
Puerto | Pines Arduino
SLOT 1, SLOT 2 |
PORT_1 | D11, D12 |
PORT_2 | D9, D10 |
PORT_3 | A2, A3 |
PORT_4 | A0, A1 |
PORT_6 | D8, A6 |
PORT_7 | A7, D13 |
PORT_8 | D8, A6 |
PORT_9 | D6, D7 |
PORT_10 | D5, D4 |
M1 | D6, D7 |
M2 | D5, D4 |
El mapeo de puertos lo podemos ver si miramos el código del fichero MeMCore.h
/********************* Mbot Board GPIO Map *********************************/ MePort_Sig mePort[17] = { { NC, NC }, { 11, 12 }, { 9, 10 }, { A2, A3 }, { A0, A1 }, { NC, NC }, { 8, A6 }, { A7, 13 }, { 8, A6 }, { 6, 7 }, { 5, 4 }, { NC, NC }, { NC, NC }, { NC, NC }, { NC, NC }, { NC, NC },{ NC, NC }, };
Como podemos ver cada puerto consta de dos slots (slot 1 y slot 2) y cada slot corresponde a un pin de nuestro Arduino.
Entonces ¿Cómo acceder a estos pines? , bueno pues una manera sencilla sería utilizando la propia librería MePort tal y como se muestra a continuación:
#include <MeMCore.h> MePort port(PORT_2); int16_t slot1Pin = port.pin1(); // SLOT 1 del puerto 2 int16_t slot2Pin = port.pin2(); // SLOT 2 del puerto 2
Por tanto en la variable slot1Pin tendremos el pin D9 y en la variable slot2Pin tendremos el pin D10 de nuestra placa mCore puesto que hemos especificado (en este caso) el puerto 2 (PORT_2).
Por supuesto también podemos poner directamente el pin que queremos utilizar sin usar la librería:
int16_t slot1Pin = 9;
int16_t slot2Pin = 10;
Como hemos comentado anteriormente en la placa mCore ya tenemos muchos componentes integrados y en la siguiente tabla podemos ver los pines asociados a estos componentes:
Componente | Pin asociado |
Sensor de luz | A6 |
Buzzer | D8 |
Pulsador | A7 |
LEDS RGB | D13 |
Motor 1 | D6, D7 |
Motor 2 | D4, D5 |
Emisor de infrarrojos | D3 |
Receptor de infrarrojos | D2 |
Esto lo podemos ver en el esquema de la placa mCore que nos proporciona Makeblock:
Realizada esta introducción voy a poner algunos ejemplos de código programado desde el IDE de Arduino donde podemos ver cómo se interactúa con los distintos componentes mediante la utilización de la propias librerías de Makeblock, sin ellas e incluso con librerías de terceros.
Componentes integrados en la placa
Aquí podemos ver los diferentes componentes de la placa mCore:
Vamos con los ejemplos:
Buzzer
Ejemplo sin utilizar la librería de Makeblock:
NOTA: En este caso utilizaremos la librería NewTone.
// Notas #include "pitches.h" #include <NewTone.h> const int pinBUZZER = 8; const int melodia_notas[7] = {NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, 0, NOTE_F5, NOTE_GS5}; const int melodia_total_notas = 7; const int melodia_duracion[] = {8, 8, 8, 8, 8, 8, 2}; void setup() { pinMode(pinBUZZER, OUTPUT); } void loop() { melodia(melodia_notas,melodia_duracion,melodia_total_notas); } void melodia(const int notas_melodia[], const int duracion_notas[], const int total_notas) { for (int nota = 0; nota < total_notas; nota++) { int duracionNota = 1000 / duracion_notas[nota]; NewTone(pinBUZZER, notas_melodia[nota], duracionNota); int pausaEntreNotas = duracionNota * 1.30; delay(pausaEntreNotas); noNewTone(pinBUZZER); } }
Ejemplo utilizando la librería de Makeblock:
// Notas #include "pitches.h" #include <MeMCore.h> const int melodia_notas[7] = {NOTE_F5, NOTE_FS5, NOTE_G5, NOTE_GS5, 0, NOTE_F5, NOTE_GS5}; const int melodia_total_notas = 7; const int melodia_duracion[] = {8, 8, 8, 8, 8, 8, 2}; double factor_delay=0.3; MeBuzzer buzzer; void setup() { } void loop() { melodia(melodia_notas,melodia_duracion,melodia_total_notas); } void melodia(const int notas_melodia[], const int duracion_notas[], const int total_notas) { for (int nota = 0; nota < total_notas; nota++) { int duracionNota = 1000 / duracion_notas[nota]; buzzer.tone(notas_melodia[nota], duracionNota); /* La función "buzzer.tone" ya introduce el delay de la duración de la nota a diferencia de la librería "tone" --> con lo cual solo hay que añaidr el 30% ojo! que si la nota es 0 no se introduce el delay de la duración de la nota y solo en este caso si que hay que añadir la duración de la nota + 30% en el delay */ factor_delay=0.3; if (notas_melodia[nota] == 0) factor_delay=1.3; int pausaEntreNotas = duracionNota * factor_delay; delay(pausaEntreNotas); buzzer.noTone(); } }
Driver motores DC
NOTA: Si miramos el esquema de la placa vemos que para controlar los motores se utiliza el chip TB6612.
Ejemplo sin utilizar la librería de Makeblock:
/* * OBSERVACION: * * pinAIN1 y pinAIN2 utilizan el mismo Pin de tal manera que cuando uno está a HIGH el otro estará a LOW * Los mismo para pinBIN1 y pinBIN2 * El Pin stantbye ya se encuentra a +5V y por tanto en HIGH. * */ const int pinPWMA = 6; const int pinAIN1_AIN2 = 7; const int pinPWMB = 5; const int pinBIN1_BIN2 = 4; void setup() { pinMode(pinPWMA, OUTPUT); pinMode(pinAIN1_AIN2, OUTPUT); pinMode(pinPWMB, OUTPUT); pinMode(pinBIN1_BIN2, OUTPUT); } void loop() { Avance(255); delay(2000); Retroceso(255); delay(2000); Izquierda(255); delay(2000); Derecha(255); delay(2000); Parar(); delay(2000); } void Avance(int velocidad) { analogWrite(pinPWMA, velocidad); digitalWrite(pinAIN1_AIN2, LOW); analogWrite(pinPWMB, velocidad); digitalWrite(pinBIN1_BIN2, HIGH); } void Retroceso(int velocidad) { analogWrite(pinPWMA, velocidad); digitalWrite(pinAIN1_AIN2, HIGH); analogWrite(pinPWMB, velocidad); digitalWrite(pinBIN1_BIN2, LOW); } void Izquierda(int velocidad) { analogWrite(pinPWMA, velocidad); digitalWrite(pinAIN1_AIN2, HIGH); analogWrite(pinPWMB, velocidad); digitalWrite(pinBIN1_BIN2, HIGH); } void Derecha(int velocidad) { analogWrite(pinPWMA, velocidad); digitalWrite(pinAIN1_AIN2, LOW); analogWrite(pinPWMB, velocidad); digitalWrite(pinBIN1_BIN2, LOW); } void Parar() { analogWrite(pinPWMA, 0); digitalWrite(pinAIN1_AIN2, HIGH); analogWrite(pinPWMB, 0); digitalWrite(pinBIN1_BIN2, HIGH); }
Ejemplo utilizando la librería de Makeblock:
Vemos en el ejemplo que podemos utilizar dos librerías: MeDCMotor y MBotDCMotor. La ventaja de la primera librería respecto a la segunda es que podemos especificar distintas velocidades para cada motor por el contrario con la segunda librería la velocidad especificada se aplicará a los dos motores pero tiene la ventaja que nos simplifica el escribir más código ya que con una sola línea podemos programar las instrucciones.
#include <MeMCore.h> //**************************** // METODO 1 //**************************** MeDCMotor motor1(M1); MeDCMotor motor2(M2); //**************************** // METODO 2 //**************************** MBotDCMotor motor(M1); void setup() { } void loop() { //**************************** // METODO 1 //**************************** // El valor puede estar entre -255 y 255 // Avanzar motor1.run(-255); motor2.run(255); delay(2000); // Retroceder motor1.run(255); motor2.run(-255); delay(2000); //Izquierda motor1.run(255); motor2.run(255); delay(2000); //Derecha motor1.run(-255); motor2.run(-255); delay(2000); // Parar motor1.stop(); motor2.stop(); delay(2000); //**************************** // METODO 2 //**************************** // Avanzar motor.move(1,255); delay(2000); // Retroceder motor.move(2,255); delay(2000); // Izquierda motor.move(3,255); delay(2000); // Derecha motor.move(4,255); delay(2000); // Parar motor.move(1,0); delay(3000); }
RGB Led
Ejemplo sin utilizar la librería de Makeblock:
NOTA: En este caso utilizaremos la librería NeoPixel de Adafruit.
#include <Adafruit_NeoPixel.h> const int pinLEDS=13; const int NUMLEDS=2; int led1 = 0; int led2 = 1; Adafruit_NeoPixel led = Adafruit_NeoPixel(NUMLEDS, pinLEDS, NEO_GRB + NEO_KHZ800); void setup() { led.begin(); } void loop() { led.setPixelColor(led1, led.Color(255,0,0)); led.setPixelColor(led2, led.Color(0,0,255)); if (led1 == 0) { led1=1; led2=0; } else { led1=0; led2=1; } led.show(); delay(500); }
Ejemplo utilizando la librería de Makeblock:
#include <MeMCore.h> MeRGBLed led(PORT_7,2); int led1 = 1; int led2 = 2; void setup() { } void loop() { led.setColor(led1, 255, 0, 0); led.setColor(led2, 0, 0, 255); if (led1 == 1) { led1=2; led2=1; } else { led1=1; led2=2; } led.show(); delay(500); }
Sensor de luz
Ejemplo sin utilizar la librería de Makeblock:
int sensorPin = A6; void setup() { Serial.begin(9600); pinMode(sensorPin, INPUT); } void loop() { unsigned int valorSensor = analogRead(sensorPin); Serial.print("luminosidad= "); Serial.println(valorSensor); delay(100); }
Ejemplo utilizando la librería de Makeblock:
#include <MeMCore.h> MeLightSensor sensorLuz(PORT_6); void setup() { Serial.begin(9600); } void loop() { unsigned int valorSensor = sensorLuz.read(); Serial.print("lumionosidad= "); Serial.println(valorSensor); delay(100); }
Módulos adicionales
Seguidor de líneas
Ejemplo sin utilizar la librería de Makeblock:
const int pinIzquierdo = 10; const int pinDerecha = 9; void setup() { Serial.begin(9600); pinMode(pinIzquierdo, INPUT); pinMode(pinDerecha, INPUT); } void loop() { int lecturaSensorIzquierdo= digitalRead(pinIzquierdo); int lecturaSensorDerecho= digitalRead(pinDerecha); if (lecturaSensorIzquierdo == LOW && lecturaSensorDerecho == LOW) Serial.println("Ambos sensores dentro de la linea"); else if (lecturaSensorIzquierdo == LOW && lecturaSensorDerecho == HIGH) Serial.println("Sensor izquierdo fuera de la linea"); else if (lecturaSensorIzquierdo == HIGH && lecturaSensorDerecho == LOW) Serial.println("Sensor derecho fuera de la linea"); else if (lecturaSensorIzquierdo == HIGH && lecturaSensorDerecho == HIGH) Serial.println("Ambos sensores fuera de la linea"); delay(200); }
Ejemplo utilizando la librería de Makeblock:
#include <MeMCore.h> MeLineFollower seguidorLineas(PORT_2); void setup() { Serial.begin(9600); } void loop() { int valorSensor = seguidorLineas.readSensors(); switch(valorSensor) { case S1_IN_S2_IN: Serial.println("Sensor izquierdo y derecho dentro de la lína negra"); break; case S1_IN_S2_OUT: Serial.println("Sensor derecho fuera de la linea negra"); break; case S1_OUT_S2_IN: Serial.println("Sensor izquierdo fuera de la linea negra"); break; case S1_OUT_S2_OUT:Serial.println("Sensor izquierdo y derecho fuera de la lína negra"); break; default: break; } delay(200); }
Sensor PIR
Ejemplo sin utilizar la librería de Makeblock:
const int pinPIR = 12; const int pinModePIR = 11; void setup() { Serial.begin(9600); /* MODO: LOW: non-repeatable trigger HIGH: repeatable trigger IMPORTANTE: si se quiere poner en modo repeatable trigger comentar las dos lineas siguientes, es decir, no poner nada, ya que por defecto esta en este modo. Si se pone a HIGH o incluso se pone el pinMode(pinModePIR, OUTPUT); el sensor no funcionará correctamente. */ //pinMode(pinModePIR, OUTPUT); //digitalWrite(pinModePIR, LOW); } void loop() { int lecturaPIR= digitalRead(pinPIR); if(lecturaPIR == HIGH) Serial.println("Persona detectada"); else Serial.println(""); delay(20); }
Ejemplo utilizando la librería de Makeblock:
#include <MeMCore.h> MePIRMotionSensor myPIRsensor(PORT_1); void setup() { Serial.begin(9600); /* MODO: 0: non-repeatable trigger 1: repeatable trigger IMPORTANTE: si se quiere poner en modo repeatable trigger no poner nada, ya que por defecto esta en este modo. Si se pone myPIRsensor.SetPirMotionMode(1); el sensor no funcionará correctamente. */ //myPIRsensor.SetPirMotionMode(0); } void loop() { if(myPIRsensor.isHumanDetected() ) Serial.println("Persona detectada"); else Serial.println(""); delay(20); }
Sensor de sonido
Ejemplo sin utilizar la librería de Makeblock:
int sensorPin = A1; void setup() { Serial.begin(9600); pinMode(sensorPin, INPUT); } void loop() { unsigned int valorSensor = analogRead(sensorPin); Serial.print("sonido= "); Serial.println(valorSensor); delay(100); }
Ejemplo utilizando la librería de Makeblock:
#include <MeMCore.h> MeSoundSensor sonido(PORT_4); void setup() { Serial.begin(9600); } void loop() { unsigned int valorSensor = sonido.strength(); Serial.print("sonido= "); Serial.println(valorSensor); delay(100); }
Adaptador RJ25
NOTA: En los siguientes ejemplos supondremos que tenemos conectado un servomotor al slot 1 del adaptador RJ25.
Ejemplo sin utilizar la librería de Makeblock:
#include <Servo.h> int16_t servoPin = 9; Servo servo; void setup() { servo.attach(servoPin); } void loop() { servo.write(0); delay(2000); servo.write(180); delay(2000); }
Ejemplo utilizando la librería de Makeblock:
#include <MeMCore.h> MePort port(PORT_2); int16_t slot1Pin = port.pin1(); // SLOT 1 del puerto int16_t slot2Pin = port.pin2(); // SLOT 2 del puerto Servo servo; void setup() { servo.attach(slot1Pin); } void loop() { servo.write(0); delay(2000); servo.write(180); delay(2000); }
Sensor de ultrasonidos
Ejemplo sin utilizar la librería de Makeblock:
NOTA: En este caso utilizaremos la librería NewPing.
#include <NewPing.h> const int pinTRIGGER = 12; const int pinECHO = 12 ; const int MAX_DISTANCIA = 200; NewPing sonar(pinTRIGGER, pinECHO, MAX_DISTANCIA); void setup() { Serial.begin(9600); } void loop() { delay(50); unsigned int distancia_medida = sonar.ping_cm(); Serial.print("Distancia: "); Serial.print(distancia_medida); Serial.println("cm"); }
Ejemplo utilizando la librería de Makeblock:
#include <MeMCore.h> MeUltrasonicSensor sonar(PORT_1); void setup() { Serial.begin(9600); } void loop() { delay(50); unsigned int distancia_medida= sonar.distanceCm(); Serial.print("Distancia: "); Serial.print(distancia_medida); Serial.println("cm"); }