Hello guys, need some help!

Hi guys,

What i want to do is, from 2 temp sensors get the average value and according to that value move a servo motor.At the maximum temperature i also open a relay (fan).

However sometimes my serial print shows -52.40 celcius more or less making my servo move back a position, but the reading from the temp sensors is fine!

Serial print :

Requesting temperatures...DONE
Temperature for Device 1 is: 21.94
Temperature for Device 2 is: 22.37
Average temp is...-52.31

Requesting temperatures...DONE
Temperature for Device 1 is: 22.00
Temperature for Device 2 is: 22.37
Average temp is...-52.28


etc .. etc...

My code is as follows :

#include <Servo.h>
#include <OneWire.h>
#include <DallasTemperature.h>

int DS18S20_Pin = 3;        // Set temperature sensor in pin 0
int thresholdcold = 21;     // Threshold for cold temperature
int thresholdhot = 23;      // Threshold for hot temperature
int thresholdnormal =22;   // Threshold for normal temperature
int servocold = 174;        // Angle in which servo will go to
int servohot = 0;           // Angle in which servo will go to
int servonormal = 80;       // Angle in which servo will go to
int previousPosition = 80;
int ServoDelay = 30;        // Servo delay
int led = 13;
int Relay_Pin = 12;

Servo servo1;

float Temp1=0;
float Temp2=0;
float AverageTemp=0;
 


// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 3

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

void setup(void)
{
  Serial.begin(9600); // Begin communicating with computer
  
  Serial.println("Dallas Temperature IC Control Library Demo");
 
  servo1.attach(9); // Attaches servo to specified pin
  
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
 
}

void loop(void) {
  
 // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");
  
  Serial.print("Temperature for Device 1 is: ");
  Serial.println(sensors.getTempCByIndex(1)); // Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire
  
  Serial.print("Temperature for Device 2 is: ");
  Serial.println(sensors.getTempCByIndex(0));
  
  delay(1000);
  

  Temp1=sensors.getTempCByIndex(1);             //Store sensor 1 value
  Temp2=sensors.getTempCByIndex(0);             //Store sensor 2 value
  
  AverageTemp= (Temp1 + Temp2) / 2;             //Average value of sensor 1 & sensor 2
  
  Serial.print("Average temp is...");
  Serial.println (AverageTemp);
  
 // if (Temp1 > 23 || Temp2 > 23 ){              
    
 //  digitalWrite(led, HIGH);                                                        // Testing spikes
    
 //   Serial.println ("ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
 // }
  

  
  
  if(AverageTemp <= thresholdcold) // If temperature is above the threshold, activate sequence
  {
   
	if (servocold != previousPosition){
  
   for(previousPosition != 0; previousPosition < servocold; previousPosition += 1)  // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    servo1.write(previousPosition);              // tell servo to go to position in variable 'pos' 
    delay(ServoDelay);                       // waits 15ms for the servo to reach the position 
  } 
  
        	servo1.write(servocold);
		previousPosition = servocold;
		}
  }
 
  else if(AverageTemp >= thresholdhot) // If temperature is above the threshold, activate sequence
  {
  
		if (servohot != previousPosition){
  
  for(previousPosition != thresholdhot; previousPosition -= 1;)  // goes from 0 degrees to 180 degrees 
  {                                                                                     // in steps of 1 degree 
    servo1.write(previousPosition);              // tell servo to go to position in variable 'pos' 
    delay(ServoDelay);                       // waits 15ms for the servo to reach the position 
  } 
	    servo1.write(servohot);
		previousPosition = servohot;


		}

      digitalWrite(led, HIGH);
      digitalWrite(Relay_Pin, HIGH);
  }
 
 
 
 
 
  else if(AverageTemp >= thresholdnormal) // If Fract is above the threshold, activate sequence
  {
   
	while (previousPosition != servonormal){
  
  if (previousPosition < servonormal)  // goes from 0 degrees to 180 degrees 
  {                                                                                     // in steps of 1 degree 
    servo1.write(previousPosition++) ;             // tell servo to go to position in variable 'pos' 
    delay(ServoDelay);                       // waits 15ms for the servo to reach the position 
  } 
  
  else  // goes from 0 degrees to 180 degrees 
  {                                                                                     // in steps of 1 degree 
    servo1.write(previousPosition--);              // tell servo to go to position in variable 'pos' 
    delay(ServoDelay);                       // waits 15ms for the servo to reach the position 
  } 
	    servo1.write(servonormal);

		//previousPosition = servonormal;

                digitalWrite(led, LOW);
                digitalWrite(Relay_Pin, LOW);
		}

      
  }
}

