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 CCS Technical Support

12F1822 I/O
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
aldina



Joined: 09 Oct 2009
Posts: 26

View user's profile Send private message Send e-mail

PostPosted: Mon Sep 28, 2015 4:41 pm     Reply with quote

It could be a fault with WDT? I don't know more I should think or make.
Code seems so easier... and I can't see where is the problem.
I appreciate all of your help and thoughts.
Really thank you
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Sep 28, 2015 4:45 pm     Reply with quote

I didn't see much that was wrong with your compiler version, compared
to vs. 5.049. The little differences would not affect your problem.

I noticed one thing about the logic of your program. In Pisca(), you
call the Right(), Left(), and SpeedH() functions and get values, and then
you execute an if() or else-if() statement based on those values. You
then in some cases, call another function. Example:

You said that the 101 case is one of the problem cases.
Code:
// 101   *** PROBLEM ***
      else if(RH_Signal >= 400 && LH_Signal < 400 && Hex >= 400) // 101
      {
         OUTPUT_HIGH(PIN_A5); // ON direito
         OUTPUT_HIGH(PIN_A4); // ON esquerdo
         printf("Case:011, Picsa: 1 1 \r");
   
         T_OFF_RC();             
       }
   


The code above then calls the function below. But I noticed these things:
1. The function below calls Right() again. What if the value returned
by Right() is different than the value that caused case 101 to be executed ?

2. To execute case 101, RH_Signal must be >= 400.
But in the code below, you are checking to see if RH_Signal is < 400.
Why ? What if the first call to Right() in Pisca() gets a RH value of 400
but then in case 101 it calls Right() again and gets 399 ? Or what if it
gets 401 ? What is the purpose of this code ?

3. You report problems only when the relay is energised (I assume).
A relay has contacts that have noise. The relay coil stores energy.
If you are missing the diode across the relay, you will get a voltage spike
that could damage the relay driver chip. Or even if you have diode, it
will dump the spike into the power supply rail. If your voltage regulator
can't regulate the load voltage very well, you power rail (+5v ?) will be
affected. This may be a cause of your problem.

Code:

// The following function is only called for these input levels:
//  else if(RH_Signal >= 400 && LH_Signal < 400 && Hex >= 400) // 101

void T_OFF_RC()
{
   int16 RH_OFF;
   int16 x = 0;
   
  while (true)
   {     
      restart_wdt();
      RH_OFF = 0;
     
      RH_OFF = Right();  // *** Calls the Right() function AGAIN.  Why ?
      delay_us(10);
           
      if (RH_OFF < 400)   // *** Why the OPPOSITE of RH_Signal above ? 
      {
         OUTPUT_LOW(PIN_A5); // OFF direito
         OUTPUT_HIGH(PIN_A4); // ON esquerdo
         printf("T_OFF_RC: 1 0 \r");
   
         delay_ms(20);
         x++;
         if (x>=35) break;  // 35*20ms = 700ms --> SAI
      }
       
      else
      {
         break;
      }
   } 
}
aldina



Joined: 09 Oct 2009
Posts: 26

View user's profile Send private message Send e-mail

PostPosted: Mon Sep 28, 2015 5:42 pm     Reply with quote

The logic i'm thinking is:

If input speed is >= 400 (about 2V) then A4 and A5 outputs are High and they will be HIGH while not Right() or Left(),

As soon as Right() or Left() return a value >= 400, it means that relay is ON, then outputs (A5 andor A4) stay High while relay is ON, That's why I call T_OFF function and see again the value or Right() ou Left() to know when the ralay is OFF and turn OFF outputs according.

Maybe I'm not thinking correct, but was the way I found to know when relay is ON or OFF when it has input speed high.

I know that when it has no speed signal input is easier because as soon as is has relay signal it goes up (HIGH) and then goes down (LOW) when relay turns OFF,

You ask:
Quote:

The code above then calls the function below. But I noticed these things:
1. The function below calls Right() again. What if the value returned
by Right() is different than the value that caused case 101 to be executed ?

Yes, above code tests 101 status, then in the T_OFF_RC() tests 001. It means Right input LOW because relay is OFF, so A5 output should be LOW until a new rise up of relay or untill time < 700ms.

