Porta Serial RS-232C: Software e Hardware

 

Prof. Eduardo Augusto Bezerra <eduardob@inf.pucrs.br>

Faculdade de Informática e Faculdade de Engenharia, PUCRS

Porto Alegre, Agosto de 2004

http://www.inf.pucrs.br/~eduardob/



Prof. Eduardo Augusto Bezerra <Eduardo.Bezerra@ufsc.br>


Departamento de Engenharia Elétrica e Eletrônica, UFSC


http://gse.ufsc.br/bezerra/

 

Florianópolis, Março de 2021

 



1. Acesso às portas de entrada/saída usando a linguagem C/C++

 

·        Nessa seção é utilizada a abordagem botton-up na apresentação dos exemplos de programa nas linguagens C e C++ para acesso às portas serial (RS-232C) e paralela de um computador pessoal.

 

Porta Serial RS-232C

acesso direto ao hardware – inportb, outportb

linguagem C – MS-DOS/Windows 9x

 

·        O primeiro exemplo, listado a seguir, usa a porta serial via acesso direto ao hardware do computador, e os exemplos seguintes utilizam recursos de mais alto nível como, por exemplo, interrupções e chamadas de sistema (function call). O sistema operacional e compilador utilizados estão identificados nos comentários no início do programa.

 

Obs. Uma chamada de sistema é uma rotina implementada em software, fazendo parte do sistema operacional ou como um driver, que é utilizada pelo sistema operacional ou pela aplicação para acesso ao hardware. Uma chamada de sistema pode solicitar uma interrupção, que por sua vez é originada no firmware do computador pessoal, ou fornecida pelo driver em software. A função tanto da chamada de sistema quanto da interrupção é a mesma, ou seja, chegar na interface a nível de hardware e utilizar características específicas dessa porta de entrada e saída.


 

/*

       serial_io.c

      

       Programa em C para gerencia da porta serial RS-232C utilizando acesso direto

ao hardware pelas instrucoes in e out.

      

       Eduardo Augusto Bezerra, Maio de 2003

      

       compilador Turbo C++ versao 1.0 (Borland)

*/

#include <stdio.h>

#include <dos.h>

#include <process.h>

#include <conio.h>

#define end_ctrl_50  0x03FD        /* Enderecos da UART 8250 */

#define end_dado_50  0x03F8

#define LRC                0x03FB

#define MSB                0x03F9

#define LSB                0x03F8

#define MCR                0x03FC

#define LSR                0x03FD

#define MSR                0x03FE

#define IOR                0x03F8

#define IIR                0x03FA

#define IER                0x03F9

 

void inic8250(){                         /* inicializacao da 8250   */

       outportb(LRC, 0x80);       /* DLAB = 1, programa velocidade em MSB e LSB */

       outportb(MSB, 0x00);      

       outportb(LSB, 0x0C);       /* 00H 0CH == 9600 bps */

       outportb(LRC, 0x07);              /* 8 bits de dados, 1 stop bit, sem paridade */

}     

 

void reseta8250(){                       /* reseta a 8250     */

       inportb(LSR);

       inportb(MSR);

       inportb(IOR);

       inportb(IIR);

}     

 

void enable8250(){                       /* habilita a 8250   */

       outportb(IER, 0x01);

}     

 

void disable8250(){                      /* desabilita interrupcoes da 8250 */

       outportb(IER, 0x00);

}     

 

void transm_dado(unsigned char caracter){              /* transmite um caracter */

       while (!(32 & inportb(end_ctrl_50)) == 32);

       outportb(end_dado_50, caracter);

}

 

unsigned char status(){                  /* Le status da 8250 */

       return (inportb(end_ctrl_50) & 0x01);

}

 