So... any help would be greatly appreciated!! thanks!

  Temp1=sensors.getTempCByIndex(1);             //Store sensor 1 value
  Temp2=sensors.getTempCByIndex(0);             //Store sensor 2 value

Why aren't these the values you print?

Theomv:
My code is as follows :

 // call sensors.requestTemperatures() to issue a global temperature 

// request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");
 
  Serial.print("Temperature for Device 1 is: ");
  Serial.println(sensors.getTempCByIndex(1)); // Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire
 
  Serial.print("Temperature for Device 2 is: ");
  Serial.println(sensors.getTempCByIndex(0));
 
  delay(1000);
 
  Temp1=sensors.getTempCByIndex(1);             //Store sensor 1 value
  Temp2=sensors.getTempCByIndex(0);             //Store sensor 2 value
 
  AverageTemp= (Temp1 + Temp2) / 2;             //Average value of sensor 1 & sensor 2
 
  Serial.print("Average temp is...");
  Serial.println (AverageTemp);

Looks like you are getting different results after the 1-second delay. Try printing out the values you get after the delay to see if the match the average.

Hi , thanks for the help.

It does print out the correct average.

Requesting temperatures...DONE
Temperature for Device 1 is: 21.94
Temperature for Device 2 is: 22.37
Average temp is...22.12

Requesting temperatures...DONE
Temperature for Device 1 is: 21.94
Temperature for Device 2 is: 22.31
Average temp is...22.09

But sometimes , lets say once every 3 minutes it prints

Requesting temperatures...DONE
Temperature for Device 1 is: 21.94
Temperature for Device 2 is: 22.37
Average temp is...-52.53

Do you think that has to do with the delay?

Your output would seem to imply that there is some problem with your averaging algorithm since the printed average is obviously on the average of the two printed sensor values. However this is misleading since you are not printing the inputs to the averaging algorithm, you are printing the results from a previous sensor reading and then average subsequent sensor readings. Try printing the inputs to the average and see what you get. My guess is that you have glitches in your sensor readings.

AverageTemp= (Temp1 + Temp2) / 2.0f; //Average value of sensor 1 & sensor 2

Try to force the divider to also be a float using 2.0f;

Ok, first things first , i tried what johnwasser said about the delay thing, and it seems to work, for now at least. I'll give it some extra time and check back with you guys! thanks!

Hi, how are you supplying the servo with power, if from the Arduino this could be causing the intermittent problem.

The servo can overload the 5V supply in the Arduino, in all cases it is suggested that the servo be powered from a separate supply.

Tom.. :slight_smile:

Can you post a CAD or picture of a hand drawn circuit diagram please, even a picture of your project if possible.

Ok, just to check back with my info in case others have similar problems,

I used the delay after the results as suggested and it didnt work.

I used the AverageTemp= (Temp1 + Temp2) / 2.0f; and from yesterday night i didnt have any problems so far!

So thanks to HugoPT for his suggestion and the others of course.

If that doesnt work also i will check back with you again!

Thanks guys!

I tried all the proposed solutions to no avail unfortunately...

I also tried to power my arduino using an external power supply.. that didn't work either..

I also did my code way much simpler!

#include <Servo.h>
#include <OneWire.h>
#include <DallasTemperature.h>

int DS18S20_Pin = 2;        // Set temperature sensor in pin 0
int thresholdcold = 21;     // Threshold for cold temperature
int thresholdhot = 23;      // Threshold for hot temperature
int thresholdnormal =22;   // Threshold for normal temperature
int servocold = 174;        // Angle in which servo will go to
int servohot = 0;           // Angle in which servo will go to
int servonormal = 80;       // Angle in which servo will go to
int previousPosition = 80;
int ServoDelay = 30;        // Servo delay
int led = 13;
int Relay_Pin = 12;

Servo servo1;

float Temp1;
float Temp2;
float AverageTemp;
 


// Data wire is plugged into pin 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices (not just Maxim/Dallas temperature ICs)
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

void setup(void)
{
  Serial.begin(9600); // Begin communicating with computer
  
  Serial.println("Dallas Temperature IC Control Library Demo");
 
  servo1.attach(9); // Attaches servo to specified pin
  
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
 
}

