Temperature Gauge using Stepper motor and DS18B20 temp sensor

Im looking for some advice im trying to make a temperature gauge with a stepper motor and a DS18B20 temp sensor through a arduino nano. I have very little knowledge on arduino programming I can get the temperature to display through the serial monitor using the one wire libary. what im not sure how to do is to convert that output from the sensor to the stepper diver/motor?

Any help would be appreciated.

I have very little knowledge on arduino programming

So, acquire some. Lots and lots of examples around.

I can get the temperature to display through the serial monitor using the one wire libary.

What's a "libary"?

what im not sure how to do is to convert that output from the sensor to the stepper diver/motor?

Is that a question, or a statement?

Only you have any idea how many steps to take if the temperature is 27 degrees. That is not something we can help with.

It would help if we knew the particulars of your stepper motor and stepper driver. How do you home the stepper to provide a "zero reference"? Once the stepper is "homed" it is a matter of translating the temperature to the number of steps that puts the meter pointer at the correct position to indicate the temperature.

Stepper basics tutorial

Simple stepper program

groundFungus thanks for the pointers.

Im going to be using a arduino NANO, DS18B20 temp sensor, Easy Driver board (stepper driver) and a stepper motor from a car dash board a lot like this one Automotive Gauge Stepper Motor [x27.168] : ID 2424 : $9.95 : Adafruit Industries, Unique & fun DIY electronics and kits the motor has built in stops so doesnt have continuous rotation my gauge has a 90 degree sweep.

What im tring to achieve is this:
When I power up I want the stepper to rotate counter clockwise so the motor his the minimum temp stop which is 50 degrees and this should be the reference set for the motor. I them want to read the temperature from the sensor but the stepper shouldnt start to rise until the temp reaches 50+ degrees and reach max scale at 110 degrees.

I hope that is information helps.

Im sorry for my lack of knowledge

the motor has built in stops so doesnt have continuous rotation my gauge has a 90 degree sweep.

That's not going to tell you where the stepper is when the Arduino powers up, or prevent you from trying to drive past the limits. You must establish where the stepper starts and respect the physical limits.

Im sorry for my lack of knowledge

No need to apologize, we all start somewhere.

First you will need to know how many steps that your motor needs to move the pointer from 50 to 110 degrees (temperature) to get a steps per degree scaling factor.

The MotorKnob example from the Stepper library shows how to position a stepper in relation to a digitized analog voltage. Instead of the val = analogRead, do a temperature measurement. If the temperature is under 50 degrees do nothing. If the temperature is over 50 degrees, move the motor the number of steps to indicate the temperature ((temperature - 50) * steps per degree).

Ok ive found this example sketch for a temperature gauge that uses the same sensor as the one im using but the motor and driver are different to the ones thats im going to use also this sketch uses a micro switch to set a reference position for the pointer/motor but I want to run the pointer down to a mechanical stop and make the motor skip steps on prupose by telling the motor to move more steps than possible and once its finished trying to move passed the stop (needle should be at minimum scale) then set the reference point for the motor.

any help editing this sketch?

#include "Arduino.h"

// The preferred stepper motor driver
#include <AccelStepper.h>
#include <OneWire.h>

// Easy-to-use OneWire DS18B20 temperature library
#include <DallasTemperature.h>

// We want half step (not full step) control of the stepper
#define HALFSTEP 8

// Motor pin definitions
// Blue - 28BYJ48 pin 1
// Pink - 28BYJ48 pin 2
// Yellow - 28BYJ48 pin 3
// Orange - 28BYJ48 pin 4
// Red - 28BYJ48 pin 5 (VCC)

#define motorPin1 3 // IN1 on the ULN2003 driver 1
#define motorPin2 4 // IN2 on the ULN2003 driver 1
#define motorPin3 5 // IN3 on the ULN2003 driver 1
#define motorPin4 6 // IN4 on the ULN2003 driver 1

#define sensorPin 2 // Stepper microswitch sensor
#define tempPin 12 // DS18B20 Temperature sensor

// Initialize with pin sequence IN1-IN3-IN2-IN4 for using the AccelStepper with 28BYJ-48
AccelStepper stepMotor(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);

// Initialise OneWire comms
OneWire oneWire(tempPin);

// DallasTemp object needs that OneWire setup
DallasTemperature tempSensor(&oneWire);

// Temperature capture
int currTemp = 0;
int oldTemp = 0;

