Arduino/touch screen climate control

I wrote the following code for a climate control system but I'm having an issue. Arduino uno. Hc05 I know my phone is connecting to the arduino because it shows up on the bt link on the app, the lights blink and then change rhythm when you select it. It's cold here and I'd love to have a heater in my truck. Please help. I didn't comment every single line but should be enough to follow. Thank you.

#define pin1 2 //motor #1 +
#define pin2 3 //motor #1 -
#define pw1 9 //motor 2 pwm
#define pin3 4 //motor #3 +
#define pin4 5 //motor #3 -
int analogPin1 = A0; //read location for bypass valve pot
int analogPin2 = A1; //read location for flapper valve pot
int analogPin3 = A2; //read location for temp sensor
long previousMillis = 0;
long interval = 2000;


void setup() {
  // put your setup code here, to run once:
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  pinMode(pin4, OUTPUT);
  pinMode(pw1, OUTPUT);
  Serial.begin(9600);
  digitalWrite(pin1, LOW);
  digitalWrite(pin2, LOW);
  digitalWrite(pin3, LOW);
  digitalWrite(pin4, LOW);
  analogWrite(pw1, 50);


}

void loop() {
  // put your main code here, to run repeatedly:

  float potvoltage1; //reference signal from flapper motor pot
  float potvoltage2; //reference signal from bypass valve pot
  int testvoltage = 1023;
  float refvoltage; //comparison value for reference signals...provided by arduino
  int tempF; //reference sinal from temperature sensor
  int temprequest; //requested change from android app
  int fanSpeed; //calculated value based on val
  int value; //another calculated value based on val, for a different purpose
  int val;


  if (Serial.available() >= 2 )
  {
    unsigned int a = Serial.read();
    unsigned int b = Serial.read();
    unsigned int val = (b * 256) + a;
    Serial.print(val); //Added this line to test the incoming data...it is for test purposes only

    if (val > 200 && val < 300) //requested change in fan speed
    {
      fanSpeed = (val * ( 250 / 20));
      analogWrite(pw1, fanSpeed);
    }
    else if (val > 300 && val < 400) //requested new flapper zone
    {
      value == ((val - 300) * 261);
      potvoltage2 = analogRead(analogPin2);
      if (value < potvoltage2)
      {
        while (value < potvoltage2)
          digitalWrite(pin3, HIGH);
        digitalWrite(pin4, LOW);
        potvoltage2 = analogRead(analogPin2);
      }
      if (value > potvoltage2)
      {
        while (value > potvoltage2)
          digitalWrite(pin3, LOW);
        digitalWrite(pin4, HIGH);
        potvoltage2 = analogRead(analogPin2);
      }
    }
    else if (val > 100 && val < 200) // change in temperature setting
      potvoltage1 = analogRead(analogPin1);
    temprequest = (val - 100);
    {
      if (val == 164 )
      {
        while (potvoltage1 != 41 ); //where 41 = bypass valve closed pot signal voltage
        digitalWrite(pin1, HIGH);
        digitalWrite(pin2, LOW);
        potvoltage1 = analogRead(analogPin1);
      }
      else if (val == 186)
      {
        while (potvoltage1 != 977 ); //where potvoltage is the signal voltage from the bypass valve and 977 = bypass valve open pot signal voltage
        digitalWrite(pin2, HIGH);
        digitalWrite(pin1, LOW);
        potvoltage1 = analogRead(analogPin1);
      }
      else if (val > 64 && val < 86 )//begin loop to move valve aperture
      {
        tempF = analogRead (analogPin2);
        while (tempF < temprequest) //temperature requested is hotter than current temp
        {
          while (refvoltage > potvoltage1)
          {
            unsigned long currentMillis = millis();
            if (currentMillis -  previousMillis < interval)
            {
              previousMillis = currentMillis;
              refvoltage == (refvoltage + 40); //where refvoltage is the reference voltage for the next segment (1/24th)
              digitalWrite(pin2, HIGH);
              digitalWrite(pin1, LOW);
            }
          }
        }
        while (tempF > temprequest) // temperature requested is cooler than current temp
        {
          while (refvoltage < potvoltage1)
          {
            unsigned long currentMillis = millis();
            if (currentMillis - previousMillis < interval)
            {
              previousMillis = currentMillis;
              refvoltage == (refvoltage - 40); //moving down the scale .2V at a time
              digitalWrite(pin1, HIGH);
              digitalWrite(pin2, LOW);
            }
          }
        }
      }



    }



  }
}

