Determining if a variable is NOT between 2 numbers and if it is higher or lower
eagletalontim
Posts: 1,399
This is probably quite simple, but I just can't seem to put this down in SPIN code. I have a variable that ranges between 1 and 17800 which is the pulse output of my solar panel array for the east and west location. This variable is EWLocation. Every 10 minutes, the EWLocation value is saved into EWTrackArray[track_index] if the sun is picked up as full sunlight and the panels are facing the sun. The "track_index" is a number between 0 and 144 which is calculated based on the local time. If it is cloudy the next day at the same time, the panels will know to follow the EWTrackArray instead of using the sun sensor. The problem is, the array continues to move back and forth for 1 to 2 seconds the whole day as if it can't quite stop the array in time to set the EWLocation to the corresponding EWTrackArray. Hopefully this did not confuse anyone!
So what I am trying to figure out is how to check if EWLocation is outside a "buffer" range of say +/- 50 of the stored EWTrackArray. So if EWLocation is 4000 and the EWTrackArray is 4200, it will track back to the range EWTrackArray is calling for. Also, if EWLocation is 4200 and EWTrackArray is 4000, it will track back as well. The buffer of +/- 50 should keep it from constantly trying to track.
Here is a bit of the code I am using now :
To clarify variables :
East_Count / West_Count is the ADC readings from the 2 sensors that pick up the sun location.
Up_Count / Down_Count are also ADC readings from 2 more sensors.
Park_Value is either a 1 or 0 which puts the panels into Park mode for night or high winds / storms.
command is a variable set via the web console to control the panels from a phone or computer.
So what I am trying to figure out is how to check if EWLocation is outside a "buffer" range of say +/- 50 of the stored EWTrackArray. So if EWLocation is 4000 and the EWTrackArray is 4200, it will track back to the range EWTrackArray is calling for. Also, if EWLocation is 4200 and EWTrackArray is 4000, it will track back as well. The buffer of +/- 50 should keep it from constantly trying to track.
Here is a bit of the code I am using now :
To clarify variables :
East_Count / West_Count is the ADC readings from the 2 sensors that pick up the sun location.
Up_Count / Down_Count are also ADC readings from 2 more sensors.
Park_Value is either a 1 or 0 which puts the panels into Park mode for night or high winds / storms.
command is a variable set via the web console to control the panels from a phone or computer.
repeat if shutdown == 0 AND command == 0 AND move_EW_flag == 0 AND move_UD_flag == 0 if East_Count > 1000 or West_Count > 1000 if EWdiffavg => max_diff AND hold_ew == 0 if East_Count > West_Count AND moving_EW_flag <> 2 goEast elseif West_Count > East_Count AND moving_EW_flag <> 1 goWest else EWoff if East_Count > 1000 or West_Count > 1000 EWTrackArray[track_index] := EWlocation elseif East_Count > Park_Value AND hold_ew == 0 OR West_Count > Park_Value AND hold_ew == 0 if EWLocation < EWTrackArray[track_index] AND EWTrackArray[track_index] > 0 AND moving_EW_flag <> 2 goEast elseif EWLocation > EWTrackArray[track_index] AND EWTrackArray[track_index] > 0 AND moving_EW_flag <> 1 goWest elseif moving_EW_flag > 0 EWoff if Up_Count > 800 or Down_Count > 800 if UDdiffavg => max_diff AND hold_ud == 0 if Up_Count > Down_Count AND moving_UD_flag <> 2 goUp elseif Down_Count > Up_Count AND moving_UD_flag <> 1 goDown elseif moving_UD_flag > 0 UDoff if Up_Count > 800 or Down_Count > 800 UDTrackArray[track_index] := UDlocation elseif Up_Count > Park_Value AND hold_ud == 0 OR Down_Count > Park_Value AND hold_ud == 0 if UDLocation > UDTrackArray[track_index] AND UDTrackArray[track_index] > 0 AND moving_UD_flag <> 2 goUp elseif UDLocation < UDTrackArray[track_index] AND UDTrackArray[track_index] > 0 AND moving_UD_flag <> 1 goDown else UDoff
Comments
This should check if the first section is NOT true, then continue on to the next AND EWLocation < EWTrackArray[track_index] AND EWTrackArray[track_index] > 0 AND moving_EW_flag <> 2 correct?
Are you sure about this indentation? This first line under repeat does nothing.
hysteresis?
It seems from the goEast/goWest calls that there is only stop-start control so using a PID loop wouldn't
help here.
The way to get clear and easy to understand code is to split it up into several routines, one to determine
where it should be, one to implement the hysteresis. More simpler routines with few variables each is
better than fewer complicated routines with many variables.
When it was time to rotate your panels you would turn on a transistor to power the H bridge. In between repositioning your panels you could turn off your transistor saving energy unless you had high winds or a storm in which case you'd 'park' them.
In an 'overcast' condition there would be no movement.
Here's a little method that might be of use. If the number is lower than your range it returns a positive (because you want to move in that direction to get into range); it it's higher than your range it returns negative.
result := x - (x #> lower <# higher)
Inside the parens it amounts to the following: Compare x with the lower limit and choose the greater of the two, then compare that with the upper limit and choose the lesser of the two. Subtracting that from x yields zero when x is within the limits. The result is negative or positive when below or above the limits respectively.
That's what the absolute value of (EWLocation - EWTrackArray) was for. There will always be some overshoot for a system that stops the motor when the target position is reached so by simply adding a bit of hysteresis the "hunting" oscillation and waste of energy can be eliminated. For a typical solar panel system the energy saved by stopping a bit past the optimum position more than makes up for the slight loss of efficiency it entails.
@lardom : You are correct, I have 2 IR sensors for the east and west offset enough to determine when the sun is between the 2 sensors. When they both equal the same, the sun is in the center. Same goes for the up and down.
@kwinn : I did not know about the ABS function. I should probably read the Prop manual! That does seem quite a bit simpler than my other code that does appear to be working so far.
I am going to post my horrible code so don't laugh :P This has been a work of art being added to ever so often over the past year or more.... Have fun with it! The PST has been nulled out because I needed that extra cog. I also want to store the EWTrackArray[] into the eeprom, but am not quite sure how to store an array with the same eeprom save method I have now. That is the only one I have used that I understand how to implement into my code.
If I need to add comments to specific parts on why I did it the way I did, please let me know. I am not big on putting many comments into my code.
This is why a company I once worked for had posters all over the facility that read: If you don't have time to do it right, when will you make time to do it over?
-Phil
So true, and you have the advantage of everything you learned from the first round.
I know the basics of SPIN and just enough to be dangerous but get the job done. There is a bunch of code in that program that I would not know if it could be simplified unless I went with assembly which I don't know at all. Some of the functions are specifically written they way they are because clouds are highly unpredictable and timing of the processing of the code and when a cloud hits can never be judged. This is why I have different COGS doing specific things. I am sure I could eliminate 1 or 2 of the COGS if I really had to.
Indeed. It saddens me to see so many unwilling to restart or rebuild when obvious mistakes have been identified. I was once working in a client's office while the client worked on a pet project. I asked if I could assist. Nope -- it was working without my help. Well, for about five minutes. Then, of course, the client wanted me to fix what was broken versus teaching how to do it correctly in the first place.
Maybe I'm a nut, but I treat my personal projects every bit as seriously as I treat my professional projects.
I wouldn't take any of these posts (including mine) too seriously, particularly if you have working code. Where one stands on this issue depends mainly on where your personality falls on the line between good enough and perfect.
Personally I prefer to be a bit closer to perfect than good enough, so reducing the code size a bit or making it a little easier to see what is going on keeps me tinkering with it longer than is needed to get it working.
Pay attention to those who give you examples of parts of your code that could be simplified, examples not in words but in actual code snippets, the rest are just preaching at you. There are many fine Spin and PASM programmers on this list with lots of "time in the saddle".
The most puzzling things can be firmware or hardware glitches that happen only rarely, say an odd stack overflow that only occurs on the summer solstice, with a bright full moon.
Here is the view of my solar production with the Prop Tracking : https://enlighten.enphaseenergy.com/pv/public_systems/7bbq689770/overview
Most of the glitches I have had are due to me forgetting to add a "check" into the code that looks for something that happens occasionally or getting the panels to stop at a certain time if they begin to move to track, then a cloud gets in the way. All of that is fixed now.
The Wifi has been a random issue and I believe it is because I am using a PHP socket server which dies occasionally due to my server's settings. I would like to switch this to use the Spinneret since I have one already and don't use it anymore. That is another project though. The Xbee does not have very good reception as well, so upgrading to a better antenna may be one thing I could do.
The whole reason for this thread was because I was trying to implement cloudy day tracking that learns on it's own. It worked for the most part, just kept overshooting the target number and causing it to track back and forth which is unneeded power usage and wear on the actuators. One simple line of code is all I needed, but my brain was stuck!
Thank everyone for the help on this thread and I am sure there will be more eventually....especially when I get started on the spinneret project.