Posts Tagged ‘C’

Sistema de controle com PIC e porta Serial (rs232) parte 2

0saves

Hoje vou mostrar como fazer a parte do PC para se conectar com o PIC , e tem algumas alteraçoes no codigo do pic tambem.
Não vou entrar em muitos detalhes sobre o codigo do PIC pois este era o foco da parte 1
Segue o codigo:

#include "16f628a.h"                           // Inclui o cabeçalho especifico do pic a ser utilizado
#include "stdio.h"                              // Inclui as funçoes padroes de entrada e saida
#fuses HS,NOWDT,NOPROTECT                       // Configuração dos fuses (ver manual)
#use delay(clock=4000000)                       // Seta o clock interno para 4Mhz
#use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B1)  // Seta o baud rate para 9600, e define o pino B2 como TX e B1 como RX
 
unsigned char x[4];  //Variavel do tipo char com 4 posiçoes (string de até 3 carateres) ou do tamanho do comando que desejarem utilizar
// lembrando que sempre deve ter um caractere a mais pois tem o '\0' no final da string
unsigned int pino; //Variavel que armazenara o pino que esta sendo utilizado
 
void main(void) // função principal
{
   delay_ms(100); //tempo para inicializar a conexão
   do {
      gets(x); // pega a string e coloca na variavel x
      if(x[0] == 'a' || x[0]=='A') // Fazer isso para todas as portas desejadas, podendo ser A,B,C.. depende do pic
      {
         switch(x[1]) // Ve se qual pino da porta quer controlar
         {
            case '0':
               pino = PIN_A0;
               break;
            case '1':
               pino = PIN_A1;
               break;
            case '2':
               pino = PIN_A2;
               break;
            case '3':
               pino = PIN_A3;
               break;
            default:
               pino = 0; // se não for nenhum, coloca como 0;
               break;
         }
      }
      else if(x[0] == 'b' || x[0]=='B') // mesma coisa que antes, porem agora para a porta B (e assim pode continuar)
      {
         switch(x[1])
         {
            case '0':
               pino = PIN_B0;
               break;
            case '1':
               pino = 0; // pino reservado para RS232
               break;
            case '2':
               pino = 0; // pino reservado para RS232
               break;
            case '3':
               pino = PIN_B3;
               break;
            case '4':
               pino = PIN_B4;
               break;
            case '5':
               pino = PIN_B5;
               break;
            case '6':
               pino = PIN_B6;
               break;
            case '7':
               pino = PIN_B7;
               break;
            default:
               pino = 0;
               break;
         }
      }
      else
      {
       pino=0;
       // Se não existir a porta que foi escolhida, seta o pino para 0 para que não mude o que foi escolhido anteriormente
      }
 
      if(pino != 0) // Se o pino existir (não for 0)
      {
         if(x[2]=='l' || x[2]=='L')// Se o comando for L ou l (de ligar) 
         {
            output_high(pino); // Coloca o valor 1 logico no pino escolhido
            printf("200\n\r");
         }
         else if(x[2]=='d' || x[2]=='D') // Se o comando for D ou d(de desligar) 
         {
            output_low(pino); // Coloca o valor 0 logico no pino escolhido 
            printf("200\n\r");
         }
         else // Se o comando não for de ligar ou desligar
         {
            printf("505\n\r"); //Avisa que o comando é invalido
         }
      }
      else // Se o pino não existir (variavel pino igual a 0)
      {
         printf("505\n\r");
      }
   } while (TRUE); // mantem o laço de repetição rodando em loop infinito
}

