View previous topic :: View next topic |
Author |
Message |
MDM1985
Joined: 16 Oct 2014 Posts: 14
|
|
Posted: Wed Oct 22, 2014 5:07 am |
|
|
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 |
|
|
MDM1985
Joined: 16 Oct 2014 Posts: 14
|
|
Posted: Wed Oct 22, 2014 11:30 am |
|
|
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
|
|
Posted: Wed Oct 22, 2014 3:00 pm |
|
|
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
|
|
Posted: Wed Oct 22, 2014 4:18 pm |
|
|
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
|
|
Posted: Thu Oct 23, 2014 12:06 am |
|
|
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. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Oct 23, 2014 1:06 am |
|
|
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
|
|
Posted: Thu Oct 23, 2014 10:33 am |
|
|
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 |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Thu Oct 23, 2014 3:26 pm |
|
|
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
|
|
Posted: Fri Oct 24, 2014 10:58 am |
|
|
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
|
|
Posted: Fri Oct 24, 2014 11:30 am |
|
|
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
|
|
Posted: Fri Oct 24, 2014 12:16 pm |
|
|
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 ).
MDM |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Fri Oct 24, 2014 5:21 pm |
|
|
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
|
|
Posted: Sat Oct 25, 2014 7:04 am |
|
|
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
|
|
Posted: Sat Oct 25, 2014 1:10 pm |
|
|
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
|
|
Posted: Sun Oct 26, 2014 3:37 am |
|
|
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 |
|
|
|