void loop(void) {
  
  
float Temp1 = sensors.getTempCByIndex(1) ;
float Temp2 = sensors.getTempCByIndex(0) ;
float AverageTemp = (Temp1 + Temp2) / 2.0f; ;
  
 // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");
  
  Serial.print("Temperature for Device 1 is: ");
  Serial.println(Temp1); // Why "byIndex"? You can have more than one IC on the same bus. 0 refers to the first IC on the wire
  
  Serial.print("Temperature for Device 2 is: ");
  Serial.println(Temp2);
  
  

 
  Serial.print("Average temp is...");
  Serial.println (AverageTemp);
  
  delay(1000);
  
 // if (Temp1 > 23 || Temp2 > 23 ){              
    
 //  digitalWrite(led, HIGH);                                                        // Testing spikes
    
 //   Serial.println ("ERROR!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
 // }
  

  
  
  if(AverageTemp <= thresholdcold) // If temperature is above the threshold, activate sequence
  {
   
	if (servocold != previousPosition){
  
   for(previousPosition != 0; previousPosition < servocold; previousPosition += 1)  // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    servo1.write(previousPosition);              // tell servo to go to position in variable 'pos' 
    delay(ServoDelay);                       // waits 15ms for the servo to reach the position 
  } 
  
        	servo1.write(servocold);
		previousPosition = servocold;
		}
  }
 
  else if(AverageTemp >= thresholdhot) // If temperature is above the threshold, activate sequence
  {
  
		if (servohot != previousPosition){
  
  for(previousPosition != thresholdhot; previousPosition -= 1;)  // goes from 0 degrees to 180 degrees 
  {                                                                                     // in steps of 1 degree 
    servo1.write(previousPosition);              // tell servo to go to position in variable 'pos' 
    delay(ServoDelay);                       // waits 15ms for the servo to reach the position 
  } 
	    servo1.write(servohot);
		previousPosition = servohot;


		}

      digitalWrite(led, HIGH);
      digitalWrite(Relay_Pin, HIGH);
  }
 
 
 
 
 
  else if(AverageTemp >= thresholdnormal) // If Fract is above the threshold, activate sequence
  {
   
	while (previousPosition != servonormal){
  
  if (previousPosition < servonormal)  // goes from 0 degrees to 180 degrees 
  {                                                                                     // in steps of 1 degree 
    servo1.write(previousPosition++) ;             // tell servo to go to position in variable 'pos' 
    delay(ServoDelay);                       // waits 15ms for the servo to reach the position 
  } 
  
  else  // goes from 0 degrees to 180 degrees 
  {                                                                                     // in steps of 1 degree 
    servo1.write(previousPosition--);              // tell servo to go to position in variable 'pos' 
    delay(ServoDelay);                       // waits 15ms for the servo to reach the position 
  } 
	    servo1.write(servonormal);

		//previousPosition = servonormal;

                digitalWrite(led, LOW);
                digitalWrite(Relay_Pin, LOW);
		}

      
  }
}

Now when the fault occurs my serial print looks like this

Requesting temperatures...DONE
Temperature for Device 1 is: 22.25
Temperature for Device 2 is: -127.00
Average temp is...-52.38

nothing seems to work

Maybe i have a faulty sensor?

do you have any more suggestions? Thanks!

-127 is a suspicious number (0xFF00 was received from the device). Does the library check the CRC on the data? See if you can do a CRC check to see if this is a data transmit error or a fault in the sensor.

DavidOConnor:
-127 is a suspicious number (0xFF00 was received from the device). Does the library check the CRC on the data? See if you can do a CRC check to see if this is a data transmit error or a fault in the sensor.

At this point it is taking me too long to figure out what is the exact problem :confused:

Is there a code that i can use that i can ignore those values?

You can check the CRC to see if you have valid data. Or you can buy a third sensor and do a median select on the three temperature values.

Hi, my post #7, asked how you were powering the servo, and a circuit diagram please.
If you are using the 5V pin on the arduino, it possibly could cause your problem.
HOW ARE YOU SUPPLYING POWER TO THE SERVO, and a circuit diagram PLEASE.

Tom..... :slight_smile:

-127 is the error code for "DEVICE_DISCONNECTED". Sounds like a wiring or electrical problem.

float Temp1 = sensors.getTempCByIndex(1) ;
float Temp2 = sensors.getTempCByIndex(0) ;
float AverageTemp = (Temp1 + Temp2) / 2.0f; ;
  
 // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  Serial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  Serial.println("DONE");

Get the temperatures, then ask the devices to get ready to report temperatures. You've got the cart on the wrong end of the horse. No wonder you keep stepping in shit.

Ok guys i've been very busy to understand the solution to my problem... I used a code which seems to work... Dont know yet, i have to test it for a few days.

#include <Servo.h>
#include <OneWire.h>
#include <DallasTemperature.h>