int main(){

       int opcao = 0;

       unsigned char caracter = '';

       unsigned char aux = '';

      

       inic8250();

       reseta8250();

       outportb(IER, 0x00);       /* sem interrupcoes */

       while (opcao != 4){

              clrscr();

              printf("Entre com:\n");

              printf("\t\t\t1 - Transmitir um caracter pela serial\n");

              printf("\t\t\t2 - Receber um caracter pela serial\n");

              printf("\t\t\t3 - Transmitir arquivo pela serial\n");

              printf("\t\t\t4 - Sair do programa\n");

              opcao = getch() - '0';

              caracter = '';

              /* transmissao de um caracter */

              if (opcao == 1)

                     while (caracter != 0x1B){         /* repete ate' pressionar ESC */

                           disable8250();

                           printf("\nEntre com o carcter a ser transmitido ... ");

                           caracter = getch();

                           printf("%c", caracter);

                           transm_dado(caracter);            /* envia um caracter */

                     }

              /* recepcao de um caracter */

              if (opcao == 2){

                     printf("\n\nAguardando caracter na porta serial ... ");

                     for (;;){

                           while(!status()) if (kbhit()) break;

                           if (kbhit() && getch()) break;

                           aux = inportb(end_dado_50); /* recebe um caracter */

                           printf("\nRecebido o caracter --> %c", aux);

                     }

              }

              /* transmissao de arquivo */

              if (opcao == 3){

                     FILE *fp;

                     char arq[20];

                     printf("\n\nNome do arquivo: "); gets(arq);

                     if (!(fp = fopen(arq, "r"))){

                           printf("\nArquivo nao existe!");

                           exit(-1);

                     }

                     while(!feof(fp)){          /* transmite arquivo */

                           caracter = fgetc(fp);

                           disable8250();

                           transm_dado(caracter);

                           if (status()) putch(inportb(end_dado_50));

                     }

                     fclose(fp);

                     printf("\nPressione qualquer tecla para o menu.");

                     while(!kbhit());

              }

       }

    return 0;

}


 

·        A função outportb (int porta, unsigned char valor); envia para o endereço especificado em porta um byte especificado em valor. A função inportb (int porta); le um byte de um endereço especificado em porta. Com essas duas funcoes é possível acessar todos os registradores da 8250, enviando palavras de controle para sua programação, bem como enviando e recebendo bytes da interface RS-232C. Os endereços utilizados no programa acima foram discutidos na seção 1 (portas de entrada/saida, porta serial RS-232C em detalhes).

 

 

Porta Serial RS-232C

Uso de interrupcoes – int 14H

linguagem C – MS-DOS/Windows 9x

 

 

·        Outra forma de acessar a UART 8250 é por intermédio dos serviços da ROM-BIOS (interrupção 14H da BIOS), listados na tabela a seguir:

 

 

 

INT 14H

Entrada

Saida

1

Inicializa parametros da porta serial

AL = parametro

AH = 00

DX = nr. da porta.

AX = status da porta

2

Transmite um caracter

AL = caracter

AH = 01

DX = nr. da porta

 

AH = status: passa/falha

3

Recebe um caracter

AH = 02

DX = nr. da porta

AH = status: passa/falha

AL = caracter

4

Obtem status da porta serial

AH = 03

DX = nr. da porta

AH = codigo de status

 

 

 

 

Inicialização – AL:

7

6

5

4

3

2

1

0

 

Bits    0 .. 1  : tamanho da palavra                           10 = 7 bits

                                                                              11 = 8 bits

 

Bit     2        : stop bits                                              0 = 1 stop bit

                                                                                1 = 2 stop bits

 

Bits    3 .. 4  : paridade                                      00, 10 = sem paridade

                                                                               01 = paridade impar

                                                                               11 = paridade par

 

Bits    5 .. 7  : taxa de transferencia                         000 = 110 bps

                                                                             001 = 150 bps

                                                                             010 = 300 bps

                                                                             011 = 600 bps

                                                                             100 = 1200 bps

                                                                             101 = 2400 bps

                                                                             110 = 4800 bps

                                                                             111 = 9600 bps

 

·        No exemplo a seguir a 8250 é programada para transferências a 9600 bps, 1 stop bit, 8 bits de dados e sem paridade.

 

 


/*

       serial_bios.c

      

       Programa em C para gerencia da porta serial RS-232C

       utilizando a INT 14H da BIOS.

      

       Eduardo Augusto Bezerra

       Maio de 2003

      

       compilador Turbo C++ versao 1.0 (Borland)

*/

#include <stdio.h>

#include <dos.h>

#include <conio.h>

#define SERIAL 0x14

#define ESC 0x1B

 

