Understanding Step Widget

I wonder how the code can display anything when the Read_Temp() hasn’t been called anywhere.
You can use millis() to call it periodically as follows:

#include <blynk.h>
#include "DS18.h"

float temp;

DS18 sensors(D5);

char auth[] =

// How often we update the temperature
#define INTERVAL_MS   10000

// Global variable to track time (used for temp sensor readings)
system_tick_t time_millis;

void Read_Temp()
{
 (sensor.read());
  // Read temp directly here to global var temp, then use everywhere
  temp = sensors.fahrenheit();
  Serial.printf("Temp = ");
  Serial.println(temp);  
}

void setup() 
{
  Serial.begin(115200);
  Blynk.begin(auth);

 // Set time to 0
  time_millis = 0;
}

void loop() 
{
  Blynk.run();

  // Check if our interval > 10s
  if( millis() - time_millis > INTERVAL_MS ) 
  {
     //Set time to the 'current time' in millis
     time_millis = millis();
     Read_Temp();
   }
}

But I’m suggesting that you’d better go the Particle Forum to search for help because different syntax, hardware and libraries are used

1 Like

Good advice and this is what I have been doing. Taking your suggestions, reading on Blynk and Particle. Thank you once again

@mpo881 Please don’t pm general questions, posting to public topic gives much better chances to get help.

I don’t see any issues with the step widget.

The sensors.fahrenheit() returns those odd values, so search for a proper way to read the temperature values from your sensor. I’m guessing you have to do the reading only upon successful sensors.read() call.

So, you probably should take the advice given by @khoih and move sensor reading to a separate timer-based routine, which would run sensors.read() and, if successful, store the sensors.fahrenheit() into a global variable. And then, in the BLYNK_WRITE function just use that variable.

I did that. The timer creates the same issue.
Thanks

I’d suggest that you post your revised code and results.

Pete.

Thanks @PeteKnight
This code returns the reading with no problems

 #include "DS18.h"


DS18 sensor(D5);

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

void loop() {
    if (sensor.read()) {
    // Do something cool with the temperature
    Serial.printf("Temperature  " );
    Serial.println(sensor.fahrenheit()); 
  }
 
}

As soon as I add the stepWidget, I start seeing the errors

// This #include statement was automatically added by the Particle IDE.
#include <OneWire.h>

// This #include statement was automatically added by the Particle IDE.
#include <blynk.h>

#include "DS18.h"

DS18 sensors(D5);

float stepWidget;

char auth[] = "char auth";


BLYNK_CONNECTED() {
  
    Blynk.syncAll();
    Blynk.notify("CONNECTED");
   //Blynk.syncVirtual(V1);
  
}

BLYNK_WRITE(V25) {
    //if (sensors.read())
  stepWidget = param.asInt();
  Blynk.virtualWrite(V26, stepWidget); 
  Serial.printf("Step  ");
  Serial.println(stepWidget);
  Serial.printf("Temp  ");
  Serial.println(sensors.fahrenheit());
  Serial.printf("(int) Temp  ");
  Serial.println((int) sensors.fahrenheit());
}

void setup() {
  Serial.begin(115200);
  Blynk.begin(auth);
}

void loop() {
    Blynk.run();
  // Read the next available 1-Wire temperature sensor
  if (sensors.read()) {
    // Do something cool with the temperature
    Serial.printf("Temperature F ");
    Serial.println(sensors.fahrenheit());
      
}
}


Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Step  60.00
Temp  68.45
(int) Temp  68
Temperature F 68.45
Temperature F 68.45
Step  61.00
Temp  32.00
(int) Temp  32
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Step  62.00
Temp  68.45
(int) Temp  68
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Step  63.00
Temp  68.45
(int) Temp  68
Temperature F 68.45
Temperature F 68.45
Step  64.00
Temp  68.45
(int) Temp  68
Temperature F 68.45
Temperature F 68.45
Step  65.00
Temp  68.45
(int) Temp  68
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Step  66.00
Temp  68.45
(int) Temp  68
Step  67.00
Temp  68.45
(int) Temp  68
Step  68.00
Temp  68.45
(int) Temp  68
Step  69.00
Temp  68.45
(int) Temp  68
Temperature F 68.45
Temperature F 68.45
Step  70.00
Temp  68.45
(int) Temp  68
Temperature F 68.45
Step  71.00
Temp  68.45
(int) Temp  68
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Step  70.00
Temp  68.45
(int) Temp  68
Step  69.00
Temp  68.45
(int) Temp  68
Step  68.00
Temp  68.45
(int) Temp  68
Step  67.00
Temp  68.45
(int) Temp  68
Temperature F 68.45
Step  66.00
Temp  32.00
(int) Temp  32
Step  65.00
Temp  32.00
(int) Temp  32
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Step  64.00
Temp  68.45
(int) Temp  68
Step  63.00
Temp  68.45
(int) Temp  68
Step  62.00
Temp  68.45
(int) Temp  68
Temperature F 68.45
Step  61.00
Temp  68.45
(int) Temp  68
Step  60.00
Temp  68.45
(int) Temp  68
Step  60.00
Temp  68.45
(int) Temp  68
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45
Temperature F 68.45

