Go Down

Topic: Pay to troubleshoot my program (Read 329 times) previous topic - next topic

scott_funkhouser

Jan 08, 2018, 06:51 am Last Edit: Jan 09, 2018, 10:24 am by robtillaart
I have written a program to control my truck's climate control system from my phone. The program is written, and some parts of it work, but not enough to be functional.

The two essentials of the project are that the brains of the system are an arduino, and that the device used to control the temperature is a Thermotion bypass control valve (you can Google this to see what it is).

First, the inputs are sent to the Arduino by an app I have written.  I can send the app if needed.

The ranges are thus: a 1 byte number from 201 to 220 controls the speed of the fan. This is done via PWM and sends power to the fan through mosfets. This is the part of the program that actually works correctly.  I have tested it and used it to control the brightness of an LED from my phone. 

The second part of the program is the range selector (floor, defrost,etc), and is controlled by a single byte number 301 to 304. The hardware for this part of the program consists of an actuator motor that is controlled like a servo.  I haven't tested it in place so I'm not exactly sure of the positions but once the program works correctly I can fine tune the stopping angles.

This loop in the program reads all of the inputs correctly but seems to stall after one iteration. I have inserted some println commands and they output the expected information. Something seems broken in the loop. 

The third range is for controlling the temperature. The range of numbers is 164 to 186. 164 is for full close of the valve which is indicated by 674 bits. 186 is for full open of the valve and is indicated by 1112 bits. 65 through 85 cause a comparison between the incoming 1 byte number and the reading from an lm35 temperature sensor.

The Arduino does the comparison between the incoming 1 byte number and the temperature and either opens or closes the valve (which controls the coolant coming in from the engine) to regulate the temperature. The valve is powered by an lm298 bipolarity motor controller. The critical point for this operation is that it happens slowly without freezing out the other functions so that the fan or zone can be adjusted while the temperature is acclimating itself. 

Currently I am using millis for this and was attempting to add the 200-300 loops and 300-400 loops to the inside of the temperature adjusting loops when I realized the program wasn't working and abandoned progress to get the existing work running. 

That's pretty much where I'm at.  I'm willing to pay a fair price to get this working because I currently don't have a heater in my truck and it's below freezing here most days right now. 

Please post any questions, I'm sure I've left things out. 
Thank you

Code: [Select]

int pinMotor1Plus = 2; //motor #1 +
int pinMotorNeg = 3; //motor #1 -
const byte pinMotor2PWM = 9; //motor 2 pwm
const byte pinMotor3Plus = 4; //motor #3 +
const byte pinMotor3Neg = 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

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() {
  // put your main code here, to run repeatedly:

  float refvoltage; //comparison value for reference signals...provided by arduino
  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 potvoltage1; //input from motor1 position
  int potvoltage2; //input from motor3 position
  int val; //bluetooth data in

  int tempF; //temperature converted to Fahrenheit
  float tempS;//value from temp sensor
  float tempC;//calulated value of temp sensor in Celsius


  if (Serial.available() >= 2 ) {
    unsigned int a = Serial.read();
    unsigned int b = Serial.read();
    val = (b * 256) + a;
    //Serial.println(val);
  }
  //*******************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) {
     
      Serial.println(potvoltage2);
      while (value < analogRead(analogPin2));
      digitalWrite(pinMotor3Plus, HIGH);
      digitalWrite(pinMotor3Neg, LOW);
    }
    else if (value > potvoltage2) {
      while (value > analogRead(analogPin2));
      Serial.println(potvoltage2);
      digitalWrite(pinMotor3Plus, LOW);
      digitalWrite(pinMotor3Neg, HIGH);
    }
  }

  //*****************100 to 200*******************
  else if (val > 100 && val < 200) {// change in temperature setting
    potvoltage1 = analogRead(analogPin1);
    int refvoltage = analogRead(analogPin1);
    tempS = analogRead(analogPin3);
    tempC = (tempS * .48);
    tempF = (tempC * 1.8) + 32;
    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 (temprequest > 64 && temprequest < 86 ) { //begin loop to move valve aperture
      while (tempF < temprequest) {//temperature requested is hotter than current temp
        refvoltage = (potvoltage1 + 40);
        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) {
          refvoltage = (potvoltage1 - 40);
          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);
          }
        }
      }
    }
  }
}



