CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

RS 232 error

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jcerbaro



Joined: 23 Jun 2016
Posts: 2

View user's profile Send private message

RS 232 error
PostPosted: Thu Jun 23, 2016 11:36 pm     Reply with quote

Hello! I have a problem when trying to communicate via RS232 with my PC.

I'm using PIC16F877A. It's a PID Speed Control of a DC motor.

I've already tested the RS232 with a simpler code, and it worked fine, but in my code it's not!

In this code, the variable "velocidade" is not coming out.

If I use the command "putc('x');", it works, but when i use "putc(velocidade);", it doesn't.

PLEASE, IGNORE THE PORTUGUESE COMENTS, the code is self explanatory for you guys.

my code is this:

Code:
#include <16F877A.h>
#include <string.h>
#include <stdlib.h>
#use delay(clock=12000000)
#fuses HS, PUT, NOWDT, NOBROWNOUT, NOLVP
#define TX PIN_C6
#define RX PIN_C7
#use rs232(baud=9600, xmit=TX, rcv=RX, bits=8, parity=N, ERRORS)


//************************//
//*** VARIÁVEIS DO PID ***//
//************************//
int kp, ki, kd;                             //Constantes do PID.
int p;                                      //Parcela proporcional no sinal de controle.
int i;                                      //Parcela integral no sinal de controle.
int i_anterior = 0;                         //Parcela integral no sinal de controle no instante anterior.
int d;                                      //Parcela derivativa no sinal de controle.


//******************************//
//*** VARIÁVEIS DE USO GERAL ***//
//******************************//
unsigned int ready1 = 0;                    //Variável que é habilitada a cada x ms, para entrar na atualização do PID.
unsigned int ready2 = 0;                    //Variável que é habilitada a cada x ms, para enviar um dado pela serial.
unsigned int pulsos = 0;                    //Conta quantos pulsos o encoder envia.
int erro = 0;                                   //Diferença entre a velocidade atual e o setpoint, em pulsos.
int erro_anterior = 0;                      //Diferença no momento anterior.
unsigned int duty_cicle = 127;              //Tamanho do duty_cicle.
unsigned int velocidade = 0;                //RPS medido. (pulsos / 32 * 20)
unsigned int setpoint = 0;                  //RPS recebida pela serial.
int diferenca = 0;                          //diferença de RPS entre recebida e medida.
int contador1 = 0;                          //ajuste do timer0.
int contador2 = 0;                          //ajuste da porta serial.
int j = 0;                                  //Contador do recebimento.


//***************************//
//*** VARIÁVEIS PARA UART ***//
//***************************//
char uart_recebido[4];                      //String recebida pela serial.


//***************************//
//*** INTERRUPÇÃO DA UART ***//
//***************************//
#int_rda
void uart_read(void)
{
   
    //Interrupção toda a vez que tem algo pra ser lido. Lê 4 vezes e aí atribui para o destino.
    uart_recebido[j] = getc();
    j++;
   
    if (j==4)
    {
        j=0;
        setpoint = (int)uart_recebido[0];
        kp = (int)uart_recebido[1];
        ki = (int)uart_recebido[2];
        kd = (int)uart_recebido[3];
    }
}


//***********************************//
//*** INTERRUPÇÃO DO MODO CAPTURA ***//
//***********************************//
//Sim, do jeito que eu usei fica a mesma coisa que uma interrupção externa, mas funciona mesmo assim...
#int_ccp2
void encoder()
{
    pulsos++;                               //Conta quantos pulsos dá.
}


//*****************************//
//*** INTERRUPÇÃO DO TIMER0 ***//
//*****************************//
#int_timer0
void habilitador(void)
{
   
    //Calculado para setar "ready1" a cada 10ms para atualizar o PID.
    contador1++;
   
    if (contador1 == 15)
    {
        ready1 = 1;
        contador2++;
        contador1 = 0;
    }
   
    //A cada 5 atualizações, habilita "ready2" para enviar pela serial.
    if (contador2 == 5)
    {
        ready2 = 1;
        contador2 = 0;   
    }
   
    set_timer0(131 - get_timer0());
}


//***********************************//
//*** FUNÇÃO DO SINAL DE CONTROLE ***//
//***********************************//
void PID (void)
{
    velocidade = pulsos / 32 * 20;
   
    diferenca = setpoint - velocidade;
   
    erro = diferenca * 250 / 100; //muda de tipo RPS para tipo duty cicle. VERIFICAR!
    //erro = setpoint - velocidade;
   
    p = kp * erro;
    i = ki * (i_anterior + erro);
    d = kd * (erro - erro_anterior);
   
    duty_cicle = p + i + d;
   
    i_anterior = i;
   
    pulsos = 0;
}


//*******************//
//*** FUNÇÃO MAIN ***//
//*******************//
void main(void)
{
    //Timer0 controla o tempo de amostragem. Calculado para dar 50ms.
    setup_timer_0(RTCC_INTERNAL | RTCC_DIV_16);
    set_timer0(131);
   
    //Timer1 para o modo de captura em CCP2.
    setup_timer_1(T1_INTERNAL);
    setup_ccp2(CCP_CAPTURE_RE);
   
    //Timer2 para o PWM em CCP1.
    setup_timer_2(T2_DIV_BY_4,255,1);
    setup_ccp1(CCP_PWM);
    set_pwm1_duty(duty_cicle);
   
    enable_interrupts(GLOBAL);
    enable_interrupts(INT_CCP2);
    enable_interrupts(INT_TIMER0);
    enable_interrupts(INT_RDA);
   
    //Inicializa as constantes do PID, até receber outras da serial.
    setpoint = 20;
    kp = 10;
    ki = 10;
    kd = 0;
   
    while(TRUE)
    { 
       if (ready1 == 1)       
        {
            PID();
            set_pwm1_duty(duty_cicle);
            ready1 = 0;
           
            if (ready2 == 1)
            {
                putc(velocidade); //ESSA TRANQUEIRA NÃO FUNCIONA DE JEITO NENHUM!
                ready2=0;
            }
        }
    }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jun 23, 2016 11:50 pm     Reply with quote

Quote:
unsigned int pulsos = 0;

velocidade = pulsos / 32 * 20;

In CCS for your PIC, an unsigned int is 8 bits. It can have a value
from 0 to 255. You are dividing it by 640. This will always give a
result of 0.

You should edit your program, and everywhere that you want an
unsigned 16-bit integer, you should change it to 'int16'. Example:
Code:
int16 pulsos;


If pulsos is made into a 2-byte variable, then to be safe, before using it,
you should disable interrupts and copy it to another variable. Example:
Code:
int16 captured_pulsos;

disable_interrupts(GLOBAL);
captured_pulsos = pulsos;
enable_interrupts(GLOBAL);

velocidade = captured_pulsos / 32 * 20;


In most places where you have 'int', you really want 'signed int16'.
Example:
Code:
signed int16 kp, ki, kd;                             
signed int16 p;                                       
signed int16 i;                                       
signed int16 i_anterior = 0;                         
signed int16 d; 
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group