18
En este último tutorial, conectaremos nuestro Arduino a una red Ethernet. Usaremos un Arduino Ethernet Shield (escudo) que es práctico y fácil de usar. De esta sencilla forma, podremos acceder a contenidos web como cliente, usar Arduino como servidor web para mostrar datos de sensores e infinidad de cosas que se os puedan ocurrir. Este tutorial será un ejemplo sencillo para familiarizarnos con la shield Ethernet. El objetivo será crear un servidor web en nuestro Arduino para mostrar datos con los que trabaja Arduino, en este caso veremos el tiempo que a trascurrido desde que se puso en marcha la placa. Un servidor web no es más que un dispositivo que atiende peticiones de otro dispositivo cliente a través de una dirección IP, es decir, si nosotros accedemos a la IP de Arduino (proporcionada por la Ethernet Shield) mediante un navegador, estaremos solicitando una información, Arduino como servidor, nos servirá la información solicitada. Solo necesitaremos nuestro Arduino (nosotros usaremos Arduino Mega), una tarjeta Ethernet Shield , un cable Ethernet y el cable de porgamación USB.

Arduino Tutoriales

  • Upload
    mariohc

  • View
    100

  • Download
    9

Embed Size (px)

Citation preview

Page 1: Arduino Tutoriales

En este último tutorial, conectaremos nuestro Arduino a una red Ethernet. Usaremos un Arduino Ethernet Shield (escudo) que es práctico y fácil de usar. De esta sencilla forma, podremos acceder a contenidos web como cliente, usar Arduino como servidor web para mostrar datos de sensores e infinidad de cosas que se os puedan ocurrir.

Este tutorial será un ejemplo sencillo para familiarizarnos con la shield Ethernet. El objetivo será crear un servidor web en nuestro Arduino para mostrar datos con los que trabaja Arduino, en este caso veremos el tiempo que a trascurrido desde que se puso en marcha la placa.

Un servidor web no es más que un dispositivo que atiende peticiones de otro dispositivo cliente a través de una dirección IP, es decir, si nosotros accedemos a la IP de Arduino (proporcionada por la Ethernet Shield) mediante un navegador, estaremos solicitando una información, Arduino como servidor, nos servirá la información solicitada.

Solo necesitaremos nuestro Arduino (nosotros usaremos Arduino Mega), una tarjeta Ethernet Shield, un cable Ethernet y el cable de porgamación USB.

Page 3: Arduino Tutoriales

Arduino Mega.

01.#include <SPI.h> 02.#include <Ethernet.h> 03. 04.// Configuración de direccion MAC e IP. 05.byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; 06.IPAddress ip(192,168,1,177); 07. 08.// Inicia la libreria Ethernet server con el puerto 80 (por defecto el puerto HTTP). 09.EthernetServer server(80); 10. 11.void setup() { 12.// Inicia el puerto serie. 13.Serial.begin(9600); 14. 15.// Inicia la conexión Ethernet y el servidor. 16.Ethernet.begin(mac, ip); 17.server.begin(); 18.Serial.print("IP local del servidor "); 19.Serial.println(Ethernet.localIP()); 20.} 21. 22.void loop() { 23.EthernetClient client = server.available(); // Escucha a los clientes entrantes. 24. 25. 26.if (client) { // Si un cliente se conecta al servidor: 27.Serial.println("Nuevo cliente"); 28.boolean currentLineIsBlank = true; // Marcador para enviar la respuesta desde el servidor. 29.while (client.connected()) { // Repite mientas existe clientes conectados: 30.if (client.available()) { 31.char c = client.read(); 32.Serial.write(c); // Imprime por el puerto serie la petición del cliente (caracter a caracter)

Page 4: Arduino Tutoriales