I wanted to add more information but the post above got kind of long. So I wasn't getting anything out of the Arduino's outputs, that's when I added the serial.print(val) function to the Bluetooth receive routine so I could see what was coming in. Nothing. I'm pretty sure the app is working but I am currently reviewing it as well. It has labels that show my slider positions are changing and they are working. The data from the labels is then converted to 2 byte numbers and sent to the arduino. With the mit app inventor it's pretty simple so I feel like the issue is in the code I wrote.

Please correct your post above and add code tags around your code:
[code]`` [color=blue]// your code is here[/color] ``[/code].

It should look like this:// your code is here
(Also press ctrl-T (PC) or cmd-T (Mac) in the IDE before copying to indent your code properly)

Sorry I missed that. Any other info I can add that would help?

If you were pressing ctrl-T you would see unexpected indentation - would suggest you get rid of the wrong semi colons you have here and there in your if statements for example

else if (val > 100 && val < 200)[color=red];[/color]

This means if the test is true do nothing

OK I fixed the two whole semi-colons that were placed inappropriately, which, by the way were inconsequential to the question I'm asking here because something in or before the bluetooth data acquisition is what's causing my issue. As stated above the "Serial.print(val)" statement was added to supervise the data stream coming into the arduino and is executed before any of the other functions of the program. FYI "No format adjustments required" was the message I got when I pressed ctrl-t so I guess it's formatted correctly. Now, have I satisfied the requirements of the nit-pick Gods so we can look at and evaluate the actual coding? If the coding is too complex for you I'm happy to await a response from someone who can understand and assist with the program I've written.

Where do you print? (Serial console?) where is your BT connected? (which pins?) seems the same ones... 3.3V BT ? 5V arduino ? (probably need SoftwareSerial if you want to debug at same time)

Where is the new code?

What are you actually sending from MIT App inventor? Have you actually tested if with a simple serial print or write to get the communication working first? (Are you sending binary or ASCII for example would be a question?)

While you are at it fix also the « inconsequential » bugs so that later you get a chance to have a working code...
value [color=red]==[/color] ((val - 300) * 261);

In this code

   if (val > 200 && val < 300) //requested change in fan speed
    {
      fanSpeed = (val * ( 250 / 20));
      analogWrite(pw1, fanSpeed);
    }

fanSpeed will be between 2400 and 3600 where anlogWrite expects a value between 0 and 255

In this code

else if (val > 300 && val < 400) //requested new flapper zone
    {
      value == ((val - 300) * 261);
      potvoltage2 = analogRead(analogPin2);
      if (value < potvoltage2)

value will be between 261 and 25839 whereas the analogRead will be maxed at 1024... seems weird.. are you sure? (will be tough to exit the while (value > potvoltage2) you have later if value is above 1024)

I’m reading this in my phone, so the formatting and proper indent not only helps but also prevents code expressions to be confused with tags like if you had a [i] or other such things a 8 and a ) gives you this for example 8) would be kinda annoying in code

Ps: in your while you don’t need to keep setting the pins, do that once before entering the while and just read your analog value. (Would you need to reset these pins after?)

I have been revising the code at the beginning of the post to conserve space. I have three sliders on the MIT app, which send values of 164-186, 201-220, and 301-304. In the code for //requested new flapper zone, for instance, the arduino receives 301-304 and subtracts 300 leaving 1-4 (4 flapper zones). Then they're multiplied by 261 (one fourth of 1024) which gives a 2 bit number value for the desired reference voltage. The motor is then activated (forward or reverse) until the value returned from the flapper motor (potvoltage2) is the same as the value assigned to the variable value. Thank you for pointing out that the fan speed routine is missing a modifier, that's very helpful. fanspeed should == ((val-200)*(250/20)) where fanspeed will equal a number that is (x)20ths of 250. Also a great catch, thank you. Now on to the bad ...I uploaded blink to my atrium and I get nothing. Furthermore the l, rx, and tx, lights remain lit at all times when the arduino is powered, meaning, I believe, that she's fried. Ordered another any try again Thursday. Will definitely look into the math errors and double check everything between now and then. Thanks again for the helpful suggestions

