Hello everyone. I hope I am posting this in the right area. Let me try and give some background on the project:
I am setting up a hydroponics monitoring system modeled very similarly to the one posted here:
Basically I have a variety of sensors (EC, PH, CO2, humidity, and temperature) that I want to use to take measurements, display the measurements on an LCD, and save the measurements in a data logger.
One key difference between what I am doing and what is shown in the above link is the presence of a data logger (DL from now on). As the title suggests, I am having trouble interfacing all of the sensors, LCD screen, and data logger with the Arduino Uno. I have some pictures that I will try to upload, but let me try to describe what my system looks like in case my picture are not clear enough.
Basically, I have a data logging shield that is placed on top of the Uno. At first I planned to place an LCD shield on top of the data logging shield so all the components are connected, but I believe this is an issue because both the data logger and the lcd use digital pin 10 (correct me if this is wrong!)
So, I disconnected the lcd from the uno+DL and tried to use a bunch of jumper wires to connect the relevant pins from the lcd to the uno+DL, except I connected pin 10 on the LCD to pin 4 on the uno+DL.
All of the sensors are connected to the LCD, and then I used more jumpers to connect the sensors pins from the lcd to the uno+DL.
In my head, this should 100% work, but I am having some issues:
-
The LCD isn't displaying data like it should. Sometimes their is nothing but 'noise' on the display. Sometimes nothing is displayed. Sometimes the data is displayed for a few seconds, and then disappears. Sometimes the data stays, but doesn't update as the measurements change (its like the screen is frozen on the same values). Hopefully you get the idea.
-
The logger isn't recording data that matches the measurements shown on the diplay (I tried using just the LCD+uno without the DL and the display seemed to be working as intended, so i have a general idea of what the data should look like.).
Does anyone have any suggestions? A few of my guesses:
I am accidentally using the same pin on multiple different things.
Could their be an issue with memory? Am i just asking my arduino to do too much?
CHeck out my code below. Hopefully you made it through all me text. Thank you in advance for your help.
links:
I belive this is the data logger, but i am not completely sure:
https://www.elabpeers.com/arduino-data-logger.html
//Libraries
#include <DHT.h>
#include <U8glib.h>
#include <stdio.h>
#include <OneWire.h>
#include <Arduino.h>
#include <Adafruit_Sensor.h>
#include "DFRobot_EC.h"
#include <EEPROM.h>
#include <SD.h>
#include <Wire.h>
#include <RTClib.h>
// ADAFRUIT DATA LOGGER - A simple data logger for the Arduino analog pins
#define LOG_INTERVAL 1000 // mills between entries
//PINS
#define EC_PIN 1 //EC meter pin
#define PH_PIN 2 //pH meter pin
#define CO2_PIN 3 //ORP meter pin
#define DHT_PIN 5 // DHT pin
#define DHTTYPE DHT22 // DHT 22 (AM2302)
#define DS18B20_PIN 6 //EC solution temperature pin
#define CHIPSELECT_PIN 10 // for the data logging shield, we use digital pin 10 for the SD cs line
#define CHIPSELECT_PIN_LCD 4
DFRobot_EC ec;
// AVERAGING VALUES
#define MEDIAN_SAMPLE 8
#define MEASUREMENTS_TAKEN 100
// EC - solution temperature variables
#define StartConvert 0
#define ReadTemperature 1
// EC values - CHANGE THESE PARAMETERS FOR EC PROBE CALIBRATION
#define EC_PARAM_A 0.00754256
//pH values - CHANGE THESE PARAMETERS FOR PH PROBE CALIBRATION
#define PH_PARAM_A 1.0
#define PH_PARAM_B 0.0
#define XCOL_SET 55
#define XCOL_SET2 65
#define XCOL_SET_UNITS 85
//--------SENSOR GLOBALS--------
DHT dht(DHT_PIN, DHTTYPE);
U8GLIB_NHD_C12864 u8g(13, 11, CHIPSELECT_PIN_LCD, 9, 8);
int tmp, chk;
unsigned int AnalogAverage = 0, averageVoltage = 0, levelAverage;
float phValue, hum, temp, solution_temp, ECcurrent, co2;
OneWire ds(DS18B20_PIN);
//--------LOGGER GLOBALS--------
//RTC_DS1307 RTC; // define the Real Time Clock object
RTC_PCF8523 RTC;
char filename[13] = "LOGGER00.CSV";
unsigned long int last_record_time;
//------------------------------
void draw() {
u8g.setFont(u8g_font_04b_03);
u8g.drawStr( 0,11,"Temp:");
u8g.setPrintPos(XCOL_SET,11);
u8g.print(temp);
u8g.drawStr( XCOL_SET_UNITS, 11,F("C"));
u8g.drawStr(0,21,F("Humidity:"));
u8g.setPrintPos(XCOL_SET,21);
u8g.print(hum);
u8g.drawStr( XCOL_SET_UNITS,21,F("%"));
u8g.drawStr(0,31,F("pH:"));
u8g.setPrintPos(XCOL_SET,31);
u8g.print(phValue);
u8g.drawStr(0,41,F("EC:"));
u8g.setPrintPos(XCOL_SET,41);
u8g.print(ECcurrent);
u8g.drawStr( XCOL_SET_UNITS,41,F("mS/cm"));
u8g.drawStr(0,51,F("Sol.Temp:"));
u8g.setPrintPos(XCOL_SET,51);
u8g.print(solution_temp);
u8g.drawStr( XCOL_SET_UNITS,51,F("C"));
u8g.drawStr(0,61,F("CO2:"));
u8g.setPrintPos(XCOL_SET,61);
u8g.print(co2);
u8g.drawStr( XCOL_SET_UNITS,61,F("ppm"));
}
/*float TempProcess(bool ch) {
static byte data[12];
static byte addr[8];
static float TemperatureSum;
if(!ch){
if ( !ds.search(addr)) {
ds.reset_search();
return 0;
}
if ( OneWire::crc8( addr, 7) != addr[7]) {
return 0;
}
if ( addr[0] != 0x10 && addr[0] != 0x28) {
return 0;
}
ds.reset();
ds.select(addr);
ds.write(0x44,1);
}
else{
byte present = ds.reset();
ds.select(addr);
ds.write(0xBE);
for (int i = 0; i < 9; i++) {
data[i] = ds.read();
}
ds.reset_search();
byte MSB = data[1];
byte LSB = data[0];
float tempRead = ((MSB << 8) | LSB);
TemperatureSum = tempRead / 16;
}
return TemperatureSum;
}
*/
void calculateAnalogAverage(int pin) {
int buf[MEASUREMENTS_TAKEN];
unsigned long int avgValue = 0;
AnalogAverage = 0;
for(int i=0;i<MEASUREMENTS_TAKEN;i++) {
buf[i]=analogRead(pin);
delay(10);
}
for(int i=0;i<MEASUREMENTS_TAKEN-1;i++) {
for(int j=i+1;j<MEASUREMENTS_TAKEN;j++) {
if(buf[i]>buf[j]) {
tmp=buf[i];
buf[i]=buf[j];
buf[j]=tmp;
}
}
}
for(int i=(MEASUREMENTS_TAKEN/2)-(MEDIAN_SAMPLE/2);i<(MEASUREMENTS_TAKEN/2)+(MEDIAN_SAMPLE/2);i++) {
avgValue+=buf[i];
}
AnalogAverage = avgValue/MEDIAN_SAMPLE;
}
void read_pH() {
calculateAnalogAverage(PH_PIN);
phValue=(float)AnalogAverage*5.0/1024;
phValue = 3.5*phValue+.52;
//phValue=PH_PARAM_A*phValue+PH_PARAM_B;
}
void read_EC() {
calculateAnalogAverage(EC_PIN);
// solution_temp = TempProcess(ReadTemperature);
//TempProcess(StartConvert);
float temp1 = dht.readTemperature();
averageVoltage=AnalogAverage*(float)5000/1024;
//float TempCoefficient=1.0+0.0185*(solution_temp-25.0);
//float CoefficientVolatge=(float)averageVoltage*TempCoefficient;
ECcurrent = ec.readEC(averageVoltage,temp1);
//ECcurrent=EC_PARAM_A*CoefficientVolatge;
}
void read_CO2() {
float voltage;
float voltage_difference;
calculateAnalogAverage(CO2_PIN);
voltage = AnalogAverage*(5000/1024.0);
if(voltage == 0) {
co2=-100.0;
}
else if(voltage < 400) {
co2=0.0;
}
else {
voltage_difference=voltage-400;
co2=voltage_difference*50.0/16.0;
}
}
void log_record(unsigned long int m) {
File logfile;
//DateTime record_time;
Serial.println(filename);
// if (! rtc.initialized()) {
// Serial.println("RTC is NOT running!");
// following line sets the RTC to the date & time this sketch was compiled
SdFile::dateTimeCallback(dateTime);
logfile = SD.open(filename, FILE_WRITE);
Serial.println(logfile);
logfile.print(m); //log milliseconds since start
logfile.print(", ");
DateTime now = RTC.now(); // fetch the time
//logfile.print(record_time.unixtime()); //log time - seconds since 1/1/1970
//logfile.print(" ");
logfile.print(now.year(), DEC);
logfile.print("/");
logfile.print(now.month(), DEC);
logfile.print("/");
logfile.print(now.day(), DEC);
logfile.print(" ");
logfile.print(now.hour(), DEC);
logfile.print(":");
logfile.print(now.minute(), DEC);
logfile.print(":");
logfile.print(now.second(), DEC);
Serial.print(now.year(), DEC);
Serial.print("/");
Serial.print(now.month(), DEC);
Serial.print("/");
Serial.print(now.day(), DEC);
Serial.print(" ");
Serial.print(now.hour(), DEC);
Serial.print(":");
Serial.print(now.minute(), DEC);
Serial.print(":");
Serial.println(now.second(), DEC);
logfile.print(",");
logfile.print(temp);
logfile.print(",");
logfile.print(hum);
logfile.print(",");
logfile.print(phValue);
logfile.print(",");
logfile.print(ECcurrent);
logfile.print(",");
logfile.print(solution_temp);
logfile.print(",");
logfile.print(co2);
logfile.print("\n");
logfile.close();
}
void dateTime(uint16_t* date, uint16_t* time) {
DateTime now = RTC.now();
// return date using FAT_DATE macro to format fields
*date = FAT_DATE(now.year(), now.month(), now.day());
// return time using FAT_TIME macro to format fields
*time = FAT_TIME(now.hour(), now.minute(), now.second());
}
void setup() {
//---------SENSOR SETUP---------
pinMode(13,OUTPUT);
Serial.begin(9600);
dht.begin();
u8g.setContrast(0);
u8g.setRot180();
// TempProcess(StartConvert);
//------------------------------
//---------LOGGER SETUP---------
pinMode(10, OUTPUT); //make sure that the default chip select pin is set to output, even if you don't use it.
//pinMode(4, OUTPUT);
if (!SD.begin(CHIPSELECT_PIN)) { //see if the card is present and can be initialized:
return; // don't do anything more
}
last_record_time = 0;
File newfile;
for (uint8_t i = 0; i < 100; i++) {
filename[6] = i/10 + '0';
filename[7] = i%10 + '0';
if (! SD.exists(filename)) { //only open a new file if it doesn't exist
newfile = SD.open(filename, FILE_WRITE);
break; // leave the loop!
}
}
Wire.begin();
if (!RTC.begin()) {
newfile.println(F("RTC failed"));
}
//if (! rtc.initialized() || rtc.lostPower()) {
// Serial.println("RTC is NOT initialized, let's set the time!");
//RTC.adjust(DateTime(F(__DATE__), F(__TIME__)));
newfile.println(F("Millis,Time,Temp,Humidity,pH,EC,Solution Temp,CO2"));
newfile.close();
//------------------------------
}
void loop() {
digitalWrite(13, HIGH);
delay(800);
digitalWrite(13, LOW);
hum = dht.readHumidity();
temp= dht.readTemperature();
read_pH();
read_EC();
read_CO2();
Serial.print("1");
unsigned long int time_since_start = millis();
if (time_since_start > last_record_time + LOG_INTERVAL) {
log_record(time_since_start);
last_record_time = time_since_start;
}
Serial.print("2");
u8g.firstPage();
do {
draw();
}
while( u8g.nextPage() );
Serial.print("3");
}