33.if (c == '\n' && currentLineIsBlank) { // Se envia la respuesta a una petición de un cliente cuando a finalizado la petición: 34.// Respuesta: 35.client.println("HTTP/1.1 200 OK"); // Enviar un encabezado de respuesta HTTP estándar 36.client.println("Content-Type: text/html"); 37.client.println("Connection: close"); // Se cerrará la conexiós despues de enviar la respuesta. 38.client.println("Refresh: 5"); // Refrescar automáticamente la página después de 5 segundos. 39.client.println(); 40.client.println("<!DOCTYPE HTML>"); // Tipo de documento. 41.client.println("<html>"); // Etiqueta html inicio del documento. 42.client.print("Hola soy Arduino!! - "); 43.client.print(millis()); // Tiempo de funcionamiento en ms. 44.client.print("ms encendido. "); 45.client.println("<br />"); // Etiqueta html salto de linea. 46.client.println("</html>"); // Etiqueta html fin del documento. 47.break; 48.} 49.if (c == '\n') { // Si el caracter es un salto de linea: 50.currentLineIsBlank = true; // La petición a terminado, se respondera a dicha peticón en el sigueitne ciclo. 51.} 52.else if (c != '\r') { // Si el caracter no es un retorno de carro (la petición no a terminado). 53.currentLineIsBlank = false; // Seguimos escuchando la petición. 54.} 55.} 56.} 57.delay(1); // Espera para dar tiempo al navegador a recivir los datos. 58.client.stop(); // Cierra la conexión. 59.Serial.println("Cliente desconectado"); 60.Serial.println(); 61.} 62.}

Aunque en el código existen comentarios de las partes más importantes, hay que tener en cuenta algunas cuestiones:

• byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; Es la configuración del identificador único MAC del adaptador de red (Arduino Ethernet Shield), este debe ser único en la red. Aseguraos de que no existe otro dispositivo con esta misma dirección.

• IPAddress ip(192,168,1,177); Es la IP que Arduino tomará como servidor a la cual tendremos que acceder para ver los datos. Debe estar dentro del rango de red para poder ser visible. Intenta usar una IP lo más cercana posible a la IP del PC con el que trabajáis.

• #include <Ethernet.h> Librería para usar la shield Ethernet (incluida en la IDE de Arduino).

Este código imprime información a través de dos medios. Una a través del puerto serie y otra como servidor a través del navegador. Por esto, cuando existe un cliente solicitando información, primero imprime (carácter a carácter) la información que el

Page 5: Arduino Tutoriales

cliente solicita a través del puerto serie y luego atiende la petición imprimiendo los datos en el navegador.

Conectaremos la Shield sobre Arduino.

Y conectaremos el cable USB y Ethernet.

Page 6: Arduino Tutoriales

Una vez cargado el código en Arduino, si todo esta correcto, debe aparecer la IP del

servidor en el monitor serie.

Accederemos mediante un navegador a la IP del ahora servidor web Arduino.

Si todo está correcto, aparecerá un mensaje como el de la foto, junto al tiempo

trascurrido desde que se encendió Arduino en milisegundo. Esta información se refrescará cada 5 segundos.

Page 7: Arduino Tutoriales

En el puerto serie podremos ver las peticiones del cliente. El simple hecho de acceder a

la dirección IP de Arduino ya es una petición.

En artículos anteriores se ha explicado el uso de un módulo de ultrasonidos con Arduino. En este artículo le daremos una utilidad a nuestro modulo para hacer un radar que nos detecte la distancia a objetos sobre un área.

El módulo de ultrasonidos HY-SFR05 que usaremos en este tutorial es bastante directivo, y con ayuda de un servo, podremos hacer un barrido de 180° para explorar un área. Arduino se encargará de tomar las medidas y con un programa desarrollado en Processing podremos mostrar los datos en un PC. La comunicación Arduino-Processing la realizaremos mediante el puerto serie.

Page 8: Arduino Tutoriales

Esquema del circuito

Montaje del circuito

Como vemos en el esquema usaremos una alimentación externa de 5v. Esto se debe a que el servo consume más de lo que Arduino puede entregar. Es de vital importancia no conectar el servo al pin de 5v de Arduino, pues obtendremos medidas erróneas. Ya que usaremos una fuente externa, conectaremos a ella también el módulo de ultrasonido.

No debemos pasar por alto que al usar una fuente de alimentación externa debemos conectar la masa de Arduino con la de la fuente, de lo contrario el circuito no funcionará.

Page 9: Arduino Tutoriales

El código para este proyecto consta de dos partes, uno para Arduino y otro para Processing que veremos en otro tutorial. Arduino se encargará de tomar las medidas de distancia para cada posición del servo y mover este desde la posición de 0° a 180° y viceversa. Los datos obtenidos se enviaran por el puerto serie.

01./* 02.Arduino Ultrasonic Radar v1.1 03.Autor: FjRamirez 04.Email: [email protected] 05.Web: www.tuelectronica.es 06.Fecha: 15/04/2013 07. 08.Una modificación de luckylarry.co.uk Arduino SRF05 Radar Sketch 09.*/ 10. 11.#include <Servo.h> // Añade la libreria Servo 12.Servo leftRightServo; // Crea una variable servo 13.int leftRightPos = 0; // Variable para la posición del servo (grados) 14.int index = 0; // Contador para el número de lectura 15.long total = 0; // Variable para calcular el pormedio 16.int average = 0; // Variable para calcular el promedio 17.long duration = 0; // Variable para calcular el tiempo de llegada de la señal 18.int distance = 0; // Variable para calcular la distancia 19. 20.// CONFIGURACIÓN: 21.int echoPin = 53; // SRF05's Echo pin 22.int trigPin = 51; // SRF05's Trig pin 23.int servoPin = 12; // Pin para el cable de señal del servo 24.int servoMin = 700; // Anchura del pulso, en microsegundos, correspondiente al mínimo (0 grados) ángulo en del servo (por defecto 544) 25.int servoMax = 2400; // Anchura del pulso, en microsegundos, correspondiente al máximo (180 grados) ángulo en del servo (por defecto 2400) 26.const int numReadings = 2; // Número de lecturas en cada posición 27. 28.void setup() { 29.leftRightServo.attach(servoPin,700,2400); // Pin de salida para el servo, recorrido minimo, recorrido maximo 30.Serial.begin(9600); // Establece la velocidad de datos del puerto serie 31.pinMode(trigPin, OUTPUT); // Establece pin como salida 32.pinMode(echoPin, INPUT); // Establece pin como entrada 33.digitalWrite(trigPin, LOW); // Pone el pin a un estado logico bajo 34.} 35. 36.void loop() { 37.for(leftRightPos = 0; leftRightPos < 180; leftRightPos++) { // De izquierda a derecha. 38.leftRightServo.write(leftRightPos); 39.for (index = 0; index<numReadings; index++) { // Repite tantas veces como número de lecturas en cada posicion 40.// Pulso de 10us para inicial el modulo 41.digitalWrite(trigPin, HIGH);

Page 10: Arduino Tutoriales

42.delayMicroseconds(10); 43.digitalWrite(trigPin, LOW); 44. 45.duration = pulseIn(echoPin, HIGH, 17400); // Devuelve la longitud del pulso del pin Echo en us (3metros maximo) 46.if (!duration){ // Si la duracción es 0 47.duration = 17400; // La señal se a perdido. Se establece distancia maxima 48.} 49.distance = duration/58; // Calculamos distancia en centrimetros 50.total = total + distance; // Almacenamos la distancia para calcular promedio 51.delay(50); // Esperamos hasta la siguiente medida 52.} 53. 54.average = total/numReadings; // Calcula el promedio 55.total = 0; // Resetea variable 56. 57.// Envia datos por el puerto serie 58.Serial.print("X"); // Identificador X para la posicion del servo 59.Serial.print(leftRightPos); // Posición del servo 60.Serial.print("V"); // Identificador V para el promedio de distancia 61.Serial.println(average); // Promedio de distancia 62.} 63. 64.for(leftRightPos = 180; leftRightPos > 0; leftRightPos--) { // De derechas a izquierda 65.leftRightServo.write(leftRightPos); 66.for (index = 0; index<numReadings; index++) { 67.// Pulso de 10us para inicial el modulo 68.digitalWrite(trigPin, HIGH); 69.delayMicroseconds(10); 70.digitalWrite(trigPin, LOW); 71. 72.duration = pulseIn(echoPin, HIGH, 17400); 73.if (!duration){ 74.duration = 17400; 75.} 76.distance = duration/58; 77.total = total + distance; 78.delay(50); 79.} 80. 81.average = total/numReadings; 82.total = 0; 83. 84.Serial.print("X"); 85.Serial.print(leftRightPos); 86.Serial.print("V"); 87.Serial.println(average); 88.}

Page 11: Arduino Tutoriales

89.}