I re-read the pins during the "while" to check the reference volts. Imagine a motor connected to a potentiometer. As the motor turns, the voltage coming from the center post (I call it a reference voltage but I'm just a carpenter so it's probably not correct terminology) will change. This signal is used to determine the position of the motor (in reality the motor is attached to a gear that drives the whole apparatus) such that the position for "defrost" may be 1.2V of 5v. It is necessary to check this signal repeatedly during the move cycle in order to stop at the correct position. For this reason there is an analog read during every cycle of the loop.

It's called a "wiper", oddly enough. :slight_smile:

You need to connect the BT module to other pins using software serial and possibly a voltage adapter depending on the BT module. Some are strict 3.3V and indeed will fry if provided 5V on Rx

My point in the code

if (value < potvoltage2)
      {
        while (value < potvoltage2) // probably missing { here
          digitalWrite(pin3, HIGH);
        digitalWrite(pin4, LOW);
        potvoltage2 = analogRead(analogPin2); // and a } here I would suppose
      }

is not only that you are missing curly brackets {} most likely and if you had them that the digitalWrite() calls in the while do do anything but slow down your while loop since you keep setting the pins to the same value.

    if (value < potvoltage2) {
        digitalWrite(pin3, HIGH);
        digitalWrite(pin4, LOW);
        while (value < potvoltage2)  potvoltage2 = analogRead(analogPin2);
      }

does the same, faster

It’s not a good practice to modify previous posts, new comers then can’t understand what has been discussed

That's really great input, thank you. I threw this code together based on my minimal previous (high school) experience over 20 years ago and some tutorials I watched. I will report back Wednesday when I get my new arduino and try again.

I'm not trying to be argumentative, but for the purpose of learning I was wondering if you could clarify...if I use the loop as you wrote it above, is it not also missing the curly brackets around the "do" part of the while statement? If I understand correctly the loop is stuck in the "while" function until value becomes greater than potvalue2. That's genius because there's only one function to perform.

 if (value < potvoltage2) {
        digitalWrite(pin3, HIGH);
        digitalWrite(pin4, LOW);
        while (value < potvoltage2)  potvoltage2 = 
         analogRead(analogPin2);
      }

You are doing well from reading tutorials and 20 years ago memory! keep being curious. We all start from nowhere and the more we try, fail and learn, the better we get. So don’t apologize for asking good (or bad) questions!

to simplify - In C or C++ programming the while construct is done this way:

while ([color=blue]condition[/color]) [color=purple]expression;[/color]

And an expression; is either a single operation or a set of expressions separated by semicolons (so the definition is recursive) in which case you wrap the outter one in curly braces {}

Example:

while (condition) dothis();
doThat();

will call the doThis() and when the while ends will call the doThat() whereas if I had written

while (condition) {
   dothis();
   doThat();
}

then the expression for the while is comprised of executing in sequence doThis() and doThat() until the condition becomes false

This is applicable in many constructs and works as well for example in this
if (condition) expression1; else expression2;

if (condition) a = 7; else a = 8;

But if I wanted to do two things in the if then I need to group them into an expression and do

if (condition) {a = 7; b = 8;} else {a = 8; b = 7;}

but that’s not very readable and that’s why we indent code, so we would usually write this

if (condition) {
   a = 7;
   b = 8;
} else {
   a = 8; 
   b = 7;
}

this way that helps understand what belongs together when reading the code — hence Insisting at the beginning on proper lining up the code.

Long story short:

  • if you have only one thing to do then you don’t need the {}
  • if you want to do multiple things then combine them into one expression by grouping them in {}
  • and if you are unsure adding {} with only a simple element into it won’t hurt :slight_smile:

PS:

If I understand correctly the loop is stuck in the "while" function until value becomes greater than potvalue2. That's genius because there's only one function to perform.

