Level switch based circuit - 8051

Thread Starter

Anirban Raha

Joined Dec 4, 2013
70
Hi,
The following code is for a level sensor(float type) based circuit that turns on a motor via a solid state relay(with opto-isolators) according to lower and upper level limit switches. The motor starts when lower limit switch is open and stops when upper limit switch is closed.
The following code always turns the motor on after the initial delay, even during the following starting conditions: lower limit switch closed, upper limit switch open/closed. The motor seems to be triggered by the upper limit switch. Kindly take a look at the code. I was unable to find any error.

Code:
/***************************** Header Files Declaration ***************************************************/
#include<reg52.h>
#include<stdio.h>
#include<intrins.h>
sbit onl  = P2^2;//on indication
sbit offl = P2^3;//off indication
sbit out1= P3^7;//output to relay
bit hlvl;//high level input variable
bit llvl;//low level input variable
void delay(int n)
{
   int i,j;
   for(i=0;i<n;i++)
   {
     for(j=0;j<100;j++)
     {
     }
   }
}
void motor_on()
{
   out1=0;
   offl=0;
   onl=1;
   return;
}
void motor_off()
{
   out1=1;
   onl=0;
   offl=1;
   return;
}
void main()
{
P1 = 0xFF;
motor_off();
delay(1000);

while(1)
{
    //reading input pins
    hlvl = P1^3;
    llvl = P1^4;
    if(llvl==1) // if low level sensor becomes open, motor is turned on
      {
    motor_on();
      }
      if(hlvl==0)//if high level sensor becomes closed, motor is turned off
      {
      motor_off();
    }
}
}
P.S. The input pin P1.3 voltage was measured as low, but even then the motor starts. How is the control reaching inside the ' if(llvl==1)' statement?
 

theonewho

Joined Jul 9, 2015
17
It seems that you might be attempting to use bitmasking incorrectly.

You are using the XOR operator "^" in places where you probably want to be using a different bitwise logic operation. You'll learn more if you can move forward from this hint, so I won't give you any direct solution.
 

Thread Starter

Anirban Raha

Joined Dec 4, 2013
70
I've modified the code a bit. It seems to be working on my dev board using DIP switches in place of the level switch. The code is in Keil C btw. I don't want to connect it to my pump right away as malfunctioning could damage it. Kindly confirm if this will work or not. Ignore the hardware part.
Code:
/***************************** Header Files Declaration ***************************************************/
#include<reg51.h>
#include<stdio.h>
#include<intrins.h>

sbit onl  = P2^2;
sbit offl = P2^3;
sbit out1= P3^7;
sbit hlvl = P1^3;
sbit llvl = P1^4;

void delay(int n)
{
    int i,j;
    for(i=0;i<n;i++)
    {
        for(j=0;j<100;j++)
        {
        }
    }
}
void motor_on()
{
    out1=0;
    offl=0;
    onl=1;
    return;
}
void motor_off()
{
    out1=1;
    onl=0;
    offl=1;
    return;
}


void main()
{
P1 = 0xFF;
motor_off();
autl=1;
manl=0;
delay(1000);
  
while(1)
{
     
         if((hlvl==1)&&(llvl==1))
         {
             while(hlvl!=0)
             {
            motor_on();
           }
       }
         if((hlvl==0)&&(llvl==0))
         {
             while(llvl!=1)
             {
             motor_off();
         }
         }
}
}
 

Thread Starter

Anirban Raha

Joined Dec 4, 2013
70
There has been a pretty interesting development in the hardware part. The above program runs perfectly when DIP switches are used. However whenever I connect both my level switches, it's causing a problem. My level switches are submerged into an overhead tank on the roof. The level switches have been connected to the circuit using three 0.75sq.mm cables (each approx. 15m long). Two cables for the two switches and one cable is common for the ground. When I check the level switches with multi-meter continuity test on the receiving end they seem to be working. My code and circuit seems to be fine. Only when the level switches are connected do the problems begin.
Level switches are magnetic float switches.
The circuit is pretty simple. The input pins are connected to ground in series with the level switch contacts. So if the level switch is open, pin is high and otherwise it is low. Since I've used port 1 as input, no pull-up resistors have been used externally.
Are the cables too long? What could be the possible problem? Please help!!
 

theonewho

Joined Jul 9, 2015
17
I am unfamiliar with Keil C, but if it redefines the "^" operator to not be the XOR operator as is standard with every implementation of C that I've ever seen then I am not going to be able to help you.

I'm unclear on the purpose of the code where you are using the "^" operator:
C:
sbit onl  = P2^2;
sbit offl = P2^3;
sbit out1= P3^7;
sbit hlvl = P1^3;
sbit llvl = P1^4;
I'm going to assume that P1, P2, and P3 define input pins on your (based on Keil C, I'll assume) 8051. I'm also assuming that each of those inputs is digital and you should expect either a 1 or 0 from each of those input pins.

