Arduino uno controlled release of carbon dioxide for black fly detection

Hi,
I am very new to this so please be patient with me. I am attempting to create a device that will release carbon dioxide two times a day (10am and 2pm) for 15 min and then shut off. It will attract black flies to an area where I can photograph them. It will need to do this for 30 days with no input from an operator. I currently have a solenoid valve hooked up to the carbon dioxide tank I would like the arduino uno to control the valve. I have made a relay circuit (with help) and I have a chronodot rtc. I have tested both of them separately with simple code and they both work. I have search this forum for a code that will get the time from the chronodot and turn on/off the relay appropriately, but am having trouble. This is what I currently have

#include <Wire.h>
#include "Chronodot.h"
Chronodot RTC;

int LightOff[367] = { 
int LightOn[367] ={};

int Relay = 7; // Relay on Pin 7
int DayCode = 0;
int Year = 0;
int Month = 0;
int Day = 0;
int Hour = 0;
int Minute = 0;
int Second = 0;
int Multiplier = 0;
int Time = 0;

// ------------------------------------------

void setup() {
  
  pinMode(Relay, OUTPUT);
  
  Serial.begin(9600);
  Wire.begin();
  RTC.begin();
  
}

// -------------------------------------------

void loop() {
  
  DateTime now = RTC.now();    // Retrieve all information from ChronoDot
  Year = now.year();
  Month = now.month();
  Day = now.day();
  Hour = now.hour();
  Minute = now.minute();
  Second = now.second();
  
 int multiplier [12] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
…
DayCode = Day + multiplier[ Month - 1 ]; // Array indexes start at 0, so multiplier is 0…11
  
  // Perform Calculations to turn relay on/off
  if (Time == LightOff[DayCode])  {
      digitalWrite(Relay, LOW);  }
    if (Time == LightOn[DayCode])  {
      digitalWrite(Relay, HIGH);  }
  }
}

I really don’t know anything so my questions are:

int LightOff[367] = { 
int LightOn[367] ={};

is this where I put in the time I want the relay to be turned on/off? what does the 367 mean?

 Serial.begin(9600);
  Wire.begin();
  RTC.begin();

Is the 9600 something specific to the computer you are using or does it stay the same no matter what?

int multiplier [12] = { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
…
DayCode = Day + multiplier[ Month - 1 ]; // Array indexes start at 0, so multiplier is 0…11

Or is this where I am suppose to put in the time I want the relay turned on?

 Perform Calculations to turn relay on/off
  if (Time == LightOff[DayCode])  {
      digitalWrite(Relay, LOW);  }
    if (Time == LightOn[DayCode])  {
      digitalWrite(Relay, HIGH);  }

or is this where I put it in? :astonished:
Wow, I know this is a lot! Any help would be greatly appreciated! Thank you

That code looks as though it's intended to let you configure an on time and an off time for something every day of the year - a guess based on the 367. That … covers a multitude of sins though. In this case you don't really need such complexity. Neither does it look like it copes with turning something on twice in a day.

Once you've read the clock, assume that the solenoid should be closed. Check whether the hour is 10 and the minute less than 15 - time to turn it on. Check for 2pm the same way.

Thank you for your reply. However, I don’t really understand. Sorry. So I have tried to start over, and go in simple steps. First I need to set the time on the chronodot. I used the following code from the chronodot webpage to get the chronodot to start counting time. And it worked!

#include <Wire.h>
 
void setup()
{
  Wire.begin();
  Serial.begin(9600);
 
  // clear /EOSC bit
  // Sometimes necessary to ensure that the clock
  // keeps running on just battery power. Once set,
  // it shouldn't need to be reset but it's a good
  // idea to make sure.
  Wire.beginTransmission(0x68); // address DS3231
  Wire.write(0x0E); // select register
  Wire.write(0b00011100); // write register bitmap, bit 7 is /EOSC
  Wire.endTransmission();
}
 
void loop()
{
  // send request to receive data starting at register 0
  Wire.beginTransmission(0x68); // 0x68 is DS3231 device address
  Wire.write((byte)0); // start at register 0
  Wire.endTransmission();
  Wire.requestFrom(0x68, 3); // request three bytes (seconds, minutes, hours)
 
  while(Wire.available())
  { 
    int seconds = Wire.read(); // get seconds
    int minutes = Wire.read(); // get minutes
    int hours = Wire.read();   // get hours
 
    seconds = (((seconds & 0b11110000)>>4)*10 + (seconds & 0b00001111)); // convert BCD to decimal
    minutes = (((minutes & 0b11110000)>>4)*10 + (minutes & 0b00001111)); // convert BCD to decimal
    hours = (((hours & 0b00100000)>>5)*20 + ((hours & 0b00010000)>>4)*10 + (hours & 0b00001111)); // convert BCD to decimal (assume 24 hour mode)
 
    Serial.print(hours); Serial.print(":"); Serial.print(minutes); Serial.print(":"); Serial.println(seconds);
  }
 
  delay(1000);
}

But it is just counting. I it doesn’t actually give me the correct time. So I tried to modify another person’s code who was making a clock using the arduino, the chronodot, and an lcd screen, I think. Here is the original code.

/*
 Code under (cc) by Manuel Gonzalez, www.codingcolor.com
 http://creativecommons.org/license/cc-gpl
 Pins 12, 11, 5, 4, 3, 2 to LCD
 Analog pins 4 (SDA),5(SCL) to Chronodot
 Pins 6 (hour), 7(min) buttons 
*/

#include <Wire.h>
#include <LiquidCrystal.h>


const int hourButtonPin = 6;
const int minButtonPin = 7;

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int hourButtonState;
int minButtonState;

int seconds; //00-59;
int minutes; //00-59;
int hours;//1-12 - 00-23;
int day;//1-7
int date;//01-31
int month;//01-12
int year;//0-99;




void setup()
{

  pinMode(hourButtonPin,INPUT);
  pinMode(minButtonPin,INPUT);

  Wire.begin();
  lcd.begin(16, 2);
  
  hourButtonState = 0;
  minButtonState = 0;
  ////////////////////////////////
  seconds = 00;
  minutes = 18;
  hours = 14;
  day = 4;
  date = 05;
  month = 2;
  year = 14;
  initChrono();//just set the time once on your RTC
  ///////////////////////////////
}

void loop()
{
  check_buttons();
  get_time();
  get_date();
  display_time();
  display_date();
  delay(1000);
  
}
void display_time()
{
  char buf[12];
  
  lcd.setCursor(0, 0);
  
  if(hours == 0)
  {
    lcd.clear();
  }
  
  lcd.print("Time ");   
  lcd.print(itoa(hours, buf, 10));
  lcd.print(":");
  
  if(minutes < 10)
  {
    lcd.print("0");
  }
  lcd.print(itoa(minutes, buf, 10));
  
  lcd.print(":");
  
  if(seconds < 10){
    lcd.print("0");
  }
  lcd.print(itoa(seconds, buf, 10));

}
void display_date()
{
  char buf[12];
  
  lcd.setCursor(0, 1);
  lcd.print("Date ");
  
 if(month < 10){
    lcd.print("0");
  }  
  
  lcd.print(itoa(month, buf, 10));
  lcd.print("/");
  lcd.print(itoa(date, buf, 10)); 
  lcd.print("/"); 
  
  if(year < 10){
    lcd.print("0");
  } 
  
  lcd.print(itoa(year, buf, 10)); 
}
void initChrono()
{
  set_time();
  set_date();
}


void set_date()
{
  Wire.beginTransmission(104);
  Wire.write(3);
  Wire.write(decToBcd(day));
  Wire.write(decToBcd(date));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}
void get_date()
{
  Wire.beginTransmission(104); 
  Wire.write(3);//set register to 3 (day)
  Wire.endTransmission();
  Wire.requestFrom(104, 4); //get 5 bytes(day,date,month,year,control);
  day   = bcdToDec(Wire.read());
  date  = bcdToDec(Wire.read());
  month = bcdToDec(Wire.read());
  year  = bcdToDec(Wire.read());
}

void set_time()
{
   Wire.beginTransmission(104);
   Wire.write(0);
   Wire.write(decToBcd(seconds));
   Wire.write(decToBcd(minutes));
   Wire.write(decToBcd(hours));
   Wire.endTransmission();
}
void get_time()
{
  Wire.beginTransmission(104); 
  Wire.write(0);//set register to 0
  Wire.endTransmission();
  Wire.requestFrom(104, 3);//get 3 bytes (seconds,minutes,hours);
  seconds = bcdToDec(Wire.read() & 0x7f);
  minutes = bcdToDec(Wire.read());
  hours = bcdToDec(Wire.read() & 0x3f);
  
 


  
}
void setHour()
{
  hours++; 
  if(hours > 23)
  {
   hours = 0; 
   seconds = 0;
   minutes = 0;
  }
  set_time();
  
}
void setMinutes()
{
  minutes++;  
  if(minutes > 59)
  {
   minutes = 0;
   
  }
  seconds=0;
  
  set_time();
  
}
void check_buttons()
{
  hourButtonState = digitalRead(hourButtonPin);
  minButtonState = digitalRead(minButtonPin);
  
  if(hourButtonState == HIGH){
    setHour();
  }
  
  if(minButtonState == HIGH){
    setMinutes();
  }
}
///////////////////////////////////////////////////////////////////////

byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

I don’t want the time displayed to a screen, I would like it to display on the serial monitor, like it did in the initial code when it was just counting. So I edited the code to this

/*
 Code under (cc) by Manuel Gonzalez, www.codingcolor.com
 http://creativecommons.org/license/cc-gpl
 Pins 12, 11, 5, 4, 3, 2 to LCD
 Analog pins 4 (SDA),5(SCL) to Chronodot
 Pins 6 (hour), 7(min) buttons 
*/

#include <Wire.h>



int hourButtonState;
int minButtonState;

int seconds; //00-59;
int minutes; //00-59;
int hours;//1-12 - 00-23;
int day;//1-7
int date;//01-31
int month;//01-12
int year;//0-99;




void setup()
{
  Wire.begin();
  ////////////////////////////////
  seconds = 00;
  minutes = 18;
  hours = 14;
  day = 4;
  date = 05;
  month = 2;
  year = 14;
  initChrono();//just set the time once on your RTC
  ///////////////////////////////
}

void loop()
{
  get_time();
  get_date();
  display_time();
  display_date();
  delay(1000);
  
}
void display_time()
{
  
   Serial.print(hours); Serial.print(":"); Serial.print(minutes); Serial.print(":"); Serial.println(seconds);

}
void display_date()
{
   Serial.print(day); Serial.print(":"); Serial.print(date); Serial.print(":"); Serial.println(month); Serial.println(":");Serial.println(year);
}
void initChrono()
{
  set_time();
  set_date();
}


void set_date()
{
  Wire.beginTransmission(104);
  Wire.write(3);
  Wire.write(decToBcd(day));
  Wire.write(decToBcd(date));
  Wire.write(decToBcd(month));
  Wire.write(decToBcd(year));
  Wire.endTransmission();
}
void get_date()
{
  Wire.beginTransmission(104); 
  Wire.write(3);//set register to 3 (day)
  Wire.endTransmission();
  Wire.requestFrom(104, 4); //get 5 bytes(day,date,month,year,control);
  day   = bcdToDec(Wire.read());
  date  = bcdToDec(Wire.read());
  month = bcdToDec(Wire.read());
  year  = bcdToDec(Wire.read());
}

void set_time()
{
   Wire.beginTransmission(104);
   Wire.write(0);
   Wire.write(decToBcd(seconds));
   Wire.write(decToBcd(minutes));
   Wire.write(decToBcd(hours));
   Wire.endTransmission();
}
void get_time()
{
  Wire.beginTransmission(104); 
  Wire.write(0);//set register to 0
  Wire.endTransmission();
  Wire.requestFrom(104, 3);//get 3 bytes (seconds,minutes,hours);
  seconds = bcdToDec(Wire.read() & 0x7f);
  minutes = bcdToDec(Wire.read());
  hours = bcdToDec(Wire.read() & 0x3f);
  
}
void setHour()
{
  hours++; 
  if(hours > 23)
  {
   hours = 0; 
   seconds = 0;
   minutes = 0;
  }
  set_time();
  
}
void setMinutes()
{
  minutes++;  
  if(minutes > 59)
  {
   minutes = 0;
   
  }
  seconds=0;
  
  set_time();
  
}
///////////////////////////////////////////////////////////////////////

byte decToBcd(byte val)
{
  return ( (val/10*16) + (val%10) );
}

byte bcdToDec(byte val)
{
  return ( (val/16*10) + (val%16) );
}

This will upload, but it does not display on the serial monitor. Do you know where I am going wrong? Thank you so much for your help. I think I am going to focus on getting the time right now, and then try to control the relay later.

Thanks! :slight_smile:

You need a serial.begin in setup.

It Worked!!! Thank you so much! You have no idea how much you helped me!
Now to just figure out how to activate the relay at specific times given from the chronodot. Any advice on where to begin?
And am I suppose to give you Kara points or something? I don't know how that works. :slight_smile:

oops... maybe I spoke too soon... everytime I close the serial monitor and open it back up it starts at the initial time I set it at (instead of continuing to keep the correct time after being set). I need the chronodot to keep the correct time even if it gets disconnected. Any advice?

Generally you only need to set the clock time once and then, as long as it has a battery, it will keep time. So set the time and run your sketch, then comment out the InitChrono call and reload the sketch.

Alternatively, use one sketch that just sets the clock and another that does your CO2 stuff.

Make sure you have a functioning battery. And if you initialize the Chronodot each time you boot up, that would be a problem.