Shop OBEX P1 Docs P2 Docs Learn Events
Proper way to change the I/O pin used by an object? still stumped — Parallax Forums

Proper way to change the I/O pin used by an object? still stumped

WBA ConsultingWBA Consulting Posts: 2,935
edited 2009-08-23 16:34 in Propeller 1
I started with the propeller after UPEW, so I am still in the newbie category. I have been going through the manual, example programs, and tutorials in my learning adventure. Most of my time is being spent disassembling the code structure from the Sensirion SHT11 demo so I can make sense of each line. I am working on tweaking the code to read multiple sensors and have it working, but I know I am changing the datapin used by the Sensirion object the wrong way (I just keep re-starting the object with a different pin). I claim the newbie excuse for this mis-use of SPIN. So.......

What's the proper way to change the pins used by an object?
(I would prefer a response that tells me what direction to head rather than the straight answer as I know I will eventually figure it out, but I think I have been looking in the wrong places for the answer)

For example, the Sensirion object demo has:
sht.start(SHT_DATA, SHT_CLOCK)
and SHT_DATA and SHT_CLOCK are set as constants equaling 0 and 1.

How do I change the value of SHT_DATA during runtime? I have the clock (I/O 0) tied to 4 sensors using data lines on I/Os 1, 2, 3 and 4. So I simply want to leave the clock pin as I/O 0 and cycle the data pin through the 4 other pins.
Can I not do that because it is set as a constant earlier in the program? The manual says constants are set at compile time. Does this mean that constants declared in the code cannot be changed after compiling (in other words, during runtime)?

When I set SHT_DATA as a byte size variable and use a local variable (i) to count through the sensor pins, this doesn't work:

SHT_DATA:= i

However, re-doing the start command in my repeat block does:

sht.start(i, SHT_CLOCK)

I have tried several different ways with only getting various errors during compile. The manual isn't in plain enough English for me to capture which method I should be using to accomplish this. I started digging through the tutorials and the sticky example thread, but so far, nothing.

thanks in advance

▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Andrew Williams
WBA Consulting

Post Edited (WBA Consulting) : 8/23/2009 2:09:33 AM GMT

