Shop OBEX P1 Docs P2 Docs Learn Events
Calculate Average data - Page 2 — Parallax Forums

Calculate Average data

2»

Comments

  • NauketecNauketec Posts: 51
    edited 2008-08-25 15:02
    Hey Zoot



    I have been removing the coments but·until this stage I needed them to tell me what bits were being sent/received between micros.

    now that that is settled, I have removed them.· I am still a newbie and learning how to switch them on and off is a real time saver.

    I will be back in 4 hours to continue working but for now off to pay the rent ...

    Daniel
  • ZootZoot Posts: 2,227
    edited 2008-08-25 18:00
    Yeah, conditional compilation is really handy. Another tip -- when you do turn debugs on, keep them as short as possible -- the more text you are transmitting (DEBUG does not use a very fast baud rate to the PC) the longer it takes (relatively).

    Have you tried this code? Unless you've changed the word variable i2c data or your get ranging code, it should drop into your current program w/o change....

    Note that with 70ms ranging time, plus code overhead for the rest of the program, you may not do better than 3 loops per *second* with this program, which is a bit slow. Filtering bad or fluctuating readings in the logic of your mode choice section may be better than dropping 300ms to average the sonar readings. Again, the SRF10's ranging time can be cut way down if you cut the usable range and set the gain appropriately. At 3meters max the ranging time should be closer to 20ms or so (remember the longer the max range, the longer the ranger is waiting for a possible echo to return -- and sound really doesn't travel all that fast).

    '===========================================================
    '  Sonar Ranging
    '===========================================================
    
    i VAR NIB
    sonarRange VAR WORD
    
    GetMax_Range:
    sonarRange = 0
    FOR i = 0 TO 3
    
    ' SRF10 Ranger
      I2cAddr = $e0
      I2cReg = 0
      I2cData = 80        ' Ranging command - 80 for inches, 81 for cm, 82 for uS
      GOSUB  I2cByteWrite
      PAUSE  50 '70       ' wait for ranging to complete
      I2cReg = 1          ' address of light sensor register
      GOSUB  I2cByteRead
      I2cReg = 2          ' address of first ranging result
      GOSUB  I2cWordRead
      'DEBUG  2,0,1,       "Range ", DEC4 I2cData," Inches "
    
       sonarRange = sonarRange + i2cData
    NEXT
       sonarRange = sonarRange + 2 >> 2 ' divide by 4 with accurate rounding
    
      'Send_Mode = INA     '& %1110 'this will mask Bit 0 from the variable.
      'DEBUG   2,0,4,      "P0 - P3 ", BIN3 Send_Mode
    #IF show_avg_sonar = 1 #THEN
       DEBUG "avg: ", DEC5 sonarRange
    #ENDIF
    
      'IF I2cData < Max_Range THEN GOTO GetMax_Range
    
    '===========================================================
    '  Select mode for led micro and output to p0 p1 p2
    '===========================================================
    
    IF  sonarRange > Max_range THEN
        GOTO mode1 'Breathing
      ELSEIF ((sonarRange =< Max_range)AND( sonarRange >= Opt_Range)AND( sonarRange >=Min_Range))  THEN
        GOTO mode2 'wake up
      ELSEIF ((sonarRange < Opt_Range)AND( sonarRange >=Min_Range))THEN
        GOTO mode4  'opt range
      ELSEIF sonarRange < Min_Range THEN
        GOTO mode6  'too close
      ELSE
        GOTO mode0 'Diagnostics
    ENDIF
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • NauketecNauketec Posts: 51
    edited 2008-08-25 23:08
    Zoot

    Your sonar advise "sounds" good!

    I will start to test your code now and let you know how it goes.

    Daniel
  • ZootZoot Posts: 2,227
    edited 2008-08-25 23:35
    Are you talking about my snippet? I didn't change anything except for averaging the readings. If there are errors in choosing the mode based on the distance, then either you have bad ranges, bad thresholds (or logic) in your if/then decision segment, or errors in comm. with the slave.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • NauketecNauketec Posts: 51
    edited 2008-08-25 23:44
    Zoot

    ·My mistake here!!· I had the piece on the wall last night to do some larger room tests and forgot to move the DIP switches back to the smaller room settings.· So the good news is your code works fine the DIPS are working the way they should and I have learned how to turn on an off debugs which does help the performance

    daniel
  • NauketecNauketec Posts: 51
    edited 2008-08-26 00:06
    Hey Zoot,

    You seem to be well versed in SRF10 tech have you ever heard of it being able to report multiple contacts? If so I am wondering if there is a way to create a "blind" spot of any target under say 6 inches. I ask this due to the fact that its beam pattern is very wide, which is great for a moving robot but for something stationary on a wall, I have to be sure that nothing else on the wall sticks out greater than 2-4 inches or the sonar will only read it and disregard any other target. (I am not sure about this until I test more but it would not be a bad thing to build in as a safety measure).

    Daniel

    Post Edited (Nauketec) : 8/26/2008 12:34:16 AM GMT
  • ZootZoot Posts: 2,227
    edited 2008-08-26 01:15
    All I know about the SRF10 I read in the documentation two nights ago, though I have used some of Devantech's other products and they are all top-notch. You could contact Gerald Coe over at http://www.robot-electronics.co.uk/ and see if he has an info regarding blind spots, beam pattern etc. Are you sure it's a wide pattern? Generally the robot sonars out there have narrow beams, not wide.

    That said, I think you have a logic issue here -- I mean if a protrusion on the wall gives you a false reading where you want a positive reading (or vice versa), then can't you handle this either with your decision if/then tree or with counters or something? Also, it's not clear what you are trying to detect... if you are having the sonar reach the wall, and want to determine if someone is "within the room" then you have a couple of ways to go about:

    - use the SRF10's max range and gain settings (perhaps these settings can be written to the SRF10 on Stamp powerup/reset and based on your room size switches), so that the max range doesn't reach the wall

    - or you can have an initialize routine that takes a 5 or 10 sample readings to determine a "max" distance based on actual reality, and then anything that is 75% of that max distance or smaller by definition is "in the room" rather than being the room. This has an advantage in that room size would matter less than "actual" reality on the ground, e.g.

    ' pseudo code:
    Reset:
      RoomSizeRange = $FFFF  ' initialize to maximum
      FOR i = 0 TO 4
         RoomSizeRange = RoomSizeRange MAX i2cdata  ' take the smallest of all the samples;
                '     what you have at the end is now a "safe" theoretical room size
      NEXT
     
      RoomSizeRange = RoomSizeRange */ $C0  ' * .75% ' now scale to 75% (or any figure slightly smaller that seems reasonable)
    
      Main:
    
      '.... lots of code
    
      IF sonarRange < RoomSizeRange THEN
        DEBUG CLS, "there is someone there"
      ELSE
         DEBUG CLS, "this room is empty"
      ENDIF
    
    



    - or do counts or some kind of threshold tuning so that you don't false positives

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php


    Post Edited (Zoot) : 8/26/2008 1:22:48 AM GMT
  • NauketecNauketec Posts: 51
    edited 2008-08-26 01:49
    I have just written Coe and will hear from him Tuesday
  • NauketecNauketec Posts: 51
    edited 2008-08-26 02:10
    Hey Zoot
    The code seems to be holding well - no bugs so far.· My next task is to create a means that when the sonar directs it to go to mode4 a time counter is started.·· After "DevotionTime" = (a number for time) it will goto to mode5.· But IF while in mode5 the subject steps back out of the range set for mode4 THEN it would go to the corresponding mode. and the DevotionTime time counter would reset to 0.
    I tried my best in the routine called mode4 but it does not work· Let me know what you think or just write it in if you can.· I am now writting a global switch to turn off all the debugs as you suggested.· I feel confident with the communications between the micros now.
    Daniel


    Hey Zoot,· to help you to understand what I am trying to do:

    '===========================================================
    '· Select mode for led micro and output to p0 p1 p2
    '===========================================================
    IF· sonarRange > Max_range THEN
    ··· GOTO mode1 'Breathing
    · ELSEIF ((sonarRange =< Max_range)AND( sonarRange >= Opt_Range)AND( sonarRange >=Min_Range))· THEN
    ··· GOTO mode2 'wake up
    · ELSEIF ((sonarRange < Opt_Range)AND( sonarRange >=Min_Range))THEN
    ··· GOTO mode4· 'opt range
    · ELSEIF sonarRange < Min_Range THEN
    ··· GOTO mode6· 'too close
    · ELSE
    ··· GOTO mode0 'Diagnostics
    ENDIF

    That is· what I currently have.· What I would like to add is that when it goes from mode1 to mode2 it just does mode2 for lets say 3 seconds(although if this time amount could be variable length it would be better) then it goes to mode4 and stays there as long as the specification for mode 2 are met.
    If the subject move back to mode1 and then to mode2 again it would first do mode2 for the designated amout of time and goto mode3.
    If the subject were in mode4 and moved back it would goto mode3 not mode2.
    the only other timer is much easier.· if the subject were in mode4 for lets say 30 seconds(although if this time amount could be variable length it would be better) it would then goto mode5· if the subject moves into the distance for mode6 or back to the distance for mode4 then back to the distance for mode5 the timer would reset and they would have to wait to goto mode6 again.

    I hope that clears it up.· It is the last big piece of code!

    Daniel

    Post Edited (Nauketec) : 8/26/2008 2:34:23 AM GMT
  • ZootZoot Posts: 2,227
    edited 2008-08-26 03:53
    Well, you may want to consider a simple state machine with a few counters, so your program can keep doing it's main loop, but only change "modes" based on the counters -- for one state, the counter may increased and decreased because of the sonarrange, for some it may just count till it expires, then change to the state that's waiting for the next sonarrange change.

    I outlined several possible in posts and (I think) in some of the sample code., pseudo code outline:

    Reset:
    ' read switches and set parameters ' runs only once at powerup/reset
    
    Main:
    
    ' get sonar range code here
    
    ON state GOTO s0, s1, s2, s3
    
    s0:
    IF range < someDistance THEN  ' if short distance, then count up. when count reaches certain threshold, go to next state
       cntr0 = cntr0 + 1 MAX 255
       IF cntr0 >= 5 THEN
         state = 1
         cntr0 = 0 ' and clear counter for next state
         cntr1 = 0
       ENDIF
    ELSE
       cntr0 = 0
    ENDIF
    GOTO done
    
    s1:
    IF range > someDistance THEN ' if distance goes to high, count up, switch back state 0 if 5 or more counts
       cntr0 = cntr0 + 1 MAX 255
       IF cntr0 >= 5 THEN
         state = 0
          cntr0 = 0
       ENDIF
    ELSE                                   ' BUT if you are still good on distance, count how long you've been here
       cntr1 = cntr1 + 1 MAX 255
       IF cntr1 >= 200 THEN     ' you've been here for 200 counts, go to state 3, *then* back to 0
          state = 2
          cntr0 = 0
       ENDIF
    ENDIF
    GOTO done
    
    s2:                                   ' just do this one for 200 counts, then back to 0
       cntr0 = cntr0 + 1 MAX 255
       IF cntr0 >= 200 THEN     ' you've been here for 200 counts, go to state 3, *then* back to 0
          state = 0
          cntr0 = 0
       ENDIF
       GOTO done
    ' etc
    GOTO done
    
    done:
    
    ON state GOTO mode1, mode6, mode3 ' or whatever
    
    ''' your modes
    
    GOTO Main ' loop it
    
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • ZootZoot Posts: 2,227
    edited 2008-08-26 03:59
    P.S. -- in my sample above you will need to decide if you need a word var for the "time" counter -- 255 "clicks" may not be enough time, although at 3-4 loops per second (my estimate) that would give about a minute's worth of timer, which sounds like it would be enough. You'll need to experiment with the counts that give you the times and the "positive" readings you want. If you look at the sample you'll see that a person triggering the distance needs 5 counts -- about a full second or two of positive readings, before they trigger the next the state, and *that* state won't quite just because the distance increases for one or two loops, it'll take five loops through the main cycle before they'll be declared "gone". s2 just runs a set time until it's done.

    Remember you can add lots more states (and/or just reuse your modes if you want) that may just run modes for a certain period of time, and are not directly related to the ranging. You could also just set up one timer for all the modes, that is started by the range decision, and just runs (this actually is appealing because you could set the total "running" time individually and have the decision over which one to run be independent).

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • NauketecNauketec Posts: 51
    edited 2008-08-26 04:16
    Hey Zoot,

    Well once again you have given me plenty food for thought! I will put my best efforts on it and send you back what I have come up with.

    Iy amy take me the rest of the night/morning and I have a lot on my plate for work so I may not get it all done by morning, but I will try.

    thanks

    Daniel
  • NauketecNauketec Posts: 51
    edited 2008-08-26 05:24
    Hey Zoot I have been tying some things with your state engine code but it is just not sinking in or my brain is melting

    I have included it with·my latest·working code for you to point me back in the right direction

    My earlier post states what I am trying to do with modes:· mode2 - mode3 and mode4 - mode5

    Thanks for the help I have learned a lot so far! But enough for tonight it's 1:30 and I·got to get up in 5 hours!



    Daniel


    Post Edited (Nauketec) : 8/26/2008 5:29:44 AM GMT
  • ZootZoot Posts: 2,227
    edited 2008-08-26 14:48
    I can't encourage you enough to break your current version down into small pieces and test them each individually.

    Create a version of the main prog. that is *just* the sonar ranging (and averaging if you want) and displays it via DEBUG (cut all the other code out of the program). Make sure you are getting ranges you like, that the ranging does what you want.

    Then create another version that is just sending a mode number to the slave -- nothing fancy, no times, nothing, just the numeric data. On the slave side cut and paste a version of that program that is just the receiving of the data -- no modes or leds. Just a debug with the incoming "number".

    Then go back to your main program and without decision tree, or ranging, put in just the mode transmission and use DEBUGIN so you can just input a mode and send it to the slave. At that point load the slave program that runs the led modes. Test it out -- does the master send the right data? Does the slave receive it and run the right mode?

    Get these pieces working *perfectly* that way when you revisit the logic of deciding what happens when, your errors or problems will not be related to your mode tx/rx, your ranging, your leds, etc., just the logic and code. It will cut down on debugging time and you'll be confident that if you are seeing a problem that you are not trying to figure out if it's the ranging, the mode tx, the mode rx, the leds, etc.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • NauketecNauketec Posts: 51
    edited 2008-08-26 15:32
    Zoot, I have done that all along. What I post to you is your code pasted in to mine. All of the previous code works fine. I am just trying to add some counters. I tried your code but I am just not getting it. I pasted it into mine to post it so we can both see where it fits in context and that the terms fit.
  • ZootZoot Posts: 2,227
    edited 2008-08-26 15:39
    I'm editing this now. So this worked satisfactorily before putting in the state machine?

    Also the debugs are reallyyyyyy long. There is no way you will get any decent count for rough time, or fast sample time. These aren't conditionally defined, so I'm just going to cut them down and or comment them out so you can try out counts. Gimme a few minutes.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • ZootZoot Posts: 2,227
    edited 2008-08-26 16:28
    OK, my sample was just that. I wouldn't have compiled because I didn't use your variables. Sorry if that wasn't clear.

    In any case, the attached has a version of the state machine with your vars and terms.

    I cut realllly long debug outs down to 2 characters. I would turn off all debugs for final testing. See the Pbasic Manual for "conditional compilation" techniques which will let you turn all debug statements off or on with a single mouseclick (I did this in the attached; see comments in program). Or if you have a free switch or pin, you could put in a switch and read the switch to see if you should debug.

    Also I noticed that where you set HIGH 8 and HIGH 6 (pin definitions w/names would help here) for your active low outputs (sound board), I think, unless I am misreading something, that that portion of the program will never be reached. Is that intentional?

    On this version I commented out the range averaging -- you may want to try different thresholds in the state machine before resorting to averaging, or you may be able to get away with fewer averages (2?). The goal here is to cut the time through the main loop down so the whole thing is responsive enough.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • NauketecNauketec Posts: 51
    edited 2008-08-26 17:12
    Zoot - it is all much clearer now - I will digest and test and get back to you - Thanks Daniel
  • ZootZoot Posts: 2,227
    edited 2008-08-26 19:28
    Rockin'.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • NauketecNauketec Posts: 51
    edited 2008-08-26 21:30
    Hey Zoot, Sat in a park with code and manual and got what you are doing for counters.

    To answer the question you left in the code

    Some lines were commented out but should have been deleted (they were from earlier versions)

    What you have done is move the sonar data flter or debouncer to each IF / THEN in the State Engine.

    In the code you used I was using only mode1, mode2, mode4, mode6

    mode1 - No subject - subject outside of Max_Range
    mode2 - Subject detected - Subject inside of Max_Range equal to Mid_Range
    mode4 - Subject in Opt_Range
    mode6 - Subject - too close - in Min_Range

    I would like to put in mode3 and mode5

    mode3 - Subject in Mid_Range
    mode5 - Subject in Opt_Range for desired length of time


    So when A subject enters into mode2 it only lasts "T" amount of time then goes to mode3 ( if the subject goes(in distance) to mode4 and back to mode3 it does not first go to mode2 and then mode3


    When a subject is in mode4 for "T1" amount of time then it goes to mode5. If the subject goes (in distance)to mode 6 and then back to the distance for mode4 it goes back to mod4 and the timer restarts. Same if the subject steps back to the distance for mode 2/3 then forward again. The timer would restart.

    I hope that clears it up for you. I have my own "banger" idea of how to do it but I would like to see what your ideas would be.

    Daniel (be back in 3 hours)

    Post Edited (Nauketec) : 8/26/2008 9:49:30 PM GMT
  • ZootZoot Posts: 2,227
    edited 2008-08-26 22:32
    Yes, in my version I let the counters in the state machine filter sonar readings, but averaging may be better (or worse). Up to you -- whatever works best.

    Just follow the setup I did for your additional states. Make sure to order them correctly and define extra variables for counters if you need them (you still have room so it should be ok).

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    When the going gets weird, the weird turn pro. -- HST

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
  • NauketecNauketec Posts: 51
    edited 2008-08-27 00:35
    Zoot,

    Having a problem with your code. Not as reliable as older version. It goes to mode6 and gets stuck or goes to mode0. I am trying to cut and paste the counter routine to see what that brings.

    Counters still giving me a problem

    In the code you used I was using only mode1, mode2, mode4, mode6

    mode1 - No subject - subject outside of Max_Range
    mode2 - Subject detected - Subject inside of Max_Range equal to Mid_Range
    mode4 - Subject in Opt_Range
    mode6 - Subject - too close - in Min_Range

    I would like to put in mode3 and mode5

    mode3 - Subject in Mid_Range
    mode5 - Subject in Opt_Range for desired length of time


    So when A subject enters into mode2 it only lasts "T" amount of time then goes to mode3 ( if the subject goes(in distance) to mode4 and back to mode3 it does not first go to mode2 and then mode3


    When a subject is in mode4 for "T1" amount of time then it goes to mode5. If the subject goes (in distance)to mode 6 and then back to the distance for mode4 it goes back to mod4 and the timer restarts. Same if the subject steps back to the distance for mode 2/3 then forward again. The timer would restart.

    I hope that clears it up for you. I have my own "banger" idea of how to do it but I would like to see what your ideas would be.




    Daniel

    Post Edited (Nauketec) : 8/27/2008 2:22:47 AM GMT
  • NauketecNauketec Posts: 51
    edited 2008-08-27 03:53
    Hey Zoot - et. al.:

    I have moved this to a new thread called "Seeking timer /counter for IF THEN or CASE statements

    Thought it might be better for all those who might need the same code to follow this thread more easily

    Daniel

    end thread
Sign In or Register to comment.