Water Level Monitor using SM5100B Shield.

Hello.

I’ve been working on a portion of code to send text messages every 4 hours. I just wanted to check if this code is correct. It verifies fine, but errors occur when I run it through “Simulator for Arduino” from arduino.com.au.

The software gets stuck on a few parts, I was wondering if some of you may be able to take a look at it, and possibly fix or tell me what’s wrong.

/*
 # The sensor values are as follows.
 # 0  ~300     dry soil
 # 300~700     humid soil
 # 700~950     in water
 # The first int is the number to call.
 */

// The code to allow interfacing with Serial connections. 
#include <SoftwareSerial.h>

// Mobile Number
#define SMS_NUMBER "12345678901"

// Our threshholds for the water level (see above)
#define SENSOR_DRY 300.0
#define SENSOR_HUMID 700.0

// The period in milliseconds to wait in between reports. 4 hours = 1000 * 60 * 60 * 4
#define SMS_REPORT_INTERVAL 14400000

// The period in milliseconds in between samples of the water level sensor
#define LEVEL_SAMPLE_INTERVAL 1000

// The period in milliseconds to wait after an alarm clears to send a report. This will ensure that
// we do not send reports over and over. 30 minutes = 1000 * 60 * 30
#define ALARM_CLEAR_REPORT_INTERVAL 1800000

const int VAL_PROBE = 0; // Moisture Sensor 1.
const int MOISTURE_LEVEL = 300; // The threshold for the water sensor.

// Used to save the last point in time that a report was sent
unsigned long lastReportTime;

// Used to save the last point in time we took a reading
unsigned long lastLevelSampleTime;

// Create a "soft" serial port on pins 6(RX) and 7(TX)
SoftwareSerial modem(2,3);  //Create a 'fake' serial port. Pin 2 is the Rx pin, pin 3 is the Tx pin.

// Keep track of if we have sent an SMS for a newly triggered alarm
boolean alarmSent = false;

// A flag used to determine if we should print the current level to the terminal for inspection
boolean printLevelToTerminal = false;

char incoming_char = 0;

void setup(){

  Serial.begin(9600);
  modem.begin(9600);
  Serial.println("Starting SM5100B Communication...");

  lastReportTime = lastLevelSampleTime = millis();


  // We should see the reading from our sensor
  Serial.print("Reading: ");
  Serial.println(analogRead(VAL_PROBE));

  // Test the level again to check it's valid.
  sampleLevel();

}

boolean checkForAlarm(void)
{
  return ( Serial.println(analogRead(VAL_PROBE)) >= SENSOR_DRY);
}

void sampleLevel(void)
{
  // Get the readings from VAL_PROBE
  Serial.println(analogRead(0));
}

void printCurrentLevel(Print *p)
{
  int moisture = analogRead(VAL_PROBE);
  p->print("Water Level: ");
  Serial.println(analogRead(0));
  p->print(" - ");
  if(moisture > MOISTURE_LEVEL) {
    p->print("You need to irrigate this field!");
  } 
}

void printLevel(Print *p)
{
    p->print(Serial.println(analogRead(0)));
}


// Code to send an SMS Message.
void sendSMS(char *msg)
{
  modem.print("AT+CMGS="); 
  modem.write(34);
  modem.print(SMS_NUMBER);
  modem.write(34);
  modem.print(msg);
  modem.print(" ");
  printCurrentLevel(&modem);
  delay(500);                // Wait for ">" prompt
  modem.write(0x1A);   // CTRL-Z
}



// Main Execution Code
void loop(){
  unsigned long newTime = millis();

  // Take a water level sample if it is time
  if ((newTime - lastLevelSampleTime) > LEVEL_SAMPLE_INTERVAL)
  {
    sampleLevel();
    lastLevelSampleTime = newTime;
  } 

  if (printLevelToTerminal)
  {
    printCurrentLevel(&Serial);
    Serial.println();  
    printLevelToTerminal = false;
  }

  boolean alarmActive = checkForAlarm();

  // If we have an unsent alarm send a message
  if (alarmActive && !alarmSent)
  {
    sendSMS("(URGENT)");
    alarmSent = true;
    lastReportTime = newTime;    // This will reset the report interval 
  }

  // Or send a message if we have reached the report interval
  else if ((newTime - lastReportTime) > SMS_REPORT_INTERVAL)
  {
    lastReportTime = newTime;
    sendSMS("(Levels)");  
  }

  // Reset the alarmSent flag if an alarm clears and the interval has passed
  if (!alarmActive && alarmSent &&
    ((newTime - lastReportTime) > ALARM_CLEAR_REPORT_INTERVAL)) 
  { 
    alarmSent = false;
    lastReportTime = newTime;
    sendSMS("(Levels)");
  } 
  while (modem.available() > 0)
  {
    // Take any incoming data from the SM5100B modem and send it to the terminal
    incoming_char = modem.read();    
    Serial.print(incoming_char);
  }
  // Relay input from the terminal to the SM5100B modem
  while (Serial.available() > 0)
  {
    // If the character is CTRL-Z then set a flag we will check later to print the current level to the terminal
    incoming_char = Serial.read();
    if (incoming_char == 0x1A)
    {
      printLevelToTerminal = true;
    }
    else
    {
      modem.print(incoming_char);
    }
  }
}

Thanks in advance.
island219

// Create a "soft" serial port on pins 6(RX) and 7(TX)
SoftwareSerial modem(2,3);  //Create a 'fake' serial port. Pin 2 is the Rx pin, pin 3 is the Tx pin.

There is nothing fake about a software serial port. Any example that suggests that the software serial is somehow less than real should be left in the dustbin.

  // Test the level again to check it's valid.
  sampleLevel();

How can you do something again until you've done it once?

boolean checkForAlarm(void)
{
  return ( Serial.println(analogRead(VAL_PROBE)) >= SENSOR_DRY);
}

Serial.println() does not return a boolean. Returning the number of characters that were sent to the serial port as a boolean is stupid.

const int VAL_PROBE = 0; // Moisture Sensor 1.
  int moisture = analogRead(VAL_PROBE);
  p->print("Water Level: ");
  Serial.println(analogRead(0));

If nothing else, you should be consistent. If you need to move the moisture sensor to another pin, you have a lot of work to do. You should need to change only one line of code.

It verifies fine, but errors occur when I run it through "Simulator for Arduino" from arduino.com.au.

I never was very good at guessing games. What errors?