Comments

  • Clock LoopClock Loop Posts: 2,069
    edited 2009-08-20 08:14
    WBA Consulting said...


    What's the proper way to change the pins used by an object?
    (I would prefer a response that tells me what direction to head rather than the straight answer as I know I will eventually figure it out, but I think I have been looking in the wrong places for the answer)

    I had this issue myself, and found that one can use the DAT section to accomplish this.

    As per your request, that is the only hint I will give you.


    WBA Consulting said...

    I have tried several different ways with only getting various errors during compile. The manual isn't in plain enough English for me to capture which method I should be using to accomplish this. I started digging through the tutorials and the sticky example thread, but so far, nothing.

    After I also ran out of ideas, the DAT section was all I had left,
    and this method was not in any manual or thread.

    Make sure you look up the DAT section in the manual, because it has a two fold use,
    for assembly and for data.

    WoOt :~o

    Post Edited (Clock Loop) : 8/20/2009 8:28:30 AM GMT
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-08-20 14:11
    I made a quick check

    with the sensirion-demo-code from Cam Thompson, Micromega Corporation

    and both ways to define a variable "k" global byte and "i" local long do compile with propellertool 1.2.6 !?!

    VAR
      byte k
        
    PUB main | rawTemp, rawHumidity, tempC, rh, dewC, i
    
      term.start(16)                                        ' start VGA terminal
      'term.start(12)                                        ' start TV terminal
      f.start                                               ' start floating point object
      sht.start(k, i)                        ' start sensirion object
      'sht.start(SHT_DATA, SHT_CLOCK)                        ' start sensirion object
    
    
    



    so which version of the propellertool are you using or maybe even some other SPIN-compiler ?

    what kind of error-message do you get ?

    best regards

    Stefan
  • WBA ConsultingWBA Consulting Posts: 2,935
    edited 2009-08-20 17:15
    StefanL38.... Glad you brought up the Propeller Tool version. I started this project with version 1.0.5 and upgraded it in the middle of my frustration due to the missing tutorials. (I had 1.2.6 on my other laptop and that's where I was reading them mostly) I did not go back and try all of my failed attempts after the upgrade. I will start back over at square one with this now that I have 1.2.6 installed.

    Clock Loop... Thanks for the tip. The DAT command was one of the things I thought might be a solution and will take a deeper look at it.

    thanks!

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Andrew Williams
    WBA Consulting
  • WBA ConsultingWBA Consulting Posts: 2,935
    edited 2009-08-23 02:05
    I tried a few more things but still can't figure out how to change the data pin that the SHT object uses, without utilizing the start function of the object. Maybe I am wrong, but I would think that is not the correct way.
    It works great as it stands now. Running it on a prop demo board using P0 for clock and P1-P6 for the data lines of 6 sensors. Currently only using 2 sensors so 4 of the readings are showing invalid values (I'll be modifying the code to only display valid values or "---" so it's obvious when a sensor is not functioning). Using the VGA terminal option and displaying it on my Samsung 40" flatscreen.


    When I have the start function in the beginning of the code (with the other start functions) as:
    sht.start(i, SHT_CLOCK)
    


    and change the value of "i" in the repeat section of my code, none of the readings are valid as if the SHT object is not using the "i" value to change which pin it uses for the data line.

    When I put the start function inside the repeat block, it works fine. Isn't starting the same object over and over an incorrect method of doing this?

    Attached is current code and a picture of the VGA output. Below is the main method which has the start and repeat functions mentioned.

    PUB main | rawTemp, rawHumidity, tempC, rh, dewC, i, name
    
      term.start(16)                                        ' start VGA terminal
      'term.start(12)                                        ' start TV terminal
      f.start                                               ' start floating point object
      'sht.start(SHT_DATA, SHT_CLOCK)                              ' start sensirion object
    
      term.out(CLS)                                         ' 
       ' read and display SHT-11 sensor readings every 2 seconds
      repeat
        setColor(3)
        displayString(0, 0, string("        Current Values        ", CR))  ' display title 
        setColor(0)
        term.str(string("│  Sensor  │  Temp F │  RH % │", CR))
        term.str(string("├──────────┼─────────┼───────┤", CR))
        'start of repeating sensor sequence
        repeat i from 1 to 6                                '6 sensors on P1-P6
          sht.start(i, SHT_CLOCK)
          rawTemp := f.FFloat(sht.readTemperature) 
          rawHumidity := f.FFloat(sht.readHumidity)  
          tempC := celsius(rawTemp)
          term.str(string("│ "))
          name := lookup(i: string("LivingRm"), string("BedRoom1"), 
    string("BedRoom2"), string("  Den   "), string("Kitchen ") , string("MstrBath"))
          term.str(name)                  ' sensor name variable
          term.str(string(" │ "))
          term.str(fp.FloatToFormat(fahrenheit(tempC), 5, 1))
          term.str(string(deg, "  │")) 
          rh := humidity(tempC, rawHumidity)
          term.str(fp.FloatToFormat(rh, 5, 1))
          term.str(string("  │", CR))
        term.str(string("└──────────┴─────────┴───────┘"))
    
        
        waitcnt(cnt + clkfreq * 2)
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Andrew Williams
    WBA Consulting

    Post Edited (WBA Consulting) : 8/23/2009 8:59:59 AM GMT
  • StefanL38StefanL38 Posts: 2,292
    edited 2009-08-23 04:36
    Hello Andrew,

    if you take a look at the code inside of the method start

    PUB start(data_pin, clock_pin) 
      ' assign SHT-11 clock and data pins and reset device
      dpin := data_pin                                      ' assign data pins                       
      cpin := clock_pin                                     ' assign clock pin
      outa[noparse][[/noparse]cpin]~                                           ' set clock low
      dira[noparse][[/noparse]cpin]~~
      outa[noparse][[/noparse]dpin]~~                                          ' set data high
      dira[noparse][[/noparse]dpin]~~                                           
      REPEAT 9                                              ' send 9 clock pulses for reset
        !outa[noparse][[/noparse]cpin]                                         
        !outa[noparse][[/noparse]cpin]
    
    



    THIS start-method does only some variable-assignments, setting up IO-pin-directions and toggle IO-Pins
    in this case it is no problem to call it again and again. It would be a problem if the start-method would use a cognew to start a new cog.
    Then you would run out of cogs all doing the same and interfere with each other

    Your picture shows negative humidity. This seems to be wrong for me. Are you sure the negative humidity-values are valid ?

    I guess as you only change the dataline all clocklines are parallel connected. This means all sensors get their clockinput
    bitbanged all the time. I'm not familiar with the SHT-sensor. Does a reset bring the sensor back to working properly ?

    If you have the call of the start-method outside the repeat-loop
    how do you then change the dataline INSIDE the repeat-loop ?

    another small hint:

    you should not code

       waitcnt(cnt + clkfreq * 2)
    
    



    always as do it this way

       waitcnt(clkfreq * 2 + cnt) '<== + cnt at the END
    
    



    add the actual value of cnt at the END of the expression to keep the time that will pass by between interpreting the spin-expression
    and the REAL call of the PASM-command waitcnt (done by the interpreter) as short as you can

    best regards

    Stefan

    Post Edited (StefanL38) : 8/23/2009 4:44:29 AM GMT
  • TimmooreTimmoore Posts: 1,031
    edited 2009-08-23 05:15
    A question - you understnad you will be updating every 5.8sec? Each readtemp/readhum takes 320ms so 6x2x320ms -> 3.8sec + 2sec -> 5.8sec.
  • WBA ConsultingWBA Consulting Posts: 2,935
    edited 2009-08-23 08:56
    Timmoore: Yes, I understand the frequency of the readings. I have not bothered to change that from the demo yet during my coding. The demo in the Sensirion object was set for 2 seconds. My final project that will be using this code will be updating every 4 minutes (15 readings per hour) and will be triggered by time, not a pause in the code. I actually have not been able to self-heat the sensor by reading it too fast as the datasheet warns; not sure if you were asking because my readings were too fast or too slow. In my current setup, it's actually about 3 seconds, because I only have 2 sensors connected. (timeouts are faster then the full data communication)

    StefanL38:
    --Thanks for the clarification about the start call. I was unaware if re-starting the same object over and over would be slowly eating away free space and would eventually prevent the program from running. I was aware about the repeating cognew problem, even though I have never used the command.
    --As for the negative humidity, those are technically valid values because I only have two sensors mounted on my demo board. So 4 of the values are calculating off of null readings, which give you a temp of -39.4F and an RH of -4.6%. Since I know why those values show up, I ignore them, for now... In a finished state, those values would tell me that a sensor has been disconnected, however, my code will also recognize invalid values and display "---" in its place. (I mentioned this in the last post)
    --Yes, the clocklines are all tied together and each device that does not have its dataline being used, is actually being continually held in reset because the data line has a pullup. (a reset is 9 or more clock pulses with the dataline high). This actually doesn't cause any problems, but I will modify the code to eliminate this continuous reset problem on idle sensors or change to bussing the data lines and changing the clock.
    --A Reset refreshes the serial interface only, but typically clears any problems. I have actually eliminated the reset sequence from some programs and can get them to run without any problems. The reset makes it bulletproof and eliminates the need for extra error handling.
    --Your question "If you have the call of the start-method outside the repeat-loop how do you then change the dataline INSIDE the repeat-loop ?" is exactly what I am looking for. However, your comments made me look back into the Sensirion object and the start method. I think I need to pull out the pin assignments from that method and create a "pinassign" method. The reset sequence would also be pulled into its own method. Then the start method would call both of those, but during my repeat sequence in my main program, I can call the pinassign method to change the pins as needed. I will have to try this tomorrow.
    --Point taken on the waitcnt line. That line came from the demo code from Cam Thompson, so I assumed that it was done correctly and never thought to analyze it. I guess that's newbie lesson #57: Don't assume the code you're given is perfect.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Andrew Williams
    WBA Consulting
  • TimmooreTimmoore Posts: 1,031
    edited 2009-08-23 16:34
    ok, I just wanted to point it out that the wait for data would cause the delay tat the waitcnt was causing, but I understand what you are doing.
    I did change the wait routine when I used the sht, I found the wait period isn't as long as the spec allows and I sometimes got invalid readings. My wait code looks like
    PRI wait | t                                            ' wait for data low (450 msec timeout)
    '' 20ms for 8bit, 80ms for 12bit, 320ms for 14bit (+30%)
    '' temp is 12 or 14, humidity is 8 or 12 - defaults are 14 and 12bit
      t := cnt
      repeat until not ina[noparse][[/noparse]dpin] or (cnt - t)/(clkfreq/1000) > 450
    
    



    The only different is the wait time I changed 250 to 450, the spec says the time delay maybe upto 320ms, the 250 meant it wasn't long enough for the worse case.
Sign In or Register to comment.