Shop OBEX P1 Docs P2 Docs Learn Events
Determining if a variable is NOT between 2 numbers and if it is higher or lower — Parallax Forums

Determining if a variable is NOT between 2 numbers and if it is higher or lower

eagletalontimeagletalontim Posts: 1,399
edited 2016-06-16 23:46 in Propeller 1
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.
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

  • eagletalontimeagletalontim Posts: 1,399
    edited 2016-06-17 00:17
    I might have figured it out..... Maybe....
    if NOT ((EWLocation > EWTrackArray[track_index] - 50) AND (EWLocation < EWTrackArray[track_index] + 50)) AND EWLocation < EWTrackArray[track_index] AND EWTrackArray[track_index] > 0 AND moving_EW_flag <> 2
    

    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?
  • 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
    

    Are you sure about this indentation? This first line under repeat does nothing.
  • The indentation is off a bit. The indentation was a copy and paste from the Prop tool. Must not have caught that before I posted it.
  • kwinnkwinn Posts: 8,697
    Not sure I understand what you are asking but it sounds like a simple if/else should suffice.
      if abs(EWLocation - EWTrackArray)> 50
        dosomething
      else dosomethingelse
    
  • kwinnkwinn Posts: 8,697
    Hard to be sure without seeing the whole program, but I think this code could be simplified quite a bit using a state machine or case statements instead of all the if's.
  • I think what was asked is for a means to stabilize an adhoc control loop - in this case by adding
    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.
  • lardomlardom Posts: 1,659
    edited 2016-06-17 18:15
    You said you had two light sensors. The simplest design I can think of is...assume you had two photoresistors in tubes at different angles in relation to the sun. If they are wired as voltage dividers and fed into an ADC chip you would rotate the assembly until the voltages equal each other.
    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.
    872 x 486 - 19K
  • Wait, is this a trick question?

    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.
    pub test_val(value, lo, hi)
    
      if (value < lo)
        return 1
      elseif (value > hi)
        return -1
      else
        return 0
    
  • At the face value of the subject line, here's a trick computation.

    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.
  • kwinnkwinn Posts: 8,697
    Mark_T wrote: »
    I think what was asked is for a means to stabilize an adhoc control loop - in this case by adding
    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.

    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.
  • Wow, this thread blew up! I am sure there could be a way to simplify the code quite a bit, but I am too lazy to go through 958 lines of code and simplify it :P This tracker is quite robust and has about all the same features a high end solar tracker would offer. Most of the features were added in over time in bits and pieces.

    @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.
  • ...but I am too lazy to go through 958 lines of code and simplify it.

    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?
  • I've always found that starting over is better than trying to fix something that was ill-conceived in the first place.

    -Phil
  • kwinnkwinn Posts: 8,697
    I've always found that starting over is better than trying to fix something that was ill-conceived in the first place.

    -Phil

    So true, and you have the advantage of everything you learned from the first round.
  • The code works as it is now, so if it ain't broke....don't fix it... right? :)

    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.
  • kwinn wrote: »
    I've always found that starting over is better than trying to fix something that was ill-conceived in the first place.

    -Phil

    So true, and you have the advantage of everything you learned from the first round.

    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.
  • @eagletalontim, "If it's not broke" sounds like the Rube Goldberg approach. It's going to annoy you until you know that you've done your best. "958 lines of code" is part of the learning process.
  • I feel like I have done an awesome job with the current program. It is quite easy to change and implement any additional features I might come up with. Another, more knowledgeable person may come along and say the code is Smile and can be completely redone, but I am not 100% proficient in the SPIN language and need a boost here and there :) Just clearing out the old PST code and removing a few nulled out lines, I reduced the code down to 820 line :) Pretty big difference!
  • Try using a case statement with a range operator.
  • kwinnkwinn Posts: 8,697
    I feel like I have done an awesome job with the current program. It is quite easy to change and implement any additional features I might come up with. Another, more knowledgeable person may come along and say the code is Smile and can be completely redone, but I am not 100% proficient in the SPIN language and need a boost here and there :) Just clearing out the old PST code and removing a few nulled out lines, I reduced the code down to 820 line :) Pretty big difference!

    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.
  • Good job eagletalontim, your code works, it does what you want it to, you can now optimize as you see fit when you see fit.
    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".
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2016-06-20 19:34
    A lot depends on what the consequences are if something doesn't work or even locks up. In this case, you are at home there to press reset and at worst you lose a day or two of solar benefit. I was wondering what happens if you get a long stretch of dark cloudy days? The important thing is that you understand it and will be able to go back and make adjustments as you go along. Really, congratulations on your accomplishment!

    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.
  • The code has been running for a little over a year between 2 solar panel setups I have. The first one is a small 440W solar panel array that rotates and tilts. I have made no modifications to it and with the way I set everything up, it should last for many more years. The 440W charges a battery bank in my shed which I run my 12V T-8 lights from and a few other things including the larger 40ft 2.15KW system tracking circuit. That system is grid tied so the output goes directly back to the grid.

    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.
Sign In or Register to comment.