moderator "paragraphed" the original text.

wvmarle

a single byte number 301 to 304.
I'm very bad at reading blobs of grey - please fix your Enter key - but this one stood out and points to some fundamental design issues in your program.

The range of an unsigned byte is 0-255.

Quote
164 is for full close of the valve which is indicated by 674 bits. 186 is for full open of the valve and is indicated by 1112 bits.
674 resp. 1112 bits are HUGE values (85 resp. 139 bytes worth of data!). That can't be right.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

scott_funkhouser

Not sure what is meant by "fix enter key." I was trying to describe analog input "analogRead()" You didn't even read the code. I am not a coder AT ALL. I watched some tutorials and Googled some other stuff and wrote some code. It sorta works and I want to finish it. If you would like to help with that, that would be super.

wvmarle

Not sure what is meant by "fix enter key."
Find your Enter key. If it works already, great, start using it. A big blob of grey is hard to read, a properly paragraphed text is.

Indeed I didn't start reading the code, that big blob of grey obscuring the description is hard enough - and if you try to send a "single byte" from your app and it's supposed to be a value that doesn't fit in a byte, you first have to fix that part as otherwise it can't work, period. No use trying to read the code.

There are three major parts to this project: the phone app providing input to your Arduino sketch; the Arduino sketch parsing that input and providing electronic signals to some external hardware, and the external hardware that does things based on the input. They all have to be fine.

Your description implies the app is broken. Make sure that the app works and provides the correct commands to your sketch (that includes byte values that are 0-255, not 300-something). Then when you have that, and can provide a complete and unambiguous description of commands that the app produces, the way it is sent to the sketch, and the outputs the sketch has to produce, then it's time to start looking at the sketch.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

PaulS

Quote
you can Google this to see what it is
Or you could (have) post(ed) a link. Which would have resulted in more interest?
The art of getting good answers lies in asking good questions.

robtillaart

#5
Jan 09, 2018, 10:37 am Last Edit: Jan 09, 2018, 10:41 am by robtillaart
A quick look at your code shows that you have multiple loops inside loop().

This is a common cause for freezing of applications, so maybe for your sketch too.

Furthermore the loop executes the last value received over and over again.
is this by design?


PS, I edited your post into a paragraphs.
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

scott_funkhouser

I was told nested loop()'s are ok.  Are you saying there are loops that overlap?  

WVMarle, as I mentioned in my description, my familiarity with this subject is minimal so I'm not sure what more I should include. Maybe it would be more effective and less argumentative if you could just indicate what more information is needed.  I am offering this as a PAYING gig for a completed, functioning code that will be appropriately compensated.  If you think you have the capabilities for that, make me a list of what you would like to know, give me an IDEA of the cost, and we can go from there.  If you don't think you're up to the task, maybe just conserve the space for interested, capable individuals so they don't have to scroll through 4 pages of nonsense to dig out any relevant material.

As for the app, I tried to include a link here, but I was unsuccessful.  I am a carpenter, and not the most tech savvy. It can be downloaded at the MIT App Inventor 2 GALLERY by searching carclimatecontrol_copy.  I double checked last night and the data being sent from the APP is, in fact, a TWO byte number so the data range is appropriate.  You will also notice, if you read the code, that I have inserted some (currently commented out) println commands.  These commands do, in fact, print out the expected values on the serial monitor.  I have also previously added println(val) commands in the different loops to make sure the correct data is reaching the appropriate areas in the program.  They also all worked as expected.