Descripción de configuración de variables

numReadings nos permite configurar cuantas medidas se tomaran en cada posición del servo. El valor en esta posición será un promedio de los valores obtenidos. Esto se usa para evitar posibles fallos en la medida. Cuanto más aumentemos este valor obtendremos una medida más exacta en puntos en los que puedan existir reflexiones o multitrayectos del sonido. El aumentar este valor implica un mayor tiempo empleado para rastrear una zona.

servoMin y servoMax permiten establecer la duración mínima y máxima del pulso de salida para el servo correspondiente a 0° y 180°. Es posible que dependiendo de nuestro servo tengamos que modificar estos valores haciendo unas pruebas previas. Si vemos que el servo no hace todo su recorrido o hace movimientos extraños, varía estos datos hasta conseguir su recorrido total.

Una vez cargado el código en Arduino podremos ver en el monitor serie algo parecido a

esto.

Page 12: Arduino Tutoriales

Para interpretar los datos y mostrarlos de forma visual tendremos que seguir este

tutorial: Radar con Processing.

En este primer tutorial de Processing crearemos un entorno visual para usarlo con nuestro radar Arduino de artículos anteriores. Con un barrido de 180° podremos medir la distancia de un área y visualizar si se producen cambios.

Debemos tener conectado Arduino a nuestro PC mediante el cable USB y cargado con el código del tutorial Radar con Arduino. Arduino nos envía una serie de parámetros por el puerto serie que Processing debe descomponer e interpretar. Estos parámetros son XgradosVvalor, donde grados y valor son datos numéricos.