If my assumptions are correct:
  • you set the values for onl, offl, out1, hlvl, and llvl when those variables are instantiated. These variables will only ever have a very few values, and they may not be the ones you intend...
    • 0 XOR 3 = 3
    • 0 XOR 4 = 4
    • 0 XOR 7 = 7
    • 1 XOR 3 = 2
    • 1 XOR 7 = 6
    • 1 XOR 4 = 5
  • you set new values for outl, offl, onl in the motor_on() and motor_off() functions -- ok.
  • you do not set new values for hlvl and llvl, yet you check conditionals on these values in your main() function. This is probably the source of most of your problems. In the first version of the code you posted you did read these values, but you were using the XOR operator so the values were probably not what you expected and thus where not triggering the motor_on() and motor_off() functions called in the conditional branches.
  • additionally, autl and manl are never defined and most C compilers will be angry with you about that; again I'm not familiar with Keil C further than a quick Google search to see that it supports the 8051 architecture.
With regard to your use of XOR -- Typically programmers want to bitmask the contents of a register or value because a particular bit or combination of bits has a special meaning, i.e. - 0x01 means thing A, and 0x02 means thing B. In my example 0x01 and 0x02 are bits that can be set independent of any other bits in the value so if you wanted to check for the "thing A" flag you would have a value, I'll call it input, and you would bitmask it to get only the value of the the "thing A" flag, i.e. - input && 0x01. The resulting value of this operation will be either a 0 or a 1 and will represent the value of the "thing A" flag that you might be interested in.

If you're attempting to do something similar to this, using XOR is probably not what you need to do. Typically you will use the AND operator (&&) to extract specific bits from a value.
 

djsfantasi

Joined Apr 11, 2010
9,156
I agree with theonewho. Plus remember if you are looking at the third bit, you'll have to test for 0 or 4 unless you right shift the bit position into the first bit. In this simple example, it would look like:
Out = (input && 0x04) >>2
Then you could check for 0 or 1
 

djsfantasi

Joined Apr 11, 2010
9,156
Not being familiar with Keil C either nor the sbit command, your link was instructive. IMHO, the syntax of the command is a bit strange. But the link does help me understand your code better. Unfortunately, it's not helping me understand the problem. Yet
 

Thread Starter

Anirban Raha

Joined Dec 4, 2013
70
Not being familiar with Keil C either nor the sbit command, your link was instructive. IMHO, the syntax of the command is a bit strange. But the link does help me understand your code better. Unfortunately, it's not helping me understand the problem. Yet
I do understand that ^ is the XOR bitwise operator. All my life I have used it that way for computer programming. But I have started embedded programming with Keil c, so I am most comfortable with it. Anyways 'autl' and 'manl' can be ignored. They are from another version of the program where I use auto and manual modes. I have deleted that part for simplicity.
The problem is that when I attach my level switches directly, the circuit works. When I attach them through three 15m cables and submerge them in the overhead tank, its not working. I can provide my circuit diagram if you think its necessary.
 

djsfantasi

Joined Apr 11, 2010
9,156
Have you disconnected the cable from the uP and measured it's resistance when submerged and not? When submerged, there may be an electrical path through the liquid (water?) that results in the switch being always on.
 

Thread Starter

Anirban Raha

Joined Dec 4, 2013
70
Have you disconnected the cable from the uP and measured it's resistance when submerged and not? When submerged, there may be an electrical path through the liquid (water?) that results in the switch being always on.
Yup.. Multimeter reads open...But the switch is not always on...it just behaves randomly...like sometimes the high level switch acts as if it were the low level switch...and if conducting water is the problem...then how is my circuit working in a bucket of water?
 

djsfantasi

Joined Apr 11, 2010
9,156
I am trying to guide you to the various points where your design might fail. If it works fine when directly connected - your base circuit is likely not the problem. And in your post #9, you stated that the ciruit did not work when submerged. And then in post you state it works when submerged in a bucket of water. So which is it?

Basically, I suspect something between the circuit and the sensors. Could be one of multiple cables, the total length of cables, the cable connections, or submersion. Each of those points could be introducing a failure. How and why? (rhetorical question, which you should be able to answer, perhaps with some research)

I see seven scenarios which should be individually investigated. Also,it would be useful for you to describe the behavior when it does NOT work.
  • directly connected
  • through one 15m cable
  • through two 15m cables
  • through three 15m cables
  • through one 15m cable, submerged
  • through two 15m cables, submerged
  • through three 15m cables, submerged
 
Top