Go Down

Topic: How would I make this if statement? (if somehting is within x amount?) (Read 2872 times) previous topic - next topic

XOIIO

for example when I throw it in after celsius has been declared in the loop, the led turns on once, then doesn't again.

Code: [Select]
#include <OneWire.h>
#include <LiquidCrystal.h>

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)
LiquidCrystal lcd(6, 7, 5, 4, 3, 2);
float lasttemp;
int ledstate;

void setup(void) {
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  lcd.begin(8, 2);
  lcd.setCursor(0,0);
  lcd.print("STARTING");
  lcd.setCursor(0, 1);
  lcd.print("STARTING");
  delay(1000);
  lcd.clear();
}

void loop(void) {
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius, fahrenheit;
 
      if ( (celsius >= lasttemp - 0.2) && (celsius <= lasttemp + 0.2) ) {
      digitalWrite(13, HIGH); }
      else {
        digitalWrite(13, LOW);
      }

  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");
  lasttemp = celsius;
  lcd.setCursor(0, 0);
  lcd.print(celsius);
  lcd.print(" C ");
  lcd.setCursor(0, 1);
  lcd.print(fahrenheit);
  lcd.print(" F ");
  Serial.print(lasttemp);
  Serial.println();
 
}

Arrch

Work flow:

1) calculate the value of celcius
2) check if the derivative is within a certain range
3) update the lasttemp variable

AWOL

Code: [Select]
float celsius, fahrenheit;
 
      if ( (celsius >= lasttemp - 0.2) && (celsius <= lasttemp + 0.2) ) {

Pluck some random value off the stack and compare it to lasttemp?
Not good - It might not even be a valid "float".
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

XOIIO


Code: [Select]
float celsius, fahrenheit;
 
      if ( (celsius >= lasttemp - 0.2) && (celsius <= lasttemp + 0.2) ) {

Pluck some random value off the stack and compare it to lasttemp?
Not good - It might not even be a valid "float".



well the float is appearing in serial just fine, I'm thinking this just happens too fast to give the LED a chance to turn off. A way to fix that would be to delay but I need it to update constantly. I'm really not sure how this could be done, or if it even can be. Maybe it would need to be the last 3 temps or something, I wonder how you would rig that up.

I think I might just need to forget this part and leave it as is.

Arrch


well the float is appearing in serial just fine,


That because by the time you've printed it, you've given it a value.

XOIIO

hmm, I got something, I added a counter so it only would check if celsius equals the lasttemp every second time, and the led flashes when the temp is changing, then stays solid. That's not bad actually, although it still stays onw ith soe change, I'll try doubling or tripling the counter and seeing how that goes.


Code: [Select]
#include <OneWire.h>
#include <LiquidCrystal.h>

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)
LiquidCrystal lcd(6, 7, 5, 4, 3, 2);
float lasttemp;
int ledstate;
int counter = 0;

void setup(void) {
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  lcd.begin(8, 2);
  lcd.setCursor(0,0);
  lcd.print("STARTING");
  lcd.setCursor(0, 1);
  lcd.print("STARTING");
  delay(1000);
  lcd.clear();
}

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");

  if ( (celsius >= lasttemp - 0.2) && (celsius <= lasttemp + 0.2) ) {
    digitalWrite(13, HIGH);
  }
  else {
    digitalWrite(13, LOW);
  }

  lasttemp = celsius;
  lcd.setCursor(0, 0);
  lcd.print(celsius);
 
  if ( (counter % 2) == 0) {
    if ( (celsius >= lasttemp - 0.10) && (celsius <= lasttemp + 0.10) ) {
    digitalWrite(13, HIGH);
  }
  else {
    digitalWrite(13, LOW);
  }
  }
 
  lasttemp == celsius;
  ++counter;
  lcd.print(" C ");
  lcd.setCursor(0, 1);
  lcd.print(fahrenheit);
  lcd.print(" F ");
  Serial.print(lasttemp);
  Serial.println();
}

Arrch

