Go Down

Topic: YATC - Yet Another Terrarium Controller (Read 7496 times) previous topic - next topic

dafes

Jan 07, 2013, 02:06 pm Last Edit: Feb 06, 2013, 10:41 pm by dafes Reason: 1
Hi,
I would like to start a small Terrarium Controll Project. I have two Terrariums so i need a Modular Controller to inependently Controll both.
I need to switch several lamps, two heatlamps and one pump.
The two heatlamps needs to be temperature controlled.

In future i wanted to report the Temperature over Serial or Wifi to an Linux Device to create a Temperature Graph and simulate Sun Rising/ Falling by LED Lights and PWM.

So lets start with the required Hardware i ordered so far :)


Microcontroller:
SparkFun Mega Pro 5V 41€
Relays:
Two Sainsmart 4-Channel 5V Relay Boards 8€ x 2 = 16€
LCD:
4 Line Normal LCD with I2C Adapter 21€
Temperature Sensors
Several DS1820 around 20€
PowerSupply:
At the Moment a Apple IPhone Power Adapter....
Bits and pieces:
Several Buttons and Resistors...
MicroSD Card 7€
SD/MICRO-SD Card Breakout Module 5€
Two Seeedstudio Grove - Moisture Sensor 2x5€ = 10€
Seeedstudio Grove - Watersensor 3€
Adafruit Ultimate GPS 35€






I will update this Topic with Code, Hardware Plans and Pictures. I hope anybody will find the information helpfull and or can give me suggestion to build a reliable and working solution.

Kind Regards
Dafes



robtillaart

Quote
I have two Terrariums so i need a Modular Controller to inependently Controll both.


Why not two UNO's in stead of one MEGA?  Modular is modular ;)

Quote
and simulate Sun Rising/ Falling

I discussed an algorithm here - http://arduino.cc/forum/index.php/topic,66426.0.html - might be useful

(you can also connect an LDR to the window and "read the local sunset/rise" :)
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

dafes

#2
Jan 07, 2013, 10:16 pm Last Edit: Jan 08, 2013, 01:53 pm by dafes Reason: 1

Quote
I have two Terrariums so i need a Modular Controller to inependently Controll both.


Why not two UNO's in stead of one MEGA?  Modular is modular ;)

Quote
and simulate Sun Rising/ Falling

I discussed an algorithm here - http://arduino.cc/forum/index.php/topic,66426.0.html - might be useful

(you can also connect an LDR to the window and "read the local sunset/rise" :)


Yes thats true but one othe requirement was cheap as possible :P

Thanks for the Feedback i will take a look into the sunrise algorithm :)


The next Part is the Programming Part... I want to use an SD Card to save the Settings and also to specify the "Switch Times" for each channel.(I updated the first Post with the new Hardware)
Additional i want to implement the functionality to programm the Controller over a Serial Interface in Step 1 and in Step 2 i want to replace the Serial Interface with an Bluetooth mate to configure the Controller from an Device.

Kind Regards
dafes

Edit:
I think i will add two additional Sensors. One Soil Moisture Sensor to verify if enough water in the watertank and one for the plant in the rainforest Terrarium. Has anybody a better idea for checking the water level in a Plastic Tank to prevent the pump for running dry? It should be cheap as possible :D
The moisture sensor cost 5€.

Edit2: I ordered a Watersensor to apply into the Watertank.


robtillaart

Quote
Yes thats true but one othe requirement was cheap as possible

cheap comes at a price ...

Why not one uno, just count the number of lines you need to control. Note that the analog ports can be used as digital so an UNO has 19 IO lines

You need
input:
- 1 line for all the DS18B20's
- 2 lines water sensor
- 2 lines moisture sensor
- 2 I2C RTC

output:
- 4 SD card
- 2 Serial
- 3 lines for the relays (use a shift register!)
-------
16 lines so one UNO could do the job
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

dafes


Quote
Yes thats true but one othe requirement was cheap as possible

cheap comes at a price ...

Why not one uno, just count the number of lines you need to control. Note that the analog ports can be used as digital so an UNO has 19 IO lines

You need
input:
- 1 line for all the DS18B20's
- 2 lines water sensor
- 2 lines moisture sensor
- 2 I2C RTC

output:
- 4 SD card
- 2 Serial
- 3 lines for the relays (use a shift register!)
-------
16 lines so one UNO could do the job


Yes thats right, but  :) i want a litle more space to expand.
I have an 433MHZ Sender and some 433MHZ switches so maybe i expand the Board to controll Lights over this or i want to add some Wirelesse Solution to connect it to my Network.
And just saw you forget the 5 Button pins ;) Right, Left, Up, Down and my lovely select :) So i have to use 21 Lines and i beleive uno
has only 17 ports because d0 and d1 are used for Serial Connection or do i miss something?