int main(){

       union REGS r;

       unsigned char caracter = '';

                                                       /*  7654321                     */

       r.h.ah = 0x000;                                 /*  11100011   9600 bps,        */

       r.h.al = 0x0E3;                                 /*     =       8 bits de dados, */

       r.x.dx = 0x000;                                 /*    E3H      1 stop bit,      */

       int86(SERIAL, &r, &r);                          /*             sem paridade     */

 

       while (caracter != ESC)    {

              printf ("\nEntre com o caracter: ");

              caracter = getch();

              printf("%c", caracter);

              r.h.ah = 1;                       /* AH = 1, transmite caracter */

              r.h.al = caracter;

              r.x.dx = 0;

              int86(SERIAL, &r, &r);            /* Transmite o caracter */

       }

    return 0;

}


 

·        A função int int86(int nr. interrupção, union REGS *inregs, union REGS *outregs); realiza um pedido de interrupção para a CPU. Essa segunda forma é bem mais simples do que o acesso direto à 8250 mostrado anteriormente.

 

 

Porta Serial RS-232C

acesso direto ao hardware – inb, outb

linguagem C – Linux

 

·         A listagem do programa para Linux a seguir apresenta uma versao resumida do codigo listado anteriormente para utilizacao da porta serial, via acesso direto ao hardware.

 


/*

       serial_io.c

      

       Programa em C para gerencia da porta serial RS-232C

       utilizando acesso direto ao hardware pelas instrucoes

       in e out.

      

       Eduardo Augusto Bezerra

       Maio de 2003

      

       compilador gcc version 3.2 20020903 (Red Hat Linux 8.0 3.2-7)

*/

#include <stdio.h>

#include <stdlib.h>

#include <sys/io.h>

#include <unistd.h>

#include <malloc.h>

#include <string.h>

 

#define end_ctrl_50  0x03FD        /* Enderecos da UART 8250 */

#define end_dado_50  0x03F8

#define LRC          0x03FB

#define MSB          0x03F9

#define LSB          0x03F8

#define MCR          0x03FC

#define LSR          0x03FD

#define MSR          0x03FE

#define IOR          0x03F8

#define IIR          0x03FA

#define IER          0x03F9

 

int main(){

       unsigned char caracter = ' ';

       int a;

       a = setuid(0);

       printf("setuid = %d\n", a);

       if (ioperm(end_dado_50, 2, 1)) {

             perror("ioperm");

             printf("Erro: Nao liberou a porta serial!");

       }

       /* inicializacao da 8250 */

       outb(0x80, LRC);           /* 8 bits de dados */

       outb(0x00, MSB);           /* 1 stop bit           */

       outb(0x0C, LSB);           /* sem paridade         */

       outb(0x07, LRC);

       /* reseta a 8250     */

       inb(LSR); inb(MSR); inb(IOR); inb(IIR);

       outb(0x00, IER);           /* sem interrupcoes */

       caracter = ' ';

       /* transmissao de um caracter */

       while (caracter != 0x1B){     /* repete ate' pressionar ESC */

              printf("\nEntre com o caracter a ser transmitido ... ");

              scanf("%c", &caracter);

              printf("%c", caracter);

              outb(caracter, end_dado_50);      /* envia um caracter */

       }

       return 0;

}

 

·         A porta serial RS-232C nao pode ser acessada diretamente por usuarios comuns. Apenas usuarios pertencente ao grupo uucp possuem acesso a essa porta. Uma solucao e desenvolver uma aplicacao ou driver que seja executado, por exemplo, em background como um daemon, e que responda a chamadas de sistema realizadas por programas dos usuarios. Essa aplicacao devera ser disparada por um usuario do grupo uucp de preferencia na inicializacao do sistema.

 

·         A solucao utilizada para o exemplo listado anteriormente, foi a criacao de um usuario especial pertencente ao grupo uucp, e a execucao do programa realizada por esse usuario.

 

