Need help with a math formula

First time poster here... I need help with a math formula that would adjust the brightness of a heat lamp based off the temperature reading of a sensor. Currently it is being done using if statements.

void TemperatureAssist(int Temperature2, int LightsOff){

  Serial.println("Temperature2");
  Serial.println(Temperature2);

  if (LightsOff == 0) {
      Serial.println("Lights are on");
    if (Temperature2 >= 93){
      analogWrite(BaskingLampPin, 50);
      Serial.println("Lowering output to 50%");
    }
    if (Temperature2 > 90 && Temperature2 < 93){
      analogWrite(BaskingLampPin, 75);
      Serial.println("Lowering output to 75%");
    }
    if (Temperature2 <= 90){
      analogWrite(BaskingLampPin, 100);
      Serial.println("Normal output at 100%");
    }
  }
  
}

I feel like there would be an easier way using less code to be uploaded onto the arduino. A formula that would dim the bulb as temps would rise. The formula I would normally use doesn't allow me increment with 93F being 50% power and 90F being 100% power. Any suggestions would be much appreciated.
Thank you

If it's linear, look at map.

1 Like

Welcome to the forum

What is that formula ?

y = c - x

Where y represents the bulb, and x represents the temp, c is a constant

You just have to scale x, y, and c, with the appropriate scaling values.

Highest temp reading(HTR) = highest bulb power(HBP). current temp reading(CTR) = proposed bulb power(PBP)
I use this a lot for scaling but it doesn't quite workout with the range I mentioned in the post.
PBP = (HBP*CTR)/HTR

I think this is closer if not exactly what I need. I'm going to dig into this. Thank you

Just realize, map() isn't magic, it just implements the linear equation. So you can often code it as a simple assignment of an expression to a variable.

As @octopirate mentions, it is only useful for linear mappings, not more general types.

Yes, what I meant was, you don't have to depend on it, to perform many tasks such as the one in question.

To find the value of c, does OP needs two-point calibration?

Upon re-reading the first post, the requirement was incorrectly stated. Or naively stated. It looks like there are 3 discrete power levels, just need to select one based on input value. So a simple linear equation isn't the answer. Thus also, map() isn't the answer.

1 Like

Hello funguy007
Try this untested modification of your sketch.

void TemperatureAssist(int Temperature2, int LightsOff) {

  Serial.println("Temperature2");
  Serial.println(Temperature2);

  if (LightsOff == 0) {
    Serial.println("Lights are on");
    switch (Temperature2) {
      case 0 ... 90:
        analogWrite(BaskingLampPin, 100);
        Serial.println("Normal output at 100%");
        break;
      case 91 ... 92:
        analogWrite(BaskingLampPin, 75);
        Serial.println("Lowering output to 75%");
        break;
      case 93 ... 200:
        analogWrite(BaskingLampPin, 50);
        Serial.println("Lowering output to 50%");
        break;
    }
  }
}

Have a nice day and enjoy programming in C++ and learning.
Errors and omissions excepted.
Дайте миру шанс!

1 Like

There is another flaw. 'analogWrite(100)' does not produce 100% power. It would produce 100*(100/256)% of full power, about 39%.

Here is how you would apply 75%:

  analogWrite(BaskingLampPin, 75 * 255 / 100);

255 is used as a scale factor, not 256, because 'analogWrite(255)' is actually 100% PWM output.

Also, with regard to the basic concept and implementation, you have to be careful what transfer function you use in a feedback loop, or it may oscillate.

It might be good to step back and talk about what you're trying to achieve, because the code as written doesn't lend itself to a linear curve fit, because of the discrete steps.

If we interpret the requirement as fitting the duty cycle at a handful of evenly spaced points, say 100% at 90, 75% at 91.5, 50% at 93, then we can fit a curve. In fact, it's linear with this interpretation
duty cycle = 16 - 0.1667 * temperature
In code you'd have to deal with values below 90 which would produce greater than 100% and above 96 which would go negative.

The code as presented doesn't ever turn the lamp lower than 50% which probably isn't what you want.

So, to reiterate, you probably want a clearer and more complete specification of how you want the system to behave before we get into coding specifics.

2 Likes

You could increase the clarity of this by using bool variables:

  if (LightsAreOff == false) {
      Serial.println("Lights are on");

Usually a "positive sense" goes with active circuitry:

  if (LightsAreOn == true) {
      Serial.println("Lights are on");

Which, in C language, permits you to use the short form:

  if (LightsAreOn) {
      Serial.println("Lights are on");
1 Like

Less Code? Do you like the following version using Ternary Operator (tested on UNO using PWM Pin-9)? If so, the task of message printing is left as an exercise for the readers.

void TemperatureAssist(int Temperature2, int LightsOff)
{
  Serial.println("Temperature2");
  Serial.println(Temperature2);
  if (LightsOff == 0)
  {
    Serial.println("Lights are on");
    (Temperature2 >= 93) ? (analogWrite(BaskingLampPin, 50))
    : (Temperature2 > 90 && Temperature2 < 93) ? (analogWrite(BaskingLampPin, 75))
    : (Temperature2 < 90) ? (analogWrite(BaskingLampPin, 100)) : exit(0);
  }
}
1 Like

My apologies... 100 just happened to be the max I'm willing to go. This value produces around 92F. If I use 255 then I would most likely kill what is in the enclosure.

I'm just learning C# and this is hard to get my mind around. The less code was meant towards a formula based off the reading from the sensor. The higher the reading, the less power will be supplied to the bulb.

"50" is the lowest I can go as the temperature will be around or above 93F. This forces the area to cool off. When the temp drops lower, more power is supplied to the bulb.

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