Thanks for your reply

Either you’ve posted the wrong code, or you’ve misunderstood the advice to move the temperature reading process out of the void loop.

Pete.

I’ve tried moving it everywhere possible. The result is the same. This was just my last attempt :smiley: If I add it to the variable section and use a timer, same result. If I put it in the setup section it reads it once and you already know what happens in the loop.

Probably not the cause of the issue, but…

float stepWidget;
stepWidget = param.asInt();

Either switch it to

int stepWidget;

or

stepWidget = param.asFloat();

Thank you for the reply. Ill give that a try!

I’d like to see what you did when you tried to move the code and use a timer. Can you post that version of the code and the result?

Pete.

Sure, it might take me a bit to locate the exact code.

I believe this is the code. I apologize but I have tried many different variations.

// This #include statement was automatically added by the Particle IDE.
#include <OneWire.h>

// This #include statement was automatically added by the Particle IDE.
#include <blynk.h>

#include "DS18.h"

DS18 sensors(D5);

float stepWidget;
float temp;

char auth[] = "auth token";

BlynkTimer timer;


BLYNK_CONNECTED() {
  
    Blynk.syncAll();
    Blynk.notify("CONNECTED");
   //Blynk.syncVirtual(V1);
}
 
void sendSensorsHigh() {
  
  if (sensors.read()) {
    Serial.printf("Temperature  F ");
    Serial.println(sensors.fahrenheit());
  }
}

BLYNK_WRITE(V26) {
  stepWidget = param.asInt();
  Blynk.virtualWrite(V25, stepWidget); //
  Serial.printf("Step");
  Serial.println(stepWidget);
 if(stepWidget >= sensors.fahrenheit()){
  digitalWrite(D7, HIGH);
  digitalWrite(D0, HIGH);
  Serial.println ("ON");
 }
 else if (stepWidget < sensors.fahrenheit()){
     digitalWrite(D7, LOW);
     digitalWrite(D0, LOW);
     Serial.println("OFF");
 }
}

void setup() {
  Serial.begin(115200);
  Blynk.begin(auth);
  
  pinMode(D0, OUTPUT);
  pinMode(D7, OUTPUT);
  
timer.setInterval(100L, sendSensorsHigh);
  
}

void loop() {
    Blynk.run();
    timer.run();
}

this is the result

Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Step60.00
ON
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Step60.00
OFF
Temperature  F 70.25
Temperature  F 70.25
Step61.00
OFF
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Step62.00
OFF
Step63.00
OFF
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Step64.00
OFF
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Step65.00
OFF
Temperature  F 70.25
Temperature  F 70.36
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.36
Temperature  F 70.25
Temperature  F 70.36
Temperature  F 70.25
Step66.00
OFF
Temperature  F 70.36
Temperature  F 70.36
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25
Step67.00
OFF
Temperature  F 70.25
Temperature  F 70.25
Step68.00
ON
Temperature  F 70.36
Temperature  F 70.25
Temperature  F 70.25
Temperature  F 70.25

You can see the random ON when it should be OFF
Thanks

@Toro_Blanco I also tried your suggestion

 int stepWidget;

and the result was the same

Step60
ON
Temperature  F 70.25

I appreciate your input though

This line of code is making your device read the temperature every time the step widget is pressed.
You should be taking the temperature reading at the start of the sendSensorsHigh function and saving the result to a variable.
You should then be doing the comparison between this temperature variable and the value from the step widget in that sendSensorsHigh routine.

But, I’m sure you don’t needs to be taking these readings and doing that comparison 10 times every second, which is what your timer is currently doing. I’m sure that running this timed loop every 5 or 10 seconds would be more than sufficient.

Pete.

2 Likes

Thanks for taking a look. Seems as though I have some homework to do. If I understand you I need to do something like

int inputVariable1

and then something like

if (x == y){
//do something with it here
}

Then I will adjust the timer to 5000 or something like that.
Sound good? If so, I’ll get searching
Thanks

Okay, I still dont think you’ve grasped what I was saying, and there are some issues with the way that you’ve implemented the suggestions so far, so I’ve taken your code and changed it for you.

I really want you to understand what I’ve changed and why, so that you can tweak the code to get it working the way you want it to. Please read through the revised code and my comments below, so that you understand what I’ve done and why. The code is untested, uncompiled and the logic for the temperature comparison and evaluation may be wrong - but I don’t have your hardware or have your libraries installed.

// This #include statement was automatically added by the Particle IDE.
#include <OneWire.h>

// This #include statement was automatically added by the Particle IDE.
#include <blynk.h>

#include "DS18.h"

DS18 sensors(D5);

float targetTemp;
float temp;

char auth[] = "auth token";

BlynkTimer timer;
 
void takeTempReading()
{
  if (sensors.read())
  {
    temp = sensors.fahrenheit() // Take a temperature reading and save it to the variable temp
    
    Serial.printf("Temperature  F ");
    Serial.println(temp); // Print the saved temperature value without having to re-read the sensor
    
    Blynk.virtualWrite(V1, targetTemp); // Write the saved temperature out to the Blynk widget on pin V1
  }

  if(temp >= targetTemp)
 {
  digitalWrite(D7, HIGH);
  digitalWrite(D0, HIGH);
  Serial.println ("Temperature is at or above target");
 }
 else
 {
   digitalWrite(D7, LOW);
   digitalWrite(D0, LOW);
   Serial.println("Temperature is below target");
 }
}