Regard
dafes

dafes

I have finished the button Pad to controll some basic settings... I´ve made it as small as possible so the bottom layer is a litle bit dirty soldered.

dafes

Hello,
today everything arrives and now i can start programming and soldering :)

My Plan was to build up two additional Boards:
- One Power Board to power the arduino and additional boards
- One Sensor/LCD Board to connect everything with the Arduino

I will post Pictures when i´m finished. A big question at the moment is how to handle the 1Wire Sensor Adresses and assign them to the right Terrarium.
My idea was to create an Terrarium Object(struct) and have a List of Byte[8] Sensors but i´ve got some problems with it...

Has anybody another Idea?

At the first start the Controller should ask how many Terrariums do you have and maybe then quide the user through the configuration process. All Settings will be saved on a SD Card since i´m a litle bit worry about the read/write cycle limits in eeprom.
Feedback is desired...

Kind Regards
dafes

robtillaart

Quote
A big question at the moment is how to handle the 1Wire Sensor Adresses and assign them to the right Terrarium.


your idea looks good but I see no code you have tried sofar ...
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

dafes

#8
Jan 10, 2013, 06:56 pm Last Edit: Jan 10, 2013, 07:06 pm by dafes Reason: 1

Quote
A big question at the moment is how to handle the 1Wire Sensor Adresses and assign them to the right Terrarium.


your idea looks good but I see no code you have tried sofar ...


Yes it is still pre Alpha :D
But here is something:
I created the following Object
Code: [Select]
/*
Represents a Terrarium Object

*/


typedef struct
{
   String Name;
   byte* Sensor;

}Terrarium;


Created an Array of it
Code: [Select]

const int NumTerrariums = 2;

byte sensor1[8] = { 0x10, 0xB2, 0xA0, 0x54, 0x2, 0x8, 0x0, 0x4E };
byte sensor2[8] = { 0x10, 0x3F, 0x7D, 0x54, 0x2, 0x8, 0x0, 0x5C };

Terrarium Terrariums[NumTerrariums];


Add initialize it with the following Data:
Code: [Select]


void updateTerrariums {
 Terrariums[0].Name = "Terrarium1";
 Terrariums[0].Sensor =&sensor1[0];
 Terrariums[1].Name = "Terrarium2";
 Terrariums[1].Sensor = &sensor2[0];
}

I use the sensor first in the following DS1820 libfunction:
Code: [Select]

float GetTemperature(byte sensor[8])
{
 //CRC Check
 if (OneWire::crc8(sensor, 7) != sensor[7]) {
     Serial.println("CRC is not valid!");
     return 0;
 }
 // the first ROM byte indicates which chip
 switch (sensor[0]) {
   case 0x10:
     //Serial.println("  Chip = DS18S20");  // or old DS1820
     type_s = 1;
     break;
   case 0x28:
     //Serial.println("  Chip = DS18B20");
     type_s = 0;
     break;
   case 0x22:
     //Serial.println("  Chip = DS1822");
     type_s = 0;
     break;
   default:
     Serial.println("Device is not a DS18x20 family device.");
     return 0;
 }

 ds.reset();
 ds.select(sensor);
 ds.write(0x44,1);         // start conversion, with parasite power on at the end
 
 delay(1000);     // maybe 750ms is enough, maybe not
 // we might do a ds.depower() here, but the reset will take care of it.
 
 present = ds.reset();
 ds.select(sensor);    
 ds.write(0xBE);         // Read Scratchpad

 //Serial.print("  Data = ");
 //Serial.print(present,HEX);
 //Serial.print(" ");
 for ( i = 0; i < 9; i++) {           // we need 9 bytes
   data[i] = ds.read();
   //Serial.print(data[i], HEX);
   //Serial.print(" ");
 }
 // convert the data to actual temperature
 unsigned int raw = (data[1] << 8) | data[0];
 if (type_s) {
   raw = raw << 3; // 9 bit resolution default
   if (data[7] == 0x10) {
     // count remain gives full 12 bit resolution
     raw = (raw & 0xFFF0) + 12 - data[6];
   }
 } else {
   byte cfg = (data[4] & 0x60);
   if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms
   else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms
   else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms
   // default is 12 bit resolution, 750 ms conversion time
 }
 celsius = (float)raw / 16.0;
 return celsius;
}

But i think i missed something with the pointers... I come from the c# world so i dont know the point(er)...:)

BTW: Look what i received from China :) And so nicely wrapped

dafes