Bom, agora vamos ao que interessa, o software que controla o PIC pela porta serial de um PC.
Normalmente a conexão serial é meio chatinha de fazer (seja em linux, windows, mac..) então recomendo que usem a biblioteca que se encontra neste site ( http://www.teuniz.net/RS-232/ ) que facilita bastante o nosso trabalho, e ja deixa portavel para outros OS tambem. Essa biblioteca é extremamente simples de ser utilizada, não vejo sentido em reescrever todo o codigo para a comunicação serial se ja tem uma biblioteca boa que faz isso, a não ser para aprender como funciona (recomendo que leiam o codigo da biblioteca)

Segue o codigo:

#include "stdio.h"
#include "stdlib.h"
#include "conio.h"
#include "windows.h"
#include "string.h"
#include "rs232.h"
 
void loop(); // Declarando a função loop que está la em baixo
 
unsigned char comando[5]; // comando a ser enviado
unsigned char buff[1024]; // comando recebido
 
int main(void) // Função principal
{
    OpenComport(1,9600); // abre a porta desejada (ver documentação)
    loop(); // Chama a função loop
    return 0;
}
 
void loop() // Função loop
{
    int n; // variavel temporaria
    n = PollComport(1,buff,1024); // n != 0  se tiver algo pra ser recebido
    if(n == 0) // se não tiver recebendo nada
    {
        printf("Digite o seu comando: "); //pergunta qual comando quer executar
        gets(comando); // Pega o comando e coloca na variavel comando
        strcat(comando,"\n\r");// adiciona uma quebra de linha (mais por motivos esteticos se for testar em terminal ou quardar log)
        cprintf(1,comando); // manda o comando para a porta serial (ou USB com FTDI)
        _sleep(200); // delay de 200 milisegundos necessario para a sincronização (pode ser de 100)
    }
    else // Se tiver recebido algo
    {
        // Switch para ver o que cada codigo representa, e exibe para o usuario.
        switch(atoi(buff))
        {
            case 200:
                printf("OK!\n\r");
                break;
            case 505:
                printf("Erro!\n\r");
                break;
            default:
                break;
        }
    }
    loop(); // Chama a função novamente, assim mantendo um loop infinito
}

Acho que da pra entender como funciona só pelos comentarios.
Esse codigo foi testado no windows 7 ultimate 64bit, utilizando o code::blocks para programar, e o GNU GCC para compilar. Para funcionar para linux tambem é necessario alterar algumas coisas, mas a logica é a mesma.

Ah, não saiam ligando os fios da serial direto no pic é preciso utilizar um MAX232 para isso, pois o sinal da serial é diferente do TTL utilizado pelo pic. Para saber como ligar o MAX232 é só olhar no datasheet.

Se quiserem testar só a comunicação serial virtualmente, recomendo o uso do virtual serial port driver da eltima, e hyper terminal.

Ainda falta eu colocar aqui a parte dos sockets (para o controle remoto), que ja está pronta só tenho que juntar tudo, e a parte eletro-eletronica tambem, por exemplo um dimmer para uma lampada, como controlar interruptores… e alguns outros exemplos do que fazer. A principio quero montar uma placa que controle varios interruptores.

Qualquer duvida, sugestão ou critica, favor deixar nos comentarios

Sistema de controle com PIC e porta Serial (rs232)

0saves

Estou fazendo um projeto para a cadeira de programação C que tem o objetivo de controlar eletronicos (sejam interruptores, motores, ou até coisas mais completas como temperatura de um ar-condicionado) remotamente, e achei interessante postar aqui o projeto para que mais gente possa ver como isso é feito (e como é mais simples do que se imagina).
Por enquanto estou desenvolvendo o projeto em partes, para juntar tudo depois.
Hoje vou falar sobre a parte do PIC enviar e receber dados pela porta serial.

Material utilizado (para testar virtualmente):

- Proteus 7.1 (para a simulação)
- PCWH Compiler IDE (CCS) 4.038 (para programar e compilar o programa em C)

Passos da montagem no proteus:
Passo 1: Criar um novo arquivo no Proteus.
Passo 2: Adicionar o PIC de sua preferencia que tenha suporte a RS232, no caso do exemplo é o PIC16F628A.
Passo 3: Adicionar os leds que quiser (de acordo com o numero de pinos que deseja controlar).
Passo 4: Colocar um resistor de 470 Ohms em cada led.
Passo 5: Ligar o LED-Resistor ou Resistor-LED (tanto faz a ordem) ao terra.
Passo 6: Adicionar um terminal virtual ao projeto
Passo 7: Ligar o pino RX do pic no TX do terminal
Passo 8: Ligar o pino TX do pic no RX do terminal
Passo 9: Salve o projeto onde preferir
por enquanto é isso no proteus, agora precisamos do programa a ser inserido no pic.

Para o programa do PIC, cada um programa no editor que preferir, e usa o compilador que quiser(Lembrando que mudando de compilador o codigo sera diferente). No exemplo eu estou usando o compilador CCS.
O programa é o seguinte:

#include <16f628a.h>                            // Inclui o cabeçalho especifico do pic a ser utilizado
#include                               // Inclui as funçoes padroes de entrada e saida
#fuses HS,NOWDT,NOPROTECT                       // Configuração dos fuses (ver manual)
#use delay(clock=4000000)                       // Seta o clock interno para 4Mhz
#use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B1)  // Seta o baud rate para 9600, e define o pino B2 como TX e B1 como RX
 
unsigned char x[4];  //Variavel do tipo char com 4 posiçoes (string de até 3 carateres) ou do tamanho do comando que desejarem utilizar
// lembrando que sempre deve ter um caractere a mais pois tem o '\0' no final da string
unsigned int pino; //Variavel que armazenara o pino que esta sendo utilizado
 
void main(void) // função principal
{
   delay_ms(100); //tempo para inicializar a conexão
 
   printf("TESTE DE CONTROLE COM PIC\n\r"); // Manda esta mesagem para o terminal
   //Para testar se foi tudo ligado corretamente, feche a função aqui, compile e teste
   do {
      printf("\n\r");
      printf("Envie um comando de 3 caracteres");
      printf("sendo abc a=porta b=pino c=estado(l ou d) \n\r");
      gets(x); // pega a string e coloca na variavel x
      if(x[0] == 'a' || x[0]=='A') // Fazer isso para todas as portas desejadas, podendo ser A,B,C.. depende do pic
      {
         switch(x[1]) // Ve se qual pino da porta quer controlar
         {
            case '0':
               pino = PIN_A0;
               break;
            case '1':
               pino = PIN_A1;
               break;
            case '2':
               pino = PIN_A2;
               break;
            case '3':
               pino = PIN_A3;
               break;
            default:
               pino = 0; // se não for nenhum, coloca como 0;
               break;
         }
      }
      else if(x[0] == 'b' || x[0]=='B') // mesma coisa que antes, porem agora para a porta B (e assim pode continuar)
      {
         switch(x[1])
         {
            case '0':
               pino = PIN_B0;
               break;
            case '1':
               pino = 0; // pino reservado para RS232
               printf("Pino reservado!");
               break;
            case '2':
               pino = 0; // pino reservado para RS232
               printf("Pino reservado!");
               break;
            case '3':
               pino = PIN_B3;
               break;
            case '4':
               pino = PIN_B4;
               break;
            case '5':
               pino = PIN_B5;
               break;
            case '6':
               pino = PIN_B6;
               break;
            case '7':
               pino = PIN_B7;
               break;
            default:
               pino = 0;
               break;
         }
      }
      else
      {
       pino=0;
       // Se não existir a porta que foi escolhida, seta o pino para 0 para que não mude o que foi escolhido anteriormente
      }
 
      if(pino != 0) // Se o pino existir (não for 0)
      {
         if(x[2]=='l' || x[2]=='L')// Se o comando for L ou l (de ligar)
         {
            output_high(pino); // Coloca o valor 1 logico no pino escolhido
         }
         else if(x[2]=='d' || x[2]=='D') // Se o comando for D ou d(de desligar)
         {
            output_low(pino); // Coloca o valor 0 logico no pino escolhido
         }
         else // Se o comando não for de ligar ou desligar
         {
            printf("Comando invalido. Tente novamente \n\r"); //Avisa que o comando é invalido
         }
      }
      else // Se o pino não existir (variavel pino igual a 0)
      {
         printf("Comando invalido. Tente novamente \n\r");
      }
   } while (TRUE); // mantem o laço de repetição rodando em loop infinito
}

Os dois promeiros includes não aparecem bem com esse plugin, mas são:
#include <16f628a.h>
#include
Acho que não tem nada de muito complicado neste codigo, no máximo a parte de configuração dos fuses, o que pode ser visto no manual do compilador, ou em qualquer tutorial basico sobre o CCS. e o resto dos comandos são basicos da linguagem C (aprenda o basico de C antes de tentar fazer isso, aqueles programinhas em terminal). Qualquer outra coisa é só postar a duvida que eu respondo.

Agora precisa compilar o programa (sugiro copiar o .hex gerado para a pasta do projeto do proteus).

Voltando ao proteus agora,

Passo 10: Clique duas vezes sobre o PIC, sete o clock para 4Mhz (em Processor Clock Frequency) e em Program File coloque o caminho para o arquivo .hex gerado pelo compilador.

Pronto, agora depois de tudo configurado é só rodar a simulação que funcionara, a menos que tenha feito algo errado (antes de perguntar, favor ler novamente e ver se esta tudo igual). Lembrando que ao copiar e colar o codigo para o seu editor de textos normalmente tem que trocar as aspas pois vai como acento.

Esta é somente a base para algo mais complexo, se quiser controlar um motor, ler um valor analogico (potenciometro, ldr, temperatura…) ou qualquer outra coisa mais complexa, tera que implementar as suas funçoes e comandos para isso.

Conforme eu for fazendo o projeto, e tiver tempo, vou postando aqui.

Uma coisa que acho importante ao compartilhar este projeto, é mostrar para as pessoas que usam arduino, que não é preciso gastar muito com uma arduino para fazer projetos simples, os microcontroladores são baratos (em torno de uns 10 reais) e são super simples de programar.

Seguem algumas imagens de como fica o projeto:

Como fica no proteus

Como fica no proteus

Funcionando no proteus com o terminal

Funcionando no proteus com o terminal

EDITANDO: Como foi pedido nos comentarios, seguem os arquivos utilizados no exemplo: Arquivos do projeto