![]() |
Forum Index : Microcontroller and PC projects : Testing for Flags.
Page 1 of 2 ![]() ![]() |
|||||
Author | Message | ||||
Phil23 Guru ![]() Joined: 27/03/2016 Location: AustraliaPosts: 1667 |
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. |
||||
WhiteWizzard Guru ![]() Joined: 05/04/2013 Location: United KingdomPosts: 2932 |
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: AustraliaPosts: 3282 |
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 KingdomPosts: 2932 |
. . . 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, etc |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 4036 |
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: AustraliaPosts: 1667 |
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 KingdomPosts: 2932 |
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: AustraliaPosts: 3282 |
Yes, it is 32. Geoff Graham - http://geoffg.net |
||||
kiiid Guru ![]() Joined: 11/05/2013 Location: United KingdomPosts: 671 |
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 KingdomPosts: 4036 |
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: AustraliaPosts: 1667 |
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 Phil |
||||
JohnS Guru ![]() Joined: 18/11/2011 Location: United KingdomPosts: 4036 |
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: AustraliaPosts: 1667 |
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: AustraliaPosts: 1667 |
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 KingdomPosts: 2932 |
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 KingdomPosts: 2932 |
. . . . 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 . . . |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10215 |
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 KingdomPosts: 2932 |
@matherp From which firmware versions will this run on please? |
||||
matherp Guru ![]() Joined: 11/12/2012 Location: United KingdomPosts: 10215 |
should run on anything 5.0 up |
||||
WhiteWizzard Guru ![]() Joined: 05/04/2013 Location: United KingdomPosts: 2932 |
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 ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |