Go Down

Topic: Arduino/touch screen climate control (Read 1 time) previous topic - next topic

scott_funkhouser

Dec 16, 2017, 05:00 pm Last Edit: Dec 16, 2017, 07:05 pm by scott_funkhouser Reason: Code delineation
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.

Code: [Select]


#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);
            }
          }
        }
      }



    }



  }
}



scott_funkhouser

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.

J-M-L

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

It should look like this:
Code: [Select]
// your code is here
(Also press ctrl-T (PC) or cmd-T (Mac) in the IDE before copying to indent your code properly)
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

scott_funkhouser

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

J-M-L

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

This means if the test is true do nothing
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

scott_funkhouser

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.

J-M-L

#6
Dec 16, 2017, 07:18 pm Last Edit: Dec 16, 2017, 07:50 pm by J-M-L
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 == ((val - 300) * 261);

In this code
Code: [Select]
   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
Code: [Select]
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?)
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

scott_funkhouser

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

scott_funkhouser

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.

outsider

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

J-M-L

#10
Dec 16, 2017, 11:28 pm Last Edit: Dec 16, 2017, 11:32 pm by J-M-L
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
Code: [Select]
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.
Code: [Select]
    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
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

scott_funkhouser

#11
Dec 17, 2017, 05:47 pm Last Edit: Dec 17, 2017, 06:39 pm by scott_funkhouser
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.

scott_funkhouser

 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.

 
Code: [Select]
if (value < potvoltage2) {
        digitalWrite(pin3, HIGH);
        digitalWrite(pin4, LOW);
        while (value < potvoltage2)  potvoltage2 =
         analogRead(analogPin2);
      }

J-M-L

#13
Dec 17, 2017, 07:57 pm Last Edit: Dec 17, 2017, 08:03 pm by J-M-L
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 (condition) expression;

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

while (condition) dothis();
doThat();
will call the doThis() and when the while ends will call the doThat() whereas if I had written 
Code: [Select]
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
Code: [Select]

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 :)


PS:
Quote
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
Code: [Select]
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
Please do not PM me for help,  others will benefit as well if you post your question publicly on the forums
Pas de messages privés SVP

scott_funkhouser

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.

Go Up