Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 04:51 07 Jul 2025 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : Testing for Flags.

     Page 1 of 2    
Author Message
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 11:00pm 30 Jun 2016
Copy link to clipboard 
Print this post

Hi All,

Does anyone have suggestions on how to test for Flags.
I'm currently setting 6 bits to indicate various status's of my water heating controller.


I'm using this Sub to set them:-

[Code]
Sub SetFlags

StatFlags=0

If SolarVolts>=SolarMin Then StatFlags=&b000001
If SolarVolts>=SolarThres Then StatFlags=StatFlags+&b000010
If TmpPan-TmpCur>=TmpDifPan Then StatFlags=StatFlags+&b000100
If TmpOut-TmpInp>=TmpDif Then StatFlags=StatFlags+&b001000
If PumpStat="Running" Then StatFlags=StatFlags+&b010000
If PumpRunTime>300 then StatFlags=StatFlags+&b100000

End Sub
[/code]

I want my control logic to make decisions based on these.

How would I test for given bit patterns like:-

????00, ignoring all but the first 2 bits.
or
00???111

There are certain things I need to ignore at given times, like input/output temp, which means nothing when runtime is less than 10 minutes.

Once it's running, solar level can be ignored, providing minimum Delta Temp is met.
This could typically but a day that's become overcast, but is still providing a certain degree of heating.

Thanks

Phil.

Edit:-
I know I can probably do some parts with shift operators.
Not Sure in AND, OR & XOR will do it either.Edited by Phil23 2016-07-02
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2932
Posted: 12:09am 01 Jul 2016
Copy link to clipboard 
Print this post

Hi Phil,

I personally would use AND to set bits in your StatFlags value.

Then to test if a bit is set, mask the bit out with an AND, then divide by the relevant value to then perform a test. If the test is a single bit then easy to use an IF...THEN..ELSE. Otherwise, if the test is more than one bit I would use SELECT CASE.

Hope this makes sense, if not then I can provide example code (but not till a bit later)

WW
 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3282
Posted: 01:00am 01 Jul 2016
Copy link to clipboard 
Print this post

Unless you are running short of RAM it does not make sense to pack multiple flags into one variable. Just use a variable for each flag.

Geoff
Geoff Graham - http://geoffg.net
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2932
Posted: 01:06am 01 Jul 2016
Copy link to clipboard 
Print this post

. . . or an array where the index is the flag reference number

i.e. StatFlag(1) represents SolarVolts flag
StatFlag(2) represents TmpPan flag
StatFlag(3) represents TmpOut flag

etc, etcEdited by WhiteWizzard 2016-07-02
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 4036
Posted: 01:19am 01 Jul 2016
Copy link to clipboard 
Print this post

I'm with Geoff on this.

Doing cunning things tends to make code hard to read and maintain so unless forced into it don't do it.

It's easy to grasp code like
if LevelTooLow and PumpOff
TurnPumpOn()
...

John
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 01:32am 01 Jul 2016
Copy link to clipboard 
Print this post

Thanks WW,

I knew using the If statements & adding the binay values was a pretty tacky way of setting the flags up, but can't quite get my head around the right way to set them; way to rusty in the head...

Had planned on using a Case Statement for the pump control, but wanted to get the flags working right first.

This is the logic I want to replace with Case Statements using flags.

[Code]
'Start Pump & Light Red LED
IF SolarVolts<SolarMin Then 'Test if Solar is Below Daylight Level
PumpStat="Stopped" 'Turn Pump Off
Pin(PinPump1)=1
Else If (SolarVolts>=SolarThres And TmpPan-TmpCur>=TmpDifPan) Or (TmpOut-TmpInp>=TmpDif And PumpStat="Running") Then 'Test if Solar and Panel Temp is
If PumpStat="Stopped" then PumpOnTime=Time$ 'above Threshold OR Required Temp Dif exists
PumpRunTime=TimeSecs(Time$)-TimeSecs(PumpOnTime)
PumpStat="Running" 'Turn Pump On
pin(PinPump1)=0
else If (SolarVolts<SolarThres AND TmpOut-TmpInp<TmpDif) And PumpRuntime>300 Then 'Pump off Test
PumpStat="Stopped" 'Turn the Pump Off.
pin(PinPump1)=1
endif
[/code]

The current IF based code will just get too messy once other conditions are introducted..

Some examples would be greatly appreciated.

Cheers.
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2932
Posted: 01:57am 01 Jul 2016
Copy link to clipboard 
Print this post

The good thing with BASIC is that there are many ways to achieve what you need - no right or wrong, just more what is best suited to you needs.

From what I've seen so far, if you have variables containing 'data' that you wish to use, then use flags with the same name but prefix with an 'f'.