Quote:
2. To execute case 101, RH_Signal must be >= 400.
But in the code below, you are checking to see if RH_Signal is < 400.
Why ? What if the first call to Right() in Pisca() gets a RH value of 400
but then in case 101 it calls Right() again and gets 399 ? Or what if it
gets 401 ? What is the purpose of this code ?

Input is always >>> 400 (it is a voltage near to 5V) when relay is On, or <<<<400 (near to 0V) when relay is off.

Quote:
3. You report problems only when the relay is energised (I assume).
A relay has contacts that have noise. The relay coil stores energy.
If you are missing the diode across the relay, you will get a voltage spike
that could damage the relay driver chip. Or even if you have diode, it
will dump the spike into the power supply rail. If your voltage regulator
can't regulate the load voltage very well, you power rail (+5v ?) will be
affected. This may be a cause of your problem.

You mean I should have a diode across the contacts of the relay? I have no one. I know it is necessary when we have relays or motors (coil) in the microcontroler outputs, so is logic that the same effect could happen when we use it to microcontroler inputs, So I will try with a diode accross coil terminals of the relay.

Thank you again
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Sep 28, 2015 5:54 pm     Reply with quote

There are two types of relay protection circuits:

1. Flywheel diode across the coil.

2. RC snubber circuit across the contacts.

I was talking about #1.
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Mon Sep 28, 2015 6:18 pm     Reply with quote

WHAT FREE version?
Code:

#include <12F1822.h>
#device ADC=10
#fuses INTRC_IO,WDT,NOMCLR,PROTECT,BROWNOUT,NOPUT
#use delay(clock=4000000)
#BYTE OSCCON = 0x119  //OSCCON register (pg 26 datasheet)
//#BYTE WDTCON = 0x117 //WDTCON (pg 26 datasheet)
#include <stdlib.h>
#include <math.h>

 // Ler speed
 int16 Speed_H()
 {
    int8 i;
    int16 speed;
    int16 speed_sum;
    int16 speed_average;

    speed = 0;   
    speed_sum = 0;
    speed_average = 0;

    set_adc_channel(2);
    delay_us(5);

    for(i=0;i<16;i++)
    {
       speed = read_adc();
       speed_sum += speed;
    }

    speed_average = speed_sum/16;

    return speed_average;
 }

// Ler sinal Direito
int16 Right()
{
   int8 i;
   int16 RH;
   int16 RH_sum;
   int16 RH_average;
   
   RH = 0;
   RH_sum =0;
   RH_average = 0;
   
   set_adc_channel(0);
   delay_us(5);
   
   for(i=0;i<16;i++)
   {
      RH = read_adc();
      RH_sum += RH;
   }
   RH_average = RH_sum/16;
   return RH_average;
}

// Ler sinal Esquerdo
int16 Left()
{
   int8 i;
   int16 LH;
   int16 LH_sum;
   int16 LH_average;
   
   LH = 0;
   LH_sum = 0;
   LH_average = 0;
   
   set_adc_channel(1);
   delay_us(5);
     
   for(i=0;i<16;i++)
   {
      LH = read_adc();
      LH_sum += LH;
   }
   LH_average = LH_sum/16;
   return LH_average;
}

// Função TOFF 4
void T_OFF4()
{
   int16 LH_OFF, RH_OFF;
   int8 x = 0;
   
   while (true)
   {     
      restart_wdt();
      LH_OFF = 0;   
      RH_OFF = 0;

      LH_OFF = Left();
      RH_OFF = Right();
      //delay_us(10);
   
      if(RH_OFF < 400 || LH_OFF < 400)
      {
         OUTPUT_LOW(PIN_A5); // OFF direito
         OUTPUT_LOW(PIN_A4); // OFF esquerdo
         delay_ms(20);
         x++;
         if (x>=35) break;  // 35*20ms = 700ms --> SAI
      }   
      return;
   } // while
} // main