Page 13: Arduino Tutoriales

001./* 002.Autor: luckylarry.co.uk 003.Radar Screen Visualisation for SRF-05 004.Maps out an area of what the SRF-05 sees from a top down view. 005.Takes and displays 2 readings, one left to right and one right to left. 006.Displays an average of the 2 readings 007.Displays motion alert if there is a large difference between the 2 values. 008.*/ 009.import processing.serial.*; // Importa la libreria serie 010.Serial myPort; // Declara el puerto serie 011.float x, y; // Variable para almacenar las coordenadas 012.int radius = 350; // Establece el radio de los objetos 013.int w = 300; // Establece un valor de anchura arbitraria 014.int degree = 0; // Varible para la posición del servo en grados 015.int value = 0; // Variable para el valor del sensor 016.int motion = 0; // Variable para indicar el sentido del barrido del servo 017.int[] newValue = new int[181]; // Matriz para almacenar cada valor nuevo de cada posición del servo 018.int[] oldValue = new int[181]; // Matriz para almacenar cada valor previo de cada posición del servo 019.PFont myFont; // Variable para configuración de fuente 020.int radarDist = 0; // set value to configure Radar distance labels 021.int firstRun = 0; // value to ignore triggering motion on the first 2 servo sweeps 022.int lf = 10; // ASCII retorno de carro 023. 024.void setup(){ 025.size(750, 450); // Establece el tamaño de la ventana 026.background (0); // Establece a negro del fondo de la ventana 027.myFont = createFont("verdana", 12); // Parametros de la fuente 028.textFont(myFont); // Establece los parametros de la fuente 029. 030.println(Serial.list()); // Lista todos los puertos series 031.myPort = new Serial(this, Serial.list()[1], 9600); // Establece un puerto serie 032.myPort.bufferUntil(lf); // Almacena en el bufer hasta llegar un retorno de carro 033.} 034./* draw the screen */ 035.void draw(){ 036.fill(0); // set the following shapes to be black 037.noStroke(); // set the following shapes to have no outline 038.ellipse(radius, radius, 750, 750); // draw a circle with a width/ height = 750 with its center position (x and y) set by the radius

Page 14: Arduino Tutoriales

