View previous topic :: View next topic |
Author |
Message |
MDM1985
Joined: 16 Oct 2014 Posts: 14
|
Hysteresis for two thresholds |
Posted: Sun Oct 19, 2014 7:55 am |
|
|
Hi. First of all very nice and useful forum. I am an electronic engineer and I need to add hysteresis for two thresholds in order to avoid the relay chattering. Here the pseudo code without hysteresis:
if a <= 100
Out = 01
Else if a > 100 and b <= 400
Out = 10
Else if b > 400
Out = 11
Else
Out = 11
I am reading a voltage value from a potentiometer using the adc channel of my pic16F886 and, when I am close to the thresholds, I would like to have a stable output. Here my solution but I don't know if it is right:
Hysteresis low = abs a - 100
Hysteresis high = abs b - 400
If a <= 100
Out = 01
If hysteresis low <= 30
Out = blind
Else if a >100 and a <= 400
Out = 10
If hysteresis low <= 30 or hysteresis high <= 30
Out = blind
Else if a > 400
Out = 11
If hysteresis high <30
Out = blind
Else
Out = 11
Thank you for your help
☺ |
|
|
rikotech8
Joined: 10 Dec 2011 Posts: 376 Location: Sofiq,Bulgariq
|
|
Posted: Sun Oct 19, 2014 12:47 pm |
|
|
I can't grasp your code very well, but here is
Simple code that will handle hysteresis:
Code: |
adc_val = read_adc();
if (adc_val > UPPER_ THRESHOLD)
{
output_high(RELAY);
}
if (adc_val < LOWER_THRESHOLD)
{
output_low(RELAY);
} |
You must define your own values for both thresholds. _________________ A person who never made a mistake never tried anything new. |
|
|
MDM1985
Joined: 16 Oct 2014 Posts: 14
|
|
Posted: Sun Oct 19, 2014 1:25 pm |
|
|
Here the code:
Code: | #define blind 0
...
int state;
adc_val = read_adc();
threshold_low = 100;
threshold_high = 400;
hysteresis_low = abs(adc_val - threshold_low);
hysteresis_high = abs(adc_val - threshold_high);
if (adc_val <= threshold_low) {
otpuput_high (relay 1);
if (hysteresis_low <= 30)
state = blind; //if the adc_val is close to the low threshold, don't do anything
}
else
if (adc_val <= threshold_high && adc_val > threshold_low) {
otpuput_high (relay 2);
output_low (relay 1);
if (hysteresis_high <= 30 || hysteresis_low <= 30)
state = blind; // if the adc_val is close to the low threshold or high threshold, don't do anything
}
else
if (adc_val > threshold_high) {
otpuput_low (relay 1);
otpuput_low (relay 2);
if (hysteresis_high <= 30)
state = blind; //if the adc_val is close to the high threshold, don't do anything
}
else {
otpuput_low (relay 1);
otpuput_low (relay 2);
} |
I would like to avoid the chattering of the relay1 when the value from potenziometer is close to the low threshold and the same for the relay 2 when the value from potenziometer is close to the high threshold; here an example:
relay 1 and 2 off
---------------------- relay 2 is still on
------------------------------- threshold_high
---------------------- relay 2 is still on
relay 2 on and 1 off
---------------------- relay 1 is still on
------------------------------- threshold_low
---------------------- relay 1 is still on
relay 1 on and 2 off |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Sun Oct 19, 2014 2:55 pm |
|
|
OK. You've got one adc input, yet want to control two relays.
Please explain more clearly EXACTLY what you want to happen.
(Say as the adc_value increases then decreases.)
Like rikotech8 I can't decipher either your real or pseudo code.
Mike |
|
|
MDM1985
Joined: 16 Oct 2014 Posts: 14
|
|
Posted: Mon Oct 20, 2014 12:01 am |
|
|
Yes,when the adc_value is changing close to the threshold, for example the low threshold, I would have a stable output. For example, when the adc_value is 101 relay is on but, when the adc_value step from 99 to 101 the relay is off on off on off on and then stable on... I would like to have a stable output without chattering. I would like to know how add two hysteresis since I have two thresholds.
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Mon Oct 20, 2014 1:03 am |
|
|
This is a classic 'state' problem:
Code: |
#define RELAY_1_ON (130)
#define RELAY_2_ON (160) //Set where you want
#define THRESHOLD (5) //threshold to turn off
#define OFF 0
#define R1 1
#define R2 2 //binary masks - place to suit the relay bits required
int8 state=OFF;
..........
//Now, assume arrive here with variable 'volt' from the adc
if (volt>RELAY_1_ON)
state|=R1; //turn relay 1 on
else
{
//only get here if _not_ above the 'on' point
if (volt<(RELAY_1_ON-THRESHOLD))
state&=(~R1); //turn relay 1 off if below ON-THRESHOLD
}
//Now the same for relay 2
if (volt>RELAY_2_ON)
state|=R2; //turn relay 2 on
else
{
if (volt<(RELAY_2_ON-THRESHOLD))
state&=(~R2); //turn relay 2 off if below ON-THRESHOLD
}
//then just output the bits to the relays
output_b(state); //whatever port you are using
|
The individual bits (R1, and R2) get turned 'on' if above the specified 'ON' points, but then have to drop 'THRESHOLD' counts below this point, before they will turn off. |
|
|
rikotech8
Joined: 10 Dec 2011 Posts: 376 Location: Sofiq,Bulgariq
|
|
Posted: Mon Oct 20, 2014 7:44 am |
|
|
I would like to mention to put a mask on state, when applied to the port:
Code: | output_b(state & 0x03) |
Only if you are using the rest of the port pins. Otherwize would be cleared.
Ttelmah, correct me if I am wrong _________________ A person who never made a mistake never tried anything new. |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1911
|
|
Posted: Mon Oct 20, 2014 8:57 am |
|
|
rikotech8 wrote: | I would like to mention to put a mask on state, when applied to the port:
Code: | output_b(state & 0x03) |
Only if you are using the rest of the port pins. Otherwize would be cleared.
Ttelmah, correct me if I am wrong |
To set a particular port pin which leaves the state of the other pins alone, use | (OR). Specifically, either read the state of the port (or if you "remember" what it is), then OR that with a pattern corresponding to the pin(s) you want to set.
To clear a particular port pin which leaves the state of the other pins alone, you need to & (AND) with a suitable pattern that will leave the state of the other pins alone. If you wanted to clear bit 0, you'd and with 0xfe to ensure that the other pins weren't cleared by the operation. |
|
|
rikotech8
Joined: 10 Dec 2011 Posts: 376 Location: Sofiq,Bulgariq
|
|
Posted: Mon Oct 20, 2014 9:17 am |
|
|
Yes I see my mistake. Thank you.
So in this case
Code: |
output_b(state | 0x03); |
should be applied? _________________ A person who never made a mistake never tried anything new. |
|
|
alan
Joined: 12 Nov 2012 Posts: 357 Location: South Africa
|
|
Posted: Mon Oct 20, 2014 9:32 am |
|
|
Not quite, that will always switch on bit 0 and 1.
What newguy meant if you were concerned about the other pins you would read back the port latches AND it with 0xfc and then OR it with state which will then only update the first 2 bits.
Must say I think I just confused myself
Code: |
output_b((input_b() & 0xfe) | state); //state must then never be more than 3
|
Regards |
|
|
MDM1985
Joined: 16 Oct 2014 Posts: 14
|
|
Posted: Mon Oct 20, 2014 12:51 pm |
|
|
Ttelmah wrote: | This is a classic 'state' problem:
Code: |
#define RELAY_1_ON (130)
#define RELAY_2_ON (160) //Set where you want
#define THRESHOLD (5) //threshold to turn off
#define OFF 0
#define R1 1
#define R2 2 //binary masks - place to suit the relay bits required
int8 state=OFF;
..........
//Now, assume arrive here with variable 'volt' from the adc
if (volt>RELAY_1_ON)
state|=R1; //turn relay 1 on
else
{
//only get here if _not_ above the 'on' point
if (volt<(RELAY_1_ON-THRESHOLD))
state&=(~R1); //turn relay 1 off if below ON-THRESHOLD
}
//Now the same for relay 2
if (volt>RELAY_2_ON)
state|=R2; //turn relay 2 on
else
{
if (volt<(RELAY_2_ON-THRESHOLD))
state&=(~R2); //turn relay 2 off if below ON-THRESHOLD
}
//then just output the bits to the relays
output_b(state); //whatever port you are using
|
The individual bits (R1, and R2) get turned 'on' if above the specified 'ON' points, but then have to drop 'THRESHOLD' counts below this point, before they will turn off. |
Sorry, but I don't understand.
When volt > RELAY_2_ON, we have also the condition volt > RELAY_1_ON thus relay 1 and relay 2 are ON? Is this correct? |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Tue Oct 21, 2014 5:41 am |
|
|
MDM1985 wrote: | Sorry, but I don't understand.
When volt > RELAY_2_ON, we have also the condition volt > RELAY_1_ON thus relay 1 and relay 2 are ON? Is this correct? |
I asked several post ago for an EXACT description of what you want.
You have not responded, so I'll ask again in a different format.
(From the trend in the thread it appears that others like myself can't decipher what you want either.)
What do you want the relay states to be :-
1) Below the lower threshold?
2) Between the two thresholds?
3) Above the upper threshold?
Mike |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19553
|
|
Posted: Tue Oct 21, 2014 7:37 am |
|
|
It is perhaps worth also pointing out that any layout you want can already be handled by just using 'state' as a value to test, rather than outputting it directly.
As written, state has four different possible value:
0 volt is below both levels
1 volt is above level1, but below level 2
2 volt is above level2 but below level 1
3 volt is above level1, and above level2
Simply test for these four values, and put out the relay pattern required for each.
Use switch(state), and just put the relay pattern for each state in the four possibilities. |
|
|
MDM1985
Joined: 16 Oct 2014 Posts: 14
|
|
Posted: Tue Oct 21, 2014 2:13 pm |
|
|
Mike Walne wrote: | MDM1985 wrote: | Sorry, but I don't understand.
When volt > RELAY_2_ON, we have also the condition volt > RELAY_1_ON thus relay 1 and relay 2 are ON? Is this correct? |
I asked several post ago for an EXACT description of what you want.
You have not responded, so I'll ask again in a different format.
(From the trend in the thread it appears that others like myself can't decipher what you want either.)
What do you want the relay states to be :-
1) Below the lower threshold?
2) Between the two thresholds?
3) Above the upper threshold?
Mike |
I would like to have relay 1 ON below the lower threshold; when the voltage value is in the middle between the lower threshold and upper threshold, I would like to have relay 1 OFF and relay 2 ON but when the voltage is changing close to the lower threshold (for example TH_LOW + 5 or TH_LOW - 5) I would like to avoid the relay chattering. The same for the upper threshold: I would like to have relay 2 OFF when the voltage is higher than the upper threshold but when the voltage is changing close to the upper threshold, I would like to avoid the relay chattering. |
|
|
Mike Walne
Joined: 19 Feb 2004 Posts: 1785 Location: Boston Spa UK
|
|
Posted: Wed Oct 22, 2014 4:36 am |
|
|
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 |
|
|
|