Regarding the hardware, the main piece is the Thermotion coolant bypass control valve https://www.thermotion.com/4-port-electronic-heater-control-valve-pn-354-69694 The manufacturer's website doesn't get much into technical specifics but I have tested it with a quick program to see the values returned at full open and full close position and the analogRead() values for these positions are 674 (closed) and 1110 (open).  The temp sensor is an LM35. The fan speed is a pwm signal controlling a 12V, 20A signal through a bank of MOSFET's. This is the one part of the program that seems to perform correctly and consistently. The mode control for the 300-400 loop of the program is done via an actuator motor https://www.partsgeek.com/gbproducts/DC/3381-05237373.html?utm_content=DN&utm_term=1995-1998+Chevrolet+K1500+HVAC+Floor+Mode+Door+Actuator+Standard+Motor+Products+95-98+Chevrolet+HVAC+Floor+Mode+Door+Actuator+1997+1996&utm_source=google&utm_medium=ff&utm_campaign=PartsGeek+Google+Base&gclid=Cj0KCQiA7dHSBRDEARIsAJhAHwjE__Rs33LVOajFZRdDViPe_-6ySTtcflJYvjduCw1xpYu_2V8YL-EaAsivEALw_wcB&ad=47433966132 that is controlled EXACTLY like a servo.
This will be supplied power from the 5v power supply included in the lm298 dual H-bridge motor controller that I have used to control the coolant bypass valve as well and needs only the signal from the arduino.

I hope I have included enough information to get this program completed.  If not I am happy to do more research and find out whatever is requested.

Again, this is a paying gig.  An individual that is capable of getting this program running will be well compensated.  I don't go to work and work all day for free, and I wouldn't expect anyone else to.  If you think you can accomplish this maybe play around with the code, get an idea of how long it will take and what it will cost, and shoot me a PM.  The Thermotion valve can be had for $50 and a 96 GM climate control actuator can be had at a junkyard for $12, or if it's easier, once I have reached an agreement with someone I can ship the hardware I have.  Again, I'm serious about this and seriously willing to pay.  Please get in touch.

Like my paragraphs?  

wvmarle

Paragraphing is a great improvement - with @robtillaart's edits I've also re-read your original message and am a bit clearer.

The thermotion web site is broken (Firefox won't open it; complains about an expired certificate).

I had a quick look at the sketch, and noticed there are several nested while statements. I haven't studied the exact code but those are often the cause of sketches getting stuck (e.g. while (a < 10) and then not updating a in the loop). There's quite some nesting going on there, there's comparing to a pot, comparing to temperature - both non/slow moving targets which is a recipe for disaster especially when combined.

For the details needed: I understand you're not technical, that's no crime. However it goes wrong when you start mixing up terminology. You say "a single byte value" but in your sketch I see you read two bytes at a time from Serial. So it's just "a single value" which happens to be in two bytes. Mind that anyone reading your post doesn't know anything about your project - what it is, what it does, what it should do... nothing at all. This is a nearly-completed thing, so correct technical details become important.

The communication between app and sketch is another concern. You send two bytes which form a single value, which is a combination of command and value, but no start/stop codes. What happens if one byte gets lost? You must have a way to account for and recover from that, as it will at times happen. That's part of telecommunication, it's not 100% reliable. Received data can never be trusted and must always be validated, especially if wireless (in this case: Bluetooth?).

From what I read so far, I'd do the communication different: one byte is the command (door, temperature, fan, ...), the second byte is the value that's to be written to it. You could use the value 255 as start and stop of communication (it looks like values are in the 0-100 range), then you get a three-byte communication but it's reliable. You wait for a 255, then read the next two values, and another 255. That sequence guarantees your communication is correct.

Then you should write up a list of expected commands and values, and what has to be done with it. There's probably no need to have the actual hardware, as without the other sensor input there's not much you can do.

Quote
an actuator motor that is controlled EXACTLY like a servo.
So you have successfully controlled it using the servo library? I don't see a servo control in your sketch. If so, that would make programming easy - all you have to tell is "this input has to produce that output" and it can be implemented. Otherwise, you have to provide details on how it's controlled.

analogRead() values for these positions are 674 (closed) and 1110 (open).
This is impossible, as analogRead() returns values 0-1023.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

robtillaart

#8
Jan 09, 2018, 08:02 pm Last Edit: Jan 09, 2018, 08:03 pm by robtillaart
rewrote the loop() to make code easier to oversee,
change temperature is the "difficult" part to understand

Code: (not tested) [Select]
//
// TODO HEADER
//
int pinMotor1Plus = 2;        // motor #1 +
int pinMotorNeg = 3;          // motor #1 -
const byte pinMotor2PWM = 9;  // motor 2 pwm
const byte pinMotor3Plus = 4; // motor #3 +
const byte pinMotor3Neg = 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

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


//////////////////////////////////////////////////
//
// SETUP SKETCH
//
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);
}


