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

Hysteresis for two thresholds
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
MDM1985



Joined: 16 Oct 2014
Posts: 14

View user's profile Send private message

PostPosted: Wed Oct 22, 2014 5:07 am     Reply with quote

Mike Walne wrote:
What you now have is a system with five states, as shown below:-

Code:
Max. ADC reading


Upper region. Set required relays state here


---------------------------------------
TH2 Do NOTHING in this region (dead-band)
---------------------------------------


Middle region. Set required relays state here



---------------------------------------
TH1 Do NOTHING in this region (dead-band)
---------------------------------------



Lower region. Set required relays state here



Min. ADC reading

There are three regions where you can change the relay states.
Make sure you do not change the relay states in either of the two dead-bands.
The width of the dead-band depends on your system (noise, jitter, etc).
How you program is up to you.

Mike


Perfect, this is the system but I don't know how implement it. Could you help me, please?
I am desperate Sad
MDM1985



Joined: 16 Oct 2014
Posts: 14

View user's profile Send private message

PostPosted: Wed Oct 22, 2014 11:30 am     Reply with quote

Here my code:

Code:

if (v < th_low - k) // k is a value to set
{
   state = 0;
}
else
if ((v > th_low + k) && (v < th_high - k))
{
   state = 1;
}
else
if (v > th_high + k)
{
   state = 2;
}

switch(state)
{

case 0:
output_high(RELAY_1);
output_low(RELAY_2);
if ((v >= th_low - k) && (v <= th_low + k)) // inside the lower dead region
{
 state = 3;
}
else
if (v > th_low + k)
{
state = 1;
}
break;

case 1:
output_low(RELAY_1);
output_high(RELAY_2);
if ((v >= th_low - k) && (v <= th_low + k)) // inside the lower dead region
{
 state = 3;
}
else
if ((v >= th_high - k) && (v <= th_high + k)) // inside the upper dead region
{
 state = 3;
}
else
if (v < th_low - k)
{
state = 0;
}
else
if (v > th_low + k)
{
state = 2;
}
break;

case 2:
output_low(RELAY_1);
output_low(RELAY_2);
if ((v >= th_high - k) && (v <= th_high + k)) // inside the upper dead region
{
 state = 3;
}
else
if (v < th_high - k)
{
state = 1;
}
break;

case 3: ??????????
break;

default: break;
}

Can anyone help me?
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Wed Oct 22, 2014 3:00 pm     Reply with quote

You're making life too complicated.
You don't need to define state 3, like I said it's a do NOTHING state.
You can get rid of the if/elses and the switches.
So your code (untested) could reduce to something like:-

Code:
if (v < th_low - k) // k is a value to set
{
   state = 0;
   output_high(RELAY_1);
   output_low(RELAY_2);
}

if ((v > th_low + k) && (v < th_high - k))
{
   state = 1;
   output_low(RELAY_1);
   output_high(RELAY_2);
}

if (v > th_high + k)
{
   state = 2;
   output_low(RELAY_1);
   output_low(RELAY_2);
}

Anything else is dead-band!!!!!

Mike
gaugeguy



Joined: 05 Apr 2011
Posts: 303

View user's profile Send private message

PostPosted: Wed Oct 22, 2014 4:18 pm     Reply with quote

That will work fine as long as the variable changes continuously. If there can be jumps between trips through the test then you could go from State = 0 to the deadband between State 1 and State 2. The current relay positions would then be incorrect and should be changed to either State 1 or State 2, but not left at State 0.
MDM1985



Joined: 16 Oct 2014
Posts: 14

View user's profile Send private message

PostPosted: Thu Oct 23, 2014 12:06 am     Reply with quote

I think that this is a threshold comparator with two hysteresis, one for the upper dead band and one for the lower.

Any advice? I think that a switch with five case could resolve the problem. Confused
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Thu Oct 23, 2014 1:06 am     Reply with quote

gaugeguy wrote:
That will work fine as long as the variable changes continuously. If there can be jumps between trips through the test then you could go from State = 0 to the deadband between State 1 and State 2. The current relay positions would then be incorrect and should be changed to either State 1 or State 2, but not left at State 0.

OK, but we're being given little to go on.

From what we have been told:-

If you're in the upper dead-band the only certainty is relay 1 OFF
If you're in the lower dead-band nothing is certain.

Mike
MDM1985



Joined: 16 Oct 2014
Posts: 14

View user's profile Send private message

PostPosted: Thu Oct 23, 2014 10:33 am     Reply with quote