// -------------------------------------------------------------------
// SETUP SETUP SETUP SETUP SETUP SETUP SETUP
// -------------------------------------------------------------------
void setup() {
Serial.begin(9600);

// Start the temperature sensor
tempSensor.begin();

// Set some constraints on the stepper motor
stepMotor.setMaxSpeed(500.0);
stepMotor.setAcceleration(100.0);
stepMotor.setSpeed(50);

// Complete anticlockwise circle until we find the reference point
stepMotor.moveTo(4096 + 100); //4096

// This is the microswitch reference point
pinMode(sensorPin, INPUT_PULLUP);

// Power to the motor is ON
stepMotor.enableOutputs();
Serial.println("Moving stepper to known reference point");

//If we are already STOPPED then move off the mark and re-reference
while (digitalRead(sensorPin) == LOW) {
stepMotor.run();
}

// Now continue to turn until we reach our reference point
while (!digitalRead(sensorPin) == LOW) {
stepMotor.run();
}

// Stop when reference point reached and set the zero position
stepMotor.stop();
stepMotor.setCurrentPosition(0);
Serial.println("Stepper motor at reference point.");

// Set the stepper motor power off
stepMotor.disableOutputs();
delay(1000);
}

long mapTempToPos(long newTemp);
void doPointerMove();

// -------------------------------------------------------------------
// LOOP LOOP LOOP LOOP LOOP LOOP LOOP LOOP
// -------------------------------------------------------------------
void loop() {

// 1. Get the temperature and remember its value
// 2. Move pointer to temperature value via stepper
// 3. Repeat if temperature changes (whole degrees only)
// 4. Allow serial monitor input if connected to IDE

// Get temperature reading in whole degrees rounded to nearest value
tempSensor.requestTemperatures();
currTemp = (int) round(tempSensor.getTempCByIndex(0));

// Has temperature changed (significantly - i.e. whole degrees)
if (currTemp != oldTemp) {
doPointerMove();
}
else
{
// Allow serial monitor input (for testing!) If you put in
// non-numeric values the world as we know it will end.
char manualTemp[3];
if (Serial.available()){
// Read all NUMERIC characters until new line
Serial.println("Manual entry detected");
int charCnt = Serial.readBytesUntil('\n', manualTemp, 3);
manualTemp[charCnt] = '\0';

// Overwrite the current temperature sensor value
currTemp = atoi(manualTemp);
doPointerMove();
}
}

// Loop delay
delay(5000);
}

// -------------------------------------------------------------------
// POINTER MOVE POINTER MOVE POINTER MOVE POINTER MOVE
// -------------------------------------------------------------------
void doPointerMove() {
Serial.println("Temperature Change Detected");

Serial.print("Temperature: ");
Serial.print(oldTemp);
Serial.print(" vs. ");
Serial.println(currTemp);

stepMotor.moveTo(mapTempToPos(currTemp));

// turn on stepper motor
stepMotor.enableOutputs();
Serial.println("Stepper Motor ON");
stepMotor.run();

Serial.println("Stepper moving to new position");
while (stepMotor.isRunning()) {
stepMotor.run();
}

// turn off stepper motor
stepMotor.disableOutputs();
Serial.println("Stepper Motor OFF");

// Remember current temperature
oldTemp = currTemp;
}

// -------------------------------------------------------------------
// MAP TEMP TO SCALE MAP TEMP TO SCALE MAP TEMP TO SCALE
// -------------------------------------------------------------------
long mapTempToPos(long newTemp) {

// Convert the temperature to the stepper 90-degree range
// Note that if you change this the pointer will have a different range
long mappedTemp = map(newTemp - 5, -5, 30, 0, 1024);

// Debugging messages
Serial.print("Input temperature: ");
Serial.print(newTemp);
Serial.print("\tMapped to scale value: ");
Serial.println(mappedTemp);

// All done
return -mappedTemp;
}