//////////////////////////////////////////////////
//
// MAIN LOOP
//
void loop()
{
  int val;
  // READ VALUE FROM SERIAL
  if (Serial.available() >= 2 )
  {
    unsigned int a = Serial.read();
    unsigned int b = Serial.read();
    val = (b * 256) + a;
  }

  // PROCESS INCOMING DATA
  if (200 < val && val < 300)
  {
    handleFan(val - 200);
  }
  if (300 < val && val < 400)
  {
    newFlapperZone(val - 300);
  }
  if (100 < val && val < 200)
  {
    changeTemperatureSetting(val);
  }
}


//////////////////////////////////////////////////
//
// HELPER FUNCTIONS
//
void changeTemperatureSetting(int value)
{
  int potvoltage1 = analogRead(analogPin1);
  int refvoltage = analogRead(analogPin1);      // same pin twice ????

  float tempC = analogRead(analogPin3) * 0.48;
  float tempF = (tempC * 1.8) + 32;
  Serial.println(tempF);

  int temprequest = value - 100;

  if (value == 164 )
  {
    // potvoltage is the signal voltage from the bypass valve
    // where 41 = bypass valve closed pot signal voltage
    while (potvoltage1 > 41 )
    {
      digitalWrite(pinMotor1Plus, HIGH);
      digitalWrite(pinMotorNeg, LOW);
      potvoltage1 = analogRead(analogPin1);
    }
  }
  else if (value == 186)
  {
    // potvoltage is the signal voltage from the bypass valve
    // and 977 = bypass valve open pot signal voltage
    while (potvoltage1 < 977 )
    {
      digitalWrite(pinMotorNeg, HIGH);
      digitalWrite(pinMotor1Plus, LOW);
      potvoltage1 = analogRead(analogPin1);
    }
  }
  else if (64 < temprequest && temprequest < 86 )
  {
    //begin loop to move valve aperture
    //temperature requested is hotter than current temp
    while (tempF < temprequest)
    {
      refvoltage = potvoltage1 + 40;
      while (refvoltage > potvoltage1)
      {
        unsigned long currentMillis = millis();
        if ((currentMillis - previousMillis) < interval)
        {
          previousMillis = currentMillis;
          // where refvoltage is the reference voltage for the next segment (1/24th)
          refvoltage = refvoltage + 40;
          digitalWrite(pinMotorNeg, HIGH);
          digitalWrite(pinMotor1Plus, LOW);
        }
      }
    }
    while (tempF > temprequest)
    {
      // temperature requested is cooler than current temp
      while (refvoltage < potvoltage1)
      {
        refvoltage = (potvoltage1 - 40);
        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);
        }
      }
    }
  }
}



