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

switching a relay when a voltage detector detects no voltage

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



Joined: 02 Sep 2014
Posts: 1

View user's profile Send private message

switching a relay when a voltage detector detects no voltage
PostPosted: Tue Sep 02, 2014 6:06 am     Reply with quote

i am currently making a UPS for a school project. im using a pic16f877a and a LM35 sensor to monitor the UPS temperature. i have been able to do that but now i have a problem with additionally switching a relay if the output of the UPS is zero detected by a voltage detector. the voltage detector input is PIN_B2 and the relay output is PIN_B4.

here is the program

[color=orange]/*
PIC16F877A and LM35 Based Temperature Monitor

MACHI M.C
20403715
*/

#include <16f877a.h>
#device adc=10 // Set ADC resolution to 10Bit
#fuses XT,NOLVP,NOWDT,NOPROTECT
#use delay(crystal=4000000)
#use rs232(baud=960,xmit=PIN_C6,rcv=PIN_C7,ERRORS)
#include <lcd.c>

#define LOAD PIN_B7
#define THRES 70.0 // load switching threshold in Celsius
#define OFF 50.0 // fan stops when temparature reaches value in degrees
#define ADC_OFF 0 // ADC off
#define RELAY PIN_B4
#define R2 PIN_B2
#define R1 PIN_B1
#include <stdlib.h>
int16 digital_reading; // ADC resolution is 10Bit, an 8Bit integer is not enough to hold the reading
float temp;



void main()
{

/* ADC Initialization */
setup_adc(ADC_CLOCK_INTERNAL); // initialize ADC with a sampling rate of Crystal/4 MHz
setup_adc_ports(RA0_ANALOG); // set PIN_A0 as analog input channel
set_adc_channel(0); // point ADC to channel 0 for ADC reading
delay_ms(1); // ADC module is slow, needs some time to adjust.

disable_interrupts(GLOBAL); // DISABE ALL INTERRUPTS.
SET_TRIS_B(0X0F); //set RB0,RB1,RB2 & RB3 as inputs, RB4,RB5,RB6 & RB7 as output.
output_low(RELAY); // relay initialy off
if (input(PIN_B2)==0)
{
output_high(PIN_B4);
}
else if (input(PIN_B2)==1)
{
output_low(RELAY);
}

/* Peripherals Configurations */
lcd_init(); // Turn LCD ON, along with other initialization commands
output_low(LOAD); // the load is initially OFF
lcd_gotoxy(1,1); // point LCD cursor to col1 row1
lcd_putc("Temperature is:"); // print on LCD
{
while(1) // infinite loop
{
digital_reading = read_adc(); // capture current temperature reading
delay_us(100); // 0.1ms delay for ADC stabilization
temp = digital_reading * 0.4883; // convert reading to Celsius
lcd_gotoxy(1,2); // point LCD cursor to col1 row2
printf(lcd_putc,"%2.1f C",temp); // print value on LCD

if(temp>=THRES)
Do
{
output_high(LOAD); // Control Load
}
while (temp>=OFF);
else output_low(LOAD);
delay_ms(1000); // 1 second delay between readings
}

}
}[/code][/color]
Ttelmah



Joined: 11 Mar 2010
Posts: 19451

View user's profile Send private message

PostPosted: Tue Sep 02, 2014 7:42 am     Reply with quote

Start by not using colour, and using the code buttons properly. Trying to post the code in orange has just resulted in a mess....

Then you have a fundamental problem about using a digital input to use this. A logic input only sees a '0' when it is below 0.6v, and is indeterminate between 0.6, and about 2.4v. However, the peripheral that can do what you want, is the comparator. This can be programmed to switch an output at a specific voltage from the internal voltage reference module, and once setup, does it for you.....
You'd need to change the pins being used, but it will be the better solution.

Now, I've pointed out some problems with the existing code in the comments. Some parts are probably wrong, but you have several things being 'not used', such as the 'OFF' threshold value, so the logic is not totally clear:
Code:

#include <16f877a.h>
#device adc=10 // Set ADC resolution to 10Bit
#fuses XT,NOLVP,NOWDT,NOPROTECT
#use delay(crystal=4000000)
#use rs232(baud=960,xmit=PIN_C6,rcv=PIN_C7,ERRORS)
#include <lcd.c>

#define THRES 700 // load switching threshold in 0.1 Celsius
#define THRES_OFF 500 // fan stops when temparature reaches value in 0.1 degrees

#define LOAD PIN_B7
#define RELAY PIN_B4
#define R2 PIN_B2
#define R1 PIN_B1
/* first comment. You make these defines, so use them.... */
#define OFF(x) output_low(x)
#define ON(x) output_high(x)

#include <stdlib.h>

void main()
{
   int16 digital_reading; // ADC resolution is 10Bit, an 8Bit integer is not enough to hold the reading
   int16 temp; //Avoid floats
   //Get in the habit of making variables local, not global. Only use global, when
   //things want to be global
   
   /* ADC Initialization */
   //setup_adc(ADC_CLOCK_INTERNAL); // initialize ADC with a sampling rate of Crystal/4 MHz
   setup_adc(ADC_CLOCK_DIV_8); //Your remark is wrong, and the selection is wrong. Needs /8 for 4MHz
   setup_adc_ports(RA0_ANALOG); // set PIN_A0 as analog input channel
   set_adc_channel(0);
   
   delay_ms(100); //LCD needs boot delay
   
   //disable_interrupts(GLOBAL); // DISABE ALL INTERRUPTS.
   //all interrupts wake up disabled
   //SET_TRIS_B(0X0F); //set RB0,RB1,RB2 & RB3 as inputs, RB4,RB5,RB6 & RB7 as output.
   //Not needed you are using standard IO, so compiler controls TRIS
   OFF(RELAY);

   /* Peripherals Configurations */
   lcd_init(); // Turn LCD ON, along with other initialization commands
   OFF(LOAD); // the load is initially OFF
   lcd_gotoxy(1,1); // point LCD cursor to col1 row1
   lcd_putc("Temperature is:"); // print on LCD
   
   while(TRUE) // infinite loop
   {
      digital_reading = read_adc(); // capture current temperature reading
      //LM35 returns 10mV/degree. ADC input has an imaginary 1024 levels (only 1023
      //actually returned) for 5v. So each step is 0.48828degrees. However the unit is
      //just not that accurate. 1% at best, so _simplify_ the maths for space
      temp=(digital_reading*5)-(digital_reading/8)
      //This gives *4.875, many times faster than the float
      //temp = digital_reading * 0.4883; // convert reading to Celsius
      lcd_gotoxy(1,2); // point LCD cursor to col1 row2
      printf(lcd_putc,"%4.1Lw C",temp); // print value on LCD
      //In C, the number in front of the decimal, is the _total field width_
      //Not the digits in front. Your format will have been overflowing every time....
      if(temp>=THRES)
         ON(LOAD); // Control Load
      else
         OFF(LOAD); //Your logic is not quite clear here.
         //No control of fan etc...
      delay_ms(1000);
      }
   }
}

Now go, and look at ex_comp.c. This shows how to setup the comparator, and use it to signal when a voltage goes below a programmed level.

If you want to do it in software, then remove the delay, and instead have a short delay like 50uSec, and a counter for the inner loop. Just update the temperature when this gets to zero (so count to 20000), and each time round the short loop while waiting, test the input.
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