Controlling a servo position using a temperature sensor

Hello

Excuse me for disturbing you.
Sorry for my English, I'm french and I use google translation

I need help probably like many people.
I am totally new to the Arduino field and I lean over to a PC Mod.

My project is to create cooling fins on the top of my box which open depending on the temperature.
Powered with a servomotor and DS18B20

With no knowledge I tried to merge two programs (knob and DS18x20)
I eased the DS18x20 to display the temperature only

But I blocked for 4 lines
Here is my complete code

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

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)
Servo myservo;  // create servo object to control a servo

int potpin = 0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin

void setup(void) {
  Serial.begin(9600);
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;
 
  if ( !ds.search(addr)) {
    ds.reset_search();
    delay(250);
    return;
  }
   for( i = 0; i < 8; i++) {  
  }
  if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
 
  delay(750);     // maybe 750ms is enough, maybe not
 
  present = ds.reset();
  ds.select(addr);    
  ds.write(0xBE);         // Read Scratchpad
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data[i] = ds.read();
  }
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.println(" Celsius ");
}
{
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  val = map(val, 0, 1023, 0, 180);     // scale it to use it with the servo (value between 0 and 180)
  myservo.write(val);                  // sets the servo position according to the scaled value
  delay(15);                           // waits for the servo to get there
}

And 4 lines that pose worries I think

int potpin = 0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin
val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  val = map(val, 0, 1023, 0, 180);     // scale it to use it with the servo (value between 0 and 180)

I look with digitalRead order, but I have not managed to adapt

I saw another program, but was told that it was not compatible with my hardware
the code

// Controlling a servo position using a temperature sensor
// by Michal Rinott <http://people.interaction-ivrea.it/m.rinott>
// edited 5-12-2010 by Will Lyon to include base setting for servo if voltage not detected on pin 7
// edited again 7-4-2010 by crenn to simplify the code a little
// edited yet again 7-5-2010 by crenn to add features
// edited again 7-21-2010 by Will Lyon - recalibrated servo positions

#include <Servo.h>

Servo myservo;  // create servo object to control a servo

//Constants
const unsigned char CONTROL = 7;  // digital pin used to detect if the system is on or off
const unsigned char temps = 0;    // analog pin used to connect the temp sensor
const unsigned char MAX_VAL = 10;

//Main global varibles
char trigger = 0;     // varible used to store the control pin value
unsigned int val;     // variable to read the value from the analog pin

unsigned int updateAvgtemp(){
  static int history[MAX_VAL]={0};
  static unsigned char lastHist=0;
  static unsigned char numHist=0;
  unsigned int temp=0;
  unsigned char counter=0;
  unsigned char arcount=0;
  history[lastHist] = analogRead(temps);
  if(numHist<MAX_VAL)
    ++numHist;
  arcount=lastHist;
  ++lastHist;
  if(lastHist>=MAX_VAL)
    lastHist=0;
  temp=0;
  counter=0;
  do{
    temp+=history[arcount];
    arcount--;
    if(arcount>MAX_VAL)
      arcount=(MAX_VAL-1);
    counter++;
  }while(counter < numHist);
  return (temp/numHist);
}

void setup()
{
  pinMode (CONTROL, INPUT);   // sets the control pin to input
  myservo.attach(9);      // attaches the servo on pin 9 to the servo object
  digitalWrite(CONTROL, LOW);   // ensure internal pullup resistor is disabled.
}
void loop()
{
  trigger = digitalRead(CONTROL); // read input of pin CONTROL  and store it
  if (trigger == HIGH){     // reads if pin CONTROL, if true, do this:
    val = updateAvgtemp();    // read the value of the temp sensor (value with range of 1024)
    val = map(val, 350, 700, 160, 80);  // scale it to use it with the servo (value between 160 and 80)
    myservo.write(val);     // sets the servo position according to the scaled value
  }
  else {
    myservo.write(180);     // sets servo position to 180 if above statment is false
  }
  delay(125);               // wait 25ms for the servo to move to it's new position and also 100ms until it gets the new value
}

Thank you in advance for your help

At what temperature should the fins be at minimum opening?
" " " " " " " " Maximum " ?

Forget the second program, its for an analog sensor, DS18B20 is digital.

Sorry for my English, I'm french and I use google translation

Why don't you post in the French section, then?

hi PaulS

I use the English section because it includes more world. Thus more knowledge and more possibility of answer :slight_smile:

Hi Outsider

Thank you to answer so fast and for your help

The room where is the made computer 20°C on average
thus the best would be 15 in 20°C a minimal opening of 20 °
Then an increasing openness
For a maximum of 90°C and an opening of 80 or 70 °

after I guess I can settle this with the line map?

In any case thank you again for your help

up pls

  for( i = 0; i < 8; i++) 
  { 
  }

What is this for? Do nothing 8 times? Why?

{
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  val = map(val, 0, 1023, 0, 180);     // scale it to use it with the servo (value between 0 and 180)
  myservo.write(val);                  // sets the servo position according to the scaled value
  delay(15);                           // waits for the servo to get there
}

