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 : MMBasic Flow Simulation
Author | Message | ||||
paceman Guru Joined: 07/10/2011 Location: AustraliaPosts: 1328 |
In the V5.3 "Reguests" thread here LouisG requested a flow simulation command. Some members suggested doing it in MMBasic was a good idea so I've improved the MMBasic V5.2 code I hashed up then and it now allows horizontal or vertical and forward or reverse code. This is running on an MX170 MM2 with an ILI9341 screen but should work with all other later variants because it uses just the basic graphics commands. The code below is a demo to show how the subroutine works but it needs a technique to get rid of the PAUSE command that holds up the main program flow. Can someone show how to do this but still be able to get back to the calling program with the simulation running since to use the subroutine, 'pipes' will variously need to be shut off/reversed etc while others keep 'running'. It also needs a few symbols for valves, pumps etc which could be bitmaps or a special font set made using TassieJim's Font-Tweak utility. If it's useful that can be done later. Greg 'FLUID FLOW SIMULATION - MMBasic V5.2 using the MX170 Micromite & ILI9341 LCD Display ' Greg Yaxley (paceman on TBS) '----------------------------------------------------------------------------------- cls const white = rgb(white) const red = rgb(red) const blue = rgb(blue) const Green = RGB(green) const gray = RGB(gray) const yellow = rgb(yellow) dim integer stx,sty,finx,finy,diam dim integer speed,direction Main: cls BOX 70, 10, 60, 30, 2,white,blue TEXT 72, 12, "HEADER",,,,yellow,blue BOX 240, 80, 40, 50, 2,white,red CIRCLE 260, 200, 20, 2,,white,yellow speed = 20 do flow(10,24,260,24,5,white,blue,speed,1) flow(260,24,260,80,5,white,blue,speed,1) flow(260,130,260,200,5,white,red,speed,1) flow(100,200,260,200,5,white,red,speed,-1) flow(100,105,100,200,5,white,red,speed,-1) flow(10,105,240,105,8,blue,red,speed,-1) loop '---------------------------------------------- sub flow(stx,sty,finx,finy,diam,cull1%,cull2%,speed,direction) 'Fluid flow is indicated as alternate coloured segments - forward, reverse or stationary. 'Forward flow (direction) is the default and defined as left to right and top to bottom of screen. 'Reverse flow (direction = -1) is right to left or bottom to top of screen. 'Pipe start/finish positions must be entered left to right or top to bottom of screen. 'Flow simulation derives from the part-segment "offset" alternately displayed at the start of 'the "pipe" and the "speed" pause between segment movements. 'The segment length variable can be varied, or fixed in the code. local integer tempx, tempy, segment=10, offset, count local integer endfirstseg, stsecseg, endsecseg if stx-finx and sty-finy <> 0 then print "Pipe must be vertical or horizontal": end if stx>finx or sty>finy then print "Pipes must be defined left to right or top to bottom": end offset = segment\2 'flow simulation is best when "offset" is about half the segment length if stx = finx then goto Vertical 'test for vertical pipe Horizontal: tempx = stx do 'Calc start & finish positions of two alternate coloured segments. Test for end of pipe before 'displaying each segment. Re-calculate positions after incrementing the start by two segments. do endfirstseg = stx + segment: stsecseg = endfirstseg+1: endsecseg = stsecseg + segment if endfirstseg >= finx then LINE stx, sty, finx, finy, diam, cull1%: exit do LINE stx, sty, endfirstseg, finy, diam, cull1% if endsecseg >= finx then LINE stsecseg, sty, finx, finy, diam, cull2%: exit do LINE stsecseg, sty, endsecseg, finy, diam, cull2% stx = endsecseg + 1 'increment next segment-pair start position. loop if count = 3 then exit sub 'we're back to start condition if speed = 0 then exit sub 'because flow is stopped, i.e. = 0 stx = tempx 'reset pipe start position count = count+1 'flag to control whether the "offset" part-segment is needed next Pause speed 'for the flow simulation if direction = -1 then swap(cull1%,cull2%) 'for reverse flow to maintain correct simulation if count < 2 or count = 3 then 'has pipe been re-filled after offset or from start? line stx, sty, stx + offset, finy, diam, cull2% 'display the 'offset' segment in next colour stx = stx + offset 'offset the start of 'normal' segment posns & re-fill (back to DO) else swap(cull1%,cull2%) 'no offset segment req'd, so change colour then re-fill pipe endif loop exit sub Vertical: tempy = sty do do endfirstseg = sty + segment: stsecseg = endfirstseg+1: endsecseg = stsecseg + segment if endfirstseg >= finy then LINE stx, sty, finx, finy, diam, cull1%: exit do line stx, sty, stx, endfirstseg, diam, cull1% if endsecseg >= finy then LINE stx, stsecseg, finx, finy, diam, cull2%: exit do LINE stx, stsecseg, finx, endsecseg, diam, cull2% sty = endsecseg + 1 'increment next segment-pair start position loop if count = 3 then exit sub 'we're back to start condition if speed = 0 then exit sub 'because flow is stopped, i.e. = 0 sty = tempy 'reset pipe start position count = count+1 'flag to control whether the "offset" part-segment is needed next Pause speed 'for the flow simulation if direction = -1 then swap(cull1%,cull2%) 'for reverse flow to maintain correct simulation if count < 2 or count = 3 then 'has pipe been re-filled after offset or from start? line stx, sty, finx, sty + offset, diam, cull2% 'display the "offset" segment in next colour sty = sty + offset 'offset start of seg "normal" segment posns & re-fill (back to DO) else swap(cull1%,cull2%) 'no offset segment req'd, so change colour then re-fill pipe endif loop end sub '---------------------- SUB Swap a%, b% LOCAL t% t% = a%: a% = b%: b% = t% END SUB '---------------------- |
||||
disco4now Guru Joined: 18/12/2014 Location: AustraliaPosts: 844 |
Hi Greg, I have had a play with this and have a SETTIMER updating in the background. Touching the screen will reverse the flows as a simple demo of the touch interface. The flow displays looks good, and with a few graphics using Jim's program I can see it could be quite a nice interface. Well done. Regards Gerry 'FLUID FLOW SIMULATION - MMBasic V5.2 using the MX170 Micromite & ILI9341 LCD Display ' Greg Yaxley (paceman on TBS) '----------------------------------------------------------------------------------- 'Modified to use SETTIMER to update the flows in the background. G.A. 'Touching the sreen will reverse the flows. cls const white = rgb(white) const red = rgb(red) const blue = rgb(blue) const Green = RGB(green) const gray = RGB(gray) const yellow = rgb(yellow) dim integer stx,sty,finx,finy,diam dim integer speed,direction,speedcounter 'Setup arrays to hold data for the pipes DIM INTEGER phase(10) 'The current write phase of each pipe display Dim Integer pipespeed(10)= (0,0,0,0,0,0,0,0,0,0,0) ' speed divider for pipes. 0 is stopped, 1 is fastest. 9 is slowest DIM INTEGER flowdirection(10)=(0,0,0,0,0,0,0,0,0,0,0) ' direction of flow. -1 is reverse anything else is forward or down Main: cls BOX 70, 10, 60, 30, 2,white,blue TEXT 72, 12, "HEADER",,,,yellow,blue BOX 240, 80, 40, 50, 2,white,red CIRCLE 260, 200, 20, 2,,white,yellow ' Start the settick timer to run as our update thread SETTICK 10,BackGroundThread,4 T_IRQ=peek(byte peek(word &H9D000090) + 23) 'read the Touch Interupt SetPin T_IRQ, INTL, TouchDown ' set interrupt to detect touch 'setup pipe initial direction and speed flowdirection(3)=-1 flowdirection(4)=-1 flowdirection(5)=-1 pipespeed(0)=1 pipespeed(1)=2 pipespeed(2)=1 pipespeed(3)=4 pipespeed(4)=1 pipespeed(5)=5 do Loop END '---------------------------------------------- SUB BackGroundThread 'disable the tick timer while its processing SETTICK 0,0,4 speedcounter=speedcounter+1 ' call each pipe and update if required flow(0,10,24,260,24,5,white,blue) flow(1,260,24,260,80,5,white,blue) flow(2,260,130,260,200,5,white,red) flow(3,100,200,260,200,10,white,red) flow(4,100,105,100,200,5,white,red) flow(5,10,105,240,105,8,blue,red) 're enable the tick timer SETTICK 20,BackGroundThread,4 end sub SUB TouchDown '? touch(x) for x =0 to 5 if flowdirection(x)=-1 then flowdirection(x)=0 else flowdirection(x)=-1 endif next x End Sub sub flow(pipeno,stx,sty,finx,finy,diam,cull1%,cull2%) 'Fluid flow is indicated as alternate coloured segments - forward, reverse or stationary. 'Forward flow (direction) is the default and defined as left to right and top to bottom of screen. 'Reverse flow (direction = -1) is right to left or bottom to top of screen. 'Pipe start/finish positions must be entered left to right or top to bottom of screen. 'Flow simulation derives from the part-segment "offset" alternately displayed at the start of 'the "pipe" and the "speed" pause between segment movements. 'The segment length variable can be varied, or fixed in the code. local integer tempx, tempy, segment=10, offset, count local integer endfirstseg, stsecseg, endsecseg 'get current count for this pipe count=phase(pipeno) speed=pipespeed(pipeno) direction=flowdirection(pipeno) if speed <> 0 then if speedcounter\speed<>speedcounter/speed Then exit sub else count=0 end if if stx-finx and sty-finy <> 0 then print "Pipe must be vertical or horizontal": end if stx>finx or sty>finy then print "Pipes must be defined left to right or top to bottom": end offset = segment\2 'flow simulation is best when "offset" is about half the segment length if stx = finx then goto Vertical 'test for vertical pipe Horizontal: tempx = stx if direction = -1 then if count=1 or count=3 then swap(cull1%,cull2%) 'for reverse flow to maintain correct simulation END IF end IF stx = stx + count*offset 'offset the start of 'normal' segment posns ' write the pipe segements do endfirstseg = stx + segment: stsecseg = endfirstseg+1: endsecseg = stsecseg + segment if endfirstseg >= finx then LINE stx, sty, finx, finy, diam, cull1%: exit do LINE stx, sty, endfirstseg, finy, diam, cull1% if endsecseg >= finx then LINE stsecseg, sty, finx, finy, diam, cull2%: exit do LINE stsecseg, sty, endsecseg, finy, diam, cull2% stx = endsecseg + 1 'increment next segment-pair start position. loop ' now fix up the first segement stx = tempx if direction = -1 then if count = 1 or count = 2 then line stx, sty, stx + count*offset, finy, diam, cull2% END IF if count=3 then line stx, sty, stx + offset, finy, diam, cull1% line stx+offset, sty, stx + count*offset, finy, diam, cull2% END IF ELSE if count = 1 or count = 2 then line stx, sty, stx + count*offset, finy, diam, cull2% end if if count = 3 then line stx, sty, stx + offset, finy, diam, cull1% line stx+offset, sty, stx + count*offset, finy, diam, cull2% end if end if 'setup for next write count=count+1 if count=4 then count=0 phase(pipeno)=count exit sub Vertical: tempy = sty if direction = -1 then if count=1 or count=3 then swap(cull1%,cull2%) 'for reverse flow to maintain correct simulation END IF end IF sty = sty + count*offset 'offset the start of 'normal' segment posns ' write the pipe segements do endfirstseg = sty + segment: stsecseg = endfirstseg+1: endsecseg = stsecseg + segment if endfirstseg >= finy then LINE stx, sty, finx, finy, diam, cull1%: exit do line stx, sty, stx, endfirstseg, diam, cull1% if endsecseg >= finy then LINE stx, stsecseg, finx, finy, diam, cull2%: exit do LINE stx, stsecseg, finx, endsecseg, diam, cull2% sty = endsecseg + 1 'increment next segment-pair start position loop ' now fix up the first segement sty = tempy if direction = -1 then if count = 1 or count = 2 then line stx, sty, finx , sty+ count*offset, diam, cull2% END IF if count=3 then line stx, sty, finx, sty + offset, diam, cull1% line stx, sty+offset , finx, sty + count*offset, diam, cull2% END IF ELSE if count = 1 or count = 2 then line stx, sty, finx, sty + count*offset, diam, cull2% end if if count = 3 then line stx, sty, finx, sty + offset, diam, cull1% line stx, sty+offset, finx, sty + count*offset, diam, cull2% end if end if 'setup for next write count=count+1 if count=4 then count=0 phase(pipeno)=count end sub '---------------------- sub flowORG(stx,sty,finx,finy,diam,cull1%,cull2%,speed,direction) 'Fluid flow is indicated as alternate coloured segments - forward, reverse or stationary. 'Forward flow (direction) is the default and defined as left to right and top to bottom of screen. 'Reverse flow (direction = -1) is right to left or bottom to top of screen. 'Pipe start/finish positions must be entered left to right or top to bottom of screen. 'Flow simulation derives from the part-segment "offset" alternately displayed at the start of 'the "pipe" and the "speed" pause between segment movements. 'The segment length variable can be varied, or fixed in the code. local integer tempx, tempy, segment=10, offset, count local integer endfirstseg, stsecseg, endsecseg if stx-finx and sty-finy <> 0 then print "Pipe must be vertical or horizontal": end if stx>finx or sty>finy then print "Pipes must be defined left to right or top to bottom": end offset = segment\2 'flow simulation is best when "offset" is about half the segment length if stx = finx then goto Vertical 'test for vertical pipe Horizontal: tempx = stx do 'Calc start & finish positions of two alternate coloured segments. Test for end of pipe before 'displaying each segment. Re-calculate positions after incrementing the start by two segments. do endfirstseg = stx + segment: stsecseg = endfirstseg+1: endsecseg = stsecseg + segment if endfirstseg >= finx then LINE stx, sty, finx, finy, diam, cull1%: exit do LINE stx, sty, endfirstseg, finy, diam, cull1% if endsecseg >= finx then LINE stsecseg, sty, finx, finy, diam, cull2%: exit do LINE stsecseg, sty, endsecseg, finy, diam, cull2% stx = endsecseg + 1 'increment next segment-pair start position. loop if count = 3 then exit sub 'we're back to start condition if speed = 0 then exit sub 'because flow is stopped, i.e. = 0 stx = tempx 'reset pipe start position count = count+1 'flag to control whether the "offset" part-segment is needed next Pause speed 'for the flow simulation if direction = -1 then swap(cull1%,cull2%) 'for reverse flow to maintain correct simulation if count < 2 or count = 3 then 'has pipe been re-filled after offset or from start? line stx, sty, stx + offset, finy, diam, cull2% 'display the 'offset' segment in next colour stx = stx + offset 'offset the start of 'normal' segment posns & re-fill (back to DO) else swap(cull1%,cull2%) 'no offset segment req'd, so change colour then re-fill pipe endif loop exit sub Vertical: tempy = sty do do endfirstseg = sty + segment: stsecseg = endfirstseg+1: endsecseg = stsecseg + segment if endfirstseg >= finy then LINE stx, sty, finx, finy, diam, cull1%: exit do line stx, sty, stx, endfirstseg, diam, cull1% if endsecseg >= finy then LINE stx, stsecseg, finx, finy, diam, cull2%: exit do LINE stx, stsecseg, finx, endsecseg, diam, cull2% sty = endsecseg + 1 'increment next segment-pair start position loop if count = 3 then exit sub 'we're back to start condition if speed = 0 then exit sub 'because flow is stopped, i.e. = 0 sty = tempy 'reset pipe start position count = count+1 'flag to control whether the "offset" part-segment is needed next Pause speed 'for the flow simulation if direction = -1 then swap(cull1%,cull2%) 'for reverse flow to maintain correct simulation if count < 2 or count = 3 then 'has pipe been re-filled after offset or from start? line stx, sty, finx, sty + offset, diam, cull2% 'display the "offset" segment in next colour sty = sty + offset 'offset start of seg "normal" segment posns & re-fill (back to DO) else swap(cull1%,cull2%) 'no offset segment req'd, so change colour then re-fill pipe endif loop end sub '---------------------- SUB Swap a%, b% LOCAL t% t% = a%: a% = b%: b% = t% END SUB '---------------------- Latest F4 Latest H7 |
||||
paceman Guru Joined: 07/10/2011 Location: AustraliaPosts: 1328 |
Thanks for taking the time with this Gerry, yours is a lot better, it's nicely smoother and fixes the PAUSE problem. I knew that a SETTICK was going to have to be involved but couldn't figure how to incorporate it - and a "background" subroutine was something that didn't even occur to me. I think I was hung up on a "simple" solution and that obviously wasn't going to happen! Now I just need a day or two to really check out what your code's doing - my programming skills are pretty limited and very rusty. The "touch" reverse is a nifty demo (love your "read touch interrupt" line ) . It would work well with say a valve or a pump graphic but would need to be specific to a given pipe. A quick look says your code can probably do that - I need to study it. As you say, I think this simulation could be useful, especially if people need to, or want to stick with the smaller (DIP) processor. Geoff hasn't put a flow simulation as a "control" yet on the Micromite+ firmware so the more advanced Micromites could benefit too. I've played with Jim's FontTweak but have yet to get round to actually displaying a "graphic" I've created. I'll have to remedy that, maybe some valves in different orientations and similar for pump symbols - I should look up some standard Chem Eng symbols for ideas. Thanks again for looking at it - I nearly drove myself nuts trying to get it to work! Greg |
||||
Print this page |