17 oct 2012

Programar un Microcontrolador en Linux (Ubuntu)




Pues de nuevo me encuentro escribiendo un pequeño manual esperando ayudar a estudiantes que se hayan visto en el mismo problema que yo, que es el  programar un microcontrolador usando lenguaje C en una distribución de linux, en mi caso Ubuntu.

Para esto solo usaremos dos herramientas que ya están incluidas en nuestro sistema, las cuales son:
  • Un editor de texto plano (gedit, kate, etc.)
  • Terminal
Antes de empezar a programar debemos tener las herramientas necesarias para poder compilar y crear nuestros archivo .hex que es el que usaremos para programar el microcontrolador.

Instalamos lo siguiente:

sudo apt-get install avr-libc binutils-avr avrdude gcc gcc-avr

Ahora si, ya podemos empezar a programar. 
Para ver la manera de compilar nuestro programa y generar el archivo .hex desde la terminal, haremos un programa sencillo que enciende y apaga un led.

Abrimos nuestro editor de texto y copiamos el siguiente codigo:

#include <avr/io.h>
#include <avr/iom8535.h> //biblioteca para el atmega8535
#define F_CPU 1000000UL
#include <util/delay.h>

int main(void)
{
DDRB = 0x01; //pone portb para salida
while(1){
PORTB = 0b00000001; //prende el led inicialmente
_delay_ms(250); //esperamos 250 mili-segundos
PORTB = 0b00000000; //apaga el led
_delay_ms(250); //esperamos 250 mili-segundos
}
return 1;
}

Por el momento no explicaré el código, ya que el motivo de este tutorial es para compilar y crear el archivo .hex usando una distribución de Linux.

Para compilar nuestro programa nos dirigimos a la ubicación donde hemos guardado nuestro archivo, una vez estando ahí abrimos una terminal y escribimos lo siguiente:

avr-gcc -mmcu=atmega8535 nombre_programa.c -o nombre_salida

Notemos que -mmcu=atmega8535 es el microcontrolador en el cual cargaré el .hex, dependiendo del microcontrolador que vayan a usar será el nombre que deberán incluir.

-mmcu=nombre_del_uc_a_usar

Si nuestro programa no generó errores es hora de pasar a la creación de nuestro .hex, para esto en la terminal escribimos lo siguiente.

avr-objcopy -O ihex nombre_salida source.hex 

Y con esto hemos generado nuestro archivo .hex que será el que programaremos en el microcontrolador.

Para ver su funcionamiento podemos hacer uso de Proteus , esto lo explicaré posteriormente en mi canal de youtube.

Espero que este pequeño tutorial haya sido de ayuda. 
Hasta la próxima... 








11 sept 2012

Servidor-UDP en C

Ahora es turno de mostrar el código fuente de nuestro servidor no orientado a conexión.
El código es sencillo de entender por lo que no considero necesario explicarlo.

/*************************************************************
* Prueba de un Servidor NO orientada a conexion (UDP)
*************************************************************/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//variables globales para el servidor
#define MAXBUFFER 100

struct sockaddr_in my_direcc; //contendra la direccion ip y el puerto del servidor
struct sockaddr_in client; //contendra la direccion ip y el puerto del cliente
int sockfd,addr_len;
int MYPORT;
char buffer[MAXBUFFER];
char sendBuffer[MAXBUFFER];
//creamos el socket
void crearSocket()
{
if((sockfd = socket(AF_INET,SOCK_DGRAM,0))==-1){
perror("Socket");
exit(1);
}
}

void atributos()
{
my_direcc.sin_family = AF_INET;
my_direcc.sin_port = htons(MYPORT);
my_direcc.sin_addr.s_addr = INADDR_ANY; //se usa la ip local, permite conexiones de cualquier direccion
bzero(&(my_direcc.sin_zero),8);
}

void socket_name()
{
if(bind(sockfd,(struct sockaddr*)&my_direcc,sizeof(struct sockaddr))==-1){
perror("bind");
exit(1);
}
}