You got it and To be even better if you did not need to maintain the value of potvoltage2 for further down in the code you could even write while (value < analogRead(analogPin2)); here the expression in the while loop is just empty, you just have the semi colon and no réal expression.

Hope this helps

Man you have been so helpful. I'm standing here screaming at my arduino because it won't work and I'm dying to try these things out. I actually posted here because I was afraid the if/then's in the temperature change function were too deeply nested. Can you look at one of those and comment on the viability there? Welcome any suggestions you got. So is the situation with the rx/tx/l lights coming on and staying on fatal? They won't even go off when I press reset. Guess I'll rewrite some code and try to remain patient for Wednesday when my new arduino arrives. I will be ordering half a dozen atmega chips so I never have to wait again.

So I got my new board. I cleaned up the code using your suggestions and uploaded it. I am able to control the brightness of a fan connected to the output pins designated for the fan speed. Unfortunately I am not getting anything out of the temperature change function. I added a print.ln after the temperature math at the beginning of the routine and got nothing. Do you see anything that jumps out at you?

#define pin1 2 //motor #1 +
#define pin2 3 //motor #1 -
#define pw1 9 //motor 2 pwm
#define pin3 4 //motor #3 +
#define pin4 5 //motor #3 -
int analogPin1 = A0; //read location for bypass valve pot
int analogPin2 = A1; //read location for flapper valve pot
int analogPin3 = A2; //read location for temp sensor
long previousMillis = 0;
long interval = 2000;


void setup() {
  // put your setup code here, to run once:
  pinMode(pin1, OUTPUT);
  pinMode(pin2, OUTPUT);
  pinMode(pin3, OUTPUT);
  pinMode(pin4, OUTPUT);
  pinMode(pw1, OUTPUT);
  Serial.begin(9600);
  digitalWrite(pin1, LOW);
  digitalWrite(pin2, LOW);
  digitalWrite(pin3, LOW);
  digitalWrite(pin4, LOW);
  analogWrite(pw1, 50);


}

void loop() {
  // put your main code here, to run repeatedly:

  int testvoltage = 1023;
  float refvoltage; //comparison value for reference signals...provided by arduino
  float tempF; //temperature converted to Fahrenheit
  int tempC;//temperature in Celsius
  int tempS;//reference signal from temperature sensor
  int temprequest; //requested change from android app
  int fanSpeed; //calculated value based on val
  int value; //another calculated value based on val, for a different purpose
  int val;
  int potvoltage1;
  int potvoltage2;


  if (Serial.available() >= 2 )
  {
    unsigned int a = Serial.read();
    unsigned int b = Serial.read();
    unsigned int val = (b * 256) + a;

    if (val > 200 && val < 300) //requested change in fan speed
    {
      fanSpeed = ((val - 200) * 12.5);
      analogWrite(pw1, fanSpeed);
    }
    else if (val > 300 && val < 400) //requested new flapper zone
    {
      value = ((val - 300) * 261);
      potvoltage2 = analogRead(analogPin2);
      if (value < potvoltage2)
      {
        digitalWrite(pin3, HIGH);
        digitalWrite(pin4, LOW);
        while (value < analogRead(analogPin2));
      }
      else if (value > potvoltage2)
      {
        digitalWrite(pin3, LOW);
        digitalWrite(pin4, HIGH);
        while (value > analogRead(analogPin2));
      }
    }
    else if (val > 100 && val < 200) // change in temperature setting
      potvoltage1 = analogRead(analogPin1);
      tempS = analogRead(analogPin2);
      tempC = (tempS - 0.5) * 100;
      tempF = (tempC * (9/5)) + 32;
      Serial.println(tempF);
      temprequest = (val - 100);
    {
      if (val == 164 )
      {
        while (potvoltage1 > 41 ); //where 41 = bypass valve closed pot signal voltage
        digitalWrite(pin1, HIGH);
        digitalWrite(pin2, LOW);
        potvoltage1 = analogRead(analogPin1);
      }
      else if (val == 186)
      {
        while (potvoltage1 < 977 ); //where potvoltage is the signal voltage from the bypass valve and 977 = bypass valve open pot signal voltage
        digitalWrite(pin2, HIGH);
        digitalWrite(pin1, LOW);
        potvoltage1 = analogRead(analogPin1);
      }
      else if (val > 64 && val < 86 )//begin loop to move valve aperture
      {
        while (tempF < temprequest) //temperature requested is hotter than current temp
        {
          while (refvoltage > potvoltage1)
          {
            unsigned long currentMillis = millis();
            if (currentMillis - previousMillis < interval)
            {
              previousMillis = currentMillis;
              refvoltage = (refvoltage + 40); //where refvoltage is the reference voltage for the next segment (1/24th)
              digitalWrite(pin2, HIGH);
              digitalWrite(pin1, LOW);
            }
          }
        }
        while (tempF > temprequest) // temperature requested is cooler than current temp
        {
          while (refvoltage < potvoltage1)
          {
            unsigned long currentMillis = millis();
            if (currentMillis - previousMillis < interval)
            {
              previousMillis = currentMillis;
              refvoltage = (refvoltage - 40); //moving down the scale .2V at a time
              digitalWrite(pin1, HIGH);
              digitalWrite(pin2, LOW);
            }
          }
        }
      }



    }



  }
}
1 Like