·         Como o programa utiliza acesso direto ao hardware via instrucoes inb e outb, apenas usuarios pertencentes ao grupo root possuem permissao para executar esse programa. Uma solucao para possibilitar a execucao por usuarios comuns (no caso o usuario pertencente ao grupo uucp), foi a utilizacao da funcao setuid na linha 35. Essa funcao altera a identidade do processo atual (process ID) para o valor passado como argumento. No caso o valor 0 informa ao Linux que o processo pertence ao root. Nesse caso um usuario root tera que compilar o programa, e logo a seguir alterar as permissoes do arquivo para 4755 (chmod 4755 nome_do_arquivo_executavel). Isso possibilitara que um usuario comum execute o programa com funcoes para acesso direto ao hardware.

 

·         A funcao ioperm na linha 37 e utilizada para fornecer acesso a portas para usuarios que nao possui privilegios de root (ver man ioperm para maiores informacoes).

 

Porta Serial RS-232C

Acesso via descritores de arquivos – open/read/write/close

linguagem C++ e Sistema Operacional Linux

 

 

·         A listagem a seguir apresenta a implementacao para as funcoes membro da classe RobotLinux, utilizada para controlar o braco robo que e um dos exemplos utilizados na disciplina. O computador pessoal se comunica com o circuito de controle do braco robo via porta serial RS-232C.

 

 

 


/************************************************************

 * File RobotLinux.cpp - Implementation for the RobotLinux class

 *

 * This class has the implementation for virtual

 * methods from Robot.h (and Robot.cpp)

 *

 * Project: Fischer Arm

 *

 * Author: Eduardo Augusto Bezerra

 * Date: 04/04/2003

 *

 * Last change: Eduardo Augusto Bezerra

 * Date: 26/04/2003

 *

 * Methods for controlling the robot in C++ under linux

 * This code has been tested on linux Red Hat 8.0

 *

 *************************************************************/

 

#include "RobotLinux.h"

 

/************************************************************

 * Constructor

 *************************************************************/

RobotLinux::RobotLinux(void){

   motorWord = 0;

   fd = -1;

}

/************************************************************

 * Destructor

 *************************************************************/

RobotLinux::~RobotLinux(void){

   close(fd);

}

 

/************************************************************

 * void RobotLinux::openSerial(int ser)

 *

 * open the serial connection;

 * sets the serial parameters to 9600 Baud, no parity, 8, 1;

 * and turns all motors off

 *

 *************************************************************/

void RobotLinux::openSerial(int ser){

   // serial names

   const char *com1="/dev/ttyS0", *com2="/dev/ttyS1",

              *com3="/dev/ttyS2", *com4="/dev/ttyS3";

 

   struct termios options;

 

   switch(ser) {

        case 1: strcpy(serial,com1);

                break;

        case 2: strcpy(serial,com2);

                break;

        case 3: strcpy(serial,com3);

                break;

        case 4: strcpy(serial,com4);

                break;

        default: cout << "Error! valid ports are 1, 2, 3 and 4. "

                      << "Will try to open port 1." << endl;

      }

 

   fd = open(serial, O_RDWR|O_NOCTTY|O_NDELAY);

   if (fd == -1)      // ERROR!!

      cout << "Error opening " << serial << endl;

   else

      fcntl(fd, F_SETFL, 0);

   cout << "Serial port in use: " << serial << endl << endl;

 

   // Program serial port to 9600, 8, 1, no parity

   //

 

   // Get the current options for the port

   tcgetattr(fd, &options);

 

   // Set the baud rate to 9600

   cfsetispeed(&options, B9600);

   cfsetospeed(&options, B9600);

 

   // Enable the receiver and set local mode

   options.c_cflag |= (CLOCAL | CREAD);

 

   // Setting parity checking (no parity) 8N1

   options.c_cflag &= ~PARENB;        /* no parity */

   options.c_cflag &= ~CSTOPB;        /* 1 stop bit */

   options.c_cflag &= ~CSIZE;         /* Mask the character size bits */

   options.c_cflag |= CS8;            /* Select 8 data bits */

  

   // Setting raw input

   options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

 

   // Setting raw output

   options.c_oflag &= ~OPOST;

 

   // Set the new options for the port

   tcsetattr(fd, TCSANOW, &options);

 

   motorsOff();                // motors off

}

 

/************************************************************

 * char sendCommand(char motorWord)

 *

 * gets a full word representing all inputs (1..8)

 *************************************************************/

