I'm trying to add sounds to my pet enclosure controller. They are tropical so I've snatched 24 hours worth of tropical rainforest sounds and am trying to play them in hour order. Now, I had it sort of working last night except there was no time correlation, just a Player.next() call whenever the player was idle. The issue is somewhere in the playSounds() module just above setup. The if statement is the problem, I think, because the conditions are met going into it, as per the lcd1.print statements, but it will not run the if statements in the {} mostly just a switch case and a soundNow() to buzz a buzzer to let me know it reached there. It's probably something stupid, it usually is with my code, but maybe it just needs a different head to spot it. Any help appreciated?
And now for the code ;
//Date and time, 2xLCDs, a DHT(digital hygrometer)
#include "RTClib.h"
#include <LCD_I2C.h>
#include <DHT.h>
#include <DHT_U.h>
#include "I2CKeyPad.h"
#include "HX710.h" // pressure sensors
#include "PCF8574.h"
//#include "X9C10X.h"
#include "DFRobotDFPlayerMini.h"
#define DHTPIN 7 // Digital pin connected to the DHT sensor
#define DHTTYPE DHT22 // DHT 22
#define FPSerial Serial1
const uint8_t KEYPAD_ADDRESS = 0x22;
const uint8_t RELAYS_ADDRESS = 0x24;
const uint8_t BUSY_PIN = 6; // from mp3
const uint8_t DOUT1 = 5;
const uint8_t PD_SCK1 = 4;
const uint8_t DOUT2 = 3;
const uint8_t PD_SCK2 = 2;
const uint8_t BACKGROUND_SWITCH_PIN = 8; // sound switch
const uint8_t BACKGROUND_LED = 9; // LED so show status of switch
const uint8_t ALARM_LED = 10; // same as above
const uint8_t HEART_LED = 13;
const uint8_t ALARM_SWITCH_PIN = 12;
const uint8_t DHT_NEG_RELAY = 4;
LCD_I2C lcd1(0x27, 20, 4);
LCD_I2C lcd2(0x26, 20, 4);
DHT dht(DHTPIN, DHTTYPE);
DFRobotDFPlayerMini myDFPlayer;
HX710 ps1,ps2;
PCF8574 PCF1(RELAYS_ADDRESS);
PCF8574 PCF2(KEYPAD_ADDRESS); // to be fleshed out later
RTC_DS3231 rtc;
//I2CKeyPad keyPad(KEYPAD_ADDRESS);
uint8_t lowWater=10,highWater=50;
uint16_t itt =24,maxItt=25;
uint16_t counter1High=0,counter1Low=0;
uint32_t value1=0,value2=0;
uint16_t x = 0;
uint16_t i=0;
uint16_t LDRValue=0;
uint16_t it =0;
uint16_t countLow=0,countHigh=0,maxHigh=10,maxLow=10;
uint8_t idealH = 75,idealT = 28,minT=25;
uint8_t hit = 0;
char daysOfTheWeek[7][8] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
char monthsOfYear[12][8] = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};
const uint8_t LDRPin = A1;
const uint8_t SOUNDER_PIN = A0;
DateTime now;
void setTime()
{
displayTime(0,3,2);
lcd2.setCursor(0, 3);
lcd2.blink();
lcd2.cursor();
return;
}
void displayDHT(int col, int row, int disp)
{
float h = dht.readHumidity();
float t = dht.readTemperature();
float f = dht.readTemperature(false);
if (isnan(h) || isnan(t) || isnan(f))
{
lcd1.setCursor(0,2);
lcd1.print("Can't read DHT!");
delay(1000);
soundNow();
PCF1.write(DHT_NEG_RELAY, 0);
delay(3000);
PCF1.write(DHT_NEG_RELAY, 1);
soundNow();
lcd1.setCursor(0,2);
lcd1.print(" "); //Just to clear above line without a full clear
}
if (disp == 1)
{
lcd1.setCursor(col,row);
lcd1.print("Habitat Temp:");
lcd1.print(t);
lcd1.print(char(223));
lcd1.print("C");
lcd1.setCursor(col,row+1);
lcd1.print("Humidity: ");
if (h < 100)
{
lcd1.print(" ");
}
lcd1.print(h);
lcd1.print("%RH");
}
if (disp == 2)
{
lcd2.setCursor(col,row);
lcd2.print("Habitat Temp:");
lcd2.print(t);
lcd2.print(char(223));
lcd2.print("C");
lcd2.setCursor(col,row+1);
lcd2.print("Humidity: ");
if (h < 100)
{
lcd2.print(" ");
}
lcd2.print(h);
lcd2.print("%RH");
}
return;
}
void displayRTC_Temp(int col,int row,int disp)
{
if (disp==1)
{
lcd1.setCursor(col,row);
lcd1.print("Ambiant Temp:");
lcd1.print(rtc.getTemperature());
lcd1.print(char(223));
lcd1.print("C");
}
else if (disp==2)
{
lcd2.setCursor(col,row);
lcd2.print("Ambiant Temp:");
lcd2.print(rtc.getTemperature());
lcd2.print(char(223));
lcd2.print("C");
}
return;
}
void displayTime(int col,int row,int disp)
{
if (disp == 1)
{
DateTime now = rtc.now();
lcd1.setCursor(col,row);
if(now.hour() < 10) lcd1.print('0');
lcd1.print(now.hour(), DEC);
lcd1.print(':');
if(now.minute() < 10) lcd1.print('0');
lcd1.print(now.minute(), DEC);
lcd1.print(':');
if(now.second() < 10) lcd1.print('0');
lcd1.print(now.second(), DEC);
}
if (disp == 2)
{
DateTime now = rtc.now();
lcd2.setCursor(col,row);
if(now.hour() < 10) lcd2.print('0');
lcd2.print(now.hour(), DEC);
lcd2.print(':');
if(now.minute() < 10) lcd2.print('0');
lcd2.print(now.minute(), DEC);
lcd2.print(':');
if(now.second() < 10) lcd2.print('0');
lcd2.print(now.second(), DEC);
}
return;
}
void displayDate(int col,int row,int disp)
{
if(disp == 1)
{
DateTime now = rtc.now();
lcd1.setCursor(col,row);
lcd1.print(daysOfTheWeek[now.dayOfTheWeek()]);
lcd1.print(" ");
if(now.day() < 10) lcd1.print('0');
lcd1.print(now.day(), DEC);
switch(now.day())
{
case 1:
case 21:
case 31:
lcd1.print("st");// if day is 1,21 or 31 ad an st after it
break;
case 2:
case 22:
lcd1.print("nd");// if day is 2 or 22 ad an nd after it
break;
case 3:
case 23:
lcd1.print("rd");// if day is 3 or 23 ad an rd after i
break;
default:
lcd1.print("th");// everything else gets a th
break;
}
lcd1.print('/');
lcd1.print(monthsOfYear[now.month()-1]);
lcd1.print('/');
lcd1.print(now.year(), DEC);
}
if(disp == 2)
{
DateTime now = rtc.now();
lcd2.setCursor(col,row);
lcd2.print(daysOfTheWeek[now.dayOfTheWeek()]);
lcd2.print(" ");
if(now.day() < 10) lcd2.print('0');
lcd2.print(now.day(), DEC);
switch(now.day())
{
case 1:
case 21:
case 31:
lcd2.print("st");// if day is 1,21 or 31 ad an st after it
break;
case 2:
case 22:
lcd2.print("nd");// if day is 2 or 22 ad an nd after it
break;
case 3:
case 23:
lcd2.print("rd");// if day is 3 or 23 ad an rd after i
break;
default:
lcd2.print("th");// everything else gets a th
break;
}
lcd2.print('/');
lcd2.print(monthsOfYear[now.month()-1]);
lcd2.print('/');
lcd2.print(now.year(), DEC);
}
return;
}
void soundNow()
{
analogWrite(SOUNDER_PIN,255);
delay(30);
analogWrite(SOUNDER_PIN,0);
delay(20);
analogWrite(SOUNDER_PIN,255);
delay(30);
analogWrite(SOUNDER_PIN,0);
delay(20);
return;
}
void heartBeat()
{
digitalWrite(HEART_LED,HIGH);
delay(100);
digitalWrite(HEART_LED,LOW);
delay(100);
return;
}
void checkWaterLevel()
{
itt++;
//delay(100);
if(itt>=maxItt)
{
itt=0;
while( !ps1.isReady() );
ps1.readAndSelectNextData( HX710_DIFFERENTIAL_INPUT_10HZ );
delay(20);
value1 = (((ps1.getLastDifferentialInput())/1000)+801);
lcd1.setCursor(0,2);
lcd1.print("1: ");
lcd1.setCursor(4,2);
lcd1.print(" ");
lcd1.setCursor(4,2);
if(value1<1000) lcd1.print('0');
lcd1.print(value1);
delay(20);
while( !ps2.isReady() );
ps2.readAndSelectNextData( HX710_DIFFERENTIAL_INPUT_10HZ );
lcd1.setCursor(0,3);
lcd1.print("2: ");
lcd1.setCursor(4,3);
lcd1.print(" ");
lcd1.setCursor(4,3);
value2 = (((ps2.getLastDifferentialInput())/1000)+415);
if(value2<1000) lcd1.print('0');
lcd1.print(value2);
if(value2>value1+highWater)
{ lcd1.setCursor(11, 3);
lcd1.print(" ");
if(counter1High>maxHigh)
{
counter1High=0;
//lcd1.setCursor(11, 3);
//lcd1.print("H2O HIGH");
}
else
{
counter1High++;
counter1Low=0;
}
}
else if (value2<=value1+lowWater)
{
lcd1.setCursor(11,3);
lcd1.print("H2O LOW ");
//delay(100);
if(counter1Low>maxLow)
{
if(digitalRead(ALARM_SWITCH_PIN) == HIGH)
{
alarmSound();
}
else
{
//counter1Low=0;
}
}
else
{
counter1Low++;
counter1High=0;
}
}
}
return;
}
void checkSwitches()
{
if(digitalRead(ALARM_SWITCH_PIN) == HIGH)
{
digitalWrite(ALARM_LED,HIGH);
}
else
{
digitalWrite(ALARM_LED,LOW);
}
if(digitalRead(BACKGROUND_SWITCH_PIN) == HIGH)
{
digitalWrite(BACKGROUND_LED,HIGH);
}
else
{
digitalWrite(BACKGROUND_LED,LOW);
}
return;
}
void checkLight()
{// tests ambient light levels and shuts off backlights
// for increased darkness at night
if (i>=50)
{
LDRValue = analogRead(LDRPin); //Get LDR value but not every run
i=0;
}else i++;
// These two stretch out the response so there is reduced flashing during
// darkening in the evening or lightening in morning or things temporarilly
// covering the LDR by accident
if(analogRead(LDRPin) <= 20)
{ // If low light <50 this func counts number of runs when dark
countLow++;
countHigh=0; // resets high light count because it just went dark
if(countLow>=50){ // if it is getting dark turn off the backlights
lcd1.noBacklight(); // for more darkness
lcd2.noBacklight();
countLow=0;
}
}
// This does the reverse for morning
if (analogRead(LDRPin) >20)
{
countHigh++; // counts the number of runs when it is light
countLow=0; // resets dark count
if (countHigh>=50)
{
lcd1.backlight();
lcd2.backlight();
countHigh=0;
}
}
return;
}
void checkHabitat()
{ hit++;
float h = dht.readHumidity();
float t = dht.readTemperature();
if (isnan(h) || isnan(t))
{
lcd1.setCursor(0,2);
lcd1.print("Can't read DHT!");
delay(500);
soundNow();
PCF1.write(DHT_NEG_RELAY, 0);
delay(3000);
PCF1.write(DHT_NEG_RELAY, 1);
soundNow();
delay(1000);
lcd1.setCursor(0,2);
lcd1.print(" "); //Just to clear above line without a full clear
}
now=rtc.now();
if(now.hour() > 21 && now.hour() < 6)
{
idealT = 26; // Night time temp/humidity
idealH = 65;
}
else if(now.hour()>11 && now.hour()<14)
{
idealT = 28; // Mid day temp/humidity
idealH = 78;
}
else
{
idealT = 27; // Normal temp/humidity
idealH = 75;
}
if (hit >40)
{
if (h > idealH && t>minT)
{
fansOn();
}
if (h < idealH)
{
fansOff();
}
if (t < idealT)
{
heatOn();
}
if(t>idealT)
{
heatOff();
}
if((t ==idealT)&&(h ==idealH))
{
fansOff();
heatOff();
}
hit=0;
}
return;
}
void heatOn()
{
PCF1.write(0, 0);
PCF1.write(1, 0);
lcd2.setCursor(10, 3);
lcd2.print("heat ON ");
return;
}
void heatOff()
{
PCF1.write(0, 1);
PCF1.write(1, 1);
lcd2.setCursor(10, 3);
lcd2.print("heat OFF");
return;
}
void fansOn()
{
PCF1.write(2, 0); // fan1 on
PCF1.write(3, 0); // fan2 on
lcd2.setCursor(0, 3);
lcd2.print("fans ON ");
return;
}
void fansOff()
{
PCF1.write(2, 1); // fan1 on
PCF1.write(3, 1); // fan2 on
lcd2.setCursor(0, 3);
lcd2.print("fans OFF");
return;
}
/*void readKeys(int dateOrTime) // date = 1, time = 2
{
int tempi = PCF2.read8(); // All Keys read
lcd2.setCursor(0, 3);
lcd2.print(tempi,BIN);
if(tempi != 0)
{
switch(tempi)
{
case 9: // 00010001 Keypad number 1
{
if (dateOrTime==1)
{
}
}
break;
case 10: // 00010010 Keypad number 4
{
}
break;
case 20: // 00010100 Keypad number 7
{
}
break;
case 24: // 00011000 Keypad number *
{
}
break;
case 33: // 00100001 Keypad number 2
{
}
break;
case 34: // 00100010 Keypad number 5
{
}
break;
case 36: // 00100100 Keypad number 8
{
}
break;
case 40: // 00101000 Keypad number 0
{
}
break;
case 65: // 01000001 Keypad number 3
{
}
break;
case 66: // 01000010 Keypad number 6
{
}
break;
case 68: // 01000100 Keypad number 9
{
}
break;
case 72: // 01001000 Keypad number #
{
}
break;
case 129: // 10000001 Keypad number A
{
}
break;
case 130: // 10000010 Keypad number B
{
}
break;
case 132: // 10000100 Keypad number C
{
}
break;
case 136: // 10001000 Keypad number D
{
}
break;
default:
break;
}
}
}*/
void alarmSound()
{
//digitalWrite(ALARM_LED,HIGH);
soundNow();
delay(20);
soundNow();
delay(30);
soundNow();
delay(50);
soundNow();
delay(20);
soundNow();
delay(30);
soundNow();
delay(50);
//digitalWrite(ALARM_LED,LOW);
return;
}
void playSounds()
{ DateTime now = rtc.now();
lcd1.setCursor(10,1);
lcd1.print(now.hour());
lcd1.setCursor(15,1);
lcd1.print(digitalRead(BUSY_PIN));
lcd1.setCursor(17,1);
lcd1.print(digitalRead(BACKGROUND_SWITCH_PIN)); // these 2 return 1 so the the next if statement condition should be true.
if(BACKGROUND_SWITCH_PIN == HIGH && digitalRead(BUSY_PIN) != 0)
{
soundNow();
switch(now.hour())
{
case 0:
{
//myDFPlayer.start();
myDFPlayer.play(0); //Play the first mp3
lcd1.setCursor(10,2);
lcd1.print("playing 00");
break;
}
case 1:
{
// myDFPlayer.start();
myDFPlayer.play(1); //Play the first mp3
lcd1.setCursor(10,2);
lcd1.print("playing 01");
break;
}
case 2:
{
//myDFPlayer.start();
myDFPlayer.play(2);
lcd1.setCursor(10,2);
lcd1.print("playing 02");
break;
}
case 3:
{
//myDFPlayer.start();
myDFPlayer.play(3);
lcd1.setCursor(10,2);
lcd1.print("playing 03");
break;
}
case 4:
{
//myDFPlayer.start();
myDFPlayer.play(4);
lcd1.setCursor(10,2);
lcd1.print("playing 04");
break;
}
case 5:
{
//myDFPlayer.start();
myDFPlayer.play(5);
lcd1.setCursor(10,2);
lcd1.print("playing 05");
break;
}
case 6:
{
//myDFPlayer.start();
myDFPlayer.play(6);
lcd1.setCursor(10,2);
lcd1.print("playing 06");
break;
}
case 7:
{
//myDFPlayer.start();
myDFPlayer.play(7);
lcd1.setCursor(10,2);
lcd1.print("playing 07");
break;
}
case 8:
{
//myDFPlayer.start();
myDFPlayer.play(8);
lcd1.setCursor(10,2);
lcd1.print("playing 08");
break;
}
case 9:
{
//myDFPlayer.start();
myDFPlayer.play(9);
lcd1.setCursor(10,2);
lcd1.print("playing 09");
break;
}
case 10:
{
//myDFPlayer.start();
myDFPlayer.play(10);
lcd1.setCursor(10,2);
lcd1.print("playing 10");
break;
}
case 11:
{
//myDFPlayer.start();
myDFPlayer.play(11);
lcd1.setCursor(10,2);
lcd1.print("playing 11");
break;
}
case 12:
{
//myDFPlayer.start();
myDFPlayer.play(12);
lcd1.setCursor(10,2);
lcd1.print("playing 12");
break;
}
case 13:
{
//myDFPlayer.start();
myDFPlayer.play(13);
lcd1.setCursor(10,2);
lcd1.print("playing 13");
break;
}
case 14:
{
//myDFPlayer.start();
myDFPlayer.play(14);
lcd1.setCursor(10,2);
lcd1.print("playing 14");
break;
}
case 15:
{
// myDFPlayer.start();
myDFPlayer.play(15);
lcd1.setCursor(10,2);
lcd1.print("playing 15");
break;
}
case 16:
{
//myDFPlayer.start();
myDFPlayer.play(16);
lcd1.setCursor(10,2);
lcd1.print("playing 16");
break;
}
case 17:
{
//myDFPlayer.start();
myDFPlayer.play(17);
lcd1.setCursor(10,2);
lcd1.print("playing 17");
break;
}
case 18:
{
//myDFPlayer.start();
myDFPlayer.play(18);
lcd1.setCursor(10,2);
lcd1.print("playing 18");
break;
}
case 19:
{
//myDFPlayer.start();
myDFPlayer.play(19);
lcd1.setCursor(10,2);
lcd1.print("playing 19");
break;
}
case 20:
{
//myDFPlayer.start();
myDFPlayer.play(20);
lcd1.setCursor(10,2);
lcd1.print("playing 20");
break;
}
case 21:
{
//myDFPlayer.start();
myDFPlayer.play(21);
lcd1.setCursor(10,2);
lcd1.print("playing 21");
break;
}
case 22:
{
//myDFPlayer.start();
myDFPlayer.play(22);
lcd1.setCursor(10,2);
lcd1.print("playing 22");
break;
}
case 23:
{
//myDFPlayer.start();
myDFPlayer.play(23);
lcd1.setCursor(10,2);
lcd1.print("playing 23");
break;
}
}
// }
}
/*else
{
myDFPlayer.pause(); //pause the mp3
lcd1.setCursor(10, 1);
lcd1.print("paused");
}*/
return;
}
void setup ()
{
// Setup PINs
pinMode(ALARM_SWITCH_PIN,INPUT);
pinMode(BACKGROUND_SWITCH_PIN,INPUT);
pinMode(BUSY_PIN,INPUT);
pinMode(BACKGROUND_LED,OUTPUT);
pinMode(ALARM_LED,OUTPUT);
pinMode(HEART_LED,OUTPUT);
pinMode(A0,OUTPUT);
pinMode(A1,INPUT);
FPSerial.begin(9600);
if (!myDFPlayer.begin(FPSerial, /*isACK = */true, /*doReset = */true))
{ //Use serial to communicate with mp3.
lcd1.setCursor(0,0);
lcd1.print(F("Unable begin:"));
lcd1.setCursor(0,1);
lcd1.print(F("Check wires"));
lcd1.setCursor(0,2);
lcd1.print(F("Insert SD card!"));
delay(3000);
lcd1.setCursor(0,0);
lcd1.print(F(" "));
lcd1.setCursor(0,1);
lcd1.print(F(" "));
lcd1.setCursor(0,2);
lcd1.print(F(" "));
}
// Setup MP3 player
myDFPlayer.setTimeOut(500); //Set serial communictaion time out 500ms
myDFPlayer.volume(2); //Set volume value (0~30).
myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);
myDFPlayer.enableDAC(); //Enable On-chip DAC
if (! rtc.begin())
{
lcd1.setCursor(0,1);
lcd1.print("Can't find RTC");
while (1) delay(10);
}
if (!PCF1.begin())
{
lcd1.setCursor(0,2);
lcd1.print("not initialize PCF1");
delay(1000);
lcd1.setCursor(0,2);
lcd1.print(" ");
}
if (!PCF1.isConnected())
{
lcd1.setCursor(0,2);
lcd1.print("not initialize PCF1");
delay(100);
lcd1.setCursor(0,2);
lcd1.print(" ");
while(1);
}
/*if (!PCF2.begin())
{
lcd1.setCursor(0,2);
lcd1.print("not initialize PCF2");
delay(1000);
lcd1.setCursor(0,2);
lcd1.print(" ");
}
if (!PCF2.isConnected())
{
lcd1.setCursor(0,2);
lcd1.print("not initialize PCF2");
delay(100);
lcd1.setCursor(0,2);
lcd1.print(" ");
while(1);
}*/
// Make sure ALL relays are OFF(active low)
PCF1.write8(0xFF); // All relays OFF
// PCF2.write8(0xFF); // All Keys OFF
// Setup DHT
dht.begin();
// Setup LCDs
lcd1.begin();
lcd2.begin();
lcd1.backlight();
lcd2.backlight();
lcd1.clear();
lcd2.clear();
// Setup RTC
rtc.clearAlarm(1);
rtc.clearAlarm(2);
rtc.disableAlarm(1);
rtc.disableAlarm(2);
rtc.writeSqwPinMode(DS3231_OFF);
// Setup pressure sensors
ps1.initialize( PD_SCK1 , DOUT1 );
ps2.initialize( PD_SCK2 , DOUT2 );
}
void loop ()
{
//readKeys();
//soundNow();
heartBeat();
checkSwitches();
checkLight();
displayDate(0,0,1);
displayTime(0,1,1);
playSounds();
displayRTC_Temp(0,0,2); // col,row display
displayDHT(0,1,2);
checkWaterLevel();
checkHabitat();
delay(30);
}
I know, it's a little overkill but I had nothing better to do in my retirement. I'll have to tidy it sometime!
I had the devil of a time trying to hold temp and humidity between allowable levels until I realised I didn't have to. I just picked a median value and forwent the complications. What do you think of it, as a piece of code? Thanks.
Larry