void recibir()
{
addr_len = sizeof(struct sockaddr);
if(recvfrom(sockfd,buffer,MAXBUFFER,0,(struct sockaddr*)&client,(socklen_t*)&addr_len)==-1){
perror("Recibir");
exit(1);
}
else{
printf("%s \n",buffer);
printf("direction IP: %s \t",inet_ntoa(client.sin_addr));
printf("PORT: %d \n",MYPORT);
}
}

void enviarDato()
{
sprintf(sendBuffer,"confirmation of message received");
if(sendto(sockfd,sendBuffer,MAXBUFFER,0,(struct sockaddr*)&client,sizeof(struct sockaddr))<0){
perror("function sendto");
exit(1);
}
}

void cerrarSocket()
{
close(sockfd);
}

int main(int argc, char *argv[])
{
if(argc > 1)
{
MYPORT = atoi(argv[1]);
crearSocket();
atributos();
socket_name();
recibir();
enviarDato();
cerrarSocket();
}
else
printf("Error: invalid arguments\n");
return 1;
} 

Como podrán observar nuestro servidor requiere de 2 argumentos que le debemos indicar desde linea de comandos, los cuales son:

  • Nombre del programa.
  • Puerto, que es por donde se transmitirá la información.
Y así doy por finalizado este sencillo tutorial donde se llevo acabo la creación de un cliente-servidor no orientado a conexión bajo una distribución de Linux, en este caso Ubuntu 10.04, espero que les haya servido de algo.
Hasta la próxima . . . 

Cliente-UDP en C

Lo prometido es deuda, el código fuente que a continuación se muestra es para crear nuestro cliente NO orientado a conexión.
No explicaré el código, pues las funciones usadas en este programa fueron explicadas  en este apartado.

Código fuente:

/*****************************************************************
* Prueba de un Cliente NO orientada a conexion (UDP)
*****************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

//longitud máxima del buffer
#define MAX_BUFFER 1000
//atributos para el uso del socket
char sendBuffer[MAX_BUFFER];
char recvBuffer[MAX_BUFFER];
int direccIP;
int PORT;
int sockfd;
int sock_len;
struct sockaddr_in serv_addr; //informacion de la direccion de destino
size_t len;

void crearSocket()
{
if((sockfd = socket(AF_INET,SOCK_DGRAM,0))==-1){
perror("Socket");
exit(1);
}
}

void atributos()
{
//atributos del servidor
  len = sizeof(struct sockaddr_in);
  serv_addr.sin_family = AF_INET;    // Ordenación de bytes de la máquina 
  serv_addr.sin_port = htons(PORT);  // short, Ordenación de bytes de la red 
  serv_addr.sin_addr.s_addr = direccIP;
}

void enviarDato()
{ //enviamos el mensaje 'hello world'
sprintf(sendBuffer,"hello world");
if(sendto(sockfd,sendBuffer,strlen(sendBuffer),0,(struct sockaddr*)&serv_addr,len)<0){
perror("function sendto");
exit(1);
}
}

void recibirDato()
{ //recibimos la respuesta del servidor
sock_len = sizeof(struct sockaddr);
if(recvfrom(sockfd,recvBuffer,MAX_BUFFER,0,(struct sockaddr*)&serv_addr,(socklen_t*)&sock_len)<0){
perror("function recvfrom");
exit(1);
}
else
printf("%s \n",recvBuffer);
}

void cerrarSocket()
{
close(sockfd);
}

int main(int argc,char *argv[])
{
if(argc > 1){
direccIP = inet_addr(argv[1]);
PORT = atoi(argv[2]);
crearSocket();
atributos();
enviarDato();
recibirDato();
cerrarSocket();
}
else
{
printf("Error: intent ./name_program direction_IP port\n");
}

Como podrán observar el programa recibe 3 parámetros desde linea de comandos  que son:
  • Nombre del programa.
  • Dirección IP de la PC con la deseamos hacer la comunicación.
  • Puerto por el cual se transmitirá la información.

6 sept 2012

26 ago 2012

Creación de un applet animado

En esta ocasión crearemos un applet sencillo, donde se muestra la animación de una pelota que se desplaza en el eje X.
Antes de mostrar el código daremos un pequeño resumen de las funciones que se utilizaron para esta animación.

¿Que es un applet?
Un applet desde el punto de vista de código java lo podemos definir como un pequeño programa diseñado para ser ejecutado en el contexto de una página web y desde el punto de vista de una página html representa una pequeña ventana gráfica dentro de la misma.

Un applet se carga y se ejecuta desde cualquier explorador que soporte java.

Creación de un applet
Para crear un applet, únicamente necesitamos escribir una clase que derive de la clase Applet que se encuentra en el paquete java.applet

Los métodos para crear nuestra animación son los siguientes:

public void init():  este método es llamado una sola vez cuando se carga el applet, es usado generalmente para cargar los componentes del applet, por ejemplo: cargar las imágenes y sonidos, crear los botones, etiquetas, etc.

public void start(): este método sera llamado cada vez que se inicie la ejecución del applet. Esto es después de que se ejecute el método init() y cada vez que se vuelva a mostrar la página web que muestra el applet.

public void stop(): Este método es llamado para informar al applet que su ejecución va a ser detenida. Esto ocurre siempre que la página que muestra el applet es remplazado por otra página y justo antes de que sea destruido.

public void paint(): La clase Applet hereda este método de la clase Container. Es llamado cada vez que es necesario repintar el contenedor del applet, es decir;  el área de dibujo. El parámetro g  de la clase Graphics que pertenece al paquete java.awt, hace referencia a la ventana gráfica.

Creación de la animación
Para hacer la animación de nuestro applet haremos uso de un hilo (Thread  - llamado también proceso ligero o subproceso ) no explicaremos lo que es un hilo, ya que no es nuestra intención alargar mas el tema. Los hilos en java se pueden crear de dos formas:

  •  Escribiendo una nueva clase derivada de Thread que se encuentra en el paquete java.awt.
  • Hacer que una clase existente implemente la interfaz Runnable.
Una clase que implemente la interfaz Runnable tiene que sobreescribir el método run  aportado por ésta. El método run deberá tener el código que debe ejecutar el hilo.


El código es el siguiente:

import java.awt.*;
import java.applet.*;

public class MiApplet extends Applet implements Runnable {
    Thread anima;  //creación del hilo 
    int radio=10;     //radio de la pelota
    int x, y;       //posición del centro de la pelota
    int dx = 1;     //desplazamiento en x
    int retardo = 50; 
    int anchoApplet;
    int altoApplet;

  public void init(){
    setBackground(Color.white);
//dimensiones del applet
    anchoApplet = getSize().width;
    altoApplet = getSize().height;
//posición inicial de partida
    x = anchoApplet/4;
    y = altoApplet/2;
  }

  public void start(){
     if(anima  == null){
        anima= new Thread(this);
        anima.start();
     }
  }

  public void stop(){
     if(anima != null){
        anima = null;
     }
  }

  public void run(){
    while (true) {
        mover();
        try{
        Thread.sleep(retardo);
        }catch(InterruptedException e){
        break;
        }
    }
  }
  void mover(){
    x += dx;
    if (x >= (anchoApplet-radio) || x < radio) dx*= -1;
    repaint();   //llama a paint
  }

  public void paint(Graphics g){
    g.setColor(Color.red);
    g.fillOval(x-radio, y-radio, 2*radio, 2*radio);
  }
}

19 ago 2012

cliente-servidor UDP en Linux

El primer ejemplo que mostraré es la creación de un cliente servidor NO orientado a conexión (UDP).
Para esto haremos uso del lenguaje C y del manejo de sockets.

Creación del Cliente :
Un cliente NO orientado a conexión sigue la siguiente estructura:

Creación del servidor:
El servidor NO orientado a conexión sigue la siguiente estructura:

 Para crear un cliente-servidor debemos de saber que es un socket, así que antes de empezar a programar daremos un pequeño resumen de las funciones mencionadas anteriormente.

¿Qué es un socket?
De manera sencilla diremos que un socket es un conector electrónico por el cual dos programas pueden intercambiar datos de forma correcta.

Para lograr la comunicación del cliente con el servidor debemos crear el socket, para esto haremos uso de la función socket(), esta función retorna un descriptor de socket que es de tipo int.

sockfd = socket(int dominio, int tipo, int protocolo):

    sockfd: es el descriptor del socket devuelto, lo utilizaremos para recibir y enviar datos.
    dominio: dominio donde se realiza la conexión, para este ejemplo usaremos AF_INET
    tipo: Especifica la semántica de la comunicación, sus valores mas comunes son SOCK_STREAM  si es orientado a conexión (TCP) y SOCK_DGRAM si NO es orientado a conexión (UDP).
    protocolo: Protocolo particular para ser usado con el conector, generalmente usaremos el valor de 0.

Si tiene éxito, la función devuelve un int que indica el valor del conector. En caso de error el valor es -1.

para hacer uso de la función socket() debemos incluir las bibliotecas :
#include <sys/types.h>
#include <sys/socket.h>


La función bind()  asocia el socket dado por sockfd a la dirección especificada por addr.
 bind(int sockfd, struct sockaddr* addr, int addrlen)

sockfd: Descriptor del socket creado con anterioridad.
addr: Estructura de datos en la que se define la dirección y el puerto al que se asocia el socket.
addrlen: Longitud de la estructura de datos anterior.

La estructura sockaddr no suele ser utilizada, es mas común encontrarse con sockaddr_in, cuya descripción se muestra a continuación:

struct in_addr{
  unsigned long int s_addr;
}

struct sockaddr_in{
  int sin_family;
  unsigned short int sin_port;
  struct in_addr sin_addr;

sin_family: Dominio de comunicaciones del socket (generalmente AF_INET).
sin_port: Puerto al que se asocia el socket.
sin_addr.s_addr: Dirección IP a la que se asocia el socket. 

En caso de error la funcion bind() retorna -1, para hacer uso de esta función debemos incluir las siguientes bibliotecas:

#include <sys/types.h>
#include <sys/socket.h>

La función
sendto(int sockfd, const void *buf, int lonbuf, int flags, const struct sockaddr*addr, int lonaddr); 

Esta función escribe "buflen" bytes de datos mediante el socket especificado por sockfd.

sockfd: Descriptor del socket creado con anterioridad.
buf: Puntero a buffer, buf contiene los datos a escribir en el socket.
lonbuf:  Longitud de los datos a enviar.
flags: Opciones de envío, por lo general se usa el valor de 0.
addr: Estructura que contiene la dirección y el puerto por el cual se va a enviar la información.
lonaddr: Longitud de la estructura de datos anterior.

En caso de error la función sendto() retorna -1, para poder usar esta función debemos incluir las siguientes bibliotecas.

#include <sys/types.h>
#include <sys/socket.h>

 La función

recvfrom(int sockfd, const void *buf, int lonbuf,int flags, const struct sockaddr *from, int lonfrom );

Esta función almacena los datos recibidos en buf, estos datos provienen de la dirección ip contenida en la estructura from.

sockfd: Descriptor del socket creado con anterioridad.
buf: Puntero a buffer, buf contiene los datos recibidos.
lonbuf: Longitud de los datos recibidos.
flags: Opciones de recepción, generalmente 0.
from: Estructura de datos que contiene la dirección IP y el puerto por el cual se han enviado los datos a recibir.
lonfrom: Longitud de la estructura de datos anterior.

Para poder usar esta función debemos incluir las bibliotecas:

#include <sys/types.h>
#include <sys/socket.h>

la función close(int sockfd);
es la mas sencilla de entender, recibe como argumento el descriptor del socket que queremos cerrar. Esta función retorna 0 en caso de cerrar correctamente el socket, de no ser así retorna -1.
Para usar la función close()  debemos incluir la biblioteca

#include <unistd.h>


. . . y así doy por finalizado este pequeño tutorial, pero pronto publicaré el código fuente que implementa tanto al cliente como al servidor.




Bienvenido