void newFlapperZone(int value)
{
  value = value * 261;
  int potvoltage2 = analogRead(analogPin2);
  if (value < potvoltage2)
  {
    Serial.println(potvoltage2);
    while (value < analogRead(analogPin2));   // this line can block as it waits for the analog pot to turn
    digitalWrite(pinMotor3Plus, HIGH);
    digitalWrite(pinMotor3Neg, LOW);
  }
  else if (value > potvoltage2) {
    while (value > analogRead(analogPin2));   // this line can block as it waits for the analog pot to turn
    Serial.println(potvoltage2);
    digitalWrite(pinMotor3Plus, LOW);
    digitalWrite(pinMotor3Neg, HIGH);
  }
}


void handleFan(int value)
{
  int fanSpeed = value * 12.5;
  fanSpeed = constrain(fanSpeed, 0, 255);
  analogWrite(pinMotor2PWM, fanSpeed);
}


The change temperature needs to be rewritten inanother way.

TBC
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

robtillaart

#9
Jan 09, 2018, 08:51 pm Last Edit: Jan 09, 2018, 08:54 pm by robtillaart
Cleaned up a bit more, removed some whiles that aren't needed,
added minimal comments

Can you please check if you read the code that it makes sense / does what you want to?

Code: (still not tested) [Select]
//
//    FILE: test.ino
//  AUTHOR: Rob Tillaart
// VERSION: 0.0.1
// HISTORY:
// 0.0.1    2018-01-08 initial version
//

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

const int bypassValvePin = A0;    // read location for bypass valve pot
const int flapperValvePin = A1;   // read location for flapper valve pot
const int temperaturePin = A2;    // read location for temp sensor

int tempRequestF = 70;         // acceptable initial value?
const int minTempF = 64;
const int maxTempF = 86;

//////////////////////////////////////////////////
//
// SETUP SKETCH
//
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);
}


//////////////////////////////////////////////////
//
// MAIN LOOP
//
void loop()
{
  int val = 0;
  // READ VALUE FROM SERIAL
  if (Serial.available() >= 2 )
  {
    unsigned int a = Serial.read();
    unsigned int b = Serial.read();
    val = (b * 256) + a;
  }

  // PROCESS INCOMING DATA
  if (100 < val && val < 200)
  {
    tempRequestF = val - 100;
  }
  if (200 < val && val < 300)
  {
    handleFan(val - 200);
  }
  if (300 < val && val < 400)
  {
    newFlapperZone(val - 300);
  }

  // updates one step the temperature to tempRequest
  // in every iteration of loop()
  updateTemperature();
}


//////////////////////////////////////////////////
//
// HELPER FUNCTIONS
//

// updateTemperature makes one step per call
void updateTemperature()
{
  // HANDLE MINIMUM
  if (tempRequestF == minTempF)
  {
    // potvoltage is the signal voltage from the bypass valve
    // where 41 = bypass valve closed pot signal voltage
    int potvoltage1 = analogRead(bypassValvePin);
    Serial.print("REQUESTTEMP: ");
    Serial.print(tempRequestF);
    Serial.print("\tPOTVOLTAGE1: ");
    Serial.println(potvoltage1);
    if ( potvoltage1 > 41 )
    {
      cool();
    }
    return;
  }


  // HANDLE MAXIMUM
  if (tempRequestF == maxTempF)
  {
    // potvoltage is the signal voltage from the bypass valve
    // and 977 = bypass valve open pot signal voltage
    int potvoltage1 = analogRead(bypassValvePin);
    Serial.print("REQUESTTEMP: ");
    Serial.print(tempRequestF);
    Serial.print("\tPOTVOLTAGE1: ");
    Serial.println(potvoltage1);
    if (potvoltage1 < 977 )
    {
      heat();
    }
    return;
  }


  // HANDLE BETWEEN MIN and MAX
  if (minTempF < tempRequestF && tempRequestF < maxTempF )
  {
    // DETERMINE CURRENT TEMPERATURE
    float tempC = analogRead(temperaturePin) * 0.48;
    float tempF = (tempC * 1.8) + 32;
    Serial.print("REQUESTTEMP: ");
    Serial.print(tempRequestF);
    Serial.print("\tACTUALTEMP : ");
    Serial.println(tempF);

    // ADJUST TEMPERATURE
    if (tempF < tempRequestF)
    {
      heat();
    }
    else
    {
      cool();
    }
  }
}


