Go Down

Topic: A helping hand required - Noob needs some sketching advice.. (Read 5734 times) previous topic - next topic

wildbill

Try this:
Code: [Select]

int Sonar()
{
delay(100);
int uS = sonar.ping_median(10);
Distance = (uS / US_ROUNDTRIP_CM);
if(Distance <= Tank_Full)
  {
  purge();
  }
}

void purge()
{
digitalWrite(Relay_1, RELAY_ON);
delay(50);                      // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
do
  {
  unsigned int uS = sonar.ping_median(10); // Send 10 pings and return median, get ping time in microseconds (uS).
  Distance=(uS / US_ROUNDTRIP_CM);
  Serial.print("Tank Purging ... Height ");
  Serial.print(Distance);
  Serial.println("cm");
  delay(100);
  }
while(Distance < Tank_Empty);

digitalWrite(Relay_1, RELAY_OFF);  // Shut the Valve before returning...
Serial.println("Valve Closed");
}

It doesn't take care of the ten minute requirement, but I'm not sure it needs to - the purge only happens when the tank is full.

UKHeliBob

Quote
The Alarms library is great, but you should be sure to check the readme file for it.  It has two things that can be gotchas.

First delay() must never be used anywhere in the sketch.  You can only use Alarm.delay() in sketches that incorporate the Alarm library. 
Is this really the case ?  It is true that Alarm.delay() must be called in order for the alarms to be checked but that is not the same as saying that delay() must not be used.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

fpga6

From the Alarms Read Me file:

Quote
Note that the loop code calls Alarm.delay(1000) - Alarm.delay must be used
instead of the usual arduino delay function because the alarms are serviced in the Alarm.delay
method.
Failing to regularly call Alarm.delay will result in the alarms not being triggered so always use
Alarm.delay instead of delay in sketches that use the Alarms library.


Usually the best thing is to have at least one Alarm.delay() in the void loop(), so it is called frequently.

fpga6

I went back to research your comment on the web.  I could not find anything that specifically says the delay() should never be used.  The various documents on the web say the sketch should use Alarm.delay.  So I am not sure if delay() poisons the sketch or not.

As debugging step a long time ago I made sure that there were no delay() functions in any of my sketches, and I have had no trouble since.

When I get some time I will insert some delay()s into one of my sketches and test for reliable operation.

-Night-

Wildbill,

Thanks that is perfect, it looks so simple when you know how..

-Night-

Hi, I have hit my next stumbling block, my knees are getting very sore  :)

So the code below reads the temperature and displays it in the function, but doesn't pass it back to the loop..

Why is that?

Code: [Select]
#include <EEPROM.h> // EEProm Memory Library
#include <LiquidCrystal.h> // LCD Library

float temp;
int tempPin = A1;  // make variables// thermistor is at A1
int settemp = 26; // make a variable called temp
#define Relay_1 42 // Arduino Digital I/O pin number (BioGas Dump Valve)
#define Relay_2 44 // Arduino Digital I/O pin number (Immersion Heater)
#define Relay_3 46 // Arduino Digital I/O pin number (Mixer Drive)
#define Relay_4 48 // Arduino Digital I/O pin number (Spare)
#define RELAY_ON 0  // Define Relay On
#define RELAY_OFF 1 // Define Relay Off
int led =13; // led is at pin

/*
*******************************
****   LIBRARY SETUP HERE  ****
*******************************
*/
LiquidCrystal lcd(7, 8, 9, 10, 11, 12); //Define LCD Pin connections


void setup() {
  Serial.begin(9600);
  analogReference(INTERNAL); //Set internal 1.1v for temperature sensor UNO
  //analogReference(INTERNAL1V1); //Set internal 1.1v for temperature sensor Mega
  EEPROM.write (1,settemp);
  pinMode(13, OUTPUT);
}



void loop(){
  Temperature();
  Serial.print("Current Temperature is ");
  Serial.println(temp);
}