So the flag for SolarVolts becomes fSolarVolts (or even flagSolarVolts

Can someone confirm is there is a limit to the number of characters to a variable name!

 
Geoffg

Guru

Joined: 06/06/2011
Location: Australia
Posts: 3282
Posted: 03:12am 01 Jul 2016
Copy link to clipboard 
Print this post

Yes, it is 32.
Geoff Graham - http://geoffg.net
 
kiiid

Guru

Joined: 11/05/2013
Location: United Kingdom
Posts: 671
Posted: 08:45am 01 Jul 2016
Copy link to clipboard 
Print this post

Maybe it is a good time for introduction of BIT type variables? By an old habit I am 'packing' flags as well - it simply hurts to spend 32 bits for a single one.
http://rittle.org

--------------
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 4036
Posted: 09:46am 01 Jul 2016
Copy link to clipboard 
Print this post

Except for the really huge programs there's no need for a BIT data type, as until that huge size it's enough to use ordinary data type(s) (normally float or integer).

The kind of program so far mentioned does not seem huge at all.

I think a new data type would add complexity and reduce free space for user programs so may not be the best solution.

No doubt Geoff has the most important view (and final decision) on this.

John
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 11:51am 01 Jul 2016
Copy link to clipboard 
Print this post

  JohnS said   I'm with Geoff on this.

Doing cunning things tends to make code hard to read and maintain so unless forced into it don't do it.

It's easy to grasp code like
if LevelTooLow and PumpOff
TurnPumpOn()
...

John


Yes Agree,

One of the reasons I decided to setup the Flags was so I could view some system status while developing the control logic.

Once I add the heat pump & motorised ball valves there will be a lot of status to monitor & observe.

Will really lend it's self to a graphical interface on a MicroMite Plus...




There are a few curly situations.

Like first thing of a morning, the input & output temp sensors are useless.

Right now (7:30am) I see current temp at 13.5°C.
Input at 6.3, Output at 9.4°C, both irrelevant temps based more on ambient influence.

They require about 8-10 minutes of runtime before meaningful data is returned.

Once Solar Volts reaches 350mV there is sun sufficient to begin heating the panels.
Once the panels are 5° above water temp the pump is started.

The other situation I've observed is that when it becomes overcast, Solar volts can drop well below 350mV, yet there is still quite a lot of energy present.

Enough to keep the panel above the water temp and temp out above temp in.

I know I'm trying to be greedy with the amount of heating I'm trying to achieve.

4,200kJ to raise 1000 litres 1°C.

I got 4° a few days back; 16,800kJ=4.7kWh=$1.13 on my current rate. $101.00 over the billing period. Pump run cost is 11c for 6 hours.

Back in Mid March, I was producing around 5kW hours with a single panel.
The 4.7kW hours earlier this week was with the current 3 panels.

All that said, I'm open to advice, very aware that some of my "Brilliant Ideas" have serious short comings.

Cheers

PhilEdited by Phil23 2016-07-02
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 4036
Posted: 11:59am 01 Jul 2016
Copy link to clipboard 
Print this post

I'm sure everyone wants to help if they can, and it sounds an interesting project too.

It sounds like figuring out which sensor has a sane value and when is tougher than the code!

John
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 03:06pm 01 Jul 2016
Copy link to clipboard 
Print this post

  JohnS said   I'm sure everyone wants to help if they can, and it sounds an interesting project too.[/quote]

Yes it is interesting.

A fair bit of hardware consideration too.
Currently 3 panels on the roof, 2400mm black Coro sheets with 25mm irrigation pipe under clear poly carb. Total volume of water that goes to the roof is about 50 litres.

Plumbed in parallel, but not sure I've got the flow rate evenly distributed yet.

Circulation rate is about 6-7 litres/minute.

Circulation pump draws 85 watts & two motorised ball valves will control whether the water goes thru the panels or the heat pump.

BUT, in cooler weather I'd like it to pass thru both; Why sacrifice a solar benefit that can be gained in place of only heat pump input.
[Quote]
It sounds like figuring out which sensor has a sane value and when is tougher than the code!


That bits reasonably easy to figure in your head, translating the sensor output & getting it into logic and code is the hard bit.

Interesting exercise last week....
It was 14°C, overcast & gloomy, but had a feeling there was energy available.

Picked up the black side cover off a computer, measured it at 12°C with the laser thermometer.

Placed it in the "Sun", which was basically non existent, & it rose to 23° in under 5 minutes.

Ran the pump manually for 2 1/2 hours & saw a Delta T° of 0.4°, the whole 1000 litres rising by 0.2.

Cheers.

Phil.
 
Phil23
Guru

Joined: 27/03/2016
Location: Australia
Posts: 1667
Posted: 03:34pm 01 Jul 2016
Copy link to clipboard 
Print this post

  WhiteWizzard said   Hi Phil,

I personally would use AND to set bits in your StatFlags value.

Then to test if a bit is set, mask the bit out with an AND, then divide by the relevant value to then perform a test.


Can't quite get my head around that.

I did manage a variation to set the bit using an OR, but still don't think I'm on the right track.

[Code]
SolarMin=100
SolarThres=350
SolarVolts=250
TmpCur=14
TmpInp=12.5
TmpOut=14.6
TmpDif=.5
TmpPan=18
TmpDifPan=5
PumpStat$="Running"
PumpRunTime=200

SetFlags

Print Bin$(StatFlags,6)



Sub SetFlags

StatFlags=0

StatFlags=(PumpRunTime>300 OR 0)<<1
StatFlags=(PumpStat$="Running" OR StatFlags)<<1
StatFlags=(TmpOut-TmpInp>=TmpDif OR StatFlags)<<1
StatFlags=(TmpPan-TmpCur>=TmpDifPan OR StatFlags)<<1
StatFlags=(SolarVolts>=SolarThres OR StatFlags)<<1
StatFlags=(SolarVolts>=SolarMin OR StatFlags)

End Sub
[/code]

RUN
011001
>

An example would be welcomed.

Cheers

Phil.
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2932
Posted: 09:03pm 01 Jul 2016
Copy link to clipboard 
Print this post

Hi Phil,

The way in which you are setting your flags in your original post is fine (i.e. when testing whether or not to set ALL flag condition bits sequentially).

However, if you ever need to work on just a single flag bit then you would need to use OR (not AND as I posted. Sorry, my brain was running ahead of my fingers typing! ).

So for example if you wanted to test whether to set a single flag bit such as your TmpDif then use:
IF (TmpOut-TmpInp)>=TmpDif THEN StatFlags=StatFlags OR &b001000


In this way none of the other bits are affected.

Regarding Testing for bit patterns (i.e. your original question), I will post in a short while as want to test it on a MM here so I get the syntax 100% correct . . . .

WW
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2932
Posted: 09:25pm 01 Jul 2016
Copy link to clipboard 
Print this post

. . . . continuing from my previous post; to test for a condition where ALL required flag bits are SET then use the following:


testCondition = &b011010 'set ALL the bits you wish to be true to '1'. Any bits here set to '0' will ignore that flag
IF (StatFlags AND testCondition) = testCondition THEN
......
ENDIF


In the above, I am using a mask variable called 'testCondition' in which the flag bit conditions you wish to ALL be TRUE are set to 1 in the testCondition variable.

Is this what you need, or will then be scenarios where you need IF Condition1 OR Condition2 THEN . . . Edited by WhiteWizzard 2016-07-03
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10215
Posted: 09:41pm 01 Jul 2016
Copy link to clipboard 
Print this post

Here are a range of functions and subroutines that allow a program to maintain up to 32 single bit flags. These are stored in a "hidden" bit of memory. The use of the functions "flag" which returns true if the flag is set and "notflag" which returns true if the flag is clear makes the test for combinations extremely simple. By setting constants to name the flags you can then make the code very easy to read. It is probably good practice to clear all flags at the top of the program to get them all into a known state - don't assume they will start off clear.

Option explicit
option default NONE
const myflagA=19
const myflagB=27
clearallflags()
'
setflag(myflagA)
print flag(myflagA)
print notflag(myflagA)
print flag(myflagA) and notflag(myflagB) 'test for A set and B not set
'
toggleflag(myflagB)
print flag(myflagB)
print notflag(myflagB)
print flag(myflagA) and flag(myflagB) 'test for A set and B set
end


CSub clearallflags 'clears 32 hidden flags
00000000
3C029D00 8C430090 A060003C 8C430090 A060003D 8C430090 A060003E 8C420090
03E00008 A040003F
End CSub
'
CSub setflag 'set a flag (0-31)
00000000
8C830000 3C029D00 8C440090 000310C3 24050001 00821021 9044003C 30630007
00651804 00641825 03E00008 A043003C
End CSub
'
CSub clearflag 'clear a flag (0-31)
00000000
8C830000 3C029D00 8C440090 000310C3 24050001 00821021 9044003C 30630007
00651804 00031827 00641824 03E00008 A043003C
End CSub
'
CSub toggleflag 'invert a flag (0-31)
00000000
8C830000 3C029D00 8C440090 000310C3 24050001 00821021 9044003C 30630007
00651804 00641826 03E00008 A043003C
End CSub
'
CFunction flag 'test the status of a flag (0-31) and return 1 if set and 0 if not set
00000000
8C830000 3C029D00 8C440090 000310C3 30630007 00821021 8044003C 24020001
00621004 00821024 00621007 03E00008 00021FC3
End CFunction
'
CFunction notflag 'test the status of a flag (0-31) and return 0 if set and 1 if not set
00000000
8C820000 3C039D00 8C640090 000218C3 30420007 00831821 8064003C 24030001
00431804 00831824 00431007 2C420001 03E00008 00001821
End CFunction

'
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2932
Posted: 10:16pm 01 Jul 2016
Copy link to clipboard 
Print this post

@matherp

From which firmware versions will this run on please?
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10215
Posted: 10:24pm 01 Jul 2016
Copy link to clipboard 
Print this post

  Quote  From which firmware versions will this run on please?


should run on anything 5.0 up
 
WhiteWizzard
Guru

Joined: 05/04/2013
Location: United Kingdom
Posts: 2932
Posted: 10:34pm 01 Jul 2016
Copy link to clipboard 
Print this post

Yep - got it running nicely.

Took a while for me to 'tune into' your offering, but once there, this is a very useful bit of code.

Thanks - should prove useful for the other Phil
 
     Page 1 of 2    
Print this page
The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025