void cool()
{
  digitalWrite(pinMotor1Plus, HIGH);
  digitalWrite(pinMotorNeg, LOW);
}


void heat()
{
  digitalWrite(pinMotorNeg, HIGH);
  digitalWrite(pinMotor1Plus, LOW);
}


void newFlapperZone(int value)
{
  Serial.println("NEWFLAPPERZONE");
  value = value * 261;
 
  int potvoltage2 = analogRead(flapperValvePin);
  Serial.print("VALUE: ");
  Serial.println(value);
  Serial.print("POTVOLTAGE2: ");
  Serial.println(potvoltage2);
 
  while (value < potvoltage2)
  {
    potvoltage2 = analogRead(flapperValvePin);
    Serial.print("POTVOLTAGE2: ");
    Serial.println(potvoltage2);
    digitalWrite(pinMotor3Plus, HIGH);
    digitalWrite(pinMotor3Neg, LOW);
  }
  while (value > potvoltage2)
  {
    potvoltage2 = analogRead(flapperValvePin);
    Serial.print("POTVOLTAGE2: ");
    Serial.println(potvoltage2);
    digitalWrite(pinMotor3Plus, LOW);
    digitalWrite(pinMotor3Neg, HIGH);
  }
}


void handleFan(int value)
{
  Serial.println("HANDLEFAN");
  int fanSpeed = value * 12.5;
  fanSpeed = constrain(fanSpeed, 0, 255);
  analogWrite(pinMotor2PWM, fanSpeed);
}


give it a try
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

scott_funkhouser

It feels like it performs the way I had envisioned.  I like that you broke it into functions.  I tried that myself and I think I got a little carried away, and never got that iteration to work either.

Unfortunately I am currently awaiting delivery of one atmega328 with a bootloader installed, and six more blanks because I've already burned through three Arduinos. Don't know what I'm doing wrong but hopefully once I get the system up and running I can get it stabilized enough to avoid this issue. Anyways, once they show up I'll get it set up and run your code through it.

I did notice a couple small issues that are exactly as I wrote them, I just never saw them before because I had been staring at the screen for hours, but they're minor data issues that won't affect the flow of the program itself, which is where I was failing.

I wonder if you might have some insight into another small issue I was experience during testing: the coolant bypass valve that controls the temperature, is a servo-like motor that turns a butterfly valve connecting the supply and return hoses from the engine to the heater. It differs from a servo in that it is controlled by reversing the polarity (thus the pinmotor1Plus and pinmotor1Neg swapping from high to low).  The position of this butterfly valve is monitored via a potentiometer that turns as the motor turns. While I was frustrated with the overall program not functioning I wrote a separate small program to test the values being returned from this potentiometer. With an analogRead() performed on this potentiometer and executed by the same app that operates the overall system, with a quick sweep of the slider bar the value returned starts way off and then eventually stabilizes. If I wait a few seconds and try again it again settles in at the same value. I feel like the value is correct because it always ends up on the same value, but the first few samples are not good and this will affect the program's operation. Is there something I can do like adding a resistor, or possibly comparing the analogRead() value returned with the system voltage?  Or something else?

robtillaart