float Temperature() {
  int tvalue = analogRead(tempPin);  // make tvalue what ever we read on the tempPin
  float temp = (tvalue / 9.31); // the math / conversion to temp
  delay (1000); // wait for the lcd to refresh every 250 milliseconds
  if (temp < settemp) // if the temperature is lower
  {
    digitalWrite(Relay_2, RELAY_ON); // turn on the heater
    digitalWrite(led,HIGH);
  }
  else // if that doesn't happen, then turn the heater off
  {
    digitalWrite(Relay_2, RELAY_OFF);
    digitalWrite(led,LOW);
  }
  lcd.setCursor (0,1); // set the cursor to 0,0
  lcd.print ("                    "); // Print set to and your ideal temperature in f
  lcd.setCursor(0,1);
  lcd.print ("Thermostat Set To "); // Print set to and your ideal temperature in f
  lcd.print (settemp);
  lcd.print ('C');
  lcd.setCursor(0,3);
  lcd.print("                    ");
  lcd.setCursor(0,3);
  lcd.print("Temperature= ");
  lcd.print(temp);
  lcd.print("C");
  Serial.print("Temperature = ");
  Serial.print(temp);
  Serial.println("C");
}

UKHeliBob

You are determining the temperature in the Temperature() function, which has been defined as returning a float value but you never return one.

The temp variable declared at the top of the sketch has global scope and is available throughout the program.   The temp variable declared in the Temperature() function is local to that function and its value will not be the same as the global one even though the name is the same.

Two options
1.  Remove the float specifier on the temp variable in the Temperature() function so that it is the global version that holds the value.  On exit from the function the functions in loop() will be able to access the value.  Replace the float specifier of the Temperature() function with void to indicate that it will not be returning a value.

2.  Use a different variable name in the Temperature() function declared as a float.  At the end of the function return the value to the calling line like this
Code: [Select]
return nameOfNewVariable;Then in loop() do this
Code: [Select]
temp = Temperature();
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

wildbill

UKHeliBob's covered the issue, but there's also:

Option 3 - Don't use temp in loop at all and get rid of the global. In this example at least, all your temperature based stuff is happening in the Temperature function, including printing it to serial, so there is no need to reprint it in loop and hence no need to return it or have a global. The other options cover you if the full sketch needs temp elsewhere for other purposes.

Normally when controlling temperature like this, systems try to avoid rapid switching when you're close to the setpoint to avoid excessive mechanical wear on the relay. A simple way involves a dead band around the setpoint so that you only turn on the heat when you're some degrees below the setpoint and turn it off when you're a few above.

-Night-

Thanks Guys...

I realize my sketch contains too much stuff to be tidy, but I have the arduino bug now and curiosity is getting the better of me.

UKHeliBob, both ways work :)  Which would be the standard method used?

Option 2 however gives a different result.

Current Temperature is 20.00 (from the loop)
Temperature = 20.84C (from the function)

Is this something to do with my variable type?


Wildbill, I had considered the heater switching on an off all the time being an issue, however my solution was to run it on an alarm say every 30 mins. However as my programming ability is increasing in leaps and bounds with your help I think I may now set a tolerance of say 3 degrees.

Is there a simple way of writing  this in this condition

if (temp < settemp) // if the temperature is lower

Thanks



wildbill

Quote
Is this something to do with my variable type?

Probably. Did you use an int?

Code: [Select]

const int TemperatureTolerance = 3; // top of your code somewhere
if (temp < settemp-TemperatureTolerance)
  {
  //on
   }
if (temp > settemp+TemperatureTolerance)
  {
  //off
   }




UKHeliBob

There is no real standard way for what you are doing.  Normally you would return a value if it needs to be used by the program that calls the function and it is regarded as good practice to minimise the use of global variables as far as possible to avoid issues such as the one you had where there were 2 different variables with the same name.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Go Up