gaugeguy wrote:
That will work fine as long as the variable changes continuously. If there can be jumps between trips through the test then you could go from State = 0 to the deadband between State 1 and State 2. The current relay positions would then be incorrect and should be changed to either State 1 or State 2, but not left at State 0.


This is right. Have you any advice?
If I try this code:
Code:

if (v < th_low - k) // k is a value to set
{
   state = 0;
 
}

if ((v > th_low + k) && (v < th_high - k))
{
   state = 1;
   
}

if (v > th_high + k)
{
   state = 2;
   
}

and the variable changes continuously then it is OK!
But when the adc read the first time (after the start of the system), and the value of the variable v = read_adc() is inside the dead region, the output is incorrect. Thus I have tried this code:

Code:

if (v < th_low - k) // k is a value to set
{
   state = 0;
 
}

if ((v > th_low + k) && (v < th_high - k))
{
   state = 1;
   
}

if (v > th_high + k)
{
   state = 2;
   
}


switch (state)
case 0:

output_high(RELAY_1);
output_low(RELAY_2);
if (v > th_low + K)
{
state = 1;
}
 
break;

case 1:

output_low(RELAY_1);
output_high(RELAY_2);
if (v < th_low - K)
{
state = 0;
}
if (v > th_high + K)
{
state = 2;
}

break;

case 2:

output_low(RELAY_1);
output_low(RELAY_2);
if (v < th_high - K)
{
state = 1;
}
 
break; 

default: break;

but this code has the same behaviour.
I don't know what to do anymore Crying or Very sad
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Thu Oct 23, 2014 3:26 pm     Reply with quote

Maybe you need to have a radical rethink.

Start with your relay states.
With your current system you change both relays as you pass from the lower region to the middle one.
Suppose you change to this:-
Code:
Max. ADC reading

Upper region. Relay 1 OFF, Relay 2 ON

---------------------------------------
TH2 Upper dead-band.
---------------------------------------

Middle region. Relay 1 ON, Relay 2 ON

---------------------------------------
TH1 Lower dead-band.
---------------------------------------

Lower region. Relay 1 ON, Relay 2 OFF

Min. ADC reading

What you now KNOW for certain is:-

1) In the lower dead-band Relay 1 is ON.
2) In the upper dead-band Relay 2 is ON.

In either dead-band you only KNOW about one of the Relays.
The state of the other is going to be right half of the time.

Mike

OR You could have the middle region with both relays OFF.
Might make life easier.
I don't know, it's your project, and you're making us second guess.
MDM1985



Joined: 16 Oct 2014
Posts: 14

View user's profile Send private message

PostPosted: Fri Oct 24, 2014 10:58 am     Reply with quote

I think that this code could solve my problem:
Code:

v = read_adc();

switch (state)
{

case 0:  //IDLE STATE; only the first time.

if (v < th_low)
{
state = 1;
}

if (v < th_high && v > th_low)
{
state = 2;
}

if (v > th_high)
{
state = 3;
}
break;
 

case 1:  //state under the lower threshold

output_high(RELAY_1);
output_low(RELAY_2);

if (v >= th_high + k)
{
state = 3;
}
else if ((v >= th_low + k) && (v <= th_high - k))
{
state = 2;
}
break;

case 2:  //in the middle

output_low(RELAY_1);
output_high(RELAY_2);

if (v >= th_low + k)
{
state = 1;
}
else if (v >= th_high + k)
{
state = 3;
}
break;
 
case 3:  //state above the higher threshold

output_high(RELAY_1);
output_low(RELAY_2);

if (v >= th_low - k)
{
state = 1;
}
else if ((v >= th_low + k) && (v <= th_high - k))
{
state = 2;
}
break;
 
default:
state = 0;
break;
}

This is the physical system:

state 3
____________________ th_high + k
___________________________ th_high
____________________ th_high - k

state 2

____________________ th_low + k
___________________________ th_low
____________________ th_low - k

state 1
According to you, this code is proper?
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Fri Oct 24, 2014 11:30 am     Reply with quote

OK. I've had a quick look at your code.
It's quite cumbersome but should, in principle, work.

You're now:-

Getting into a known state at start-up. OK
Then depending on latest state deciding on a possible new state. OK

However it looks like you've got a typo or so.
You may have an odd test missing.
You don't need to worry about the hysteresis of a far away band.
(E.g. When in the lower region, your State1 you only need to handle the lower dead-band, not the upper dead-band)

I'm not going to do it for you.

You need to try it all out on REAL hardware.