Code: [Select]
  lasttemp = celsius;
  ...
  if ( (counter % 2) == 0) {
    if ( (celsius >= lasttemp - 0.10) && (celsius <= lasttemp + 0.10) ) {


Same issue as before, the second if statement will always evaluate to true, so you may as well remove it.

XOIIO


Code: [Select]
  lasttemp = celsius;
  ...
  if ( (counter % 2) == 0) {
    if ( (celsius >= lasttemp - 0.10) && (celsius <= lasttemp + 0.10) ) {


Same issue as before, the second if statement will always evaluate to true, so you may as well remove it.


whoops, thought I had deleted that one

XOIIO

hmm, so I relaxed the limits a bit, and the temperature is stable (the lcd displays way faster than serial), however the led doesn't turn on at all. I know for a fact that the counter is working too. hmm

Code: [Select]
  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");

  if ( (celsius >= lasttemp - 0.2) && (celsius <= lasttemp + 0.2) ) {
    digitalWrite(13, HIGH);
  }
  else {
    digitalWrite(13, LOW);
  }

  lcd.setCursor(0, 0);
  lcd.print(celsius);
 
  if ( (counter % 2) == 0) {
    if ( (celsius >= lasttemp - 0.50) && (celsius <= lasttemp + 0.50) ) {
    digitalWrite(13, HIGH);
  }
  else {
    digitalWrite(13, LOW);
  }
  }
 
  lcd.print(" C ");
  lcd.setCursor(0, 1);
  lcd.print(fahrenheit);
  lcd.print(" F ");
  lasttemp == celsius;
  ++counter;
}

Arrch

Code: [Select]
  lasttemp == celsius;

== is for comparison like in if statements
= is for assignments.

XOIIO


Code: [Select]
  lasttemp == celsius;

== is for comparison like in if statements
= is for assignments.


ah shit that's right. *facepalm*

Now I just need to get that counter to work better, so that it checks once every, hmm, 6 times or something. I don't know exactly, but I want to compare the temperatures between the last 30 seconds, that would make sure it has normalized

Arrch


but I want to compare the temperatures between the last 30 seconds, that would make sure it has normalized


The Blink Without Delay example demonstrates on how to perform periodic actions (such as comparing values 30 seconds apart) without blocking the rest of your code.

XOIIO



but I want to compare the temperatures between the last 30 seconds, that would make sure it has normalized


The Blink Without Delay example demonstrates on how to perform periodic actions (such as comparing values 30 seconds apart) without blocking the rest of your code.


yup, that occurred to me just a little while ago, and it's working-ish, there is some fluctuation with the LED but I do have a fan going. Aside from that it seems to be working peachy.

Code: [Select]
#include <OneWire.h>
#include <LiquidCrystal.h>

OneWire  ds(10);  // on pin 10 (a 4.7K resistor is necessary)
LiquidCrystal lcd(6, 7, 5, 4, 3, 2);
float lasttemp;
int ledstate;
int counter = 0;
long previousMillis = 0;
long interval = 10000;

void setup(void) {
  pinMode(13, OUTPUT);
  Serial.begin(9600);
  lcd.begin(8, 2);
  lcd.setCursor(0,0);
  lcd.print("STARTING");
  lcd.setCursor(0, 1);
  lcd.print("STARTING");
  delay(1000);
  lcd.clear();
}

void loop(void) {
  unsigned long currentMillis = millis();
  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");

  if ( (celsius >= lasttemp - 0.2) && (celsius <= lasttemp + 0.2) ) {
    digitalWrite(13, HIGH);
  }
  else {
    digitalWrite(13, LOW);
  }

  lcd.setCursor(0, 0);
  lcd.print(celsius);

  if (currentMillis - previousMillis > interval) {
    if ( (celsius >= lasttemp - 0.05) && (celsius <= lasttemp + 0.05) ) {
    digitalWrite(13, HIGH);
  }
  else {
    digitalWrite(13, LOW);
  }
  }
 
  lcd.print(" C ");
  lcd.setCursor(0, 1);
  lcd.print(fahrenheit);
  lcd.print(" F ");
  lasttemp = celsius;
}

XOIIO

hmm, im having a bit of trouble figuring this out actually. I need it to check once every 30 seconds (got that part down) if the temperature has stayed the same the last 30 seconds. thing is, if I put the same delay on the temperature, of course it will match. hmmm

Arrch

Would do you mean by "put the same delay on the temperature"?

Go Up