int DS18S20_Pin = 2;        // Set temperature sensor in pin 0
int thresholdcold = 21;     // Threshold for cold temperature
int thresholdhot = 24;      // Threshold for hot temperature
int thresholdnormal =22;   // Threshold for normal temperature
int servocold = 174;        // Angle in which servo will go to
int servohot = 0;           // Angle in which servo will go to
int servonormal = 80;       // Angle in which servo will go to
int previousPosition = 80;
int ServoDelay = 30;        // Servo delay
int led = 13;
int Relay_Pin = 12;
OneWire ds(DS18S20_Pin);

unsigned long Time = (millis()/1000);

Servo servo1;


 
#define ONEWIREPIN 2	/* OneWire bus on digital pin 7 */
#define MAXSENSORS 2	/* Maximum number of sensors on OneWire bus */
 
// Model IDs
#define DS18S20 0x10
#define DS18B20 0x28
#define DS1822 0x22
 
// OneWire commands
#define CONVERT_T 0x44 // Tells device to take a temperature reading and put it on the scratchpad
#define COPYSCRATCH 0x48 // Copy EEPROM
#define READSCRATCH 0xBE // Read EEPROM
#define WRITESCRATCH 0x4E // Write to EEPROM
#define RECALLSCRATCH 0xB8 // Reload from last known
#define READPOWERSUPPLY 0xB4 // Determine if device needs parasite power
#define ALARMSEARCH 0xEC // Query bus for devices with an alarm condition
 
class Sensor /* hold info for a DS18 class digital temperature sensor */
{
public:
byte addr[8];
boolean parasite;
float temp;
 
};
 
 
int HighByte, LowByte, TReading, SignBit, Tc_100;
byte i, j, sensors;
byte present = 0;
boolean ready;
int dt;
byte data[12];
byte addr[8];
//OneWire ds(ONEWIREPIN);	// DS18S20 Temperature chip i/o
Sensor DS[MAXSENSORS];	/* array of digital sensors */
 
 
 
 
void setup(void) {
// initialize inputs/outputs
// start serial port
Serial.begin(9600);


  servo1.attach(9); // Attaches servo to specified pin
  
  pinMode(13, OUTPUT);
  pinMode(12, OUTPUT);
 


sensors = 0;
Serial.println("Searching for sensors...");
while ( ds.search(addr)) {
if ( OneWire::crc8( addr, 7) != addr[7]) {
Serial.print("CRC is not valid!\n");
break;
}
delay(1000);
ds.write(READPOWERSUPPLY);
boolean parasite = !ds.read_bit();
present = ds.reset();
Serial.print("temp");
Serial.print(sensors,DEC);
Serial.print(": ");
DS[sensors].parasite = parasite;
for( i = 0; i < 8; i++) {
DS[sensors].addr[i] = addr[i];
Serial.print(addr[i], HEX);
Serial.print(" ");
}
//Serial.print(addr,HEX);
if ( addr[0] == DS18S20) {
Serial.print(" DS18S20");
}
else if ( addr[0] == DS18B20) {
Serial.print(" DS18B20");
}
else {
Serial.print(" unknown");
}
if (DS[sensors].parasite) {Serial.print(" parasite");} else {Serial.print(" powered");}
Serial.println();
sensors++;
}
Serial.print(sensors,DEC);
Serial.print(" sensors found");
Serial.println();
for (i=0; i<sensors; i++) {
Serial.print("temp");
Serial.print(i,DEC);
if (i<sensors-1) {
Serial.print(",");
}
}
Serial.println();
 
}
 
void get_ds(int sensors) {	/* read sensor data */
for (i=0; i<sensors; i++) {
ds.reset();
ds.select(DS[i].addr);
ds.write(CONVERT_T,DS[i].parasite);	// start conversion, with parasite power off at the end
 
if (DS[i].parasite) {
dt = 75;
delay(750); /* no way to test if ready, so wait max time */
} else {
ready = false;
dt = 0;
delay(10);
while (!ready && dt<75) {	/* wait for ready signal */
delay(10);
ready = ds.read_bit();
dt++;
}
}
 
present = ds.reset();
ds.select(DS[i].addr);
ds.write(READSCRATCH); // Read Scratchpad
for ( j = 0; j < 9; j++) { // we need 9 bytes
data[j] = ds.read();
}
 
/* check for valid data */
if ( (data[7] == 0x10) || (OneWire::crc8( addr, 8) != addr[8]) ) {
LowByte = data[0];
HighByte = data[1];
TReading = (HighByte << 8) + LowByte;
SignBit = TReading & 0x8000; // test most sig bit
if (SignBit) // negative
{
TReading = (TReading ^ 0xffff) + 1; // 2's comp
}
if (DS[i].addr[0] == DS18B20) { /* DS18B20 0.0625 deg resolution */
Tc_100 = (6 * TReading) + TReading / 4; // multiply by (100 * 0.0625) or 6.25
}
else if ( DS[i].addr[0] == DS18S20) { /* DS18S20 0.5 deg resolution */
Tc_100 = (TReading*100/2);
}
 
 
if (SignBit) {
DS[i].temp = - (float) Tc_100 / 100;
} else {
DS[i].temp = (float) Tc_100 / 100;
}
} else {	/* invalid data (e.g. disconnected sensor) */
DS[i].temp = NAN;
}
}
}
 