Mike
MDM1985



Joined: 16 Oct 2014
Posts: 14

View user's profile Send private message

PostPosted: Fri Oct 24, 2014 12:16 pm     Reply with quote

Mike Walne wrote:
OK. I've had a quick look at your code.
It's quite cumbersome but should, in principle, work.

You're now:-

Getting into a known state at start-up. OK
Then depending on latest state deciding on a possible new state. OK

However it looks like you've got a typo or so.
You may have an odd test missing.
You don't need to worry about the hysteresis of a far away band.
(E.g. When in the lower region, your State1 you only need to handle the lower dead-band, not the upper dead-band)

I'm not going to do it for you.

You need to try it all out on REAL hardware.

Mike


Hi Mike, sorry but I don't understand this:
Quote:
However it looks like you've got a typo or so.
You may have an odd test missing.

Could you explain me with more detail, please?

Anyway, i worry about the far away dead band in order to have a system that can manage also a discrete voltage changing (for example when the voltage at the input of the adc has a jump from 1 to 4 volt - of course, this is not the case of a potentiometer Smile ).

MDM
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Fri Oct 24, 2014 5:21 pm     Reply with quote

As I said before I only did a quick check.
I thought you had missed a test, but on more careful examination they do all seem to be there.
There are, however, some glaring errors which testing in the real world will reveal.
I have duplicated your code and added some comments.

Code:
v = read_adc();

switch (state)
{

case 0:  //IDLE STATE; only the first time.

if (v < th_low)
{
state = 1;
}

if (v < th_high && v > th_low)
{
state = 2;
}

if (v > th_high)
{
state = 3;
}
break;
 

case 1:  //state under the lower threshold
// Here you're in State_1 from a previous test.
// When you do your new tests and your voltage is in the upper dead-band you will not get a new result.
// However you know for certain that you are no longer in State_1 and can change to a new one.
// Think about it.

output_high(RELAY_1);
output_low(RELAY_2);

if (v >= th_high + k)
{
state = 3;
}
else if ((v >= th_low + k) && (v <= th_high - k))
{
state = 2;
}
break;

case 2:  //in the middle

output_low(RELAY_1);
output_high(RELAY_2);

// Check this next line of code very carefully.
if (v >= th_low + k)
{
state = 1;
}
else if (v >= th_high + k)
{
state = 3;
}
break;
 
case 3:  //state above the higher threshold

output_high(RELAY_1);
output_low(RELAY_2);

// Similar issues to both case 1 and case 2 !!!!!!!!!!!!!!
if (v >= th_low - k)
{
state = 1;
}
else if ((v >= th_low + k) && (v <= th_high - k))
{
state = 2;
}
break;
 
default:
state = 0;
break;
}


As a further repeat comment, you can skip most of the 'elses', they just add to the confusion.
I believe I have now done more than enough for you.
It's up to you to do some testing, testing testing then more testing.

Mike
MDM1985



Joined: 16 Oct 2014
Posts: 14

View user's profile Send private message

PostPosted: Sat Oct 25, 2014 7:04 am     Reply with quote

Mike Walne wrote:
As I said before I only did a quick check.
I thought you had missed a test, but on more careful examination they do all seem to be there.
There are, however, some glaring errors which testing in the real world will reveal.
I have duplicated your code and added some comments.

Code:
v = read_adc();

switch (state)
{

case 0:  //IDLE STATE; only the first time.

if (v < th_low)
{
state = 1;
}

if (v < th_high && v > th_low)
{
state = 2;
}

if (v > th_high)
{
state = 3;
}
break;
 

case 1:  //state under the lower threshold
// Here you're in State_1 from a previous test.
// When you do your new tests and your voltage is in the upper dead-band you will not get a new result.
// However you know for certain that you are no longer in State_1 and can change to a new one.
// Think about it.

output_high(RELAY_1);
output_low(RELAY_2);

if (v >= th_high + k)
{
state = 3;
}
else if ((v >= th_low + k) && (v <= th_high - k))
{
state = 2;
}
break;

case 2:  //in the middle

output_low(RELAY_1);
output_high(RELAY_2);

// Check this next line of code very carefully.
if (v >= th_low + k)
{
state = 1;
}
else if (v >= th_high + k)
{
state = 3;
}
break;
 
case 3:  //state above the higher threshold

output_high(RELAY_1);
output_low(RELAY_2);

// Similar issues to both case 1 and case 2 !!!!!!!!!!!!!!
if (v >= th_low - k)
{
state = 1;
}
else if ((v >= th_low + k) && (v <= th_high - k))
{
state = 2;
}
break;
 
default:
state = 0;
break;
}