I modified some pin definition to make it more readable

I got rid of useless variables as well

I modified also your {} when you are dealing with temperature:

    else if (val > 100 && val < 200) // change in temperature setting
[color=blue]      potvoltage1 = analogRead(analogPin1);[/color]
[color=green]      tempS = analogRead(analogPin2);
      tempC = (tempS - 0.5) * 100;
      tempF = (tempC * (9/5)) + 32;
      Serial.println(tempF);
      temprequest = (val - 100);[/color]
[color=red]    {[/color]
[color=green]      if (val == 164 )[/color]

--> here you will only execute the blue part if the if is true and then you go into the rest of the green code. I notice you have the red { later, so may be you added code at the wrong place? (that's why I usually put the opening bracket just after the if or while, on the same line to ensure I mark my blocks well)

here is a suggestion...

const byte pinMotor1Plus = 2; //motor #1 +
const byte pinMotorNeg = 3; //motor #1 -
const byte pinMotor2PWM = 9; //motor 2 pwm
const byte pinMotor3Plus = 4; //motor #3 +
const byte pinMotor3Neg = 5; //motor #3 -

const byte analogPin1 = A0; //read location for bypass valve pot
const byte analogPin2 = A1; //read location for flapper valve pot
const byte analogPin3 = A2; //read location for temp sensor

unsigned long previousMillis = 0;
unsigned long interval = 2000;


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

  pinMode(pinMotor1Plus, OUTPUT);
  pinMode(pinMotorNeg, OUTPUT);
  pinMode(pinMotor3Plus, OUTPUT);
  pinMode(pinMotor3Neg, OUTPUT);
  pinMode(pinMotor2PWM, OUTPUT);

  digitalWrite(pinMotor1Plus, LOW);
  digitalWrite(pinMotorNeg, LOW);
  digitalWrite(pinMotor3Plus, LOW);
  digitalWrite(pinMotor3Neg, LOW);
  analogWrite(pinMotor2PWM, 50);
}

void loop() {
  float refvoltage; //comparison value for reference signals...provided by arduino
  float tempF; //temperature converted to Fahrenheit
  int temprequest; //requested change from android app
  int fanSpeed; //calculated value based on val
  int value; //another calculated value based on val, for a different purpose
  int val;
  int potvoltage1;
  int potvoltage2;


  if (Serial.available() >= 2 ) {
    unsigned int a = Serial.read();
    unsigned int b = Serial.read();
    unsigned int val = (b * 256) + a;

    // ********************* 200 TO 300 *********************
    if (val > 200 && val < 300) { //requested change in fan speed
      fanSpeed = ((val - 200) * 12.5);
      analogWrite(pinMotor2PWM, fanSpeed);
    }


    // ********************* 300 TO 400 *********************
    else if (val > 300 && val < 400) { //requested new flapper zone
      value = ((val - 300) * 261);
      potvoltage2 = analogRead(analogPin2);
      if (value < potvoltage2) {
        digitalWrite(pinMotor3Plus, HIGH);
        digitalWrite(pinMotor3Neg, LOW);
        while (value < analogRead(analogPin2));
      } else if (value > potvoltage2) {
        digitalWrite(pinMotor3Plus, LOW);
        digitalWrite(pinMotor3Neg, HIGH);
        while (value > analogRead(analogPin2));
      }
    }

    // ********************* 100 TO 200 *********************
    else if (val > 100 && val < 200) { // change in temperature setting
      potvoltage1 = analogRead(analogPin1);
      tempF = ((analogRead(analogPin2) - 0.5) * 180.0) + 32.0;
      Serial.println(tempF);
      temprequest = (val - 100);
      if (val == 164 ) {
        while (potvoltage1 > 41 ); // where 41 = bypass valve closed pot signal voltage
        digitalWrite(pinMotor1Plus, HIGH);
        digitalWrite(pinMotorNeg, LOW);
        potvoltage1 = analogRead(analogPin1);
      }
      else if (val == 186) {
        while (potvoltage1 < 977 ); // where potvoltage is the signal voltage from the bypass valve and 977 = bypass valve open pot signal voltage
        digitalWrite(pinMotorNeg, HIGH);
        digitalWrite(pinMotor1Plus, LOW);
        potvoltage1 = analogRead(analogPin1);
      }
      else if (val > 64 && val < 86 ) { // begin loop to move valve aperture
        while (tempF < temprequest) { // temperature requested is hotter than current temp
          while (refvoltage > potvoltage1) {
            unsigned long currentMillis = millis();
            if (currentMillis - previousMillis < interval) {
              previousMillis = currentMillis;
              refvoltage = (refvoltage + 40); //where refvoltage is the reference voltage for the next segment (1/24th)
              digitalWrite(pinMotorNeg, HIGH);
              digitalWrite(pinMotor1Plus, LOW);
            }
          }
        }
        while (tempF > temprequest) // temperature requested is cooler than current temp
        {
          while (refvoltage < potvoltage1)
          {
            unsigned long currentMillis = millis();
            if (currentMillis - previousMillis < interval)
            {
              previousMillis = currentMillis;
              refvoltage = (refvoltage - 40); //moving down the scale .2V at a time
              digitalWrite(pinMotor1Plus, HIGH);
              digitalWrite(pinMotorNeg, LOW);
            }
          }
        }
      }
    }
    // ******************************************************

  } // end if Serial >= 2
}

But..... not sure this is exactly what you want to do as there are probably bugs or weird stuff:

Some comments:

refvoltage is a local variable to the loop and is not initialized so not sure what the while (refvoltage > potvoltage1) will do

what is that supposed to do?

while (refvoltage > potvoltage1) {
            unsigned long currentMillis = millis();
            if (currentMillis - previousMillis < interval) {
              previousMillis = currentMillis;
              refvoltage = (refvoltage + 40); //where refvoltage is the reference voltage for the next segment (1/24th)
              digitalWrite(pinMotorNeg, HIGH);
              digitalWrite(pinMotor1Plus, LOW);
            }

The way you handle millis() there does not work (I suppose you want a timeout), but here the way this is written (currentMillis - previousMillis) will always be 0, may be 1 from time to time

probably need to dig into your logic for each cases

I am able to control the brightness of a fan connected to the output pins designated for the fan speed.

Just what does "control the brightness of a fan" mean? Is that anything like controlling the speed of an LED?

PaulS:
Just what does "control the brightness of a fan" mean? Is that anything like controlling the speed of an LED?

not all fans are created equal :slight_smile:

Haha Yeah it was pretty late when I hit the "post" button. It was supposed to say "brightness of an LED connected to the fan control pins" but my sleep deprived brain squeezed it all together. I made the suggested changes but the compiler made me put all of the "temp" variables back in at the top. The refvoltage is used as a comparison value so the motor only moves a small amount at a time. I am trying to avoid the valve going full open and full closed back and forth and never settling in at the desired value. The value is set before the motor begins moving as the current position plus 40 (1/24th of the total range of motion) so the motor will move until the reference signal coming from the motor's pot equals the refvoltage, wait for the sensor to come up to temp, and then reevaluate. I will look into the mill is () but your suggestion doesn't include a comparison?