char RobotLinux::sendCommand(char motorWord){

 

   char commandWord[2];

   commandWord[0] = '\xc1';         // 1st byte: 193 in hexadecimal

   commandWord[1] = motorWord;      // 2nd byte: motorWord

   int i;

 

   if (fd == -1)

      cout << "Erro: the serial port is closed. Please, "

           << "use the openSerial() method to open it. " << endl;

   else{

      int n = write(fd, commandWord, 2);  // send 2 bytes command & motors

      if (n < 0)

         cout << "Error! write() command and motor bytes failed." << endl;

      else {

         fcntl(fd, F_SETFL, FNDELAY);

         i = read(fd, commandWord, 1); // read 1 Byte interface status

         fcntl(fd, F_SETFL, 0);

         commandWord[1] = 0;      /* set end of string, so we can printf */  

      }

   }

   return commandWord[0];

}


 

·         De forma semelhante ao exemplo de acesso direto ao hardware, a solucao utilizada no caso da aplicacao para controle do braco robo foi a criacao de um usuario especial pertencente ao grupo uucp, e a execucao dos programas para acesso a serial (ao braco robo) realizada por esse usuario.

 

·         No programa anterior, nas linhas 46 e 47 estao listados os nomes dos arquivos que identificam as portas seriais com1 a com 4 no Linux. Esses nomes substituem os antigos /dev/cua0 a /dev/cua3.

 

·         Uma das portas (1, 2, 3 ou 4) e aberta na linha 64, de acordo com a selecao do usuario. O flag O_RDWR faz com que a porta seja aberta para entrada e saida. O flag O_NOCTTY garante que o programa nao sera o “terminal em controle” da porta. Se esse flag nao for utilizado, outras entradas de dados (ex. ^C enviado pelo teclado) pode afetar o programa. O flag O_NDELAY avisa ao Linux que o programa ira ignorar o sinal DCD da RS-232C. Se esse flag nao for utilizado, o processo ficara desativado ate que o outro lado da comunicacao ative o pino DCD (coloque 0 nesse pino).

·         A funcao fcntl na linha 68 e utilizada para configurar a porta serial para possiveis operacoes de leitura. O flag F_SETFL e utilizado em conjunto com o terceiro argumento para ativar ou desativar o modo de leitura da porta. Ao se utilizar 0 como terceiro argumento na funcao fcntl, uma operacao de leitura na porta serial (read) ira bloquear a execucao do programa ate que um carcter seja recebido, um intervalo de tempo expire, ou um erro ocorra. Para realizar leituras nao bloqueantes na serial, utlizar o flag FNDELAY, no lugar do 0.

·         A funcao tcgetattr na linha 75 e utilizada para ler os parametros associados ao descritor de arquivo fd (no caso a porta serial aberta), e armazena-los na variavel options. Esses dados correspondem ao status atual da porta serial.

·        Logo a seguir, na linha 78, a funcao cfsetispeed e utilizada para programar a porta serial para velocidade de recepcao de 9600 bps. Na linha seguinte a funcao cfsetospeed e utilizada para programar a porta serial para velocidade de transmissao de 9600 bps.

·        Nas linhas seguintes os demais parametros para a comunicacao serial sao armazenados no registro options. A porta serial do braco robo esta configurada para comunicacao a 9600 bps, com 8 bits de dados, 1 stop bit e sem paridade.

·        A funcao tcsetattr na linha 97 realiza a escrita do registro options, programando assim a UART do computador pessoal de acordo com os dados do protocolo estabelecido pelo circuito do braco robo.

·        O envio de comandos para o braco robo e realizado na linha 118 por intermedio da funcao write que envia o comando a ser realizado, utilizando para isso o descritor do arquivo aberto na linha 64. A funcao write funcao o numero de bytes enviados, ou –1 caso tenha ocorrido um erro.

·        Notar o uso do flag FNDELAY na funcao fcntl (linha 122) para configurar a operacao de leitura nao-bloqueante do status da serial. Esse flag faz com que a funcao read retorne 0, caso nao existam dados disponiveis para serem lidos na porta serial.

 

·        A seguir sao apresentados programas para acesso a porta paralela. Caso os programas nao consigam escrever/ler o dado desejado na porta, verificar as possiveis causas:

 

