Home thermometer using a servo

Hi, can anybody help me with my thermometer code, please? My sketch works fine and uses a servo, with an attached pointer indicating the room temperature. However, I want to alter the scale to read from a minimum of 10c to a maximum of 30c. Can anybody help me
with coding please, so I can expand the min/max scaling? my existing code as follows:-

/*  Atmega 328  (Nano)
 *  sensor type DS18B20
 *  22/01/2024
 */

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

const int SERVO_PIN  = 5; // Arduino pin connected to Servo Motor's pin
const int SENSOR_PIN = 2; // Arduino pin connected to DS18B20 sensor's DATA pin
const float TEMPERATURE_THRESHOLD = 30; // °C  20

Servo servo; // create servo object to control a servo
OneWire oneWire(SENSOR_PIN);         // setup a oneWire instance
DallasTemperature sensor(&oneWire); // pass oneWire to DallasTemperature library
float temperature;
float servoposraw;
float servopos;


void setup() {
  Serial.begin(9600);      // initialize serial
  servo.attach(SERVO_PIN); // attaches the servo on pin 5 to the servo object,  pin 5?  servo.write(0);
  servo.write(0);
  sensor.begin();          // initialize the sensor
}

void loop() {
  delay(1000);
  sensor.requestTemperatures();             // send the command to get temperatures
  temperature = sensor.getTempCByIndex(0);  // read temperature in Celsius
  servoposraw =(180./60.)*temperature;
  servopos = 180 - servoposraw;
  servo.write(servopos);
  Serial.println(servopos);
  Serial.print("Temperature: ");
  Serial.print(temperature);
  Serial.print("°C => servo angle: ");
 
}

I didn't quite understand your difficulty, but see if the code below meets your needs.

/*  Atmega 328  (Nano)
    sensor type DS18B20
    22/01/2024
*/

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

const int SERVO_PIN  = 5; // Arduino pin connected to Servo Motor's pin
const int SENSOR_PIN = 2; // Arduino pin connected to DS18B20 sensor's DATA pin
const float TEMPERATURE_THRESHOLD = 30; // °C  20

Servo servo; // create servo object to control a servo
OneWire oneWire(SENSOR_PIN);         // setup a oneWire instance
DallasTemperature sensor(&oneWire); // pass oneWire to DallasTemperature library
float temperature;
float servoposraw;
float servopos;


void setup() {
  Serial.begin(9600);      // initialize serial
  servo.attach(SERVO_PIN); // attaches the servo on pin 5 to the servo object,  pin 5?  servo.write(0);
  servo.write(0);
  sensor.begin();          // initialize the sensor
}

void loop() {
  delay(1000);
  sensor.requestTemperatures();             // send the command to get temperatures
  temperature = sensor.getTempCByIndex(0);  // read temperature in Celsius
  if (temperature >= 10 and temperature <= 30) {
    servoposraw = (180. / 60.) * temperature;
    servopos = 180 - servoposraw;
    servo.write(servopos);
    Serial.println(servopos);
    Serial.print("Temperature: ");
    Serial.print(temperature);
    Serial.print("°C => servo angle: ");
  }
}

You want the 20 degrees of temperature to play out over the 180 degrees of the servo.

You can use map()

    servoAngle = map(temperature, 10, 30, 0, 180;

and you probably want to use constrain()

   servoAngle = constrain(servoAngle, 0, 180);

because map() will cheerfully extrapolate and give servo angles out of range.

Oh, servopos not servoAngle, sry.

HTH

a7

1 Like

Many thanks for your prompt reply, must admit I struggle with code, it took me ages to put my sketch together and compile it to run. Thanks for your help I'll check it out. Regards Jevray

map() is for integers.

What I think @Jevray wants is to replace this line
servoposraw =(180./60.)*temperature;
with this
servoposraw =(180./20.)*(temperature-10);
and you are correct about the range. That can be taken care of thus:

if (servopos < 0) servopos = 0;
if (servopos > 180) servopos = 180;

Thanks for your prompt reply, yes (20 degrees to play out over 180 degrees) I'll check out your snippet of code, I'm not that good when it comes to undestanding and putting together progranning code, now I see the answer I have a much better idea. Thanks again Jevray

Thank you, I'm grateful for the help you guys have come up with, It looks easy when I can see it written down, most helpful, and thanks for replying so quickly. Regards Jevray.

Yes, but you can hand it floats.

I had done, and just now googled

When we pass a float value to a function having int argument, the Implicit typecasting is done here from float to int.


Looks plausible and avoids map(), always a good thing, and uses simple logic instead of constrain().

And... works. There is no roll for servoposraw, it is assigned already conditioned like map() would have done. I used your idea thusly:

  servopos = (180.0 / 20.0) * (temperature - 10.0);

  if (servopos < 0) servopos = 0;
  if (servopos > 180) servopos = 180;

  servo.write(servopos);

map() does make it a little easier to mess with the endpoints and stuff.

a7

Hi, I have put those few lines into my sketch, and it works fine. Thanks for your input.
Regards Jevray

????!!! What about this line
servopos = 180 - servoposraw;
which was used to reverse the direction of the servo?
Without that, @Jevray will have a backwards thermometer!

Yes, my bad. I had @ruilviana's idea and tossed that when I was making yours mine and forgot had missed the reversal line totally.

More fun was when I was sending both version's angle to one servo.

Which was after failing to attach the second servo I was used. Also caused some head scratching.

a7

Hi, hadn't noticed in which direction the servo rotates, as I'm putting a pulley system together for a vertical mode of operation. How do I alter the code to reverse the direction?
I may or may not need to, but just in case. Regards Jevray

This is what makes it go "backwards"

    servopos = 180 - servoposraw;

Simply omit that and increasing temperatures will yield increasing servo angles. Throw some servoposraw numbers on the right hand side of that assignment and watch it reverse.

If you had used map() on temperature you could see it another way

    servoAngle = map(temperature, 10, 30, 0, 180);

versus

    servoAngle = map(temperature, 10, 30, 180, 0);

But as shown by @odometer, it's all just some simple maths at the end, stuff from so long ago I don't remember learning it. I mean I don't remember ever not knowing it. :expressionless:

There are a number of things that crop up going the wrong way or "upside down", like switches that are LOW when pressed - these are usually handled easily at an exact moment by a bit of code.

    bool buttonIsPressed = !digitalRead(buttonPin);

where the pulled LOW wiring is immindiantly corrected with the logical not operator '!', and forever more reads right-side up.

HTH

a7

Thanks for the info, you've been very helpful, and that's made the coding easier for me to comprehend. It took me hours to get to this stage but learned something more from the help posted here, at a later date might be adding a display! Regards Jevray

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.