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

Calculate Average data

NauketecNauketec Posts: 51
edited 2008-08-27 03:53 in BASIC Stamp
Trying to average 4 sonar ping into a single value within a loop condition.

The first ping output is I2cData, how do I get an average count within 4 loops

· ' SRF10 Ranger
· I2cAddr = $e0
· I2cReg = 0
· I2cData = 80····· ' Ranging command - 80 for inches, 81 for cm, 82 for uS
· GOSUB· I2cByteWrite
· PAUSE· 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 "


thanks a lot

Daniel


·
«1

Comments

  • FranklinFranklin Posts: 4,747
    edited 2008-08-23 03:15
    You need to take 4 readings and then add them and devide by 4 but you knew that. attach your complete code so we can see where the data is and how it is derived.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - Stephen
  • ZootZoot Posts: 2,227
    edited 2008-08-23 08:25
    Nauketec -- you PM'ed me about your project -- an installation coming up in two weeks at a museum. I encourage you to post the *full* program here AND a schematic or even a block wiring/mechanical diagram. Then if you care to, change the subject of your first post in this thread, and just devote the whole single thread to your questions. I'm happy to help, but others I'm sure will also and you can keep the ball rolling.

    In any case, in your PM you also showed a snippet of a simple state machine... you may find that averaging out your reading is not relevant depending on your state machine. If your sonar shows <= 2 meters 10x in a row, and that kicks you to the "interact" state, it may not matter what the average is, because your state machine will wait for things to be steady.

    E.g.
    Main:
    
      ' read sensors
      ' read more sensors
      ' etc
    
    State_Machine:
    
      ON state GOTO state0, state1, state2, state3
    
    
    state0:
    
    state1:
       IF range > 200 THEN
          cntr = 0 ' out of range, clear count
       ELSE
          cntr = cntr + 1 ' < 200 start counting
          IF cntr > 10 THEN ' 10x in range! whoo hoo!
             state = 2  ' next state
             cntr = 0  ' reset cntr so next state can use it "clean"
          ENDIF
       ENDIF
       GOTO states_done
    
    state2:  ' you only get here because of low range 10x in a row
       ' blink lights
       ' move flashing head
        ' make noise
       IF range < 200 THEN  ' still in range, keep counter clear
          cntr = 0 
       ELSE
          cntr = cntr + 1
          IF cntr > 100 THEN ' they have to be out of range 100x before you "quit on them"
             state = 3  ' next state
             cntr = 0
           ENDIF
        ENDIF
        GOTO states_done
    
    state3:
        FOR cntr = 0 TO 9
           ' make whoop whoop goodbye sound 10x
        NEXT
        state = 1
        cntr = 0  ' back to the waiting game
        GOTO states_done
            
    ' yet more states....
    
    States_Done:
       
       DEBUG "States Done", CLREOL, CR
     
       GOTO Main
    
    





    The attached has some different sampling routines and comments about range times, if you want to average your readings.

    (Aside -- something I've tested by tokenizing to the nth byte more than once -- if you are using BS2p40s as you mentioned here: http://forums.parallax.com/showthread.php?p=744688 than I2CIN and I2COUT are the *only* high level communication commands where I say *don't* wrap them in a subroutine. For reasons I can bore you with, I2CIN and I2COUT appear to be so cosmically compact in the interpreter that as long as you make your device, register and command values constants, you don't need subs. Others may say it's "dirty", but one of the advantages of an interpreted language is taking advantage of really sweet tokens. So I'm doing that in the attached example.)


    DO
    Post your material!
    LOOP

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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-23 08:48
    Heh. I'm such a dork. You had posted both programs in the other thread..... presuming this is the same project????

    In any case here's some comments and a revision of the "slave" program (this looks like a cool project btw).

    On the LED slave program I DEFINED YOUR PINS and redid the part at the beginning (for clarity). Presuming the light show modes work. I can't encourage you enough to define your pins and use constants -- it makes a program much easier to read.

    On the "main" program, you have it defined as bs2p but it looked like you used the "bit-banged" I2C routines available for the BS2 which does NOT have I2C built in? If there is not a really good reason, use I2CIN and I2COUT. See the stamp manual. Very very powerful and you can format incoming data on the fly, etc. See my example above.

    I leave it to you to fold in the I2C and SRF10 reading snippet I attached above into your main program and test your sensors.

    Then, please go through your main program and assign PIN names using the PIN definition. For example, at the beginning you have HIGH 6. If this read HIGH led, or HIGH chipSelect or whatever, it makes it easier for others who are looking at it, plus if you move pins around (for any reason, like say, a malfunction on opening night), you just have to change the ONE reference to the pin and know that the rest of your code should work as it always has.

    Then come back with the next working (or semi-working smile.gif) version of the program and we'll take the next steps.

    Remember I only edited the slave program, not the master program. I only attach it here so everything is one thread.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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-23 16:22
    Hey Zoot that bit of code for the LED Micro did the trick!·I want to test it a bit more then I will post the next task.· It is getting closer!

    By the way,·I am working from a circuit board that was already printed. So I cant just re-wire a pin.· I designed it a few months ago before I learned all these little tips on programming that should have been incorporated into the board design.· I learned a lot and will know better next time.· But this board is 10" by 11" to facilitate the 220 leds on it so I can't just make another and another and ....· but I have made some changes to it.· I did allow for some extra holes just for the unexpected changes.



    thanks Daniel
  • ZootZoot Posts: 2,227
    edited 2008-08-23 17:02
    Somebody said...
    So I cant just re-wire a pin.

    Ahhh... you can always solder a jumper (wire) from point to point if desperation strikes smile.gif

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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-23 18:18
    Ah but somebody who has already been down that path also leaves Proto holes to use as a "Murphy's Law" playground.· It is alway wise to allow for the unexpected.
  • ZootZoot Posts: 2,227
    edited 2008-08-24 02:56
    SDA/SCL must be on pin 0/1 or pin 8/9. The builtin I2C functions will not work on other pins. You have them defined pins 4 and 5. If you can, move them, trust me using the built-in I2C functions will save you some real hassle.

    If you still want to use the bit-banged routine, the concept is the same, add each read to a variable then divide by the number of readings.

    I do think that the state machine may serve you better as it will filter out noise (2 bad readings on an average could pull it down, even though it's false).

    Also, I'll go check out the SRF10 documentation. Something doesn't seem quite right.

    Last but not least, what kind of max range are you looking for? Regardless of stated distance capability, my experience with 40khz sonar units has been that you can get decent readings to say 2 or 3 meters then you may not be able to depend on them so well and they become much more subject to interference as the sound wave attenuates.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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-24 03:47
    OK, I'm checking out your code and will post some snippets for you in a bit (need to check out SRF10).

    One thing, I *do* think you should not use such a straight parsing of the ranges, e.g.

    
        IF  i2cdata > Max_range THEN
          GOTO mode1 'Breathing
        ELSEIF ((i2cdata =< Max_range) AND( i2cdata >= Opt_Range)) THEN
          GOTO mode2  'wake up
       ELSEIF ((i2cdata < Opt_Range) AND ( i2cdata >=Min_Range))THEN
          GOTO mode3 'opt range
        ELSEIF i2cdata < Min_Range THEN
         GOTO mode6   'too close
        ELSE
          GOTO mode0
        ENDIF
    
    



    You need hysteresis here -- dampening -- the state machine example I posted would serve better -- then I do think you could bail on averaging samples.

    Now, you've got SDA and SCL on 4 and 5 with all your bit banged routines. Can you, and do you want to, move SDA and SCL from 4 and 5 to 8/9 or 0/1 on either bank? It looks like not all of auxio is used?

    'X8 NOT USED ' make this SDA
    'X9 NOT USED ' make this SCL

    I can't encourage you enough to do this and use the builtin i2c commands -- it will cut huge amounts of code and var space out of your program and eliminate *possible* sources of errors and problems. So if you have a ranging problem, you'll know it's the ranging, or how you are handling the ranging, but not i2c communication itself.

    OK, onward -- you have a lot of cases in the program like this:

    '=========================================================================
    '         prg10 - TBD3
    '=========================================================================
    
    mode10:
    
    DEBUG  2,0,5,"mode 10 TBD3                                        "
    
    OUTA = 7  'TO OUPUT 111 ON PINS 6 7 8   ' I am presuming this is 
    
    GOTO main
    
    



    I thought that your master out was a subset of pins 0-3? OUTA is 0-3, OUTB is 4-7, etc. But you said this portion is working currently? -- wait -- I see, those are in/out with sound effects... regardless, if you are trying to put data 6, 7, 8 above that will not work.

    The shift and such method will not work if you are wired like above because everything is grouped by "fours" -- pins 0-3, 4-7, 8-11, 12-15, etc. Pins 6 and 7 are the two highest bits of OUTB and pin8 is the lowest bit of bit OUTC.

    If this is how it's wired than you would need to mask then add your mode to OUTS which is a word representing all 16 bits of the current i/o bank.

    Presuming defs at bottom are current. See a few comments. Name definitions would really help. I see now why you are going through some of the acrobatics on reading/writing i/o -- the groups aren't necessarily aligned in chunks of 4 (which helps if you want to use OUTA/INA/DIRA and such). So since you prob. don't want to rewire anything if not necessary smile.gif, I would shift to working on the entire words for OUTS/INS/DIRS because you can set whatever pins you want... but in a subroutine, e.g.

    'The MAINIO designations for DIRS command are as follows:
     'PO NOT USED
     'P1 OUT TO LED BS2P40 TO SEND WHAT MODULE 0 - 7 TO RUN
     'P2 OUT TO LED BS2P40 TO SEND WHAT MODULE 0 - 7 TO RUN
     'P3 OUT TO LED BS2P40 TO SEND WHAT MODULE 0 - 7 TO RUN
    ModeOut VAR OUTA  ' this is aligned
    
     'P4 OUT TO SONAR SRF10 SCL LINE
     'P5 IN FROM SONAR SRF10 SDA LINE
    SDA PIN 4   ' having this on aux 8 will let you use builtin i2c
    SCL PIN 5  ' dont' define these as cons as you did regardless
    
     'P6 OUT TO TRIGGER SOUND BOARD A WHEN LOW
     'P7 IN FROM SOUND BOARD A (BUSY SIGNAL)
     'P8 OUT TO TRIGGER SOUND BOARD B WHEN LOW
     'P9 IN FROM SOUND BOARD B (BUSY SIGNAL)
    ' not aligned so we'll have to juggle word DIRS/INS/OUTS if you want to do these all at once
    ' names are still good
    
    SoundTriggerA   PIN 6
    SoundInA        PIN 7
    SoundTriggerB PIN 8
    SoundInB        PIN 9
    
     'P10 DIP SWITCH #4 (BIN 8 COLUMN)PULLED HIGH WITH 4.7K RESISTOR
     'P11 DIP SWITCH #3 (BIN 4 COLUMN)PULLED HIGH WITH 4.7K RESISTOR
     'P12 DIP SWITCH #2 (BIN 2 COLUMN)PULLED HIGH WITH 4.7K RESISTOR
     'P13 DIP SWITCH #1 (BIN 1 COLUMN)PULLED HIGH WITH 4.7K RESISTOR
    ' ditto, but names are good
    Switch4 PIN 4
    Switch3 PIN 3
    Switch2 PIN 2
    Switch1 PIN 1
    
     'P14 NOT USED
     'P15 NOT USED
    
    'The AUXIO designations for DIRS command are as follows:
    
     'XO OUT TO OPTO ISOLATED SIGNAL OUT 2
     'X1 OUT TO OPTO ISOLATED SIGNAL OUT 1
     'X2 IN FROM OPTO ISOLATED SIGNAL IN 2
     'X3 IN FROM OPTO ISOLATED SIGNAL IN 1
    ' can hit this in one batch with out OUTA/INA/DIRA if you want
    X0 PIN 0
    X1 PIN 1
    X2 PIN 2
    X3 PIN 3
    XDIR VAR DIRA
    XIN VAR INA
    XOUT VAR OUTA
    ' now  constant for masking input/output
    XDstate   CON %0011 ' output, output, input, input
    XinMask   CON %1100
    XoutMask CON %0011
    
     'X4 NOT USED
     'X5 NOT USED
     'X6 NOT USED
     'X7 NOT USED
     'X8 NOT USED  ' put SDA here
     'X9 NOT USED  ' put SCL here
     'X10 NOT USED
     'X11 NOT USED
     'X12 NOT USED
     'X13 NOT USED
     'X14 NOT USED
     'X15 NOT USED
    
    



    But this comes back to using ALIASES/VARIABLES and SUBROUTINES, like the send_mode example. That way you are cutting a possible source of error to *one* place, you can change how you handle it if you need to.

    Here's a possible sub...

    soundOut VAR Nib ' 2 bits for sound trigs
    
    mode3:
    DEBUG  2,0,5,"mode 3 SUBJECT IN MID-RANGE                       "
    
    'what's the below about? if these are the sound pins, then 6 and 8 are inputs????
    ' it's commented out, but if you need to write to the two outputs.....
    soundOut = %11 ' this will be
    GOSUB writeSound
    
    selectMode = 7
    GOSUB writeMode
    
    xMode = %01
    GOSUB writeX
    GOTO main
    
    
    ' Subroutines
    writeMode:
       ModeOut = ModeOut & %0001 | ( selectMode << 1 ) ' mask p0 and  shift select mode 1 bit
       RETURN
    
    
    ' this subroutine write a number 0-3 to the two trigger pins (regardless of their location)
    ' in other words the two lowest bits of "soundMode" will be the trigger states
    writeSound:
      SoundTriggerA = soundMode.BIT0(0) ' the first bit of soundMode is the trigger
      SoundTriggerB = soundMode.BIT0(1) ' the second bit of soundMode is the trigger
      RETURN
    
    writeXout:
     ' put lowest two bits of xMode onto Xout pins
      XOUT = xMode  ' this will only affect pins set to "output"; if the X inputs are left as inputs, for them this is a "don't care"
    ' or fancy masking
    '  XOUT = XOUT & XinMask | xMode  ' this will only affect actual pins for this purpose
      RETURN
    
    
    

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

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


    Post Edited (Zoot) : 8/24/2008 4:22:37 AM GMT
  • ZootZoot Posts: 2,227
    edited 2008-08-24 04:36
    OK, I'll leave it to you to add the extra variables for this, but instead of averaging, do something like this -- if you adjust the "threshold" -- i.e. how many successful "hits" at that range changes your mode, you may find that you get consistent results, and that the piece won't trigger in a hair's breadth if someone is right on the "edge" of the range change and is moving a bit. It gives it some "inertia" so to speak.

    state VAR Nib
    stateCntr VAR Byte ' make it a word if you need more than 255 counts (which you may)
    ' at start of everything, the state is 0 (all vars are cleared to 0 when stamp is poweredup/reset)
    
    ON state GOTO mode1, mode2, mode3, mode6
    ' if no others, 
    GOTO mode0
    
    
    ' now at the top of your modes (not excerpted here), first parse if you need a "state" change:
    
    mode1:
        IF  i2cdata <= Max_range THEN
            stateCntr = 0  ' clear the counter
        ELSE
            stateCntr = stateCntr + 1   ' less than max, count...
            IF stateCntr > 4 THEN
                state = 1
            ENDIF
        ENDIF
       ' now all your mode  stuff ... keeps coming back to state machine
       GOTO done
    
    mode2:
        IF  ( i2cdata < Opt_Range ) AND ( i2cdata >=Min_Range ) THEN
            stateCntr = stateCntr + 1   ' less than max, count...
            IF stateCntr > 4 THEN
                state = 2
            ENDIF
        ELSE
                   stateCntr = 0  ' clear the counter
        ENDIF
      ' now all your mode  stuff ... keeps coming back to state machine
       GOTO done
    
    'etc
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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-24 04:59
    There is no light sensor on the SRF10. The values are big endian...
    said...


    Location

    Read

    Write

    0

    Software Revision

    Command Register

    1

    Unused (reads 0x80)

    Max Gain Register (default 16)

    2

    Range High Byte

    Range Register (default 255)

    3

    Range Low Byte

    N/A

    Only locations 0, 1 and 2 can be written to. Location 0 is the command register and is used to start a ranging session. It cannot be read. Reading from location 0 returns the SRF10 software revision. By default, the ranging lasts for 65mS, but can be changed by writing to the range register at location 2. The SRF10 will not respond to commands on the I2C bus whilst it is ranging. See the Changing Range and Analogue Gain sections below.

    Locations, 2 and 3, are the 16bit unsigned result from the latest ranging - high byte first. The meaning of this value depends on the command used, and is either the range in inches, or the range in cm or the flight time in uS. A value of either 0 or maximum indicates that no objects were detected. Maximum is 65535 (0xFFFF) if you are ranging in uS, 1129 for cm and 442 for inches

    Commands
    The are three commands to initiate a ranging (80 to 82), to return the result in inches, centimeters or microseconds. There is also a set of commands to change the I2C address.

    Command Action
    Decimal Hex
    80 0x50 Ranging Mode - Result in inches
    81 0x51 Ranging Mode - Result in centimeters
    82 0x52 Ranging Mode - Result in micro-seconds

    160 0xA0 1st in sequence to change I2C address
    165 0xA5 3rd in sequence to change I2C address
    170 0xAA 2nd in sequence to change I2C address

    [noparse][[/noparse]/code]

    From your program...

    GETMax_Range:
    
    ' SRF10 Ranger
      I2cAddr = $e0
      I2cReg = 0
      I2cData = 80      ' Ranging command - 80 for inches, 81 for cm, 82 for uS
      GOSUB  I2cByteWrite
      PAUSE  70      ' wait for ranging to complete
      I2cReg = 1        ' address of light sensor register   ' nothing here to read
      GOSUB  I2cByteRead
      I2cReg = 2          ' address of first ranging result
      GOSUB  I2cWordRead
      DEBUG  2,0,1, "Range ", DEC4 I2cData," Inches "
    
      Send_Mode = INA & %1110 'this will mask Bit 0 from the variable.
      DEBUG   2,0,4, "P0 - P3 ", BIN Send_Mode
    
    
    



    You are reading the sonar little endian, but I'm not sure your bit-banged i2c routines are exactly right (though it may not matter in this context).

    Wait -- I'm reading the docs again:
    said...
    The maximum range of the SRF10 is set by an internal timer. By default, this is 65mS or the equivalent of 11 metres of range. This is much further than the 6 metres the SRF10 is actually capable of. It is possible to reduce the time the SRF10 listens for an echo, and hence the range, by writing to the range register at location 2. The range register can be set in steps of about 43mm (0.043m or 1.68 inches) up to 11 metres.
    The range is ((Range Register x 43mm) + 43mm) so setting the Range Register to 0 (0x00) gives a maximum range of 43mm. Setting the Range Register to 1 (0x01) gives a maximum range of 86mm. More usefully, 24 (0x18) gives a range of 1 metre and 93 (0x5D) is 4 metres. Setting 255 (0xFF) gives the original 11 metres (255 x 43 + 43 is 11008mm). There are two reasons you may wish to reduce the range.
    1. To get at the range information quicker
    2. To be able to fire the SRF10 at a faster rate.
    If you only wish to get at the range information a bit sooner and will continue to fire the SRF10 at 65ms of slower, then all will be well. However if you wish to fire the SRF10 at a faster rate than 65mS, you will definitely need to reduce the gain - see next section.
    The range is set to maximum every time the SRF10 is powered-up. If you need a different range, change it once as part of your system initialization code.

    I would step the range down, get faster samples, probably not so many echos.

    www.robot-electronics.co.uk/htm/srf10tech.htm

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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-24 05:02
    Hey zoot I am back saw your volumes of suggestions· I can cut traces and move sonar if you really think that will help.



    I am a bit overwhelmed with all of it - it may take a moment for it to sink in.

    I may need you to help me cut and paste some of it.· as far as the changing of the sonar pins should we do that first or try some of the other code first and do it later.· It is only 2 pins and I left spare holes on all the unused pins ·to make easy changes or add pull up or pull down resistors.· so let me know.
  • ZootZoot Posts: 2,227
    edited 2008-08-24 15:25
    No problem on cut/paste whatever, but it would be good if you can answer some basic questions and make a few decisions then take it from there. Then break it down into pieces:

    - get your sonar unit working properly, via i2c, without reading non-existent light sensor, and setting up range and analogue gain so you get the best results. Personally, I would write a small program that does JUST that without any extras. I also *would* move your I2C bus to aux 8/9. It's not much to wire and only two resistors. This will eliminate a slew of code, possible problems, and free up lots of variable space because you know that the problem will not be your·bit-banged ·i2c code. For a test program you'd really only need one variable --·a place to the hold range...e.g.

    I2COUT, $E0, 0, [noparse][[/noparse] 80 ]

    I2CIN, $E0, 2, [noparse][[/noparse] range.HIGHBYTE, range.LOWBYTE ]

    DEBUG DEC5 range

    If you have a breadboard, I would pop the BS2p40 from it's socket on your custom board, and just try it out on your bench -- the ranger, the stamp, and two pullups for SDA and SCL is all you need. [noparse][[/noparse]b]Read the documentation on the ranger[noparse][[/noparse]/b] regarding setting range and gain. Only you can experiment here to see what gives you the best sonar readings.

    - go through your program and assign names to pins, etc. and use them. This is pretty much a tedious find/replace task, but it will make the code much easier to read (for you and others). Even if it doesn't work the way want, it'll be a good framework to start from. At that point I'm also more than happy to adjust code from my end.

    - then we can start putting the pieces into back into place.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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-24 16:22
    One more morning note about breaking your program into pieces -- create some super short and brief programs each of which tests out just ONE sub. Make sure it's working perfectly before you use it in your main program.

    For example, make sure that a sub like "writeMode" indeed puts the numbers you want on pins1-3 -- in it's own program -- then you know if you use that sub in your main progam you can use it like a "black box" and your primary chore in the main program will just be putting the pieces together and testing the logic and flow of the decision-making, rather than worrying if your logic is good AND if you're writing the right number to the pins AND if your ranging is working, 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-24 16:43
    Hey Zoot,

    I am here and ready to knock this stuff out.· it is working but if you think it would make this project a lot easier to shift some pins I am ready to cut and move.· Moving the sonar to AUX pins is no problem.· While I am in there I could also change the P1 -P3 over to P0 - P2 like the other board and that would cut out some code to make it cleaner.· What do you think?
  • ZootZoot Posts: 2,227
    edited 2008-08-24 18:28
    said...
    it is working

    1. I'm a big fan of things that work. "It" is the sonar? The entire project? If it works, then why redo anything smile.gif Confused.

    2. Regardless, since you have a board I wouldn't move or cut anything unless absolutely necessary. There's no reason not to use the few lines of code for "translating" your slave/master 3 bit number from whatever the pin setups are. The only place where I had a real question was using all the bitbanged code for I2C when those functions are built-in to the BS2p40 -- and the only thing *preventing* you from using those is that the I2C bus must be on p0/p1 or p8/p9. And I still wouldn't cut or solder till you try out the ranger with the built in I2C and the Stamp without all the other stuff. And again, if it works....

    3. If you did need to wire in a fresh SDA/SCL, I'm not sure you need to cut traces -- if you have access to the pins, then you can make a little "dongle" with +5v, gnd, SDA/SCL wires going to wherever they need to go on one side, and a plug/connector/header whatever on the other for the sonar -- maybe not as neat as using a header on the board, but then you don't have to modify anything with a knife. But see point #2.

    4. it still sounds like the biggest challenge is getting not necessarily clean, but *useful* info from the ranger and using in the main part of your program. My reading of the documentation is that the default settings on the SRF10 are quite high -- setting down the range a bit and adjusting the gain for optimal performance will prob. be well worth the time playing with it on the bench. 11 meters seems awfully long for a 40khz sonar. I would try cutting it back to 3 meters or so, then notch it *up* a meter at a time and see where reliability starts to fall off.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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-24 18:41
    Hey Zoot

    I made the layout with plenty of spare holes for last minute fixes, so not to worry. I have already moved the 3 bits to line up on P0 - P0
    P1 - P1 and P2 - P2.

    I thought you said I could AUXIO pins for sonar if so I can easily move them two please let me know.

    Now that the MAINIO pins line up any idea for cleaner OUTA = 0 to OUTA = 7 code? or is that it?

    Daniel
  • ZootZoot Posts: 2,227
    edited 2008-08-24 18:50
    I suggested auxio 8/9 for SDA and SCL because according to description in your main program, those pins are unused. But try it out on a breadboard first. Seriously. Or just leave it be if you are confident you are properly communicating via i2c with the ranger (have you read the version number out of that device -- it's a great way to tell if you are properly communicating w/any peripheral because it's either right or it's wrong, if the latter you know you are not necessarily communicating properly).

    I saw in your 7 cases thread you moved your pins. Did you do that on the slave side also? In other words, post your current program with the current pin definitions smile.gif

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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-24 18:59
    zoot

    I just finished moving the main micro pins to line up pin for pin with the led micro so now I need to send the 7 cases out P0, P1, P2 to be recieved by the led micro P0, P1, P2 So now I am hope this put this "bit" to rest and I can just use OUTA and INA. On the main micro P3 is tied high through a 4.7k resistor. On the LED micro I am using P3 for my led matrix and it needs to stay an output.

    daniel
  • NauketecNauketec Posts: 51
    edited 2008-08-24 19:58
    Zoot, et al

    I have the board working to a degree - - -

    It is performing what it should do but . . .

    The sonar could still use a simple averaging of the ping data.

    The name of the ping data is i2cdata

    What I am looking for is something that would read 5 (or whatever) pings store them so that
    the 5 pings could be divided by 5 and that number lets call it AvgData·

    Daniel



    ·
  • ZootZoot Posts: 2,227
    edited 2008-08-24 20:00
    Post the current version of the main program.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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-24 21:11
    Hey Zoot,

    Here is the current working main micro program.· Most of the OUTA comands are working but some are curiously going to mode7 ? ( the ones that are comented out)

    What is working is:
    • On power up the dip switches direct which program definitions to use prg0 to prg15
    • The sonar is pinging correctly and gives out data
    • The IF THEN statements to look at what the sonar measurements are and then·directs what mode# to use
    • The LED micro is following the data and going to the correct led effect module

    What can be refined is:
    • The sonar pinging to get an average of 4-5 pings
    • The IF THEN GOTO statements on the main micro
    • Why some of the OUTA comands are not working

    Let me know what you think or just paste it in where you think it needs tweeking· I am understanding much more each time I have something to look at and compare to the manual.

    Daniel


    Post Edited (Nauketec) : 8/25/2008 5:25:18 AM GMT
  • ZootZoot Posts: 2,227
    edited 2008-08-24 23:26
    This has code for averaging sonar reading.

    You have not wrapped your mode function to a subroutine (e.g. writeMode) so it's really hard to tell where your error is coming from; will look at it again tonight.

    I also used conditional definitions to turn off your debug statements (read the manual); your debug statements *will* take a lot of time in your main loop and should all be turned off when you are not using them.

    See my comments within the code.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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-24 23:45
    Zoot,



    The OUTA is a mystery!· All OUTA numbers are working except for OUTA = 1· this returns 1111

    When I try OUTA = %0001 I also get 1111 (Remember that I have pull ups on P0 P1 P2 P3)

    I am still working on that one but for now my next task is to take off the bench to hang it up in a larger room and test the sonar distances

    Daniel
  • ZootZoot Posts: 2,227
    edited 2008-08-25 00:16
    OK, now I see -- I'm surprised you get any numbers at all.

    OUTA = %1111

    will put HIGHs on pins 0-3 BUT ONLY IF THOSE PINS ARE OUTPUTS. Nowhere in your program do I see where you've defined your pins nor where you have set these pins to be outputs.

    you can do either of the following (make sure this appears below a bank statement MAINIO/AUXIO so that you are affecting the correct i/o side of the bs2p40:

    DIRA = %1111 ' make 'em all outputs
    
    



    Or if you have named pins

    ' comment any of these out if unused
    myP0 PIN 0
    myP1 PIN 1
    myP2 PIN 2
    myP3 PIN 3
    OUTPUT myP0
    OUTPUT myP1
    OUTPUT myP2
    OUTPUT myP3
    
    



    Then when you change the value of OUTA whatever value you see there is what you'll get on the pins themselves to the outside world.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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 01:01
    Hey zoot

    Yeah I had a DIRS comand all the way in the head of the program but it must of got comented out and I fogot to bring it back

    I have it on the wall now and got it to work up to 4 feet for it is now hitting walls and ceilings but it does work. The averaging would help. I will now try OUTA = 1 and see if that works

    Daniel
  • NauketecNauketec Posts: 51
    edited 2008-08-25 01:28
    Hey Zoot you had written to me about hysteresis.· Do you think I still should move the sonar to the AUXIO pins for it would be a 2 minute job.
    I am reading all your notes and I think the sonar is the next big task when that is done the worst is over.· Let me know your thoughts


    OK, I'm checking out your code and will post some snippets for you in a bit (need to check out SRF10).
    One thing, I *do* think you should not use such a straight parsing of the ranges, e.g.


    ··· IF· i2cdata > Max_range THEN
    ····· GOTO mode1 'Breathing
    ··· ELSEIF ((i2cdata =< Max_range) AND( i2cdata >= Opt_Range)) THEN
    ····· GOTO mode2· 'wake up
    ·· ELSEIF ((i2cdata < Opt_Range) AND ( i2cdata >=Min_Range))THEN
    ····· GOTO mode3 'opt range
    ··· ELSEIF i2cdata < Min_Range THEN
    ···· GOTO mode6·· 'too close
    ··· ELSE
    ····· GOTO mode0
    ··· ENDIF

    You need hysteresis here -- dampening -- the state machine example I posted would serve better -- then I do think you could bail on averaging samples.
    Now, you've got SDA and SCL on 4 and 5 with all your bit banged routines. Can you, and do you want to, move SDA and SCL from 4 and 5 to 8/9 or 0/1 on either bank? It looks like not all of auxio is used?
    'X8 NOT USED ' make this SDA
    'X9 NOT USED ' make this SCL
    I can't encourage you enough to do this and use the builtin i2c commands -- it will cut huge amounts of code and var space out of your program and eliminate *possible* sources of errors and problems. So if you have a ranging problem, you'll know it's the ranging, or how you are handling the ranging, but not i2c communication itself.





    Post Edited (Nauketec) : 8/27/2008 3:57:26 AM GMT
  • NauketecNauketec Posts: 51
    edited 2008-08-25 02:37
    Zoot

    The sonar seems to OK. Could you let me know how great the savings are to shift it to AUX pins 8,9?
    I think if I could just build in a 3-4 inch "deadband" in each of the ((i2cdata =< Max_range) AND( i2cdata >= Opt_Range)) THEN statements it whould stop any bounce in the data. I will work on other areas and wait to hear your thoughts.

    Daniel
  • ZootZoot Posts: 2,227
    edited 2008-08-25 03:39
    If it's working, it's good!

    For "dampening" you could do a simple check to see if the range is +/- a given amount, or do a counter like I suggested.

    The state machine is a like a big "if/then" that keeps repeating and only goes to the next "then" if a certain count has been reached -- like the range has to be below the threshold 4x in a row or 8x in a row (or whatever gives you good results).

    But I'm curious -- your most recent posted version doesn't have the bad INA statement removed (like in my edit) or the averaging code. It also doesn't have the conditional defs for removing all the debugs (this is slowing your sample time wayyyyyyyyyyy down). ?? The v.7 I posted was your exact version from earlier today with small edits (for sonar averaging) and I tokenized it in the Stamp IDE to make sure it was clean.

    In any case, I dropped the following snipped into your most recent project and tokenized it.

    e.g.

    
    cntr1 VAR NIB
    cntr2 VAR NIB
    cntr3 VAR NIB
    cntr4 VAR NIB
    
    '===========================================================
    '  Select mode for led micro and output to p1 p2 p3
    
        IF i2cdata > Max_range THEN
          cntr1 = cntr1 + 1 MAX 15
          IF cntr1 > 4 THEN GOTO mode1 'Breathing
        ELSE
          cntr1 = 0
        ENDIF
    
       IF ((i2cdata =< Max_range) AND( i2cdata >= Opt_Range)AND ( i2cdata >=Min_Range))  THEN
          cntr2 = cntr2 + 1 MAX 15
          IF cntr2 > 4 THEN GOTO mode1 'wakeup ''''''''''' YOU HAD MODE1 FOR BOTH THIS ONE AND THE ONE ABOVE???
        ELSE
          cntr2 = 0
        ENDIF
          
       IF ((i2cdata < Opt_Range) AND ( i2cdata >=Min_Range))THEN
          cntr3 = cntr3 + 1 MAX 15
          IF cntr3 > 4 THEN GOTO mode4 'opt range
        ELSE
          cntr3 = 0
        ENDIF
    
        IF i2cdata < Min_Range THEN
          cntr4 = cntr4 + 1 MAX 15
          IF cntr4 > 2 THEN GOTO mode6   'too close  -- quicker trigger only two positives will do it
        ELSE
          cntr4 = 0
        ENDIF
    
       ' only get here if nothing else...
        GOTO mode0
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    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 04:35
    Zoot I tried your version 7 and it does not work I will upload my working version
  • ZootZoot Posts: 2,227
    edited 2008-08-25 05:42
    Before you spend time trying to tweak your sonar average and/or when you've passed your distance ranges thresholds, you've got to take out the debug statements that run every time through the loop. Use conditional compilation (#IF #THEN #DEFINE -- see the Pbasic manual) so that you can turn these on and off.

    Then check out the sonar averaging code I posted and either use it or adapt it -- it's not complicated -- a for/next loop goes through your maxrange portion of code and runs it 4 times -- each times it adds the result of the ranging (i2cdata) to another Word variable (sonarrange). After it's done that 4 times, it divides the final total (sonarrange) by 4. See FOR/NEXT in the Pbasic manual.

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

    1uffakind.com/robots/povBitMapBuilder.php
    1uffakind.com/robots/resistorLadder.php
Sign In or Register to comment.