As a further repeat comment, you can skip most of the 'elses', they just add to the confusion.
I believe I have now done more than enough for you.
It's up to you to do some testing, testing testing then more testing.

Mike


Hi Mike, according to your comments, I have changed my code.

When I am in the state 1, I jump into the state 3 if v > th_high and I don't care about the upper dead region (so v > th_high + k is incorrect). The same when I am in the state 3 and I jump into the state 1 if v < th_low (not v < th_low - k). I also deleted the 'elses'.
I think that this code is now correct but I wait for your important comments.

Thank you!

Code:
v = read_adc();

switch (state)
{

case 0:  //IDLE STATE; only the first time.

if (v < th_low)
{
state = 1;
}

if (v < th_high && v > th_low)
{
state = 2;
}

if (v > th_high)
{
state = 3;
}
break;
 

case 1:  //state under the lower threshold

output_high(RELAY_1);
output_low(RELAY_2);

if (v >= th_high) // i don't care about the upper dead region I am in the state 1
{
state = 3;
}

if ((v >= th_low + k) && (v <= th_high))  // i don't care about the upper dead region I am in the state 1
{
state = 2;
}
break;

case 2:  //in the middle

output_low(RELAY_1);
output_high(RELAY_2);


if (v >= th_low - k)
{
state = 1;
}

if (v >= th_high + k)
{
state = 3;
}
break;
 
case 3:  //state above the higher threshold

output_high(RELAY_1);
output_low(RELAY_2);


if (v >= th_low)  // i don't care about the lower dead region when I am in the state 3
{
state = 1;
}

if ((v >= th_low) && (v <= th_high - k))  // i don't care about the lower dead region I am in the state 3
{
state = 2;
}
break;
 
default:
state = 0;
break;
}
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Sat Oct 25, 2014 1:10 pm     Reply with quote

No. It's time for you to do some real testing (I mean really serious rigorous testing).

You've not cleared the error in this section of code.
Code:
case 2:  //in the middle

output_low(RELAY_1);
output_high(RELAY_2);

if (v >= th_low - k)
{
state = 1;
}

if (v >= th_high + k)
{
state = 3;
}
break;
(In my previous post I've shown you which line it is on, and noted it's duplicated elsewhere.)
It's your project, you fix it.

Mike
MDM1985



Joined: 16 Oct 2014
Posts: 14

View user's profile Send private message

PostPosted: Sun Oct 26, 2014 3:37 am     Reply with quote

Mike Walne wrote:
No. It's time for you to do some real testing (I mean really serious rigorous testing).

You've not cleared the error in this section of code.
Code:
case 2:  //in the middle

output_low(RELAY_1);
output_high(RELAY_2);

if (v >= th_low - k)
{
state = 1;
}

if (v >= th_high + k)
{
state = 3;
}
break;
(In my previous post I've shown you which line it is on, and noted it's duplicated elsewhere.)
It's your project, you fix it.

Mike


Hi Mike, I have fixed according your comments:

v = read_adc();

switch (state)
{

case 0: //IDLE STATE; only the first time.

if (v < th_low)
{
state = 1;
}

if (v < th_high && v > th_low)
{
state = 2;
}

if (v > th_high)
{
state = 3;
}
break;


case 1: //state under the lower threshold

output_high(RELAY_1);
output_low(RELAY_2);

if (v > th_high) // i don't care about the upper dead region I am in the state 1 - I jump from state 1 to state 3 when v > th_high
{
state = 3;
}

if ((v >= th_low + k) && (v <= th_high)) // i don't care about the upper dead region I am in the state 1
{
state = 2;
}
break;

case 2: //in the middle

output_low(RELAY_1);
output_high(RELAY_2);


if (v <= th_low - k)
{
state = 1;
}

if (v >= th_high + k)
{
state = 3;
}
break;

case 3: //state above the higher threshold

output_high(RELAY_1);
output_low(RELAY_2);


if (v < th_low) // i don't care about the lower dead region when I am in the state 3 - I jump from state 3 to state 1 when v < th_low
{
{
state = 1;
}

if ((v >= th_low) && (v <= th_high - k)) // i don't care about the lower dead region I am in the state 3
{
state = 2;
}
break;

default:
state = 0;
break;
}

Tomorrow, I am going to try this code in a real hardware where I work and I will let you know.
Thank you for now.

MDM
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, 3  Next
Page 2 of 3

 
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