o       Escrita no endereco errado (378H equivale a 888 em decimal).

o       O cabo/conectores podem estar ligados de forma incorreta. Verificar!

o       O dispositivo conectado a porta esta causando o problema. Desconectar o dispositivo, e medir os bits da porta para ver se eles estao sendo alterados corretamente pelo programa no computador pessoal.

o       Os bits 0, 1 e 3 no registrador de controle das portas sao invertidos entre o registrador e o conector. Ao se escrever no registrador de controle, esses bits apareceram nos pinos do conector com valores invertidos em relacao aos escritos.

o       A porta suporta modo PS/2 e foi escrito 1 no bit 5 do registrador de controle. Isso desabilita a porta para saida de dados. Escrever 0 no bit 5 do registrador de controle para habilitar a saida.

o       Um driver de baixo-nivel do Windows esta proibindo o acesso a porta.

 

·        Caso o valor lido da porta nao e o esperado verificar, alem dos itens acima:

 

o       Os bits 0, 1 e 3 no registrador de controle das portas, e o bit 7 do registrador de status sao invertidos entre o conector e os respectivos registradores. Ao se ler desses registradores, os bits mencionados possuirao valores invertidos em relacao aos existentes nos pinos do conector.

o       A porta nao aceita o modo PS/2 e nao e possivel desabilitar o modo de saida (unidirecional). O valor lido sera sempre o ultimo valor escrito.

o       A porta suporta o modo PS/2, mas o bit 5 do registrador de controle nao foi setado para 1 de forma a desabilitar o modo de saida da porta. Escrever 1 nesse bit de forma a habilitar a leitura nos pinos de dados da porta.

 

 

 

 

Porta Serial RS-232C

Acesso via API – commapi

linguagem Java – Win32 e Solaris

 

 

·         A commapi e uma API que pode ser utilizada por desenvolvedores em programas em Java para acesso as portas de entrada e saida (paralela e serial). Os arquivos dessa API podem ser obtidos na pagina do curso (ver Exercicio 3 da aula pratica), e tambem dicas de instalacao e utilizacao.

 

·         Para instalar a commapi no Windows e preciso ter permissao de escrita no diretorio onde o jdk esta instalado. Para realizar a instalacao executar os seguintes passos (<jdk> e o caminho onde o jdk esta instalado):

 

o        Copiar o arquivo win32com.dll para o diretorio <jdk>\jre\bin

o        Copiar o arquivo comm.jar para o diretorio <jdk>\jre\lib\ext

o        Copiar o arquivo javax.comm.properties para o diretorio <jdk>\jre\lib

 

·         Uma dica extra e a execucao da aplicacao utilizando a virtual machine (java) que se encontra no mesmo diretorio do arquivo win32com.dll (<jdk>\jre\bin). O ambiente pode estar configurado para ser utilizado outro java, e nesse caso o programa nao funcionara corretamente.

 

·         A melhor forma de entender o funcionamento dessa API e por meio do estudo das aplicacoes exemplo que acompanham os arquivos. Um bom ponto de partida e a aplicacao “Serial Demo”. O arquivo README que acompanha essa aplicacao contem dicas de compilacao e utilizacao.

 

·         Na classe SerialConnection da aplicacao SerialDemo, observar:

 

o        O metodo openConnection(), na linha 90, abre uma porta serial.

o        O metodo closeConnection(), na linha 203, fecha uma porta serial liberando a mesma para uso por outra aplicacao.

o        O metodo setConnectionParameters(), na linha 167, utilizado para configurar (programar) a porta serial com os parametros fornecidos pelo usuario.

o        O metodo serialEvent(), na linha 255, utilizado para avisar a aplicacao sobre a chegada de dados na porta serial, e recepcao desses dados.

o        O metodo keyTyped(), na linha 330, utilizado para envio de dados para a porta serial. Cada caracter digitado na caixa de texto e enviado automaticamente para a porta serial aberta.

 

 

 

 

 

 

 

 

Porta Serial RS-232C

Acesso em Java via Java Native Interface (JNI)

linguagens Java, C++ – Win32 e Linux

 

 

Sockets