This is not in any function. The code you posted won't even compile. It is silly to talk about adding functionality to code that won't even compile.

Aside from that, you haven't explained what you are having problems with.

Good question, you are the expert, not me

The first line is in program DS18x20
Serial.print("ROM =");
for( i = 0; i < 8; i++) {
Serial.write(' ');
Serial.print(addr*, HEX);*
```
*// OneWire DS18S20, DS18B20, DS1822 Temperature Example
//
// OneWire Arduino Library, connecting 1-wire devices (DS18S20, etc) to Teensy
//
// The DallasTemperature library can do all this work for you!
// MilesBurton.com

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)

void setup(void) {
  Serial.begin(9600);
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
 
  if ( !ds.search(addr)) {
    Serial.println("No more addresses.");
    Serial.println();
    ds.reset_search();
    delay(250);
    return;
  }
 
  Serial.print("ROM =");
  for( i = 0; i < 8; i++) {
    Serial.write(' ');
    Serial.print(addr[i], HEX);
  }

if (OneWire::crc8(addr, 7) != addr[7]) {
      Serial.println("CRC is not valid!");
      return;
  }
  Serial.println();

// the first ROM byte indicates which chip
  switch (addr[0]) {
    case 0x10:
      Serial.println("  Chip = DS18S20");  // or old DS1820
      type_s = 1;
      break;
    case 0x28:
      Serial.println("  Chip = DS18B20");
      type_s = 0;
      break;
    case 0x22:
      Serial.println("  Chip = DS1822");
      type_s = 0;
      break;
    default:
      Serial.println("Device is not a DS18x20 family device.");
      return;
  }

ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end
 
  delay(1000);    // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
 
  present = ds.reset();
  ds.select(addr);   
  ds.write(0xBE);        // Read Scratchpad

Serial.print("  Data = ");
  Serial.print(present, HEX);
  Serial.print(" ");
  for ( i = 0; i < 9; i++) {          // we need 9 bytes
    data[i] = ds.read();
    Serial.print(data[i], HEX);
    Serial.print(" ");
  }
  Serial.print(" CRC=");
  Serial.print(OneWire::crc8(data, 8), HEX);
  Serial.println();

// Convert the data to actual temperature
  // because the result is a 16 bit signed integer, it should
  // be stored to an "int16_t" type, which is always 16 bits
  // even when compiled on a 32 bit processor.
  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; // 9 bit resolution default
    if (data[7] == 0x10) {
      // "count remain" gives full 12 bit resolution
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time
  }
  celsius = (float)raw / 16.0;
  fahrenheit = celsius * 1.8 + 32.0;
  Serial.print("  Temperature = ");
  Serial.print(celsius);
  Serial.print(" Celsius, ");
  Serial.print(fahrenheit);
  Serial.println(" Fahrenheit");*
* *the second extract is from Knob* *
/
Controlling a servo position using a potentiometer (variable resistor)
by Michal Rinott http://people.interaction-ivrea.it/m.rinott

modified on 8 Nov 2013
by Scott Fitzgerald
http://www.arduino.cc/en/Tutorial/Knob
*/

#include <Servo.h>

Servo myservo;  // create servo object to control a servo

int potpin = 0;  // analog pin used to connect the potentiometer
int val;    // variable to read the value from the analog pin

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop() {
  val = analogRead(potpin);            // reads the value of the potentiometer (value between 0 and 1023)
  val = map(val, 0, 1023, 0, 180);    // scale it to use it with the servo (value between 0 and 180)
  myservo.write(val);                  // sets the servo position according to the scaled value
  delay(15);                          // waits for the servo to get there
}*
```
As said in the first post I'm new this is my first programming.
With no knowledge I tried to mix the Knob and DS18x20 program to realize the project I explained above
And thank you for the information
I already know that the code does not compile ...
Just as I do not ask to add features
My question is on the 4 lines quoted
I suspect that it does not work with analog potentiometer in the program off with my digital sensor
but how can I make a cross product as with the map function between my sensor and my servomotor?

The first line is in program DS18x20

Where something happens in the for loop. Nothing happens in your for loop.

the second extract is from Knob

Where the code is inside the loop function.

You need to understand what the code is doing before you copy/paste it and before you leave stuff out.

My question is on the 4 lines quoted
I suspect that it does not work with analog potentiometer in the program off with my digital sensor

Once again, you are talking about code that won't even compile working, or not working. That is nonsense.

Pay some attention to the code you started from. Print both programs out. Study the reference page and the code. Draw boxes around block of code that need to stay together. Understand where those blocks of code are, and need to be when combined.

There is NO reason at all that you can't read digital and analog pins in the same sketch.

and this program?

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Servo.h>
// Data wire is plugged into port 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) DallasTemperature sensors(&oneWire);
// Pass our oneWire reference to Dallas Temperature.
OneWire oneWire(ONE_WIRE_BUS); 
       
Servo myservo;                                          // create servo object to control a servo   
int pos = 0;                                                // variable to store the servo position


void setup(void)
{   
Serial.begin(9600);                                 // start serial port   
sensors.begin();                                     // Start up the library   
myservo.attach(9);                                 // attaches the servo on pin 9 to the servo object
}


void loop(void)
{   
sensors.requestTemperatures();                      // Send the command to get temperatures   
Serial.println(sensors.getTempCByIndex(0));  // prints recieved Temp in C from digitial sensor   
pos = ((sensors.getTempCByIndex(0))-30);    // variable to store the read temperature in C subtract 30 so servo stays in range   
myservo.write(pos);                                         // tell servo to go to position in variable 'pos'     
delay(25);                                                      // waits 25ms for the servo to reach the position
}

and this program?

Look, you have the damned IDE. YOU try compiling your code. No, it still won't compile.

sorry

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Servo.h>
 
// Data wire is plugged into port 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);
Servo myservo;                                          // create servo object to control a servo   
int pos = 0;                                                // variable to store the servo position
 
void setup(void)
{
  // start serial port
  Serial.begin(115200);
  Serial.println("Dallas Temperature IC Control Library Demo");
 
  // Start up the library
  sensors.begin();
}
 
void loop(void)
{ 
  // call sensors.requestTemperatures() to issue a global temperature 
  // request to all devices on the bus
  sensors.requestTemperatures(); // Send the command to get temperatures
 
  Serial.print("Temperature : ");
  Serial.println(sensors.getTempCByIndex(0));  
  pos = ((sensors.getTempCByIndex(0))-30);    // variable to store the read temperature in C subtract 30 so servo stays in range   
  myservo.write(pos);                                         // tell servo to go to position in variable 'pos'     
  delay(25);                                                      // waits 25ms for the servo to reach the position
}

Did you have a question? Does the code do what you want?

Pgm compiles & runs OK on IDE 1.6.5, you may want to constrain pos to 20 - 80 with:

pos = constrain(sensors.getTempCByIndex(0)-30,20,80);    // variable to store the read temperature in C subtract 30 so servo stays in range

Also slow down with:

delay (2000);

thank you very much for your help

I do have a problem
during the temperature reading
the servo does not move with little gap of temperature
but it creates a noise (I guess not good for the servo)

I read that the map function, gives no decimal
do you think that this program is better?
this could possibly eliminate the micro movement that give that sound?

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Servo.h>
 
#define ONE_WIRE_BUS 2
 
OneWire oneWire(ONE_WIRE_BUS);
  
DallasTemperature sensors(&oneWire);
Servo myservo;                                         
int val;                                              
 
void setup(void)
{
  Serial.begin(9600);
  sensors.begin();
  myservo.attach(9);   
}
 
void loop(void)
{ 
  sensors.requestTemperatures(); 
 
  Serial.print("Temperature : ");
  Serial.println(sensors.getTempCByIndex(0));  
  val = (sensors.getTempCByIndex(0));       
  val = map(val, 0, 100, 15, 80);
  myservo.write(val);                                              
  delay(5000);                                                      
}

but it creates a noise (I guess not good for the servo)

It doesn't really hurt the servo. It happens because you have told the servo to move, so it needs to see if it is where it should be. Hobby servos are not terribly accurate, so the motor will move a tiny amount back and forth, seeking the new position.

I read that the map function, gives no decimal

It returns an int. The term you are looking for is float, not decimal.

To eliminate the movement, don't tell the servo to move unless the temperature has changed. To know that, you'll need to keep track of the last temperature that caused the servo to move.

I tried with

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Servo.h>
 
#define ONE_WIRE_BUS 2
 
OneWire oneWire(ONE_WIRE_BUS);
 
DallasTemperature sensors(&oneWire);
Servo myservo;                                         
int val;                                             
 
void setup(void)
{
  Serial.begin(9600);
  sensors.begin();
  myservo.attach(9);   
}
 
void loop(void)
{
  sensors.requestTemperatures();
 
  Serial.print("Temperature : ");
  Serial.println(sensors.getTempCByIndex(0));
  if (sensors.getTempCByIndex(0)!= sensors.getTempCByIndex(0))
{
  val = (sensors.getTempCByIndex(0));       
  val = map(val, 15, 40, 15, 80);
  myservo.write(val);                                             
  delay(750);                                                     
}
}

and

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

#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS);

DallasTemperature sensors(&oneWire);
Servo myservo;
int val;

void setup(void)
{
  Serial.begin(9600);
  sensors.begin();
  myservo.attach(9);
}

void loop(void)
{
  static float tempPrec=0;
  float temp;
  sensors.requestTemperatures();

  temp=sensors.getTempCByIndex(0);

  Serial.print("Temperature : ");
  Serial.println(sensors.getTempCByIndex(0));
  if (temp != tempPrec)
  {
    val = map(temp, 15, 40, 15, 80);
    myservo.write(val);
  }
  tempPrec=temp;
  delay(750);
}

but I always have vibration in the servo :slightly_frowning_face:

but I always have vibration in the servo

How are you powering the servo?

with usb

coproxo:
with usb

When you use a proper power supply, I suspect that your problems will go away.

I found it in my drawers

its good?

http://www.cowcotland.com/album-image9761.html