// Função TOFF R
void T_OFF_RS()
{
   int16 RH_OFF;
   int8 x = 0;
   
   while (true)
   {     
      restart_wdt();
      RH_OFF = 0;
     
      RH_OFF = Right();
      //delay_us(10);
     
      if (RH_OFF < 400)
      {
         OUTPUT_LOW(PIN_A5); // OFF direito
         OUTPUT_LOW(PIN_A4); // OFF esquerdo
         delay_ms(20);
         x++;
         if (x>=35) break;  // 35*20ms = 700ms --> SAI
      }
     
      return;
     
   } // While
} // main

void T_OFF_RC()
{
   int16 RH_OFF;
   int8 x = 0;
   
   while (true)
   {     
      restart_wdt();
      RH_OFF = 0;
     
      RH_OFF = Right();
      //delay_us(10);
           
      if (RH_OFF < 400) 
      {
         OUTPUT_LOW(PIN_A5); // OFF direito
         OUTPUT_HIGH(PIN_A4); // ON esquerdo
         delay_ms(20);
         x++;
         if (x>=35) break;  // 35*20ms = 700ms --> SAI
      }
       
      return;
     
   } // While
} // main

// Função TOFF L
void T_OFF_LS()
{
   int16 LH_OFF;
   int8 x = 0;
   
   while (true)
   {     
      restart_wdt();
      LH_OFF = 0;
     
      LH_OFF = Left();
      //delay_us(10);
   
      if (LH_OFF < 400)
      {
         OUTPUT_LOW(PIN_A5);
         OUTPUT_LOW(PIN_A4);
         delay_ms(20);
         x++;
         if (x>=35) break;  // 35*20ms = 700ms --> SAI
      }
       
      return;
     
   } // while
} // main

// Função TOFF L
void T_OFF_LC()
{
   int16 LH_OFF;
   int8 x = 0;
   
   while (true)
   {     
      restart_wdt();
      LH_OFF = 0;
     
      LH_OFF = Left();
      //delay_us(10);
   
      if (LH_OFF < 400)
      {
         OUTPUT_HIGH(PIN_A5);
         OUTPUT_LOW(PIN_A4);
         delay_ms(20);
         x++;
         if (x>=35) break;  // 35*20ms = 700ms --> SAI
      }
       
      return;
     
   } // while
} // main

// Função pisca C
void PiscaC()
{
   int16 RH_Signal, LH_Signal;

   while (true)
   {       
       RH_Signal = 0;
       LH_Signal = 0;
       RH_Signal = Right();
       LH_Signal = Left();
             
      if(RH_Signal >= 400 && LH_Signal >= 400)  // 111
      {
            OUTPUT_HIGH(PIN_A5); // ON direito
            OUTPUT_HIGH(PIN_A4); // ON esquerdo
            T_OFF4();
      }
         
      else if(RH_Signal >= 400 && LH_Signal < 400)  // 101
      {
         OUTPUT_HIGH(PIN_A5); // ON direito
         OUTPUT_HIGH(PIN_A4); // ON esquerdo
         T_OFF_RC();             
       }
     
      else if(RH_Signal < 400 && LH_Signal >= 400)  // 011
      {
            OUTPUT_HIGH(PIN_A5); // ON direito
            OUTPUT_HIGH(PIN_A4); // ON esquerdo
            T_OFF_LC();
      }

      else  // 000
      {
            break;
      }
   
   }
}

// Função pisca S
void PiscaS()
{
   int16 RH_Signal, LH_Signal;

   while (true)
   {       
       RH_Signal = 0;
       LH_Signal = 0;
       RH_Signal = Right();
       LH_Signal = Left();
       
       if(RH_Signal >= 400 && LH_Signal >= 400) // 110
       {
            OUTPUT_HIGH(PIN_A5); // ON direito
            OUTPUT_HIGH(PIN_A4); // ON esquerdo
            T_OFF4();
      }

      else if(RH_Signal >= 400 && LH_Signal < 400) // 100
      { 
            OUTPUT_HIGH(PIN_A5); // ON direito
            OUTPUT_LOW(PIN_A4); // OFF esquerdo
            T_OFF_RS();           
      }
 
      else if(RH_Signal < 400 && LH_Signal >= 400) // 010
      {
            OUTPUT_LOW(PIN_A5); // OFF direito
            OUTPUT_HIGH(PIN_A4); // ON esquerdo
            T_OFF_LS();
      }

      else  // 000
      {

            break;
      }
   
   }
}     