039.rectMode(CENTER); // set the following rectangle to be drawn around its center 040.rect(350,402,800,100); // draw rectangle (x, y, width, height) 041.if (degree >= 179) { // if at the far right then set motion = 1/ true we're about to go right to left 042.motion = 1; // this changes the animation to run right to left 043.} 044.if (degree <= 1) { // if servo at 0 degrees then we're about to go left to right 045.motion = 0; // this sets the animation to run left to right 046.} 047./* setup the radar sweep */ 048./* 049.We use trigonmetry to create points around a circle. 050.So the radius plus the cosine of the servo position converted to radians 051.Since radians 0 start at 90 degrees we add 180 to make it start from the left 052.Adding +1 (i) each time through the loops to move 1 degree matching the one degree of servo movement 053.cos is for the x left to right value and sin calculates the y value 054.since its a circle we plot our lines and vertices around the start point for everything will always be the center. 055.*/ 056.strokeWeight(7); // set the thickness of the lines 057.if (motion == 0) { // if going left to right 058.for (int i = 0; i <= 20; i++) { // draw 20 lines with fading colour each 1 degree further round than the last 059.stroke(0, (10*i), 0); // set the stroke colour (Red, Green, Blue) base it on the the value of i 060.line(radius, radius, radius + cos(radians(degree+(180+i)))*w, radius + sin(radians(degree+(180+i)))*w); // line(start x, start y, end x, end y) 061.} 062.} else { // if going right to left 063.for (int i = 20; i >= 0; i--) { // draw 20 lines with fading colour 064.stroke(0,200-(10*i), 0); // using standard RGB values, each between 0 and 255 065.line(radius, radius, radius + cos(radians(degree+(180+i)))*w, radius + sin(radians(degree+(180+i)))*w); 066.} 067.} 068./* Setup the shapes made from the sensor values */ 069.noStroke(); // no outline 070./* first sweep */ 071.fill(0,50,0); // set the fill colour of the shape (Red, Green, Blue) 072.beginShape(); // start drawing shape 073.for (int i = 0; i < 180; i++) { // for each degree in the array 074.x = radius + cos(radians((180+i)))*((oldValue[i])); // create x coordinate 075.y = radius + sin(radians((180+i)))*((oldValue[i])); // create y coordinate 076.vertex(x, y); // plot vertices 077.}

Page 15: Arduino Tutoriales

078.endShape(); // end shape 079./* second sweep */ 080.fill(0,110,0); 081.beginShape(); 082.for (int i = 0; i < 180; i++) { 083.x = radius + cos(radians((180+i)))*(newValue[i]); 084.y = radius + sin(radians((180+i)))*(newValue[i]); 085.vertex(x, y); 086.} 087.endShape(); 088./* average */ 089.fill(0,170,0); 090.beginShape(); 091.for (int i = 0; i < 180; i++) { 092.x = radius + cos(radians((180+i)))*((newValue[i]+oldValue[i])/2); // create average 093.y = radius + sin(radians((180+i)))*((newValue[i]+oldValue[i])/2); 094.vertex(x, y); 095.} 096.endShape(); 097./* if after first 2 sweeps, highlight motion with red circle*/ 098.if (firstRun >= 360) { 099.stroke(150,0,0); 100.strokeWeight(1); 101.noFill(); 102.for (int i = 0; i < 180; i++) { 103.if (oldValue[i] - newValue[i] > 35 || newValue[i] - oldValue[i] > 35) { 104.x = radius + cos(radians((180+i)))*(newValue[i]); 105.y = radius + sin(radians((180+i)))*(newValue[i]); 106.ellipse(x, y, 10, 10); 107.} 108.} 109.} 110./* set the radar distance rings and out put their values, 50, 100, 150 etc.. */ 111.for (int i = 0; i <=6; i++){ 112.noFill(); 113.strokeWeight(1); 114.stroke(0, 255-(30*i), 0); 115.ellipse(radius, radius, (100*i), (100*i)); 116.fill(0, 100, 0); 117.noStroke(); 118.text(Integer.toString(radarDist+50), 380, (305-radarDist), 50, 50); 119.radarDist+=50; 120.} 121.radarDist = 0; 122./* draw the grid lines on the radar every 30 degrees and write their values 180, 210, 240 etc.. */ 123.for (int i = 0; i <= 6; i++) { 124.strokeWeight(1); 125.stroke(0, 55, 0); 126.line(radius, radius, radius + cos(radians(180+(30*i)))*w, radius + sin(radians(180+(30*i)))*w); 127.fill(0, 55, 0); 128.noStroke(); 129.if (180+(30*i) >= 300) { 130.text(Integer.toString(180+(30*i)), (radius+10) + cos(radians(180+(30*i)))*(w+10), (radius+10) + sin(radians(180+(30*i)))*(w+10), 25,50);