Hi everybody,
i rebuilded some Boards to be a litle more modular.
I have created a new power board out of two pin connectors and changed the "normal" pin header to Connectors.
I will post some pictures tonight.
On Programming side there is not much progress. I have defined all Pins and at the moment i work on a small menu. I also try to find a good solution to switch the Lights timebased on and off.... I think i will create delay loop of 5 minutes in the main loop and call a function to verify if something to do on timer or temperature basis.

Code: [Select]

void loop
{
switch(Time)
{
case "12:00":
Light.On(T1.S2);
break;
}
deleay(300000);
}

dafes

Hello,
On Hardware Side:
i have rebuilded some Boards to replace Pin Headers with Connectors. I also ordered many Connectors to connect the additional Sensos to sthe Systems.
I ordered some 3,5mm Audio Jacks to connect the sensors and 25m Shielded 4 lines Wire.
On Software Side:
I defined all IO Pins to match the Sensors and everything. At the moment i have only a small test setup to test all Boards and Sensors.
In the next weeks i will write a small menu and the "scheduler". I think i will use 5m delay loop like:
Code: [Select]

void loop()
{
time = GetTime();
switch(time)
{
case(12):
  if(!Switch.Status(Terrarium1,Switch1)) {
   Switch.On(Terrarium1,Switch1); }
break;
}
delay(30000);
}

Or is it better to use a Timer based Interrupt?

robtillaart

Quote
String Name;


Strong advice to remove the String usage form your sketch and replace it with a char array as the String class has "destructor" problems ..

Quote
Or is it better to use a Timer based Interrupt?

Don't use delay either => check the Blink without delay example how to schedule functionality in your code

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

dafes


Quote
String Name;


Strong advice to remove the String usage form your sketch and replace it with a char array as the String class has "destructor" problems ..

Quote
Or is it better to use a Timer based Interrupt?

Don't use delay either => check the Blink without delay example how to schedule functionality in your code



Thank you for the feedback. I wil avoid using String and try the millis thing.
I have just finished the build up and everything is now connected.
Now i can concentrate my time to programming a running beta.

robtillaart

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

dafes


Keep us informed of your progress!

Sure :)

Here is the loop Code:
Code: [Select]
void loop() {
//Display
if(SettingsScreen) { DisplaySettings(); }
else { NormalView(); }

//Timing
  unsigned long currentMillis = millis();
 
  if(currentMillis - previousMillis > interval)
  {
    // save the last time you run the function
    previousMillis = currentMillis;
    CheckForSomethingtoDo();   
  }
}


and here is the "CheckForSomethingtoDo" function:

Code: [Select]

void CheckForSomethingtoDo()
{
  //DBEUG To Verify if Function runs
  if(DEBUG) {Serial.println("DEBUG: CheckForSomethingtoDo"); }
  _CheckForSomethingtoDoTerrarium1();
  _CheckForSomethingtoDoTerrarium2();
}

void _CheckForSomethingtoDoTerrarium1()
{
  //Temperature
  TemperatureControlT1();
}
void _CheckForSomethingtoDoTerrarium2()
{
  //Temperature
  TemperatureControlT2();
}

//Snakes
void TemperatureControlT1()
{
  DateTime now = RTC.now();
  //Sommer
  if(now.month() >= T1_SommerStart && now.month() <  T1_WinterStart)
  {
   if(DEBUG) { Serial.println("Debug: Sommer"); }
   if(GetTemperature(sensor1) >= T1_TTS)
   { 
     if(DEBUG) {Serial.print("Debug:T1 "); Serial.print(GetTemperature(sensor1)); Serial.println(" SwitchOff");}
     SwitchOff(1, 1);
   }
   else
   {
     SwitchOn(1,1);
   }   
  }
  //Winter
  else
  {
    if(DEBUG) { Serial.println("Debug: Winter"); }
   
    if(GetTemperature(sensor1) >= T1_TTW)
    {
     
      if(DEBUG) {Serial.print("Debug:T1 "); Serial.print(GetTemperature(sensor1)); Serial.println(" SwitchOff");}
      SwitchOff(1, 1);
    }
    else
    {
      SwitchOn(1,1);
    }
  } 
}


void TemperatureControlT2()
{

}

In the main class i have the following "Configuration Section":
Code: [Select]

//---------------------------------Configuration-------------------------------------------------
const boolean DEBUG = true;

//Terrarium 1
//Target Temperature Sommer
const int T1_TTS = 26;
//Target Temperature Winter
const int T1_TTW = 26;
//Sommer
const int T1_SommerStart = 5;
//Winter
const int T1_WinterStart = 10;
//Terrarium 2

//---------------------------------End-Configuration---------------------------------------------

In future i will configure this variables over a lcd and buttons and a config file on a sd card.

Go Up