void loop(void) {
  float temp;
  
  


  
  
  
  
  
  
get_ds(sensors);
for (i=0; i<sensors; i++) {
if (isnan(DS[i].temp)) {
Serial.print("NaN");
} else {
Serial.print(DS[i].temp,2);

}
if (i<sensors-1) {
Serial.print(",");
}
}
Serial.println();

float AverageTemp = ((DS[0].temp) + (DS[1].temp)) / 2.0f ;

Serial.print("Average Temp is :  ");
Serial.println ( AverageTemp);
delay(5000);


  if(AverageTemp <= thresholdcold) // If temperature is above the threshold, activate sequence
  {
   
	if (servocold != previousPosition){
  
   for(previousPosition != 0; previousPosition < servocold; previousPosition += 1)  // goes from 0 degrees to 180 degrees 
  {                                  // in steps of 1 degree 
    servo1.write(previousPosition);              // tell servo to go to position in variable 'pos' 
    delay(ServoDelay);                       // waits 15ms for the servo to reach the position 
  } 
  
        	servo1.write(servocold);
		previousPosition = servocold;
		}
  }
 
  else if(AverageTemp >= thresholdhot) // If temperature is above the threshold, activate sequence
  {
  
		if (servohot != previousPosition){
  
  for(previousPosition != thresholdhot; previousPosition -= 1;)  // goes from 0 degrees to 180 degrees 
  {                                                                                     // in steps of 1 degree 
    servo1.write(previousPosition);              // tell servo to go to position in variable 'pos' 
    delay(ServoDelay);                       // waits 15ms for the servo to reach the position 
  } 
	    servo1.write(servohot);
		previousPosition = servohot;


		}

      digitalWrite(led, HIGH);
      digitalWrite(Relay_Pin, HIGH);
  }
 
 
 

 
 
  else if(AverageTemp >= thresholdnormal) // If Fract is above the threshold, activate sequence
  {
   
	while (previousPosition != servonormal){
  
  if (previousPosition < servonormal)  // goes from 0 degrees to 180 degrees 
  {                                                                                     // in steps of 1 degree 
    servo1.write(previousPosition++) ;             // tell servo to go to position in variable 'pos' 
    delay(ServoDelay);                       // waits 15ms for the servo to reach the position 
  } 
  
  else  // goes from 0 degrees to 180 degrees 
  {                                                                                     // in steps of 1 degree 
    servo1.write(previousPosition--);              // tell servo to go to position in variable 'pos' 
    delay(ServoDelay);                       // waits 15ms for the servo to reach the position 
  } 
	    servo1.write(servonormal);

		//previousPosition = servonormal;

                digitalWrite(led, LOW);
                digitalWrite(Relay_Pin, LOW);
		}

  }   
  
  
 }

Cause this is overly complex for me, when i test the program and i disconnect one sensor my serial print says -0.06:

23.18,22.81
Average Temp is :  22.99
23.25,22.81
Average Temp is :  23.03
[b]-0.06[/b],22.87
Average Temp is :  11.41
28.37,23.25
Average Temp is :  25.81
25.93,23.06
Average Temp is :  24.49

Is that correct? Shouldnt it say Invalid CRC or something? If this is normal what can i do to print out to me that a sensor is disconnected?

Nice
job
on
the
indenting.

Theomv:
Is that correct? Shouldnt it say Invalid CRC or something? If this is normal what can i do to print out to me that a sensor is disconnected?

Well, you calculate the number of attached sensors when you start up and display that number. Then you read all the attached sensors into an array that can hold 2 sensors (which will cause memory overwrite problems if you ever have more than 2 sensors attached). Then you average the first two sensors, even is one of them doesn't exist. Naturally you will get incorrect answers.

If you find that only one sensor is attached you should fail at that point rather than going on to average two sensors.