I do not have experience with such bypass valves, but from your description I understand (that's allways an assumption) their working.

What you describe sounds like noise on the potentiometer.
This should be visible in the logging generated.

Possible fixes:
  * a low pass filter for every analog pin helps (resistor + capacitor)
  * read potmeters twice and use the last value to give it time to settle.
  * divide all read potmeter values by 4 to remove 2 bits of noise. This changes the math in some places.



With respect to the burned 328's.
Q: Can you post a schematic (drawing / photo ) that shows how you connected the Arduino ?

Q: Is it possible that the Arduino gets connected to more than 5V? ( 12V 24V whatever, peak surges )

Q: how much current do the valves draw?
You might need a transistor/mosfet to control the valves.
With respect to that in the code, what is missing imho is a "IDLE mode". This IDLE mode does not change the position of the valve but switches off the motor. Therefor it does not put a constant load on the Arduino and the valves. It should be called when the final position is reached. In code this IDLE looks like.
Code: (snippet) [Select]
void valveIdle()
{
  digitalWrite(pinPlus, LOW);
  digitalWrite(pinNeg, LOW);
}


just some morning thoughts :)
Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

PaulS

Quote
I was told nested loop()'s are ok.
Nested loops are OK. Nested loop()s are NOT. For, while, and do/while statements cause looping. They can be nested to your heart's content. The loop() function must exist only once.
The art of getting good answers lies in asking good questions.

scott_funkhouser

Thanks for the lead on the potentiometer, Rob. I'll do more research on the filter.  I did try multiple samples but it still took several iterations of the loop() before the readings stabilized.  I was doing 6 samples and throwing out the first five, using the sixth, so there's a chance that average might be slightly more accurate but the readings start at 170something and eventually level out at 68 so that's a pretty large disparity, even with an average.  I tried a resistor between the ground leg of the pot and ground but that made the temp sensor reading go bonkers.  Maybe I need to do a comparison with the system voltage rather than just a simple read, that way as the voltage fluctuates the readings remain constant as a percentage of the system voltage? I don't know. More research is definitely in order.

I definitely agree regarding the idle state. It was my intention that the motors not run constantly that's why I commanded their function in a loop assuming (erroneously it seems) that the power went off at the end of the loop.  I LITERALLY have hours of experience with the Arduino's so please don't laugh. The other state that I was trying to create was, while the bypass valve is adjusting it needs to have small pauses.  The concern is that as the system's termperature approaches the requested temperature, there will be a lag in the readings from the temperature sensor as the external temperature of the sensor will take a couple seconds to reach the inside. This will cause the valve to overshoot the target and then eventually head back in the opposite direction resulting in constant hunt for the correct temperature and reducing the system's longevity.  I initially considered delay but I definitely don't want to shut down the whole system while this part of the program is working.  I also considered millis, which I thought should be better, but still seemed clunky. My final attempt is what you saw in my original code, using millis but nesting the functions of fanspeed and flapper WITHIN the temperature adjusting function. I don't know whether this was adequate or if it could possibly even be done without using millis and maybe that would be enough. I just know that the valve must make small pauses, and that a user must be able to select a temperature and then still be able to adjust the fan and zone while the temperature is working.

As far as the diagram I am a horrible drawer. I will make an attempt this morning but no promises.  The power for the system is 12 Volts (this is an automotive system).  This power is applied to the lm298 dual H-Bridge controller.  It applies volts to the bypass valve and actuator motor as commanded by the arduino via the analog outputs. It is essentially a polarity switching relay.  The lm298 has a provision for 5V output that I use to power the arduino and the attached protoshield. The protoshield supplies power for the hc05. The arduino ONLY provides power to the temperature sensor (lm35 module) and of course the various signals such as digital outs for motors that are amplified, and a PWM signal for the fan that controls the gate of a MOSFET transistor only. There is little to no load on the arduino itself. I'm guessing the issue is in a wire that contacted another wire and I am trying to isolate some of the connections, the problem is that with the program not functioning properly I have needed to keep some of the connections accessible to individually connect components.  Hopefully next week when I get my new shipment of atmega328's, with the more professionally written code I can make more of the connections permanent. I ordered 7 of them so I'm hoping for the best.  Maybe I'll even have one left over to make the WiFi thermostat for the house that I want. Baby steps.

Go Up