Shop OBEX P1 Docs P2 Docs Learn Events
Project: GAC (Greenhouse Automation Controller) Design Process and Discussion — Parallax Forums

Project: GAC (Greenhouse Automation Controller) Design Process and Discussion

bomberbomber Posts: 297
edited 2011-12-25 20:58 in Robotics
I have been assigned to build a new project; the Greenhouse Automation Controller (GAC, for short). In a nutshell, it reads both temperature and humidity from both greenhouses using two Sensirion modules and turns on fans or the sprinklers to correct the values. The core processor is the Propeller microcontroller. I talked to tech support, and they said it was fine to mount a Sensirion module up to six feet away from the Propeller. I will be mounting a Propeller Proto Board in one greenhouse, and run some wire to the other greenhouse, where the other Sensirion will be mounted.The entire project will be powered by solar panels previously mounted on the greenhouse. I will be getting the voltage rating on those panels soon. If you have any questions, comments, or suggestions, please reply. I will be getting a schematic out there soon, this project is still in the planning stage.

Comments

  • prof_brainoprof_braino Posts: 4,313
    edited 2011-10-13 10:49
    I also recieved a request for green house automation. We plan to implement this in propforth once v5.0 comes out, but the requirements and parameters would be the same regardless of the implementation language. We can colaborate and share if you wish.

    The basic monitoring functions requested are for interior temperature, soil moiture, and humidity. Secondary requirements are external temp, humidity, and ambient light (night, sunny day, cloudy day). The basic control functions are for fans, heat, humidity, water, and lights.

    The above can be readily controled using spin. There may even be objects for particular sensors already in the OBEX, but I didn't get that far.

    The following functions might not be so easy in spin, but should be fairly straight forward in propforth:

    Display monitoring and control information on a PC using a browser via ethernet (on internal network).
    Remote display and control of system over the internet.
    Remote debugging and support over ethernet.
    Support for more than 32 IO lines.

    All the above should be fairly easy in PF 5.0.

    We did not yet decide any particulars for the devices connected to the prop.
  • WBA ConsultingWBA Consulting Posts: 2,934
    edited 2011-10-13 11:48
    The Sensirion SHT11 or SHT15 can be placed more than 200 feet from the Propeller easily. Look at post #9 on this thread. If you look at post 33, you will see that some of my modules are in use for greenhouses. Also, I have more pics, usage notes, links, and code examples on this site.

    Good luck on the project!
  • bomberbomber Posts: 297
    edited 2011-10-13 15:26
    We can colaborate and share if you wish.

    Be my guest!
  • bomberbomber Posts: 297
    edited 2011-10-14 17:20
    The Spin Code is here! I have completed a beta version of the code. Please ignore comments (other than the schematic). There may be a few errors in the code. If you find an error, please let me know
  • peleus21peleus21 Posts: 16
    edited 2011-12-18 11:38
    hey there
    i find this project very interesting as i am working on a project that very similarly controls a system based on temperature readings and other stuff as well but is very much alike except i am using the digital i/o board to control the functions. i have a problem with my code that i see possibly here as well when using your "if, then" statements with the readings from the sensor they do not work. i am very new to spin language, but i know this is not working in my code and i have tried a few different ways including your way - which makes tempA an i/o if i am correct, not a value to reference
    jamie
  • bomberbomber Posts: 297
    edited 2011-12-18 14:09
    Which sensors are you using? I (or someone else) can have a look at your code, then that person can help you.
  • peleus21peleus21 Posts: 16
    edited 2011-12-18 20:09
    my problem is in the math. if you look at the code you posted here, (Project GAC, source code) the problem is the way we get the temperature value. you cant just say (tempA being a value of 24),

    if (tempC > tempA)
    outa[fanA] := 1

    (i have a similar code to yours based on "sensirion_full_demo". i used temp1 instead of tempC so i can use tempA,tempB,tempC, etc. as over/under values.)
    tempC is a huge value that the float to format makes into a displayable value. my problem is how do i get temp1 or another named variable to a usable number to use the if/then statement.

    jamie
  • bomberbomber Posts: 297
    edited 2011-12-19 07:29
    Sorry, my bad. I would start by gettting the raw value onto the Parallax Serial Terminal. Next, observe how the value changes when the temperature (I assume you are using a temperature sensor) is varied. Then, see if you can come up with a sereies of math equasions to return that value to 'normal', checking it against a working thermometer.
  • peleus21peleus21 Posts: 16
    edited 2011-12-21 20:10
    ok so here is what i got. this allows temperature to be read as a usable value or so i thought. note: this is a beta code to test whether if/then statement is working. i am using the professional development board and the digital i/o board. the
    PUB main | count, rawTemp, temp1, read1
    OUT_REG:=0 
     Sout.start(SCLK_RLY,LAT_RLY,DATA_RLY,@OUT_REG) 
     Sin.start(SCLK_IN,LOAD_IN,DIN,@IN_REG)   
     pst.start(115200)
     f.start                                               ' start floating point object
     sht.start(SHT_DATA, SHT_CLOCK)
      tempA := 24
      tempB := 28
       
     waitcnt(clkfreq*3+cnt)
     sht.config(33,sht#off,sht#yes,sht#hires)
    
     repeat
       
       waitcnt(cnt +clkfreq/100*50)
       pst.position(1,1)
       pst.Str(String("--   INPUT --- " )) 
       pst.bin(IN_REG,8)
       pst.position(1,2)
       pst.Str(String("--  OUTPUT --- " ))
       pst.bin(OUT_REG,8) 
             
          
       
       pst.position (1,5)
       pst.Str(String("Temperature  "))
        rawTemp := f.FFloat(sht.readTemperature) 
        read1 := celsius(rawTemp)
        temp1 := fp.FloatToFormat(read1,6,2)  
        pst.str(temp1)
        pst.Str(String(","))
        pst.str(fp.FloatToFormat(read1,6,2))
        pst.str(string( Deg,"C",5,1))
        sht.config(33,sht#off,sht#yes,sht#hires)        '1 slow, hiRes measurement
        count++
        if (temp1 < 29)
        
          OUT_REG := 10000000
        else
          OUT_REG := 01000000  
       
    ' waitcnt (clkfreq*5+cnt)                           'display every 5 seconds
    

    temperature is 24.18C at time of test. this should mean OUT_REG:= 10000000 but it is 01000000 this is a copy of the teminal

    parallax serial terminal:
    -- INPUT --- 00000000
    -- OUTPUT --- 01000000


    Temperature 24.19, 24.19°C
  • bomberbomber Posts: 297
    edited 2011-12-22 07:07
    I see what might be going on. Try changing:
    if (temp1 < 29)
    

    to:
    if (temp1 < 29.00)
    
  • ElectricAyeElectricAye Posts: 4,561
    edited 2011-12-22 12:56
    bomber wrote: »
    I see what might be going on. Try changing:
    if (temp1 < 29)
    

    to:
    if (temp1 < 29.00)
    


    I don't think you can make direct comparisons with non-integers like this in SPIN. I think you will need to use the comparison operations, FCmp, in the Float Math object.
  • peleus21peleus21 Posts: 16
    edited 2011-12-22 19:15
    i tried that too. i also tried moving the tempA and B values to the constants. i also tried values similar to the basic stamp solutions ie. 2900
  • peleus21peleus21 Posts: 16
    edited 2011-12-23 22:06
    ok get this.
    if
    CON
      
    
    _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
     
     LAT_RLY       = 13
     SCLK_RLY      = 12
     DATA_RLY      = 11
     DIN           = 10
     SCLK_IN       = 9
     LOAD_IN       = 8
     SHT_DATA      = 29                                      ' SHT-11 data pin
     SHT_CLOCK     = 26                                      ' SHT-11 clock pin
     CR            = $D                                      ' carriage return
     Deg           = $B0                                     ' degree symbol
    
    
    
      
    VAR
           byte            OUT_REG
           byte            IN_REG
           byte            bit
           byte            status
           byte            tempA
           byte            tempB
           
    OBJ    Sout          : "ShiftOUT"
           Sin           : "ShiftIN"
           pst           : "Parallax Serial Terminal"
           sht           : "Sensirion_full"
           fp            : "FloatString"
           f             : "Float32"
      
    PUB main | count, rawTemp, temp1, read1
    OUT_REG:=0 
     Sout.start(SCLK_RLY,LAT_RLY,DATA_RLY,@OUT_REG) 
     Sin.start(SCLK_IN,LOAD_IN,DIN,@IN_REG)   
     pst.start(115200)
     f.start                                               ' start floating point object
     sht.start(SHT_DATA, SHT_CLOCK)
      tempA := 24.0
      tempB := 28.0
       
     waitcnt(clkfreq*3+cnt)
     sht.config(33,sht#off,sht#yes,sht#hires)
    
     repeat
       
       waitcnt(cnt +clkfreq/100*50)
       pst.position(1,1)
       pst.Str(String("--   INPUT --- " )) 
       pst.bin(IN_REG,8)
       pst.position(1,2)
       pst.Str(String("--  OUTPUT --- " ))
       pst.bin(OUT_REG,8) 
             
          
       
       pst.position (1,5)
       pst.Str(String("Temperature  "))
        rawTemp := f.FFloat(sht.readTemperature) 
        read1 := celsius(rawTemp)
        temp1 := fp.FloatToFormat(read1,6,2)  
        pst.str(temp1)
        pst.Str(String(","))
        pst.str(fp.FloatToFormat(read1,6,2))
        pst.str(string( Deg,"C",5,1))
        sht.config(33,sht#off,sht#yes,sht#hires)        '1 slow, hiRes measurement
      
        if (temp1 < 28)
          OUT_REG := 10000000
        else
          OUT_REG := 01000000 
       
        count++ 
          
    ' waitcnt (clkfreq*5+cnt)                           'display every 5 seconds
    
    PUB celsius(t)
      ' from SHT1x/SHT7x datasheet using value for 3.5V supply
      ' celsius = -39.7 + (0.01 * t)
      return f.FAdd(-39.7, f.FMul(0.01, t))  
    PUB kelvin(t) | tc
      tc := f.FAdd(-39.66, f.FMul(0.01, t))
      return f.FAdd(tc, 273.16)
    
    then pst (parallax serial terminal)

    -- INPUT --- 00000000
    -- OUTPUT --- 01000000


    Temperature 24.27, 24.27°C

    if
        if (temp1 < 28.00)
          OUT_REG := 10000000
        else
          OUT_REG := 01000000 
       
        count++ 
    

    pst is
    -- INPUT --- 00000000
    -- OUTPUT --- 10000000


    Temperature 24.46, 24.46°C

    which would be correct except
    -- INPUT --- 00000000
    -- OUTPUT --- 10000000


    Temperature 33.12, 33.12°C

    when i change the 28 to 28.00 or 28.0 for that matter, it changes the outcome. but in either outcome the if/then statement does not work
  • ElectricAyeElectricAye Posts: 4,561
    edited 2011-12-24 00:08
    peleus21 wrote: »
    ....

    when i change the 28 to 28.00 or 28.0 for that matter, it changes the outcome. but in either outcome the if/then statement does not work

    I really think you need to look at how comparisons are properly done with FloatMath operations. EDIT: oops, maybe the FCmp(a,b) is only in Float32. I'm away from my normal computer, so I can't check that out.
    Anyway, also take a look at these:
    http://forums.parallax.com/showthread.php?113354-How-to-compare-values-that-are-floats-when-using-FloatMath&

    http://forums.parallax.com/showthread.php?102784-Floating-point-compare&p=721138&viewfull=1#post721138

    http://forums.parallax.com/showthread.php?108103-Floating-point-(-Greater-than-and-Less-than-)
  • peleus21peleus21 Posts: 16
    edited 2011-12-24 12:47
    i see!
    i am doing it the stamp basic way and trying to make it work i am learning spin now and i understand what you mean. i am not writing it right at all!
    i will wwork on it and submit new code and results soon.
  • peleus21peleus21 Posts: 16
    edited 2011-12-25 14:20
    ok so here is an updated version as i have been studying my spin manuals and had to change a few things this is what i have so far
    CON
      
    
    _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
     SHT_DATA      = 7                                      ' SHT-11 data pin
     SHT_CLOCK     = 6                                      ' SHT-11 clock pin
     LAT_RLY       = 5
     SCLK_RLY      = 4
     DATA_RLY      = 3
     DIN           = 2
     SCLK_IN       = 1
     LOAD_IN       = 0
     LED_A         = 16
     LED_B         = 23
     CR            = $D                                      ' carriage return
     Deg           = $B0                                     ' degree symbol
    
    
    
      
    VAR
           byte            OUT_REG
           byte            IN_REG
           byte            bit
           byte            status
           byte            tempA
           byte            tempB
           
    OBJ    Sout          : "ShiftOUT"
           Sin           : "ShiftIN"
           pst           : "Parallax Serial Terminal"
           sht           : "Sensirion_full"
           fp            : "FloatString"
           f             : "Float32"
      
    PUB main | count, rawTemp, temp1, read1
    OUT_REG:=0 
     Sout.start(SCLK_RLY,LAT_RLY,DATA_RLY,@OUT_REG) 
     Sin.start(SCLK_IN,LOAD_IN,DIN,@IN_REG)   
     pst.start(115200)
     f.start                                               ' start floating point object
     sht.start(SHT_DATA, SHT_CLOCK)
      tempA := float(24)
      tempB := float(28)
       
     waitcnt(clkfreq*3+cnt)
     sht.config(33,sht#off,sht#yes,sht#hires)
    
     repeat
       
       waitcnt(cnt +clkfreq/100*50)
       pst.position(1,1)
       pst.Str(String("--   INPUT --- " )) 
       pst.bin(IN_REG,8)
       pst.position(1,2)
       pst.Str(String("--  OUTPUT --- " ))
       pst.bin(OUT_REG,8) 
        dira[LED_A] := 1       
        dira[LED_B] := 1   
       
       pst.position (1,5)
       pst.Str(String("Temperature  "))
        rawTemp := f.FFloat(sht.readTemperature) 
        read1 := celsius(rawTemp)
        temp1 := fp.FloatToFormat(read1,6,2)  
        pst.str(temp1)
        pst.Str(String(","))
        pst.str(fp.FloatToFormat(read1,6,2))
        pst.str(string( Deg,"C",5,1))
        sht.config(33,sht#off,sht#yes,sht#hires)        '1 slow, hiRes measurement
      
        if f.fcmp(temp1,tempB) => 0
          OUT_REG := 10000000  
          outa[LED_A] := 1
          outa[LED_B] := 0   
        else
          OUT_REG := 01000000 
          outa[LED_A] := 0
          outa[LED_B] := 1
        count++ 
          
    ' waitcnt (clkfreq*5+cnt)                           'display every 5 seconds
    
    PUB celsius(t)
      ' from SHT1x/SHT7x datasheet using value for 3.5V supply
      ' celsius = -39.7 + (0.01 * t)
      return f.FAdd(-39.7, f.FMul(0.01, t))  
    PUB kelvin(t) | tc
      tc := f.FAdd(-39.66, f.FMul(0.01, t))
      return f.FAdd(tc, 273.16)
    

    this update makes led's turn on or off depending on temo readings as well as output to the i/o board. this makes it easier to diagnose as i only need the demo board to mess with code.
    here is the terminal

    -- INPUT --- 00000000
    -- OUTPUT --- 10000000


    Temperature 20.68, 20.68°C

    as you can see, the if /then says if temp1 > 29 then 10000000
    but temp1 is 20.68 and it is 10000000

    so here was my initial thought. force it to see every part of if then as a float then when it compares it should make sense but if statement still won't work
  • peleus21peleus21 Posts: 16
    edited 2011-12-25 20:58
    Success!!! the problem turned out to be too much math instead of not enough - in a way.
    as you will see, i did have to use the f.fcmp to make if statement work properly. but i was converting values too much
    CON
      
    
    _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
     SHT_DATA      = 7                                      ' SHT-11 data pin
     SHT_CLOCK     = 6                                      ' SHT-11 clock pin
     LAT_RLY       = 5                                      ' Digital I/O LAT_RLY PIN
     SCLK_RLY      = 4                                      ' Digital I/O SCLK_RLY PIN
     DATA_RLY      = 3                                      ' Digital I/O DATA_RLY PIN
     DIN           = 2                                      ' Digital I/O DIN PIN
     SCLK_IN       = 1                                      ' Digital I/O SCLK_IN PIN
     LOAD_IN       = 0                                      ' Digital I/O LOAD_IN PIN
     LED_A         = 16
     LED_B         = 23
     CR            = $D                                     ' carriage return
     Deg           = $B0                                    ' degree symbol
     tempA         = 24.00
     tempB         = 20.00
    
    
      
    VAR
           byte            OUT_REG
           byte            IN_REG
           byte            bit
           byte            status
         
           
    OBJ    Sout          : "ShiftOUT"
           Sin           : "ShiftIN"
           pst           : "Parallax Serial Terminal"
           sht           : "Sensirion_full"
           fp            : "FloatString"
           f             : "Float32"
      
    PUB main | count, rawTemp, temp1
    
     Sout.start(SCLK_RLY,LAT_RLY,DATA_RLY,@OUT_REG)      ' start Digital I/O Board output
     Sin.start(SCLK_IN,LOAD_IN,DIN,@IN_REG)              ' start Digital I/O Board input
     pst.start(115200)                                   ' start serial terminal
     f.start                                             ' start floating point object
     sht.start(SHT_DATA, SHT_CLOCK)                      ' start sensirion sensor
     OUT_REG := 0 
       
     waitcnt(clkfreq*3+cnt)
     sht.config(33,sht#off,sht#yes,sht#hires)            ' sensirion configuration
    
     repeat
       
       waitcnt(cnt +clkfreq/100*50)
        dira[LED_A..LED_B]~~  
          
        rawTemp := f.FFloat(sht.readTemperature) 
        temp1 := celsius(rawTemp)
          
        pst.position(1,1)
        pst.Str(String("--   INPUT --- " )) 
        pst.bin(IN_REG,8)
    
        pst.position(1,2)
        pst.Str(String("--  OUTPUT --- " ))
        pst.bin(OUT_REG,8)
       
        pst.position(1,4)
        pst.Str(String("Interior Temperature"))
        pst.str(fp.FloatToFormat(temp1,6,2))
        pst.str(string( Deg,"C",5,1))
        
        IF f.fcmp(temp1,tempB) =>0                    ' if temp1 > 20'C then relay 1 & 2 off
          OUT_REG := 10000000  
          outa[LED_A] := 1
          outa[LED_B] := 0 
        else
          OUT_REG := 01000000 
          outa[LED_B] := 1
          outa[LED_A] := 0
        sht.config(33,sht#off,sht#yes,sht#hires)        '1 slow, hiRes measurement    
        count++ 
          
    ' waitcnt (clkfreq*5+cnt)                           'display every 5 seconds
    
    PUB celsius(t)
      ' from SHT1x/SHT7x datasheet using value for 3.5V supply
      ' celsius = -39.7 + (0.01 * t)
      return f.FAdd(-39.7, f.FMul(0.01, t))
    
    i discovered that by using tempB = 20.00 as ElectricAye suggested it did the conversions i needed but i was comparing it to the wrong variable. i was using
     read1 := celsius(rawTemp)
        temp1 := fp.FloatToFormat(read1,6,2) 
    
    then comparing temp1 to tempB
    when all i needed was to compare temp1 to read1

    so simple as to be blinded by it
Sign In or Register to comment.