// ******   MAIN    ******* //
void main(void)
{
   int16 HEXA;

   OSCCON=0x61;  //registo OSCCON 61->4MHZ, 71->8MHZ

   setup_adc_ports(SAN0 | SAN1 | SAN2);
   
   setup_adc(ADC_CLOCK_DIV_16);  // ver pág.143 datasheet - Tconv = 16/4M = 4us por amostra
   //setup_adc(ADC_CLOCK_INTERNAL);
   
   // Configuração das saídas
   output_low(PIN_A5); //Saida para sector Lateral Direito
   output_low(PIN_A4); //Saida para sector Lateral Esquerdo
   
   // Configuração das entradas
   // A0 - Entrada AN0 para leitura do sinal lado Direito
   // A1 - Entrada AN1 para leitura do sinal lado Esquerdo
   // A2 - Entrada Digital para leitura do sinal Speed
   // A3 - Entrada Digital para leitura do sinal de presença
   SET_TRIS_A(0x07); // 00000111 - 0x07 - ainda sem entrada de SM no MCLR (A3)

   while (true)
   {
      restart_wdt();
     
      HEXA = 0;
     
      HEXA = Speed_H();
     
      if(HEXA >= 400) // A2 - HIGH
      {
         OUTPUT_HIGH(PIN_A5); // OFF direito
         OUTPUT_HIGH(PIN_A4); // OFF esquerdo
         PiscaC();
      }
     
      if(HEXA < 400) // A2 - LOW
      {
         OUTPUT_LOW(PIN_A5); // OFF direito
         OUTPUT_LOW(PIN_A4); // OFF esquerdo
         PiscaS();
      }
   } // while
} // main

Is it possible that problem will be in my free version? Can someone compile my code to try?
I have a .exe version - 4.128, I can try it
aldina



Joined: 09 Oct 2009
Posts: 26

View user's profile Send private message Send e-mail

PostPosted: Mon Sep 28, 2015 6:26 pm     Reply with quote

I will try with diode.

And, did you understand my explanation about your 3 questions??
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Tue Sep 29, 2015 2:50 am     Reply with quote

I find the program very difficult to understand, here are some tips to make it easier for other people read your code:
- Write your program in English (comments and variable names).
- Write a short comment at the head of your program about what it is doing.
- Do not duplicate code. Two times almost identical code is allowed, but when you have three times the same code sequence it should be replaced by 1 generic function.
- Be consistent with the use of upper and lower case. A general guideline is to use lower case for function names and variables. A constant is written with all upper case. Bad examples in your code: LH_OFF, true, OUTPUT_LOW() and others.
- Try to write code that documents itself (this will get better when you have more experience). One great help here is to avoid 'magic numbers'. Example:
Code:
   output_low(PIN_A5); //Saida para sector Lateral Direito
   output_low(PIN_A4); //Saida para sector Lateral Esquerdo
Can be rewritten as:
Code:
#define MOTOR_LEFT    PIN_A5
#define MOTOR_RIGHT   PIN_A4

output_low(MOTOR_LEFT);     // Left off
output_low(MOTOR_RIGHT);    // right off
or, really nice:
Code:
#define MOTOR_LEFT   PIN_A5
#define MOTOR_RIGHT  PIN_A4

#define STAND_STILL  output_low(MOTOR_LEFT);  output_low(MOTOR_RIGHT);
#define GO_LEFT      output_high(MOTOR_LEFT); output_low(MOTOR_RIGHT);
#define GO_RIGHT     output_low(MOTOR_LEFT);  output_high(MOTOR_RIGHT);
#define GO_STRAIGHT  output_high(MOTOR_LEFT); output_high(MOTOR_RIGHT);
Do this for your other pins as well.

Avoid unnecessary comments:
Code:
   SET_TRIS_A(0x07); // 00000111 - 0x07 - ainda sem entrada de SM no MCLR (A3)
Can be rewritten as:
Code:
   set_tris_a(0b00000111); // ainda sem entrada de SM no MCLR (A3)



Also, get rid of the the watchdog. It's a great feature for life critical systems, but in all other products a watchdog introduces more problems than it solves. When needed, you can always add it later when everything else is working.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
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