Hi guys
Having some trouble here with a basic code error. I have built a code to monitor the level of liquid in a tank.
Basically the code will convert the distance into a height of liquid and produce a "percent remaining" reading.
The reading can then be requested by sms and returned to user by sms.
Currently my percent remaining is no taking away the distance from the liquid to the sensor and my sms keeps sending back the wrong message.
I'm sure its something simple i have missed but i have been pulling my hair out here for days trying to find an error but not getting anywhere. If anyone could help it would be absolutely amazing.
Thanks in advance
D.
[code]//This sketch reads a HC-SR04 ultrasonic rangefinder and returns the
//distance to the closest object in range. To do this, it sends a pulse
// the sensor to initiate a reading, then listens for a pulse
//to return. The length of the returning pulse is proportional to
//the distance of the object from the sensor.
//The circuit:
//* VCC connection of the sensor attached to +5V
//* GND connection of the sensor attached to ground
//* TRIG connection of the sensor attached to digital pin 4
//* ECHO connection of the sensor attached to digital pin 5
// include the GSM library
#include <GSM.h>
// PIN Number for the SIM
#define PINNUMBER "4825"
// initialize the library instances
GSM gsmAccess;
GSM_SMS sms;
// Pins for the sensor
const int trigPin = 4;
const int echoPin = 5;
// Number to send SMS to, make sure the index value in [] is at least as big as the number of digits in the number plus 1
const char sendTo[20] = "+353879553438";
// Incoming Text Variable
String Text;
// Outgoing Text Variables
String Out;
String Info1;
String Info2;
String Info3;
// Timer, each increment equals 1 second
int Timer = 0;
int Minutes = 0;
// Tracks last warning
int LastWarn = 0;
// True if there is a current warning
boolean WarningState = false;
boolean Acknowledged = false;
boolean Triggered = false;
boolean Bigdrain = false;
// Global array for compairing our water levels, we will store 5. [0] counts as 1 and the last spot needs to be empty.
int Levels[5] = {
0, 0, 0, 0, 0};
void setup() {
// initialize serial communication:
Serial.begin(9600);
// connection state
boolean notConnected = true;
// Start GSM connection
while(notConnected)
{
if(gsmAccess.begin(PINNUMBER)==GSM_READY)
notConnected = false;
else
{
Serial.println("Not connected");
delay(1000);
}
}
Serial.println("GSM initialized");
}
void loop()
{
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration, inches, cm, percent;
// This holds the difference between each level reading
int Difference = 0;
// Check sensor every 30 seconds
if (Timer == 0 || Timer == 30) {
PingSensor(duration);
// convert the time into a distance
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
percent = microsecondsTopercent(duration);
// Output data to serial for debugging
Serial.print("Distance from sensor to water = ");
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm, ");
Serial.println();
Serial.print(percent);
Serial.print("% water capacity remaining");
Serial.println();
Serial.println();
// After the sensor is checked move the array data left a place and add new data on the end.
for (int i=1; i<5; i++) {
Levels[i-1] = Levels[i];
}
// Math to determine percentage drop
Levels[4] = percent;
if (Levels[3] != 0) {
Difference = ((Levels[3]-Levels[4])+(Levels[2]-Levels[3])/2);
// Respond to large drain
if (Difference > 5 && !Triggered) {
Info1 = String(Levels[2]);
Info2 = String(Levels[4]);
bigDrain();
}
// If the large drain stopped stop warning
if (Bigdrain && Difference < 5) {
Bigdrain = false;
WarningState = false;
Triggered = false;
}
}
// Respond to low levels
if (percent == 20 && !Triggered) {
LastWarn = 20;
LowLevel();
}
if (percent == 15 && Triggered && LastWarn == 20) {
Triggered = false;
}
if (percent == 15 && !Triggered) {
LowLevel();
LastWarn = 15;
}
if (percent == 10 && Triggered && LastWarn == 15) {
Triggered = false;
}
if (percent == 10 && !Triggered) {
LowLevel();
LastWarn = 10;
}
if (percent == 5 && Triggered && LastWarn == 10) {
Triggered = false;
}
if (percent == 5 && !Triggered) {
LowLevel();
LastWarn = 5;
}
if (percent == 3 && Triggered && LastWarn == 5) {
Triggered = false;
}
if (percent == 3 && !Triggered) {
LowLevel();
LastWarn = 3;
}
if (percent == 2 && Triggered && LastWarn == 3) {
Triggered = false;
}
if (percent == 2 && !Triggered) {
LowLevel();
LastWarn = 2;
}
if (percent == 1 && Triggered && LastWarn == 2) {
Triggered = false;
}
if (percent == 1 && !Triggered) {
LowLevel();
LastWarn = 1;
}
}
// Check for incoming SMS
incomingSMS();
// Delay loop for 1 second
delay(1000);
// Count the loops
Timer++;
if (Timer >= 61) {
Timer = 0; // reset the counter every 60 seconds
Minutes++; // Been a minute? Add a minute
}
if (Minutes >= 5) {
Minutes = 0; // reset the counter every 6 minutes
// If there's a warning send a message every 5 minutes
if (WarningState) {
SendLevel();
}
}
// End of the main loop
}
// Function to handle low tank level
void LowLevel() {
WarningState = true;
Triggered = true;
}
// Function to let us know there was a large drain
void bigDrain() {
Bigdrain = true;
WarningState = true;
Triggered = true;
}
//Function to respond to SMS
void SendLevel() {
if (WarningState) { // Send correct message based on warning status
if (Bigdrain) { // Do this if there is a big drain warning
// Build our message
Out = "The tank has gone from ";
Out = Out + Info1;
Out = Out + "% to ";
Out = Out + Info2;
Out = Out + "% in less then a minute";
sendSMS(); // Tigger sendSMS function
}
else {
Out = "WARNING!! The current tank level is ";
Out = Out + Info2;
Out = Out + "%";
sendSMS(); // Tigger sendSMS function
}
if (!WarningState) {
Out = "The current tank level is ";
Out = Out + Info2;
Out = Out + "%";
sendSMS(); // Tigger sendSMS function
}
}
}
// Function to send SMS
void sendSMS() {
sms.beginSMS(sendTo);
sms.print(Out);
sms.endSMS();
}
// Function to read SMS
void incomingSMS(){
int x;
char c;
// If there are any SMSs available()
if (sms.available())
{
// Read message bytes
while(c=sms.read())
if (isdigit(c)) {
x = c - '0';
}
// Delete message from modem memory
sms.flush();
// If we got a 1 respond
if (x == 1) {
if (!WarningState) {
SendLevel(); // If there isn't a warning send the level
}
if (WarningState) {
WarningState = false; // If there is a warning acknowledge acknowledgement
}
}
// If we got a 9 reset everything, if there is still a problem it will report it again
if (x == 9) {
WarningState = false;
LastWarn = 0;
Triggered = false;
Bigdrain = false;
Out = "Previous data cleared";
sendSMS();
}
}
}
// Function for reading the sensor
long PingSensor (long x) {
// The sensor is triggered by a HIGH pulse of 10 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(trigPin, OUTPUT);
digitalWrite(trigPin, LOW);
delayMicroseconds(10);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
// Read the signal from the sensor: a HIGH pulse whose
// duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(echoPin, INPUT);
x = pulseIn(echoPin, HIGH);
return x;
}
long microsecondsToInches(long microseconds)
{
// According to Parallax's datasheet for the PING))), there are
// 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
// second). This gives the distance travelled by the ping, outbound
// and return, so we divide by 2 to get the distance of the obstacle.
return microseconds / 74 / 2;
}
long microsecondsToCentimeters(long microseconds)
{
// The speed of sound is 340 m/s or 29 microseconds per centimeter.
// The ping travels out and back, so to find the distance of the
// object we take half of the distance travelled.
return microseconds / 29 / 2;
}
long microsecondsTopercent(long microseconds)
{
return (420-(microseconds / 29 / 2))/4 ;
// Tank has been defined a 4m deep. This will now give a % reading
// based on the distance from bottom of tank to oil height
// 20cm has been allowed between sensor and full oil level
}
[/code]
What debug data are you getting?
Hi WildBill
Thanks for your reply.
Not getting any errors compiling pretty sure it is something to do with the order i have it written.
Sorry for not being more insightful but im a bit new to C/Arduino
I mean, what's the output from this:
// Output data to serial for debugging
Serial.print("Distance from sensor to water = ");
Serial.print(inches);
Serial.print("in, ");
Serial.print(cm);
Serial.print("cm, ");
Serial.println();
Serial.print(percent);
Serial.print("% water capacity remaining");
Serial.println();
Serial.println();
The inches and cm are both producing a 0 which causes the tank to be shown as 100% full
Oops. You don't do anything with the return value from the ping sensor function. Try:
duration=PingSensor(duration);
Thanks Wildbill I now have a reading comiing through my serial port ![]()
Dont suppose you would have any more suggestions as to why i am not getting a reading by sms?
Thanks
// convert the time into a distance
inches = microsecondsToInches(duration);
cm = microsecondsToCentimeters(duration);
percent = microsecondsTopercent(duration);
Where do you use inches or cm? Is there a reason to convert the time to inches, cms, and %? I can't think of a single one. You need ONE of the values, not all three.
Difference = ((Levels[3]-Levels[4])+(Levels[2]-Levels[3])/2);
If the values are constant, dividing by 0 is a really bad idea.
// Delay loop for 1 second
delay(1000);
Why?
Get rid of Timer, Minutes, etc, and every single delay(). Read, understand, and embrace the blink without delay philosophy.
void bigDrain() {
Bigdrain = true;
Function names and variable names that differ only by case would get you shown the door in my group. Really, it isn't that hard to some up with meaningful names. Function names should have a noun and a verb, like digitalRead(), analogWrite() etc. unless the function is a method, like Serial.print(). Then, the noun is the instance, and the method is the verb.
if (!WarningState) {
Inside the if(WarningState) block, this hasn't a snowball's chance in hell of evaluating to true.