BLYNK_CONNECTED()
{
  Blynk.syncVirtual(V26); // Ask the Blynk server for the current Target Temperature
  Blynk.notify("CONNECTED");
}


BLYNK_WRITE(V26) // Step widget used to set the Target Temperature
{
  targetTemp = param.asFloat();
  
  Blynk.virtualWrite(V25, targetTemp); //
  Serial.printf("Step");
  Serial.println(targetTemp);
}


void setup()
{
  Serial.begin(115200);
  Blynk.begin(auth);
  
  pinMode(D0, OUTPUT);
  pinMode(D7, OUTPUT);
  
  timer.setInterval(5000, takeTempReading);
}


void loop()
{
    Blynk.run();
    timer.run();
}

The comments in the code should be self explanatory, but you need to read through it to understand them. Key points to note:

  1. Your function that was called sendSensorsHigh() is now called takeTempReading() as it better describes what the function actually does.

  2. The variable called stepWidget is now called targetTemp as it better describes what it is used for. This is still a float type variable, but the value coming from the step widget is now being read as a float as well, rather than an integer. This will allow you to set the step level to 0.5 if you want to have half degree control of the target temperature (not so much of an issue when you work in Farenheit, but for those of us in the civilised world who work in Celcius it is necessary to have finer control :slightly_smiling_face:)

  3. I’ve assumed that you will want to see the actual temperature from the sensor in your Blynk app. I’ve added a line in the takeTempReading() which writes the temperature to a widget attached to virtual pin V1. If this pin is currently in use then you’ll need to change that line of code. The widget can be any display type, maybe a labelled value or gauge widget would work well.

  4. I’ve made a change to the way that the if comparisons are done. I’m now comparing the temperature to the temperature to the target temperature, whereas before you were doing the comparison the other way around. I’ve kept the comparison operators the same way around (>=) and I’ve changed the serial print message from On/Off to something that makes more sense. You’d previously commented on the D7 and D0 states being incorrect, and when you test this if it’s not working the way you want then change the HIGH and LOW commands around.

Please read through the code and the se notes, then test the code on your device with your sensor and let me now if its working the way you want it to. I’m hoping that you’ll be able to fix any issues yourself now but if not then please explain what the issue is and what you’ve tried, and we’ll help you to fix it.

Pete.

Hello @PeteKnight,

Thank you very much for your continued help, I appreciate your time. I have read through the code and noted the changes you made as well as your comments.

In response to the comments
1-agreed
2- partially agree :grin:
3-Yes, I did. After clearing up a minor editing issue, works fine (both V1 and V25 were writing targetTemp)
4- Explain the change when you have time, please. Is there a difference in making the comparison this way?

The end result is that it is working as I had expected. I look forward to your reply.

Thank you

What you were doing before was saying “if the target temperature is greater than or equal to the actual temperature then do some stuff”

What it now says is “If the actual temperature is greater than or equal to the target temperature then do some stuff” which is obviously the exact opposite of what it did before.

I’ve also deleted the “else if” and replaced it with a simple “if”. This is simply because that’s really what you want to do - you don’t need to specify the alternate criteria, you just need to acknowledge that it it isn’t greater than or equal to then it has to be lower than.

As far as which variable you put first in an if statement, there is no hard and fast rule, but the approach that most programmers tend to take is to put the thing that changes most frequently first and the thing that’s more constant second. As the measured temperature is going to be fluctuating frequently and the target temperature is more static then doing it the way I have is the ‘preferred’ format.

Sorry, my mistake. I copied and pasted and changed the virtual PIN number, but not what was being written to that virtual pin.

I think you’ll agree that giving your variables and functions meaningful names makes it easier to work out what’s happening, and in this case it was easier to see that targetTemp needed to be changed to Temp for the V1 pin.

One thing that you may want to consider for the future is introducing some hysteresis into the thermostat process.
At the moment, if the target is 70°F and the actual temperature fluctuates between 69.999° and 70.0° the thermostat will turn the heater on and off in rapid succession. Depending on the type of heater, this may be undesirable.
Hysteresis adds a degree of insensitivity or latency to the process, maybe waiting until the temperature is 0.2° above target before turning the heater off, and 0.2° below target before turning the heater on. This means you’ll get intentional fluctuations of 0.4°F, but that’s probably much better than you get with most mechanical thermostats.

Just a bit of food for thought, and something to look out for when doing your testing.

Pete.

Thanks for the explanation. I will make it a practice from this point forward.

No need for an apology. I was sure to read every line of code, several times along with the comments prior to even trying to compile it in my attempt to understand everything you passed along. I also agree with your comment about naming the variables and functions with something more appropriate.

Thanks also for the heads up on the Hysteresis, I will begin researching that. Lastly, thanks for your time, patience and knowledge.

1 Like