This is the first example in a serie of cheap (absolutely free and cheap) articles to get some basic and practical C++ knowledge. It will references the great explanations provided at www.cplusplus.com C++ tutorial. Using Arduino Duemilanove (well, really it’s a Funduino).
// C++ crash tutorial with Arduino Duemilanove.
// First example: http://softwaresouls.com/softwaresouls/2013/06/23/c-crash-tutorial-using-robotis-cm-900-board-and-ide-i/
/*
Hello World shows messages on construction and destruction
Also it lets you to salute.
Showing always its assigned identifiction number MyId
*/
class HelloWorld
{
private:
int myId; //Object identification num ber
public:
// class constructor http://www.cplusplus.com/doc/tutorial/classes/
HelloWorld(char *message, byte id)
{
myId=id;
Serial.print(message);
printId();
}
// class destructor http://www.cplusplus.com/doc/tutorial/classes/
~HelloWorld()
{
Serial.print ("Destructing object: ");
printId();
}
void printId()
{
Serial.print(" ID:");
Serial.println(myId);
Serial.println(" ");
}
void Salute(char *name)
{
Serial.print("Hi!, ");
Serial.println(name);
Serial.print("Regards from object: ");
printId();
}
};
/*
void setup() function it's only executed one time at the start of the execution.
It is called from a hidden main() function in the Ronbotis CM-900 IDE core.
\ROBOTIS-v0.9.9\hardware\robotis\cores\robotis\main.cpp
Note: "while (1)" is a forevr loop ( http://www.cplusplus.com/doc/tutorial/control ):
(Basic structure http://www.cplusplus.com/doc/tutorial/program_structure/)
int main(void) {
setup();
while (1) {
loop();
}
return 0;
}
*/
void setup()
{
Serial.begin(57600); //initialize serial USB connection
delay(3000); //We will wait 3 seconds, let the user open (Control+Shift+M) the Monitor serial console
}
//We will not see neither the construction nor the destruction of this global object because serial port it's not still initiated
HelloWorld hw0("construction object", 0); //Object construction http://www.cplusplus.com/doc/tutorial/classes/
// A counter to see progress and launch events
int iterationCounter=0; //An integer variable to count iterations http://www.cplusplus.com/doc/tutorial/variables
// void loop() will be executing the sentences it contains while CM-900 is on.
void loop()
{
// Lets's show only the first 5 iterations http://www.cplusplus.com/doc/tutorial/control/
if (iterationCounter<5)
{
Serial.print("starting iteration #");
Serial.println(++iterationCounter); // firts, iterationCounter is incremented and then printed
// We will see the consttructiona and destruction messages from this local (inside the loop function) object. Object construction http://www.cplusplus.com/doc/tutorial/classes/
HelloWorld hw1("constructing object", 1);
hw1.Salute("Joe");
if (iterationCounter==3)
{
// We will see the consttruction and destruction messages from this local (inside the "if" block inside the "loop" function) object. Objet construction http://www.cplusplus.com/doc/tutorial/classes/
HelloWorld hw2("constructing object", 2);
hw2.Salute("Jones");
} // Objet hw2 destruction http://www.cplusplus.com/doc/tutorial/classes/
//Let's show that object hw0 is alive
hw0.Salute("Pepe");
Serial.print("ending iteration #");
Serial.println(iterationCounter++); // first cpunter is printed, then incremented.
} // Objet hw1 destruction http://www.cplusplus.com/doc/tutorial/classes/
} // Program end. Objet hw0 destruction http://www.cplusplus.com/doc/tutorial/classes/
Another little pearl from www.dx.com is the Arduino compatible LCD 1602 (16 characters each of the 2 rows) display:
It’s really cheap, 6$/4.5€, works very fine and it’s easy to use! I will use as a handy debug display and little dashboard (it has 6 buttons at the bottom) while on field robots debugging, but this wioll be a near post with the sourcecode (that also will be a order receiver to program a Rapsberry Pi to control a robot using and Arduino Funduino Duemilanove.)
Two easy examples from the Arduino IDE wondeful examples, it’s important that you notice that the initialization sentence should be:
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
The hello world
/*
LiquidCrystal Library - Hello World
Demonstrates the use a 16x2 LCD display. The LiquidCrystal
library works with all LCD displays that are compatible with the
Hitachi HD44780 driver. There are many of them out there, and you
can usually tell them by the 16-pin interface.
This sketch prints "Hello World!" to the LCD
and shows the time.
The circuit:
* LCD RS pin to digital pin 12
* LCD Enable pin to digital pin 11
* LCD D4 pin to digital pin 5
* LCD D5 pin to digital pin 4
* LCD D6 pin to digital pin 3
* LCD D7 pin to digital pin 2
* LCD R/W pin to ground
* 10K resistor:
* ends to +5V and ground
* wiper to LCD VO pin (pin 3)
Library originally added 18 Apr 2008
by David A. Mellis
library modified 5 Jul 2009
by Limor Fried (http://www.ladyada.net)
example added 9 Jul 2009
by Tom Igoe
modified 22 Nov 2010
by Tom Igoe
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/LiquidCrystal
*/
// include the library code:
#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
void setup() {
// set up the LCD's number of columns and rows:
lcd.begin(16, 2);
// Print a message to the LCD.
lcd.print("Te, amo, Nuriitaa!");
}
void loop() {
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
lcd.setCursor(0, 1);
// print the number of seconds since reset:
lcd.print(millis()/1000);
}
Testing buttons
//Sample using LiquidCrystal library
#include <LiquidCrystal.h>
/*******************************************************
This program will test the LCD panel and the buttons
Mark Bramwell, July 2010
********************************************************/
// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
// define some values used by the panel and buttons
int lcd_key = 0;
int adc_key_in = 0;
#define btnRIGHT 0
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnSELECT 4
#define btnNONE 5
// read the buttons
int read_LCD_buttons()
{
adc_key_in = analogRead(0); // read the value from the sensor
// my buttons when read are centered at these valies: 0, 144, 329, 504, 741
// we add approx 50 to those values and check to see if we are close
if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
if (adc_key_in < 50) return btnRIGHT;
if (adc_key_in < 195) return btnUP;
if (adc_key_in < 380) return btnDOWN;
if (adc_key_in < 555) return btnLEFT;
if (adc_key_in < 790) return btnSELECT;
return btnNONE; // when all others fail, return this...
}
void setup()
{
lcd.begin(16, 2); // start the library
lcd.setCursor(0,0);
lcd.print("Push the buttons"); // print a simple message
}
void loop()
{
lcd.setCursor(9,1); // move cursor to second line "1" and 9 spaces over
lcd.print(millis()/1000); // display seconds elapsed since power-up
lcd.setCursor(0,1); // move to the begining of the second line
lcd_key = read_LCD_buttons(); // read the buttons
switch (lcd_key) // depending on which button was pushed, we perform an action
{
case btnRIGHT:
{
lcd.print("RIGHT ");
break;
}
case btnLEFT:
{
lcd.print("LEFT ");
break;
}
case btnUP:
{
lcd.print("UP ");
break;
}
case btnDOWN:
{
lcd.print("DOWN ");
break;
}
case btnSELECT:
{
lcd.print("SELECT");
break;
}
case btnNONE:
{
lcd.print("NONE ");
break;
}
}
}
It’s really cheap but it does not include any documentation; but don’t panic, all you will need can be found on Internet. And now, the main electronic components: the microcontroller, the dual motor driver, the ultrasonic sensor and the servo:
The microcontroller brain is a Funduino (Arduino Duemilanove clone), and as far I’ve used it (and as other buyer said is fully, at least for software, compatible). Here we will not have any problem because there are a lot of documentation about Arduino and Duemilanove.
// Blinking LED
int ledPin = 13; // LED connected to digital pin 13
void setup()
{
Serial.begin(57600);
printf ("Setup/n/l");
Serial.println("Hello world!");
pinMode(ledPin, OUTPUT); // sets the digital pin as output
}
void loop()
{
printf ("2009");
Serial.println("2009");
digitalWrite(ledPin, HIGH); // sets the LED on
delay(1000); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(1000); // waits for a second
}
Dual_H-Bridge_Motor_Driver
But to control the two motors this kit use an Dual H-Bridge motor driver (L298). Here (read the Drive Two DC Motors section) you can find a lot of useful documentation and examples, and here and here you can find also more information, specially about electronics.
Here a file with a simple example, and here another example with speed control
int ENA=5;//connected to Arduino's port 5(output pwm)
int IN1=2;//connected to Arduino's port 2
int IN2=3;//connected to Arduino's port 3
int ENB=6;//connected to Arduino's port 6(output pwm)
int IN3=4;//connected to Arduino's port 4
int IN4=7;//connected to Arduino's port 7
int ledPin = 13;
void blink(int times)
{
while (times>0)
{
digitalWrite(ledPin, HIGH); // sets the LED on
delay(500); // waits for a second
digitalWrite(ledPin, LOW); // sets the LED off
delay(500);
times--;
}
}
void initialize()
{
Serial.println("Two motors");
pinMode(ENA,OUTPUT);
pinMode(ENB,OUTPUT);
pinMode(IN1,OUTPUT);
pinMode(IN2,OUTPUT);
pinMode(IN3,OUTPUT);
pinMode(IN4,OUTPUT);
digitalWrite(ENA,LOW);
digitalWrite(ENB,LOW);//stop motors
digitalWrite(IN1,HIGH);
digitalWrite(IN2,LOW);//setting motorA's forward directon
digitalWrite(IN3,HIGH);
digitalWrite(IN4,LOW);//setting motorB's forward directon
}
void setup()
{
Serial.begin(57600);
initialize();
}
void loop()
{
int t=1;
initialize();
Serial.println("1 Full forward");
analogWrite(ENA,255);//start driving motorA
analogWrite(ENB,255);//start driving motorB
delay(1000*t);
Serial.println("2.1 Turning A");
// Backwards motor A, turning robot
digitalWrite(IN1,LOW);
digitalWrite(IN2,HIGH);// setting motorA's backwards directon
delay(500*t);
// full forward again
digitalWrite(IN1,HIGH);
digitalWrite(IN2,LOW);//setting motorA's forward directon
delay (1000*t);
Serial.println("2.2 Turning B");
// Backwards motor B, turning robot
digitalWrite(IN3,LOW);
digitalWrite(IN4,HIGH);//setting motorB's backward directon
delay(500*t);
// full forward again
digitalWrite(IN3,HIGH);
digitalWrite(IN4,LOW);//setting motorB's forward directon
delay (1000*t);
Serial.println("3 Full backward");
// full backwards
digitalWrite(IN1,LOW);
digitalWrite(IN2,HIGH);// setting motorA's backwards directon
digitalWrite(IN3,LOW);
digitalWrite(IN4,HIGH);//setting motorB's backward directon
delay (2000*t);
// Slowing motors
Serial.println("4 slowing motors");
analogWrite (ENA,180);
analogWrite (ENB,180);
delay(1000*t);
Serial.println("5 more slowing motors");
analogWrite (ENA,110);//stop driving motorA
analogWrite (ENB,110);//stop driving motorB
delay(1000*t);
Serial.println("6 stoping motors");
analogWrite (ENA,0);//stop driving motorA
analogWrite (ENB,0);//stop driving motorB
blink (3);
Ultrasonic sensor hc-sr04
The HC-SR04 ultrasonic distance sensor, example of use (here the file):
/*
HC-SR04 Ping distance sensor]
VCC to arduino 5v GND to arduino GND
Echo to Arduino pin 13 Trig to Arduino pin 12
More info at: http://goo.gl/kJ8Gl
*/
#define trigPin 9
#define echoPin 11
void setup() {
Serial.begin (115200);
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
}
void loop() {
int duration, distance;
digitalWrite(trigPin, HIGH);
delayMicroseconds(1000);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) / 29.1;
if (distance > 400 || distance < 0){
Serial.println("Out of range");
}
else {
Serial.print(distance);
Serial.println(" cm");
}
delay(500);
}
// Sweep
// by BARRAGAN <http://barraganstudio.com>
// This example code is in the public domain.
#include
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
void setup()
{
myservo.attach(3); // attaches the servo on pin 3 to the servo object
}
void loop()
{
// goes from 0 degrees to 180 degrees in steps of 1 degree
for(pos = 0; pos < 180; pos += 1) {
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for(pos = 180; pos>=1; pos-=1) // goes from 180 degrees to 0 degrees
{
myservo.write(pos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
}
I have bought the most affordable robotics platform (some photos here) I have found around Internet (at DX): 38€/49$ for all this components:
My construction:
Arduino cheap robot car
It’s really cheap, all the components work flawlessly and very well but IT DOES NOT INCLUDE ANY DOCUMENTATION and some parts (pan tilt base) are impossible to ensemble (it needs another micro servo, 3€/4$) and there is no way to mount on the robot base. Even that, I Think is a good deal, but you should work to get all the needed information (yes, all needed information is over Internet) and put your imagination to build it. I have used Lego Technics parts to mount the ultrasonic sensor.
Esta es la primera entrega de una serie (espero) de ellas sobre cómo hackear un coche teledirigido y ponerle todos los sensores y cacharros que se nos ocurran.
Por supuesto, empezaremos por el principio: cómo hacer que el coche sea autónomo a través de un Arduino. El elegido en este caso es el Arduino Leonardo, pero vale casi cualquier otro.
Materiales necesarios:
Un coche teledirigido baratillo, de los chinos mismo
Una placa Arduino
Cuatro resistencias (yo usé de 1K, pero valen de un valor +-50%)
Estaño
Funda termoretráctil
Varios cables de colores (a poder ser) de unos 20cm
Una batería de 9V
Herramientas necesarias:
Estañador
Destornillador
Pelacables (o una navaja, en su defecto)
Alicates de corte diagonal
Desoldador de estaño (no imprescindible, pero sí recomendable)
Pasos a seguir:
1. Desmonta el coche
2. Desatornilla la placa
3. Elimina el circuito integrado, ya que no lo necesitaremos para nada. Para ello tienes dos opciones:
a) Consigues calentar el estaño de sus patitas y lo sacas como Dios manda o…
b) Con los alicates le cortas las patitas por la parte de arriba y lo sacas con unas pinzas. Yo me he decidido por esta segunda opción. 😉
Éste es el aspecto que mostrará cuando las hayas cortado todas:
4. Prepara las resistencias
Lo que vamos a hacer ahora es proteger nuestra placa, por lo que vamos a coger las cuatro resistencias que tenemos (en mi caso de 1K, pero ya digo que el valor no es crítico, pueden ir desde 0,5K a 1,5K) y cuatro cables de colores de unos 10cm de largo, y los vamos a unir formando binomios resistencia-cable:
Cuando ya tengas las parejas hechas, consolida la unión con estaño.
Las cuatro parejas tendrán este aspecto:
Elimina el trozo sobrante con los alicates de corte.
5. Estudia el circuito integrado que desechaste
Fíjate en las letras impresas que tiene encima para poder Googlearlo. Si has comprado un coche en un chino o en algún sitio por el estilo, seguramente tendrás un integrado como este:
Lo que se trata es de buscar a qué corresponde cada pata del integrado para poder controlar nosotros a voluntad el coche. Fïjate que en este pdf aparecen tanto las especificaciones del transmisor (el que está en el mando), como del receptor (que es el que nos interesa). Los pines que estamos buscando son los correspondientes a:
Tierra (GND)
Derecha (RIGHT)
Izquierda (LEFT)
Marcha atrás (BACKWARD)
Hacia delante (FORWARD)
En mi caso, se trata de los pines 2, 6, 7, 10 y 11.
6. Introduce las parejas que preparaste y el quinto cable en los pines que has identificado
Lo que tienes que hacer ahora es, con ayuda del estañador y el desoldador, eliminar las patitas correspondientes a esos pines para poder introducir las resistencias por los agujeros. Procura limpiar bien la zona con el desoldador para que sea más fácil introducir la pata de la resistencia, aunque ya te digo que yo no tenía y no me costó excesivo trabajo dejar la zona presentable).
A continuación, introduce las cuatro resistencias por los pines correspondientes a las dos marchas y a los lados izquierdo y derecho de la siguiente manera:
Puedes observar que la resistencia queda hacia el lado de arriba, y cómo están limpios y preparados el resto de agujeros. Éste es el aspecto que tiene por debajo:
Una vez introduzcas las cuatro resistencias y el quinto cable que tenías apartado, pero aun no habías usado (es el que va en la patilla de GND, efectivamente), estaña los cinco pines y corta el sobrante tanto de las resistencias como del cable de tierra que te sobrará.
Éste es el aspecto que tendrá tu placa entonces:
7. Protegiendo tu placa
Lo que vas a hacer ahora es proteger esas parejas que hemos introducido con la funda termoretráctil. Para ello corta en varios trozos la funda de tal manera que cada trozo cubra totalmente la resistencia, el trozo estañado y un poco del cable. Unos 10-15 cm, vamos. Y como bien dice su nombre, aplícale calor para que se retraiga y se moldee según la resistencia y el cable. Puedes usar desde un mechero o una cerilla a un secador de pelo. Tú mismo. El objetivo es darle un mejor acabado a las conexiones eléctricas y dotar de protección mecánica y anti-abrasiva a los cables y demás componentes eléctricos.
Éste será el aspecto que tendrá finalmente tu placa.
8. Preparando el Arduino
Si no lo has hecho antes, ahora es el momento de anotar a qué color corresponde cada pin. Puedes hacer una tabla como la siguiente (la que resultó en mi caso):
PIN COLOR FUNCIÓN
2 Verde GND
6 Gris Derecha
7 Azul Izquierda
10 Blanco Marcha atrás
11 Amarillo Adelante
El código que vamos a preparar es muy sencillo, ya que únicamente se trata de verificar las cuatro funciones: las dos direcciones marcha atrás y adelante, y los dos lados izquierda y derecha. Se trata del siguiente:
/*
Probando las cuatro órdenes del coche
*/
int forward = 12; // Forward pin
int reverse = 11; // Reverse pin
int left = 10; // Left pin
int right = 9; // Right pin
void setup() // Configuración de los pines como salidas
{
pinMode(forward, OUTPUT);
pinMode(reverse, OUTPUT);
pinMode(left, OUTPUT);
pinMode(right, OUTPUT);
}
void go_forward()
{
digitalWrite(forward,HIGH); // Da la orden de adelante
digitalWrite(reverse,LOW); // Apaga la orden de marcha atrás
}
void go_reverse()
{
digitalWrite(reverse,HIGH); // Da la orden de marcha atrás
digitalWrite(forward,LOW); // Apaga la orden de adelante
}
void stop_car()
{
digitalWrite(reverse,LOW); // Apaga todas las órdenes
digitalWrite(forward,LOW);
digitalWrite(left,LOW);
digitalWrite(right,LOW);
}
void go_left()
{
digitalWrite(left,HIGH); // Da la orden de izquierda
digitalWrite(right,LOW); // Quita la orden de derecha
}
void go_right()
{
digitalWrite(right,HIGH); // Da la orden de derecha
digitalWrite(left,LOW); // Quita la orden de izquierda
}
void loop()
{
go_forward();
go_left();
delay(500);
stop_car();
delay(500);
go_reverse();
go_left();
delay(500);
stop_car();
delay(500);
go_forward();
go_right();
delay(500);
stop_car();
delay(500);
go_reverse();
go_right();
delay(500);
stop_car();
delay(500);
}
9. Conectando y probando el Arduino
Y por fin llega el último paso: donde por fin pruebas si todo esto funciona. Elimina la antena del coche si no lo has hecho ya (obviamente, no nos hará falta) y atornilla la placa con los tornillos que quitaste en el paso 2.
Conecta los cables según los pines que has declarado en el programa (en mi caso del 9 al 12) y los colores que anotaste antes. El color de tierra lo llevarás al GND de la placa, que como ves en la foto, está junto a los otros cuatro cables (en mi caso, repito):
Para realizar las pruebas de código, o variaciones, te recomiendo que aun no alimentes la placa con una batería, de tal manera que tendrás que tener la placa accesible al USB. Puedes volver a montar el coche y sujetar la placa con una goma elástica, como en mi caso, o dejarlo ya desmontado para introducir la placa y la batería dentro. Ahí según tu elección.
10. Alimentando la placa
Tan sólo falta el toque final: hacer el coche totalmente autónomo. Con el código ya probado ya sabes que se mueve solo, así que sólo falta el tema de la alimentación. Para ello puedes usar una batería normal de 9V, como esta:
Puedes fijarla tanto en el propio chasis del coche (si tienes sitio), como en la carrocería (algo como esto):
La conexión la puedes realizar con un enchufe centro-positivo en el conector de alimentación de la placa, o con unos simples cables como los ya empleados, insertándolos en los pines GND y Vin del conector POWER de la placa. Según tengas el adaptador o no.
El resultado será algo como esto:
Espero que te haya resultado divertido. Si tienes cualquier pregunta o duda, estamos aquí para ayudarte.