Acesso a dispositivo conectado a outro computador da rede

linguagem Java – Win32, Linux

 

 

Internet

Acesso usando browser com dispositivo conectado a
outro computador na Internet

linguagens HTML, Java, Servlet, C++ – J2EE, Win32 e Linux

 

 

·         As tres formas de acesso acima sao demonstradas com o auxilio da aplicacao WebRobot. Essa aplicacao utiliza esses tres conceitos, conforme mostrado no diagrama a seguir.

 

 

 

 

·         Todos os fontes que compoem essa aplicacao estao disponiveis para download em:

 

http://www.inf.pucrs.br/~eduardob/disciplinas/extensao/Robot/WebRobot/

 

·         Os seguintes diretorios contem os arquivos dessa aplicacao:

 

Client/

 

Contem robot_client.html que e o cliente em HTML. Notar na linha 141 a chamada ao programa servlet RobotServlet.class para passar o conteudo dos campos do formulario: <form method="POST" action="/robot/servlet/RobotServlet">. Essa chamada e realizada quando o usuario pressiona “Submit” no browser.

 

servlet/

 

Contem RoboServlet.java que e o programa em Java (servlet) a ser executado no servidor J2EE. Esse programa utiliza a classe HttpServletRequest para se comunicar com o cliente HTML. Por exemplo, para obter o conteudo do campo Acao do formulario, ou seja, movimento a ser realizado pelo braco robo, o programa utiliza: String userAcao = (String)request.getParameter("Acao");

 

O servlet tambem realiza a conexao via sockets a maquina onde o robo esta conectado. Para isso e preciso informar o endereco IP da maquina remota e a porta a ser utilizada (linhas 64 e 65):

 

      String serverURL = "200.17.91.157";

      int porta = 5001;

 

Apos isso basta criar a nova conexao socket (linha 73) e o stream de saida (linha 74):

     

      try{

          mySocket = new Socket(serverURL,porta);

          out = new DataOutputStream(mySocket.getOutputStream());

          in = new DataInputStream(mySocket.getInputStream());

 

O envio da string via sockets e realizado na linha 77:

 

          out.writeUTF(userName + "#" + userAcao);

 

Caso a maquina remota esteja desligada ou caso o servidor socket nao esteja em execucao naquela maquina, entao mensagens de erro sao fornecidas ao usuario (cliente HTML):

 

              }catch (UnknownHostException e) {

            outClient.println("<center><h2> ERRO: Nao encontrou host: ... </h2></center>");

      }catch (IOException e) {

            outClient.println("<center><h2>ERRO: Sem conexao de I/O para: </h2></center>");

      }

 

O arquivo HOW-TO-COMPILE-JAVAX.SERVLET.TXT contem dicas de como compilar o programa em java. O arquivo RobotServlet.class gerado deve ser colocado no servidor J2EE.

 

RobotSocketJNI/

 

Esse diretorio contem os programas em C++ utilizados para acesso a porta serial no Linux (vide descricao de um dos modulos desse programa fornecida anteriormente): Robot.h, Robot.cpp, RobotLinux.h, e RobotLinux.cpp. No programa em C++ RoboProxy.cpp, sao informadas as funcoes (metodos) a serem utilizados poelo programa em Java (JNI), que no caso sao openSerial e sendCommand. Notar a sintaxe JNI utilizada nesse programa para a definicao das funcoes. O arquivo RobotProxy.h e automaticamente gerado pelo compilador  javah a partir do RobotProxy.class (gerado a partir do Robot Proxy.java).

 

O principal programa desse diretorio e o RobotLinuxSocketserver.java. Essa classe implementa o servidor sockets, e possui tambem chamadas aos metodos nativos (JNI) para envio de comandos para o robo via porta serial. Notar o uso de robot  do tipo RobotProxy para acesso as funcoes em C++.

 

No main desse programa e instanciado o objeto socket:

 

RobotLinuxSocketserver socketServer = new RobotLinuxSocketserver();

 

O programa entra entao em um laco infinito aguardando por mensagem na porta 5001 utilizada pelo socket para comunicacao com o socket no servidor J2EE. Ao receber uma string do pela porta 5001, o programa extrai a acao a ser executada pelo braco robo, e envia o comando via chamada JNI para o programa em C++:

 

             char resp = socketServer.sendCommand(cmd);

 

