Protocolos
de comunicación: SPI
SPI es un protocolo serial síncrono
que
se utiliza para comunicar un microcontrolador con
otro y con periféricos a distancias cortas. Para hacer
una conexion SPI
siempre habrá un dispositivo maestro (usualmente un microcontrolador) que
controlará uno o varios periféricos (esclavos), se utilizan por lo generar 3 lineas de
conexión y una de selección que son:
* SO o MISO (Master In Slave Out). La linea que utiliza el esclavo para enviar datos al maestro
* SI o MOSI (Master Out Slave In). Datos del maestro al esclavo.
* SCK (Serial clock). Pulsos de reloj para sincronizar la comunicación
* CS o Select. Se usa por el master para habilitar o deshabilitar un determinado periférico
Los microcontroladores atmel incluyen las 4 lineas para usar protocolo SPI las cuales obviamente están presentes en los pines del arduino, para el arduino uno se deben usar: Pin digital 10 para CS, Pin digital 11 para SI, Pin digital 12 para SO y Pin digital 13 para SCK, en el caso del arduino mega se usaría los sig. pines: 50 (MISO), 51 (MOSI), 52 (SCK), and 53 (CS).
La alimentación del módulo puede es a 3.3 los cuales son suministrados por el arduino
* SO o MISO (Master In Slave Out). La linea que utiliza el esclavo para enviar datos al maestro
* SI o MOSI (Master Out Slave In). Datos del maestro al esclavo.
* SCK (Serial clock). Pulsos de reloj para sincronizar la comunicación
* CS o Select. Se usa por el master para habilitar o deshabilitar un determinado periférico
Los microcontroladores atmel incluyen las 4 lineas para usar protocolo SPI las cuales obviamente están presentes en los pines del arduino, para el arduino uno se deben usar: Pin digital 10 para CS, Pin digital 11 para SI, Pin digital 12 para SO y Pin digital 13 para SCK, en el caso del arduino mega se usaría los sig. pines: 50 (MISO), 51 (MOSI), 52 (SCK), and 53 (CS).
La alimentación del módulo puede es a 3.3 los cuales son suministrados por el arduino
Protocolos
de comunicación: HTTP
Hypertext
Transfer Protocol o
HTTP (en español protocolo de transferencia de hipertexto) es el protocolo
usado en cada transacción de la Web.
Es un
protocolo orientado a transacciones y sigue el esquema petición-respuesta entre
un cliente y un servidor.
Al cliente
que efectúa la petición (un navegador web o un spider) se lo conoce como "user agent"
(agente del usuario). Y a la información transmitida se la llama recurso y se la identifica
mediante un localizador uniforme de recursos (URL). Los recursos pueden ser
archivos, el resultado de la ejecución de un programa, una consulta a una base
de datos, en
este caso en particular la respuesta será la lectura de un sensor o el
resultado de la ejecución de un proceso en Arduino, etc.
El
módulo ENC28J60 y su librería desarrollada para el arduino lo
convierten en un pequeño servidor WEB capaz de responder a interacciones del
usuario desde cualquier navegador.
Librería
ENC28J60
El
módulo que usaremos está basado en un chip ENC28J60 de Microchip que
interactúa con Arduino y le permite la comunicación de datos mediante un puerto Ethernet.
Se
integra el controlador de la MAC address, un
buffer de 8 KB de transmisión/recepción de de paquetes de doble puerto y una
FIFO circular que se gestionan a nivel de hardware, además
permite la
programación de retransmisión de datos en caso de colisión.
La
librería de funciones fue desarrollada por Jean-Claude Wippler del
sitio http://jeelabs.org y liberada con licencia creative commons como
software libre,
a
partir de ahí ha sido utilizada por diferentes fabricantes para soportar
diferentes productos basados en el mismo controlador.
Antes de iniciar la operación de
nuestro módulo debemos llevara acabo la configuración de los parámetros para
comunicación en la red ethernet, datos como:
Dirección IP
Máscara de red
Puerta de enlace
Tamaño del buffer de datos.
Las principales funciones incluidas
en la librería son:
ether.begin :
Crea un objeto para interactuar con el controlador
ether.packetReceive(); Devuelve la cantidad de paquetes pendientes de recibir que estan
almacenados en el buffer.
ether.packetLoop(len); Da
entrada todos los paquetes almacenados en el buffer, len es
la cantidad de paquetes que se van a recibir;
ether.httpServerReply(homePage()); Responde al cliente que realizo la petición, homePage es
una variable que apunta a un string o
cadena de texto con formato HTML con una respuesta válida para el cliente.
El siguiente programa controla el encendido y apagado de un led mediante una pagina web que se accede desde la direccion ip del modulo enc-28j60 conectado al arduino, el diagrama de conexion del modulo con el arduino es el que ya vimos en la primera parte de este tutorial mas un led conectado en el pin digital 2 que sera el que controlemos via red:
// Arduino demo sketch for testing ethernet
// 2012-09-20 lmdiaz@tecnotinker.com
// This sketch is derived from RF12eth.pde:
// May 2010, Andras Tucsni, http://opensource.org/licenses/mit-license.php
#include <EtherCard.h>
#define DEBUG 0 // set to 1 to display free RAM on web page
#define SERIAL 0 // set to 1 to show incoming requests on serial port
// buffer for an outgoing data packet
static char outCount = -1;
// configuration, as stored in EEPROM
struct Config {
byte band;
byte group;
byte collect;
word refresh;
byte valid; // keep this as last byte
} config;
#define NUM_MESSAGES 10 // Number of messages saved in history
#define MESSAGE_TRUNC 15 // Truncate message payload to reduce memory use
static BufferFiller bfill; // used as cursor while filling the buffer
static byte history_rcvd[NUM_MESSAGES][MESSAGE_TRUNC+1]; //history record
static byte history_len[NUM_MESSAGES]; // # of RF12 messages+header in history
static byte next_msg; // pointer to next rf12rcvd line
static word msgs_rcvd; // total number of lines received modulo 10,000
byte ledstatus = 0;
byte Ethernet::buffer[1000]; // tcp/ip send and receive buffer
// ethernet interface mac address
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x31 };
// ethernet interface ip address
static byte myip[] = { 192,168,1,188 };
// gateway ip address
static byte gwip[] = { 192,168,1,1 };
#if DEBUG
static int freeRam () {
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}
#endif
void setup(){
#if SERIAL
Serial.begin(57600);
Serial.println("\n[etherNode]");
#endif
if (ether.begin(sizeof Ethernet::buffer, mymac) == 0)
Serial.println( "Failed to access Ethernet controller");
ether.staticSetup(myip, gwip);
#if SERIAL
ether.printIp("IP: ", ether.myip);
#endif
}
char okHeader[] PROGMEM =
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/html\r\n"
"Pragma: no-cache\r\n"
;
static void homePage(BufferFiller& buf, byte led) {
buf.emit_p(PSTR("$F\r\n"
"<meta http-equiv='refresh' content='$D'/>"
"<title>Controlar un led desde internet</title>"
"<body><p>Estatus del led: $D</br>"
"<a href='a'>Apagar</a> </br>"
"<a href='e'>Encender</a><br></p>"), okHeader, 1, led);
// Cronometrar el tiempo de ejecucion del programa
long t = millis() / 1000;
word h = t / 3600;
byte m = (t / 60) % 60;
byte s = t % 60;
buf.emit_p(PSTR(
"Tiempo corriendo $D$D:$D$D:$D$D</body>"), h/10, h%10, m/10, m%10, s/10, s%10);
#if DEBUG
buf.emit_p(PSTR(" ($D bytes free)"), freeRam());
#endif
}
void loop(){
word len = ether.packetReceive();
word pos = ether.packetLoop(len);
// check if valid tcp data is received
if (pos) {
bfill = ether.tcpOffset();
char* data = (char *) Ethernet::buffer + pos;
#if SERIAL
Serial.println(data);
#endif
// Pagina sin solicitud
if (strncmp("GET / ", data, 6) == 0) {
homePage(bfill, ledstatus);
}
else if (strncmp("GET /a", data, 6) == 0) {
// Recibimos el parametro a (apagar)
homePage(bfill, ledstatus);//configPage(data, bfill);
if(ledstatus == HIGH) {
digitalWrite(2, LOW);
ledstatus = LOW;
}
}
else if (strncmp("GET /e", data, 6) == 0) {
// Recibimos el parametro e (encender)
homePage(bfill, ledstatus);
if(ledstatus == LOW) {
digitalWrite(2, HIGH);
ledstatus = HIGH;
}
}
else
bfill.emit_p(PSTR(
"HTTP/1.0 401 Invalido\r\n"
"Content-Type: text/html\r\n"
"\r\n"
"<h1>401 Unauthorized</h1>"));
ether.httpServerReply(bfill.position()); // send web page data
}
}
A ver si soy capaz de ponerlo en marcha, Gracias
ResponderEliminarPudiste master?
EliminarNecesitas ayuda con algo?
Eliminarhola amigo soy el de mercadolibre me interesa saber en donde estas hubicado mi num de cel es 9933592130 mi correo es manuel_007ga@hotmail.com espero y te comuniques o me digas la direccion para que vea los productos saludos
ResponderEliminarhola amigo.. primero que nada gracias por esta aportación que has echo..
ResponderEliminararme mi circuito y funciona bien hasta cierto puto.. conecto el circuito a la red y en el explorador busco la pagina y la uso,el led se enciendo y se apaga, hasta aquí todo bien (esto lo hago con el internet de mi trabajo).. después hablo a casa y pido que busquen la pagina pero no la encuentran, sale error después quedarse cargando un buen rato..
Me podrías ayudar a solucionar esto?
Tengo que configurar el módem de mi trabajo?
Hola como bien comentas el problema radica en la configuracion del modem, para esto es un poco dificil hacer un tutorial ya que no se podria abarcar en poco espacio toda la variedad de modems que existen, basicamente se trata de redirigir el puerto de servicio usado (puerto 80) desde la interface externa del modem hacia la ip donde esta conectado el arduino y dirigir las solicitudes desde internet hacia la ip "externa" donde esta conectado el modem, o sea si configuras tu arduino en la ip 192.168.1.188, las solicitudes desde internet no se hacen hacia esa ip si no a la ip que te muestra la interface externa del modem, cabe mencionar que las direcciones ip comprendidas en el rango 192.x.x.x no existen realmente en internet y solo se usan para conectividad en redes internas ya sea empresariales o domesticas, el mapeo de puertos lo que hace es redirigir las solicitudes desde internet hacia un equipo en la red interna, por ejemplo si tu ip "externa" fuera "200.23.106.37", en el modem vas a redirigir el trafico desde esa ip hacia la ip de tu red interna, es decir 192.168.1.118, entonces queda de la siguiente forma:
EliminarInternet ---> 200.23.106.37 (puerto 80) <-modem-> 192.168.1.118 (puerto 80)
Espero haber sido claro si no me puedes preguntar cualquier duda, para hacer el mapeo de puertos revisa el manual de tu modem, espero luego me invites a probar tu arduino conectado a internet, saludos de Tabasco, México
la verdad no entiendo mucho, se me hace complicado esto de las ip ya que soy nuevo en estos temas..
Eliminarpero... podría funcionar si conecto el arduino a un módem domestico y desde otro módem domestico intento ver la pagina?.... esto por que los modems domésticos normalmente no es necesario configuar la pc, es decir, no necesitan cambiar los valores para la dirección IP, Mascara de Subred, Puerta de Enlace Predeterminada y el DNS..
o aun así habría que configurar el módem al cual esta conectado el arduino?.
hola amigo. e redirigido el puerto 80 hacia la dirección IP de arduino.. lo ise como indica en este videotutorial http://www.youtube.com/watch?feature=player_embedded&v=8H-Ea9Z_ppc.. intentado abrir la pagina que genera elarduino poniendo la IP de arduino en una pc con internet externo (diferente al modem donde esta conectadoarduino) pero no logro encontrar la pagina.. no se que es lo que tengo que configurar.
ResponderEliminarLa ip que debes usar para acceder desde internet es la ip "externa" del modem, la puedes obtener en esta pagina http://www.cual-es-mi-ip.net/, a esta ip que obtengas es a la que tienes que acceder desde otra ubicacion para poder ver tu arduino
EliminarSaludos. Me encuentro trabajando con el mismo chip que señala y he logrado algunas cosas. Me encuentro tratando de realizar el ejemplo de Twitter que viene con la librería. La verdad no he logrado hacer que funcione. Me logro conectar a la red y el nslookup funciona a la maravilla pero el twitter no se realiza. Me pregunto si usted lo ha trabajado alguna ves y si le ha servido. Gracias!
ResponderEliminarMuy buen tutorial, soy nuevo en esto de arduino ethernet, el programa me funciona de maravilla; pero como puedo agregar mas botones para controlar el encendido de otros led independientemente.
ResponderEliminary como puedo cambiar la apariencia de la pagina web.
Basicamente necesitas ingresar algunas lineas mas de html para ambas cosas, este fin de semana tratare de hacer una tercera parte del tutorial para mostraar como hacerlo, saludos
EliminarHola. Realmente me has ayudado mucho con este tutorial, es excelente. Al igual que uno de los comentarios anteriores, me interesa mucho poder manejar varios botones para varios led independientes. Vi que comentaste que pondrías esa información en otro tutorial. Podrías indicarme la página para verlo por favor?. Mil gracias.
ResponderEliminarHola no he tenido tiempo de hacer la siguiente parte del tutorial, para controlar mas de un boton podria implementarse algo de javascript, tambien he pensado agregar un lector de tarjeta sd para poder agregar iconos e imagenes a la pagina para mejorar su apariencia, la verdad es que he estado trabajando con la raspberry para comunicacion desde internet y alla todo es mas facil
EliminarSaludos, muy bueno el tutorial, ya logro enceder un led, pero el un modulo de rele no sirve, hay que cambiar alguna parte del codigo para que funcione.
ResponderEliminarhola, para activarse adecuadamente el rele necesita un transistor, no se si lo estas incluyendo en tu circuito
EliminarEste comentario ha sido eliminado por el autor.
EliminarGracias! me ha servido de mucha ayuda!
ResponderEliminarEl codigo no me complia por esto:
ResponderEliminarchar okHeader[] PROGMEM =
A que se debe ?
estimado como estas , delante de la linea coloca
Eliminarstatic const
osea quedaria de la siguiente manera
static const char okHeader[] PROGMEM =
compila y con eso deberia funcionar
Espero te aya sido de ayuda
El codigo no me complia por esto:
ResponderEliminarchar okHeader[] PROGMEM =
A que se debe ?
Que version de ide de arduino y libreria estas usando?
EliminarGracias por el tutorial amigo esta muy bien explicado pero tengo un problema al momento de compilar
EliminarEl codigo no me complia por esto:
char okHeader[] PROGMEM =
la version del IDE es la 1.6.7
espero tu ayuda gracias.
me da ese mismo error, mi versión es la 1.6.9
EliminarTambién me da el mismo error...
Eliminarbuen tutorial, soy nuevo en esto de arduino ethernet, me pregunto como realizaron la pagina web que monitorea lo que esta conectado al arduino?
ResponderEliminarEl html esta embebido en el codigo del arduino, es decir mediante las funciones que brinda la libreria se envian las cadenas de texto equivalentes a instrucciones de html, el browser o cliente solicita el recurso o sea la lectura del html mendiante la direccion ip y el puerto 80 (http)
EliminarGracias por el tutorial amigo esta muy bien explicado pero tengo un problema al momento de compilar
ResponderEliminarEl codigo no me complia por esto:
char okHeader[] PROGMEM =
la version del IDE es la 1.6.7
espero tu ayuda gracias.
Gracias luigy7 pensaba en guardar mi Enc28j60 cuando lo compre no exixtia mucha informacion de como ponerlo a funcionar mas que algunos ejemplos en Ccs pero se me hizo muy complicado ahora con arduino es mas sencillo
ResponderEliminarlo puse antes pero se lo comparto a todos , en linea char okHeader del programa falta adelante agregarle static const
ResponderEliminarosea quedaria de la siguiente manera
static const char okHeader[] PROGMEM =
compilen y con eso deberia funcionar
Espero les aya sido de ayuda
Muchas gracias,
EliminarHola, me cambia el estado del led internamente en la pagina, muestra el 0 y el 1, sin embargo no prende fisicamente el led, lo asigne al pin 2 igual, pero igual nada. No se que puede ser?
ResponderEliminar