Good evening everyone.
I have been working on a project that does some data acquisition (water pH and temperature) and is supposed to post the data to Pachube.
The code and the hardware is working fine, until I attach the (Arduino) Ethernet shield to Arduino (Uno). When I do that, it seems that the whole thing becomes incredibly slow (specifically, I have a few input buttons that each run a routine, and when pressed they worked just fine without the shield, but with the shield I have to keep pressing on them for about 3 seconds until the board registers the button press). Is the shield that much of a processor hog?
The connections are as follows:
Digital pins:
Out: 2, 3, 5, 6, 7, 9 - LCD display
Analog pins:
In: A0, A1 - pH and temperature sensor
A2, A3, A4, A5 - 4 pushbuttons (used as digital inputs on analog pins)
Arduino powered by 9VDC 2.1mm jack.
I'm using SPI.h library so digital 10, 11, 12 and 13 are used by it, and the ethernet shield reserves digital 4 for the SD card (which I have to put as a high output to disable).
I'm at a loss what to try. I am only transfering data through ethernet every 15 minutes so high transfer load doesn't seem to be the issue.
The whole code is attached next.
Thank you very much for your help and input. Hope that someone can aid me in this issue.
#include <LiquidCrystal.h>
#include <SPI.h>
#include <Ethernet.h>
#include <stdio.h>
#include <string.h>
#include "float2string.h"
#define GAIN 10
#define VREF 2.366
#define PHSENSOR 0
#define TEMPSENSOR 1
#define RESET_PIN 8
#define GAS_CONSTANT_R 8.31451
#define FARADAY_CONSTANT_F 96485
#define NERNST 59.16
#define SAMPLES 200
#define PACHUBE_API_KEY "XXX"
#define PACHUBE_FEED_ID 99999
#define T_PACHUBE_UPDATE 900000 //pachube upload time, every 15 minutes = 900000 ms
float setPoint = 7.00;
float interval_SP = 0.05;
unsigned long timer_upload = 0;
unsigned long timer_upload_old = 0;
int buttonState0 = 0; //Calibration button state, HIGH/LOW
int buttonState1 = 0; //Up button state, HIGH/LOW
int buttonState2 = 0; //Down button state, HIGH/LOW
int buttonState3 = 0; //OK button state, HIGH/LOW
float temp_mv = 0;
float ph_mv = 0;
float ph_calib7 = 0;
float ph_calib4 = 1;
float T = 0;
float E = 0;
float PH = 0;
char temp_str[6];
char ph_str[6];
char sp_str[6];
int comm_status = 0; //ethernet link state, ON/OFF
int valve_status = 0; //solenoid valve state, NOT YET IMPLEMENTED
byte mac[] = { 0x91, 0xA1, 0xDB , 0x00, 0x6F, 0x2C };
byte ip[] = { 10, 0, 0, 177 };
byte server[] = { 173, 203, 98, 29 }; // pachube.com
byte gateway[] = { 10, 0, 0, 1 };
byte mask[] = { 255, 255, 255, 0 };
int port = 80;
Client client(server, port); /* Client listening on port 80 */
LiquidCrystal lcd(9, 7, 6, 5, 3, 2);
void setup()
{
lcd.begin(16, 4);
pinMode (A2, INPUT); //defines OK button as a digital in, on an analog pin
pinMode (A3, INPUT); //defines calibration button as a digital in, on an analog pin
pinMode (A4, INPUT); //defines up button as a digital in, on an analog pin
pinMode (A5, INPUT); //defines down button as a digital in, on an analog pin
pinMode(RESET_PIN, OUTPUT);
pinMode (4, OUTPUT); //disable SD card slot on ethernet shield, due to SPI bus
digitalWrite (4, HIGH);
// Fix to kick-start Ethernet on power-up, power-failure by using reset signal from Arduino to reset-pin on Ethernet Shield
// Start fix
digitalWrite(RESET_PIN, LOW); /* Take Ethernet reset line low */
delay(200); /* momentarily */
digitalWrite(RESET_PIN, HIGH); /* Bring it up again */
delay(2000); /* Allow Ethernet time to boot */
// End of fix
Ethernet.begin(mac, ip, gateway, mask);
Serial.begin(9600);
delay(1000);
}
unsigned int readADC(unsigned char channel) {
double d = 0;
int i = 0;
for (i = 0; i < SAMPLES; i++)
{
d = d + analogRead(channel);
}
d = d / i;
return (unsigned int)(d);
}
void processData(void)
{
ph_mv = readADC(PHSENSOR);
temp_mv = readADC(TEMPSENSOR);
T = (100 * temp_mv * 5.0 / 1024);
E = (((ph_mv - ph_calib7) * 5.0 / 1024) - VREF) / (GAIN * ph_calib4);
PH= ((-1 * FARADAY_CONSTANT_F * E) / (2.303 * GAS_CONSTANT_R * (273.15 + T))) + 7.0;
floatToString(temp_str, T, 1);
floatToString(ph_str, PH, 2);
floatToString(sp_str, setPoint, 2);
lcd.setCursor (0,0);
lcd.print("T=");
lcd.print(temp_str);
lcd.print((char)223); // degree symbol
lcd.print("C");
lcd.setCursor (0,1);
lcd.print("SetPoint=");
lcd.print(sp_str);
lcd.setCursor (-4,2);
lcd.print("pH=");
lcd.print(ph_str);
lcd.setCursor (-4,3);
if (comm_status == 0) {lcd.print("Com:off");}
if (comm_status == 1) {lcd.print("Com:on");}
lcd.setCursor (5,3);
if (valve_status == 0) {lcd.print("Vlv:off");}
if (valve_status == 1) {lcd.print("Vlv:on");}
if (timer_upload - timer_upload_old > T_PACHUBE_UPDATE) //uploads to pachube every T_PACHUBE_UPDATE seconds
{
timer_upload_old = timer_upload;
String dataString = String(temp_str);
dataString = dataString + ",";
dataString = dataString + String(ph_str);
pachube_PUT(dataString);
}
if (timer_upload - timer_upload_old < 0) //when millis() overflows, updates value after first failed check
{
timer_upload_old = timer_upload;
}
}
float calibration_ph7()
{
do
{
buttonState3 = digitalRead(A2);
if (buttonState3 == HIGH)
{
if (ph_mv != 0)
{
ph_calib7 = ph_mv;
}
else
{
ph_calib7 = 0;
}
buttonState0 = 0;
buttonState3 = 0;
break;
}
}
while (buttonState3 != HIGH);
}
float calibration_ph4()
{
float difference = 0;
float new_gain = 0;
do
{
buttonState3 = digitalRead(A2);
if (buttonState3 == HIGH)
{
if (ph_mv != ((NERNST * 3) * GAIN) + (VREF - ph_calib7))
{
difference = ((NERNST * 3) * GAIN) + (VREF - ph_calib7) - ph_mv;
new_gain = (((((NERNST * 3) * GAIN) + (VREF - ph_calib7)) - difference) * GAIN) / (((NERNST * 3) * GAIN) + (VREF - ph_calib7));
ph_calib4 = new_gain / GAIN;
}
else
{
ph_calib4 = 1;
}
buttonState0 = 0;
buttonState3 = 0;
break;
}
}
while (buttonState3 != HIGH);
}
void pachube_PUT(String dataString)
{
client.print("PUT /api/feeds/");
client.print(PACHUBE_FEED_ID);
client.println(".csv HTTP/1.0");
client.println("Host: www.pachube.com");
client.print("X-PachubeApiKey: ");
client.println(PACHUBE_API_KEY);
client.print("Content-Length: ");
client.println(dataString.length(), DEC);
client.println("Content-Type: text/csv");
client.println("Connection: close");
client.println();
client.println(dataString);
}
void loop(void)
{
if (client.connected() == 0)
{
comm_status = 0;
client.connect();
}
else
{
comm_status = 1;
}
timer_upload = millis();
processData();
buttonState0 = digitalRead(A3); //checks Calib button for a press every cycle
buttonState1 = digitalRead(A4); //checks Up button for a press every cycle
buttonState2 = digitalRead(A5); //checks Down button for a press every cycle
if (buttonState0 == HIGH) //THIS IS TAKING LIKE 3 SECONDS TO REGISTER A PRESS, WITH ETH SHIELD ON
{
calibration_ph7();
calibration_ph4();
}
if (buttonState1 == HIGH) //THIS IS TAKING LIKE 3 SECONDS TO REGISTER A PRESS, WITH ETH SHIELD ON
{
setPoint = setPoint + interval_SP;
delay(150);
}
if (buttonState2 == HIGH) //THIS IS TAKING LIKE 3 SECONDS TO REGISTER A PRESS, WITH ETH SHIELD ON
{
setPoint = setPoint - interval_SP;
delay(150);
}
}