O programa em C++ por sua vez envia os comandos para o braco robo, utilizando o protocolo definido pelo programa em execucao no microcontrolador no modulo de controle do braco robo: envio de dois bytes. O primeiro byte sempre devera ser 0xc1, seguido pelo byte contendo o comando a ser realizado.

 

Para compilar o programa, utilizar o usuario serial (do grupo uucp) e executar o Makefile:

 

make clean

make

 

Para executrar o servidor socket na maquina onde se encontra o braco robo, sempre como usuario serial, executar o Makefile:

 

make runServer

 

 

·         No mesmo endereco estao tambem arquivos com dicas de como realizar o deploy da aplicacao no servidor J2EE (deploytool_HOWTO.html), e tambem o codigo fonte em perl (perl_cgi) para processamento do formulario, caso nao tenha acesso a um servidor J2EE:

 

http://www.inf.pucrs.br/~eduardob/disciplinas/extensao/Robot/WebRobot/

 

·         Uma alternativa ao J2EE seria a utilizacao do Jboss (http://www.jboss.org), totalmente gratuito, que pode ser executado diretamente na maquina onde o braco robo se encontra. Nesse caso nao seria necessaria a comunicacao via sockets.

 

 

 

2. RS-232C via rádio (wireless)

 

 

·        Nesta placa temos a utilização de um módulo transmissor e um receptor.

 

·        Componentes da placa:

 

o       Conector DB9 (fêmea) utilizado para conectar na porta serial do computador, no caso na porta COM0, nota-se que são utilizador apenas os pinos necessários ficando os outros pinos soltos.

 

o       MAX232 Circuito Integrado utilizado para compatibilizar os níveis de tensão apresentados pela porta serial (-12V/+12V) com os níveis aceitos pelo transmissor e pelo receptor (+5 volts), a alimentação do MAX232 deve ser de +5V;

 

o       Capacitores são utilizados para permitirem o funcionamento correto do MAX232 conforme é apresentado em seu manual, existem dispositivos com a mesma função e que possuem estas capacitores internamente, tornando o circuito mais compacto;

 

o       Power é um conector que permite ligar as tensões necessárias ao funcionamento do receptor, transmissor e do MAX232;

 

o       Transmissor é o dispositivo que recebe as informações da serial de forma digital e envia para que os receptores possam utilizar os dados, o transmissor utilizado aqui é o TWS-433 que trabalha com tensões de 1,5 até 12V;

 

o       Receptor é o dispositivo que recebe as informações do transmissor e converte em sinais digitais os quais são enviados para a porta serial, o receptor utilizado é o RWS-433 que deve ter uma tensão de alimentação de +5V;

 

·        Para realizar uma comunicação com envio e recepção de dados cada um dos pontos deve ter um transmissor e um receptor;

 

·        Para adquirir um par transmissor e receptor são necessários em torno de US$7.00 (Brasil/SP).

 

·        As figuras a seguir mostram o diagrama de blocos do circuito e o layout da placa.




 




 

 

 

3. Alguns links de interesse

 

·        Outra opcao (alem da commapi) para comunicacao serial em Java:

 

http://www.frii.com/~jarvi/rxtx/download.html

 

·        Dicas para o desenvolvimento de aplicacoes para USB, bem como classes gratuitas para Java e C++:

 

http://jusb.sourceforge.net/

 

·        Muita informacao interessante:

 

http://www.beyondlogic.org/

 

·        Mais informacao:

 

http://www.cera2.com/WebID/software/index.htm

 

RS-232 Interfacing

 

 

 

 

Referencias Bibliograficas Utilizadas

 
 

·        “PC Intern – The Encyclopedia of System Programming”. Michael Tisher and Bruno Jennrich. Ed. Abacus, 1996, 985 pp.

 

Partes dessas notas de aula foram traduzidas diretamente desse livro.

 

·        “The Hardware Bible”. (Electronic Edition) Winn L. Rosch. SAMs Publishing, 1997.

 

Partes dessas notas de aula foram traduzidas diretamente desse livro.

 

·        Muito material da internet!