Anda di halaman 1dari 18

En este ltimo tutorial, conectaremos nuestro Arduino a una red Ethernet.

Usaremos un Arduino Ethernet Shield (escudo) que es prctico y fcil 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 ms que un dispositivo que atiende peticiones de otro dispositivo cliente a travs de una direccin IP, es decir, si nosotros accedemos a la IP de Arduino (proporcionada por la Ethernet Shield) mediante un navegador, estaremos solicitando una informacin, Arduino como servidor, nos servir la informacin solicitada.

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

Arduino Ethernet Shield.

Cable Ethernet.

Arduino Mega.
01.#include <SPI.h> 02.#include <Ethernet.h> 03. 04.// Configuracin 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 conexin 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 peticin del cliente (caracter a caracter)

33.if (c == '\n' && currentLineIsBlank) { // Se envia la respuesta a una peticin de un cliente cuando a finalizado la peticin: 34.// Respuesta: 35.client.println("HTTP/1.1 200 OK"); // Enviar un encabezado de respuesta HTTP estndar 36.client.println("Content-Type: text/html"); 37.client.println("Connection: close"); // Se cerrar la conexis despues de enviar la respuesta. 38.client.println("Refresh: 5"); // Refrescar automticamente la pgina despus 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 peticin a terminado, se respondera a dicha peticn en el sigueitne ciclo. 51.} 52.else if (c != '\r') { // Si el caracter no es un retorno de carro (la peticin no a terminado). 53.currentLineIsBlank = false; // Seguimos escuchando la peticin. 54.} 55.} 56.} 57.delay(1); // Espera para dar tiempo al navegador a recivir los datos. 58.client.stop(); // Cierra la conexin. 59.Serial.println("Cliente desconectado"); 60.Serial.println(); 61.} 62.}

Aunque en el cdigo existen comentarios de las partes ms importantes, hay que tener en cuenta algunas cuestiones:

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; Es la configuracin 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 direccin. 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 ms cercana posible a la IP del PC con el que trabajis. #include <Ethernet.h> Librera para usar la shield Ethernet (incluida en la IDE de Arduino).

Este cdigo imprime informacin a travs de dos medios. Una a travs del puerto serie y otra como servidor a travs del navegador. Por esto, cuando existe un cliente solicitando informacin, primero imprime (carcter a carcter) la informacin que el

cliente solicita a travs del puerto serie y luego atiende la peticin imprimiendo los datos en el navegador.

Conectaremos la Shield sobre Arduino.

Y conectaremos el cable USB y Ethernet.

Una vez cargado el cdigo 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 informacin se refrescar cada 5 segundos.

En el puerto serie podremos ver las peticiones del cliente. El simple hecho de acceder a la direccin IP de Arduino ya es una peticin.

En artculos anteriores se ha explicado el uso de un mdulo de ultrasonidos con Arduino. En este artculo le daremos una utilidad a nuestro modulo para hacer un radar que nos detecte la distancia a objetos sobre un rea. El mdulo 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 comunicacin Arduino-Processing la realizaremos mediante el puerto serie.

Esquema del circuito

Montaje del circuito Como vemos en el esquema usaremos una alimentacin externa de 5v. Esto se debe a que el servo consume ms de lo que Arduino puede entregar. Es de vital importancia no conectar el servo al pin de 5v de Arduino, pues obtendremos medidas errneas. Ya que usaremos una fuente externa, conectaremos a ella tambin el mdulo de ultrasonido.

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

El cdigo 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 posicin del servo y mover este desde la posicin 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@tuelectronica.es 05.Web: www.tuelectronica.es 06.Fecha: 15/04/2013 07. 08.Una modificacin de luckylarry.co.uk Arduino SRF05 Radar Sketch 09.*/ 10. 11.#include <Servo.h> // Aade la libreria Servo 12.Servo leftRightServo; // Crea una variable servo 13.int leftRightPos = 0; // Variable para la posicin del servo (grados) 14.int index = 0; // Contador para el nmero 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 seal 18.int distance = 0; // Variable para calcular la distancia 19. 20.// CONFIGURACIN: 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 seal del servo 24.int servoMin = 700; // Anchura del pulso, en microsegundos, correspondiente al mnimo (0 grados) ngulo en del servo (por defecto 544) 25.int servoMax = 2400; // Anchura del pulso, en microsegundos, correspondiente al mximo (180 grados) ngulo en del servo (por defecto 2400) 26.const int numReadings = 2; // Nmero de lecturas en cada posicin 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 nmero de lecturas en cada posicion 40.// Pulso de 10us para inicial el modulo 41.digitalWrite(trigPin, HIGH);

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 duraccin es 0 47.duration = 17400; // La seal 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); // Posicin 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.}

89.}

Descripcin de configuracin de variables numReadings nos permite configurar cuantas medidas se tomaran en cada posicin del servo. El valor en esta posicin ser un promedio de los valores obtenidos. Esto se usa para evitar posibles fallos en la medida. Cuanto ms aumentemos este valor obtendremos una medida ms 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 duracin mnima y mxima 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 extraos, vara estos datos hasta conseguir su recorrido total.

Una vez cargado el cdigo en Arduino podremos ver en el monitor serie algo parecido a esto.

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 artculos 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 cdigo del tutorial Radar con Arduino. Arduino nos enva una serie de parmetros por el puerto serie que Processing debe descomponer e interpretar. Estos parmetros son XgradosVvalor, donde grados y valor son datos numricos.

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 posicin 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 posicin del servo 018.int[] oldValue = new int[181]; // Matriz para almacenar cada valor previo de cada posicin del servo 019.PFont myFont; // Variable para configuracin 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 tamao 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

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.}

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);

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.}

Tas una comparacin 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 lnea:
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:

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 verifcalo antes. Para usar el puerto serie adecuado solo tenemos que poner el ndice numrico que aparece junto a l en la funcin Serial.list()[1] que est en la lnea donde nos genera el error. Es posible tambin 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 versin Processing 2.0b8 de Windows.

Anda mungkin juga menyukai