Page 16: Arduino Tutoriales

131.} else { 132.text(Integer.toString(180+(30*i)), radius + cos(radians(180+(30*i)))*w, radius + sin(radians(180+(30*i)))*w, 60,40); 133.} 134.} 135./* Write information text and values. */ 136.noStroke(); 137.fill(0); 138.rect(350,402,800,100); 139.fill(0, 100, 0); 140.text("Grados: "+Integer.toString(degree), 100, 380, 100, 50); // use Integet.toString to convert numeric to string as text() only outputs strings 141.text("Distancia: "+Integer.toString(value), 100, 400, 100, 50); // text(string, x, y, width, height) 142.text("www.tuelectronica.es", 540, 380, 250, 50); 143.fill(0); 144.rect(70,60,150,100); 145.fill(0, 100, 0); 146.text("Screen Key:", 100, 50, 150, 50); 147.fill(0,50,0); 148.rect(30,53,10,10); 149.text("Primer barrido", 115, 70, 150, 50); 150.fill(0,110,0); 151.rect(30,73,10,10); 152.text("Segundo barrido", 115, 90, 150, 50); 153.fill(0,170,0); 154.rect(30,93,10,10); 155.text("Promedio", 115, 110, 150, 50); 156.noFill(); 157.stroke(150,0,0); 158.strokeWeight(1); 159.ellipse(29, 113, 10, 10); 160.fill(150,0,0); 161.text("Movimiento", 115, 130, 150, 50); 162.} 163./* get values from serial port */ 164.void serialEvent (Serial myPort) { 165.String xString = myPort.readStringUntil(lf); // read the serial port until a new line 166. 167.if (xString != null) { // if theres data in between the new lines 168.xString = trim(xString); // get rid of any whitespace just in case 169.String getX = xString.substring(1, xString.indexOf("V")); // get the value of the servo position 170.String getV = xString.substring(xString.indexOf("V")+1, xString.length()); // get the value of the sensor reading 171.degree = Integer.parseInt(getX); // set the values to variables 172.value = Integer.parseInt(getV); 173.oldValue[degree] = newValue[degree]; // store the values in the arrays. 174.newValue[degree] = value; 175./* sets a counter to allow for the first 2 sweeps of the servo */ 176.firstRun++; 177.if (firstRun > 360) { 178.firstRun = 360; // keep the value at 360 179.} 180.} 181.}

Page 17: Arduino Tutoriales

Tas una comparación cada dos barridos, el programa marca con circunferencias rojas

donde existen diferencias de medidas respecto al barrido anterior.

Si el programa nos genera un error en la línea:

1.myPort = new Serial(this, Serial.list()[1], 9600);

el problema puede deberse a que se está intentando leer un puerto serie que no existe.

En la ventana de notificaciones de Processing debe aparecer algo como esto:

Page 18: Arduino Tutoriales

Esto es un listado de los puertos serie que tiene nuestro PC, debemos usar de la lista el que Arduino nos genera, por defecto suele ser COM3, pero verifícalo antes. Para usar el puerto serie adecuado solo tenemos que poner el índice numérico que aparece junto a él en la función Serial.list()[1] que está en la línea donde nos genera el error.

Es posible también que no se nos genere un error, pero el puerto serie no sea el correcto. Si el programa no funciona, puede ser esta la causa.

Este programa ha sido testado en la versión Processing 2.0b8 de Windows.