long mapTempToPos(long newTemp) {

   // Convert the temperature to the stepper 90-degree range
   // Note that if you change this the pointer will have a different range
   long mappedTemp = map(newTemp - 5, -5, 30, 0, 1024);

What idiot wrote that crap? Expecting the temperature to be in the range -5 to 30, and using a long to hold it, does not pass the sniff test.

The position is going to be in the range 0 to 1024, so it is wasteful to use a long to hold that.

Hi,
Welcome to the forum.

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Thanks.. Tom.. :slight_smile:

PaulS:

long mapTempToPos(long newTemp) {

// Convert the temperature to the stepper 90-degree range
  // Note that if you change this the pointer will have a different range
  long mappedTemp = map(newTemp - 5, -5, 30, 0, 1024);



What idiot wrote that crap? Expecting the temperature to be in the range -5 to 30, and using a long to hold it, does not pass the sniff test.

The position is going to be in the range 0 to 1024, so it is wasteful to use a long to hold that.

To give "credit" where it's due I think you'll find the code is from here which accompanies these two videos by Ralph Bacon:-

#38 Stepper Motor 28BYJ-48 Temperature Gauge - Part 1

and

#39 Stepper Motor 28BYJ-48 Temperature Gauge - Part 2

I suspect he returns a long to maintain consistency with the standard Arduino map() function which also returns a long.

What is more amusing is he buys a 5V stepper motor (1st video 1:14) and promptly decides to run it from 9V (1st video 4:50) and then complains about it overheating (2nd video 4:50). He then goes on to write code to disable the outputs to stop it overheating :smiley:

Ian

Hi,
I'm not sure but this may help, its a library for the X25 type stepper gauges.

https://guy.carpenter.id.au/gaugette/2012/02/16/using-the-switecx25-library/

Tom.. :slight_smile:

Thanks for all the input Ive tried editing that sketch I found of that youtube video but I cant get it to work properly to start with I cant get the motor referencing to work as stated earlier I want to drive the motor into a mechanical stop (not a switch) at this point the needle will read 50 degrees.

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

#include "Arduino.h"

// The preferred stepper motor driver
#include <AccelStepper.h>
#include <OneWire.h>

// Easy-to-use OneWire DS18B20 temperature library
#include <DallasTemperature.h>

// We want half step (not full step) control of the stepper
#define HALFSTEP 8

#define tempPin 2    // DS18B20 Temperature sensor

// Definea stepper and the pins it will use
AccelStepper stepMotor(1, 10, 11);

// Initialise OneWire comms
OneWire oneWire(tempPin);

// DallasTemp object needs that OneWire setup
DallasTemperature tempSensor(&oneWire);

// Temperature capture
int currTemp = 0;
int oldTemp = 0;

// -------------------------------------------------------------------
// SETUP     SETUP    SETUP    SETUP    SETUP    SETUP    SETUP
// -------------------------------------------------------------------
void setup() {
  Serial.begin(9600);

  // Start the temperature sensor
  tempSensor.begin();

  // Set some constraints on the stepper motor
  stepMotor.setMaxSpeed(500.0);
  stepMotor.setAcceleration(100.0);
  stepMotor.setSpeed(50);

  // Complete anticlockwise circle until we find the reference point
  stepMotor.moveTo(200); //4096
  Serial.println("Moving stepper to known reference point");

// Stop when reference point reached and set the zero position
stepMotor.setCurrentPosition(0);
Serial.println("Stepper motor at reference point.");

delay(1000);
}

long mapTempToPos(long newTemp);
void doPointerMove();

// -------------------------------------------------------------------
// LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP
// -------------------------------------------------------------------
void loop() {

  // 1. Get the temperature and remember its value
  // 2. Move pointer to temperature value via stepper
  // 3. Repeat if temperature changes (whole degrees only)
  // 4. Allow serial monitor input if connected to IDE

  // Get temperature reading in whole degrees rounded to nearest value
  tempSensor.requestTemperatures();
  currTemp = (int) round(tempSensor.getTempCByIndex(0));

  // Has temperature changed (significantly - i.e. whole degrees)
  if (currTemp != oldTemp) {
    doPointerMove();
  }
  else
  {
    // Allow serial monitor input (for testing!) If you put in
    // non-numeric values the world as we know it will end.
    char manualTemp[3];
    if (Serial.available()) {
      // Read all NUMERIC characters until new line
      Serial.println("Manual entry detected");
      int charCnt = Serial.readBytesUntil('\n', manualTemp, 3);
      manualTemp[charCnt] = '\0';

      // Overwrite the current temperature sensor value
      currTemp = atoi(manualTemp);
      doPointerMove();
    }
  }

  // Loop delay
  delay(5000);
}

// -------------------------------------------------------------------
// POINTER MOVE       POINTER MOVE      POINTER MOVE      POINTER MOVE
// -------------------------------------------------------------------
void doPointerMove() {
  Serial.println("Temperature Change Detected");

  Serial.print("Temperature: ");
  Serial.print(oldTemp);
  Serial.print(" vs. ");
  Serial.println(currTemp);

  stepMotor.moveTo(mapTempToPos(currTemp));

    Serial.println("Stepper moving to new position");
  while (stepMotor.isRunning()) {
    stepMotor.run();
  }

    // Remember current temperature
  oldTemp = currTemp;
}

// -------------------------------------------------------------------
// MAP TEMP TO SCALE         MAP TEMP TO SCALE       MAP TEMP TO SCALE
// -------------------------------------------------------------------
long mapTempToPos(long newTemp) {

  // Convert the temperature to the stepper 90-degree range
  // Note that if you change this the pointer will have a different range
  long mappedTemp = map(newTemp -1, 50, 110, 0, 176);

  // Debugging messages
  Serial.print("Input temperature: ");
  Serial.print(newTemp);
  Serial.print("\tMapped to scale value: ");
  Serial.println(mappedTemp);

  // All done
  return -mappedTemp;
}

Hi,
I would suggest you write your code in stages, it looks lile you have written all the code then tried to get it working.

Can I suggest you dump the code you have, forget about the temperature for the moment.

Get some code working JUST for the stepper, make it sweep so you know how to control it.
Then get it to home and sweep to where you want.

Then do some code for the temperature, JUST the temperature, and get it working.

Then combine the two codes.

That way you will have debugged most of your code before its final compilation.
Also you will have learnt a lot about coding and how YOUR code is structured.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Tom.. :slight_smile:

Right I have wrote a sketch for controling the stepper manually but it is very jumpy/jittery and misses lots of steps? I have changed my setup slightly tho im using a nano on a keys-CNC 3 axis shield that uses A4988 drivers im going down this route because when I have finished my project I will have 3 gauges 1 controlled by temp and 2 by pressure but im just concentrating on getting 1 one the gauges working at a time them intergrate the 3 together at the end.

here is the sketch I have wrote for manually controlling the stepper.

#include <AccelStepper.h>

// AccelStepper Setup
AccelStepper stepMotor(1, 5, 2);
// Nano Pin 5 connected to STEP pin of Driver
// Nano Pin 2 connected to DIR pin of Driver


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

  // Set some constraints on the stepper motor
  stepMotor.setMaxSpeed(200.0);
  stepMotor.setAcceleration(100.0);


  // Turn anticlockwise to get motor to hit reference stop
  stepMotor.moveTo(-200);
  Serial.println("Moving stepper to known reference point");
  stepMotor.runToPosition();



  // Stop when reference point reached and set the zero position
  stepMotor.setCurrentPosition(0);
  Serial.println("Stepper motor at reference point.");

  delay(1000);
}


void loop()
{

  // Turn clockwise to 25 steps
  stepMotor.moveTo(25);
  Serial.println("Moving stepper to 25");
  stepMotor.runToPosition();
  delay(2000);

  // Turn clockwise to 50 steps
  stepMotor.moveTo(50);
  Serial.println("Moving stepper to 50");
  stepMotor.runToPosition();
  delay(2000);

  // Turn clockwise to get motor to 75 steps
  stepMotor.moveTo(75);
  Serial.println("Moving stepper to 75");
  stepMotor.runToPosition();
  delay(2000);

  // Turn clockwise to get motor to 100 steps
  stepMotor.moveTo(100);
  Serial.println("Moving stepper to 100");
  stepMotor.runToPosition();
  delay(2000);

  // Turn clockwise to get motor to 125 steps
  stepMotor.moveTo(125);
  Serial.println("Moving stepper to 125");
  stepMotor.runToPosition();
  delay(2000);

  // Turn clockwise to get motor to 150 steps
  stepMotor.moveTo(150);
  Serial.println("Moving stepper to 150");
  stepMotor.runToPosition();
  delay(2000);

  // Turn clockwise to get motor to 175 steps
  stepMotor.moveTo(175);
  Serial.println("Moving stepper to 175");
  stepMotor.runToPosition();
  delay(2000);

}

Ok I have got my sketch working to control the stepper from the temp sensor but I cant the gauge to start moving once the temp has hit 50 degrees, I cant get it to work from 50-150 but I can get it to work from 0-150. So im not sure how to implement the "if" lower than 50 degrees dont move the stepper.

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

// The preferred stepper motor driver
#include <AccelStepper.h>

// Define a stepper and the pins it will use
AccelStepper stepMotor(AccelStepper::DRIVER, 5, 2);
// STEP PIN- 5
// DIR PIN- 2

#define tempPin 12    // DS18B20 Temperature sensor

// Initialise OneWire comms
OneWire oneWire(tempPin);

// DallasTemp object needs that OneWire setup
DallasTemperature tempSensor(&oneWire);

// Temperature capture
int currTemp = 0;
int oldTemp = 0;

// -------------------------------------------------------------------
// SETUP     SETUP    SETUP    SETUP    SETUP    SETUP    SETUP
// -------------------------------------------------------------------
void setup() {
  Serial.begin(9600);

  // Start the temperature sensor
  tempSensor.begin();

 Serial.begin(115200);
    
  stepMotor.setMaxSpeed(100.0);
  stepMotor.setAcceleration(100.0);
  stepMotor.setSpeed(100.0);

  // Turn anticlockwise until hits the reference point
  Serial.println(" Stepper motor moving to reference ");
  stepMotor.runToNewPosition(-2000);
 

   long thisPosition = stepMotor.currentPosition();
   
  // Set the zero position
  stepMotor.setCurrentPosition(-1400);
  Serial.print(thisPosition);
  Serial.println(" Motor Position ");
  Serial.println(" Stepper motor at reference point. ");

   delay(5000);
}

long mapTempToPos(long newTemp);
void doPointerMove();

// -------------------------------------------------------------------
// LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP     LOOP
// -------------------------------------------------------------------
void loop() {

  // 1. Get the temperature and remember its value
  // 2. Move pointer to temperature value via stepper
  // 3. Repeat if temperature changes (whole degrees only)
  // 4. Allow serial monitor input if connected to IDE

  // Get temperature reading in whole degrees rounded to nearest value
  tempSensor.requestTemperatures();
  currTemp = (int) round(tempSensor.getTempCByIndex(0));

  // Has temperature changed (significantly - i.e. whole degrees)
  if (currTemp != oldTemp) {
    doPointerMove();
  }
  else
  {
    // Allow serial monitor input (for testing!) If you put in
    // non-numeric values the world as we know it will end.
    char manualTemp[3];
    if (Serial.available()){
      // Read all NUMERIC characters until new line
      Serial.println("Manual entry detected");
      int charCnt = Serial.readBytesUntil('\n', manualTemp, 3);
      manualTemp[charCnt] = '\0';

      // Overwrite the current temperature sensor value
      currTemp = atoi(manualTemp);
      doPointerMove();
    }
  }

  // Loop delay
  delay(5000);
}

// -------------------------------------------------------------------
// POINTER MOVE       POINTER MOVE      POINTER MOVE      POINTER MOVE
// -------------------------------------------------------------------
void doPointerMove() {
  Serial.println("Temperature Change Detected");

  Serial.print("Temperature: ");
  Serial.print(oldTemp);
  Serial.print(" vs. ");
  Serial.println(currTemp);
  
stepMotor.moveTo(mapTempToPos(currTemp));
   stepMotor.run();

  Serial.println("Stepper moving to new position");
  while (stepMotor.isRunning()) {
    stepMotor.run();
    
  }
    // Remember current temperature
  oldTemp = currTemp;
}

// -------------------------------------------------------------------
// MAP TEMP TO SCALE         MAP TEMP TO SCALE       MAP TEMP TO SCALE
// -------------------------------------------------------------------
long mapTempToPos(long newTemp) {

  // Convert the temperature to the stepper 90-degree range
  long mappedTemp = map(newTemp, 150, 0, 0, 1400); //150=max temp, 0=min temp, 1400=max scale for gauge

  // Debugging messages
  Serial.print("Input temperature: ");
  Serial.print(newTemp);
  Serial.print("\tMapped to scale value: ");
  Serial.println(mappedTemp);

  // All done
  return -mappedTemp;
}
    char manualTemp[3];
    if (Serial.available()){
      // Read all NUMERIC characters until new line
      Serial.println("Manual entry detected");
      int charCnt = Serial.readBytesUntil('\n', manualTemp, 3);
      manualTemp[charCnt] = '\0';

Suppose that 100 is sent. charCnt will be 3, and you just crapped on memory you don't own.

The 3rd argument is the maximum number of characters for readBytesUntil() to read. If your array can only hold 3 characters, including the NULL terminator, then do NOT tell readBytesUntil() that it is OK to read 3 characters.

You really do NOT understand how AccelStepper works. You MUST call run() on EVERY pass through loop() AND you MUST get rid of the stupid delay() calls.

Read up on the AccelStepper class, and learn to use it properly.

Frankly, I can't understand why you need the needle to accelerate, run at constant speed, and then decelerate when the temperature changes 1 degree. Therefore, I can't understand why you need to use the much-more-complicated AccelStepper class at all.