LiquidCrystal - display not refreshing

I have a UNO clone
2 thermocouples
1 I2C LCD
1 Relay
1 TB6600 Stepper motor driver

I use the thermocouples to monitor flue temperature on my wood burner. When the temp comes up the stepper closes an air valve. I was using a ULN2003 with a bunch of delays and this code worked. I wanted non-blocking stepper code and a stronger motor. I added the accelstepper library and a TB6600.

The TB6600/stepper performs as expected, but my display only updates ONCE at the end of a stepper move. It does not update during moves, and does not update when the motor is idle. I can push a button, the motor cycles, the screen updates once and freezes until the next push of a button. I would greatly appreciate any advice.

[code]

#include "max6675.h"
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <AccelStepper.h>

//thermocouple 1 FOR FLUE
int ktcSO = 8;
int ktcCS = 9;
int ktcCLK = 10;
//thermocouple 2 FOR FIREBOX
int ktc2SO = 5;
int ktc2CS = 6;
int ktc2CLK = 7;
//blower relay pin 4
int relay = 4;

MAX6675 ktc(ktcCLK, ktcCS, ktcSO);
MAX6675 ktc2(ktc2CLK, ktc2CS, ktc2SO);
LiquidCrystal_I2C lcd(0x3F, A4, A5);
float temp;
float temp2;
float temp3;

// AccelStepper Setup
AccelStepper stepper(1, A1, A2); //AccelStepper(motorInterfaceType, stepPin, dirPin);
// 1 = Easy Driver type interface
//  Pin A1 connected to STEP pin of Easy Driver
//  Pin A2 connected to DIR pin of Easy Driver

const byte fullclose = 0; //fully close valve button
const byte load = 1;  //opens the valve to load wood
const byte runposition = 2; //this sets the valve to the run position quickly
const byte home_switch = 3; //stops the stepper at home
//const byte ftemp = 5; //fakes the thermocouple
int rpm; // new variable sets stepper speed
int location; //new variable for stepper location
int ENA = A3; //enables rotation of stepper

// Stepper
// Stepper Travel Variables
int move_finished = 1; // Used to check if move is completed
long initial_homing = -1; // Used to Home Stepper at startup
int runningposition = -900; //steps for valve close to running position
int fullyclosed = -1000; //this is the steps to shut the valve fully
boolean alreadyRun = 0; //lock out valve from opening a second time w/o reset

void setup() {
  Serial.begin(9600);
  // give the MAX a little time to settle
  delay(500);
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.print("BOOTING");
  pinMode(relay, OUTPUT);
  digitalWrite(relay, LOW);
  delay(1000);
  //the following lines control stepper motor
  // initialize the 8 pin as an output:
  pinMode(home_switch, INPUT_PULLUP);
  pinMode(fullclose, INPUT_PULLUP);
  pinMode(load, INPUT_PULLUP);
  pinMode(runposition, INPUT_PULLUP);
  pinMode(ENA, OUTPUT);
  // pinMode(ftemp, INPUT_PULLUP); //FAKES THE THERMOCOUPLE
  // initialize the load pushbutton pin as an input:
  // pinMode(temp, INPUT_PULLUP); //digitalWrite(load, HIGH); //turn on internal pullup resistor
  Serial.begin(9600);
  lcd.clear();
  lcd.print("Homing......");
  stepperHome();
  // Serial.println("Homed to Open (Drain) position");
  //Serial.println(" ");
}

void loop() {
  // basic readout test
  temp = (ktc.readFahrenheit());
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Flue Temp");
  lcd.setCursor(10, 0);
  lcd.print(temp);
  lcd.print("F");
  temp2 = (ktc2.readFahrenheit() - 10);
  lcd.setCursor(0, 1);
  lcd.print("Firebox Temp");
  lcd.setCursor(13, 1);
  lcd.print(temp2);
  lcd.print("F");
  lcd.setCursor(0, 2);
  lcd.print("Fan");
  lcd.setCursor(4, 2);
  if (temp2 < 190)
  {
    lcd.print("LOW");
    digitalWrite(relay, HIGH);//will switch the relay NO, Fan Low
  }

  else if (temp2 > 195)
  {
    lcd.print("HIGH");
    digitalWrite(relay, LOW); //will switch the relay NC, Fan High
  }
  //delay(500);

  //if (temp2 < 190)
  {
    //digitalWrite(relay, HIGH); //will switch the relay NO, Fan Low
    //delay(2000);
  }

  //else if (temp2 > 195)
  {
    //digitalWrite(relay, LOW); //will switch the relay NC, Fan High
    //delay(2000); //Delay 2 sec.
  }

  //the following lines control stepper motor

  if (digitalRead(load) == LOW)
  {
    stepperHome();
    alreadyRun = 0;
  }
  if ((temp > 550) && (alreadyRun == 0))
  {
    alreadyRun = 1;
    rpm = 10;
    location = runningposition;
    closeAir();
    // delay(1000);
  }

  if (digitalRead(fullclose) == LOW)
  {
    stepperHome();
    //delay(5000);
    rpm = 200;
    location = fullyclosed;
    closeAir();
    alreadyRun = 1;
    //delay(1000);
  }

  if (digitalRead(runposition) == LOW)
  {
    stepperHome();
    rpm = 200;
    location = runningposition;
    closeAir();
    alreadyRun = 1;
  }
}

void closeAir() //this is the low speed close
{

  forward();
  lcd.clear();
  lcd.setCursor(0, 3);
  lcd.print("valve position");
  lcd.setCursor(15, 3);
  //lcd.print(steptemp);
}

//moves air valve to full close
void shutAir ()
{
  {
    forward();       //going forward
    lcd.clear();
    lcd.setCursor(0, 3);
    lcd.print("Closing Valve");
    lcd.setCursor(15, 3);

  }

}

void stepperHome()
{
  stepper.setMaxSpeed(50.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepper.setAcceleration(100.0);  // Set Acceleration of Stepper
  digitalWrite(ENA, LOW);
  // Start Homing procedure of Stepper Motor at startup

  Serial.print("Stepper is Homing . . . . . . . . . . . ");

  while (digitalRead(home_switch))
  {
    // Make the Stepper move CCW until the switch is activated
    stepper.moveTo(initial_homing);  // Set the position to move to
    initial_homing++;  // Decrease by 1 for next move if needed
    stepper.run();  // Start moving the stepper
    delay(5);
  }

  stepper.setCurrentPosition(0);  // Set the current position as zero for now
  stepper.setMaxSpeed(50.0);      // Set Max Speed of Stepper (Slower to get better accuracy)
  stepper.setAcceleration(100.0);  // Set Acceleration of Stepper
  initial_homing = 1;

  while (!digitalRead(home_switch))
  {
    // Make the Stepper move CW until the switch is deactivated
    stepper.moveTo(initial_homing);
    stepper.run();
    initial_homing--;
    delay(5);
  }

  stepper.setCurrentPosition(0);
  Serial.println("Homing Completed");
  digitalWrite(ENA, HIGH);

}


//these functions set the pin settings for each of the four steps per rotation of the motor (keep in mind that the motor in the kit is geared down,
//i.e. there are many steps necessary per rotation



//these functions run the above configurations in forward and reverse order
//the direction of a stepper motor depends on the order in which the coils are turned on.
void forward()
{
  //one tooth forward
  digitalWrite(ENA, LOW);
  stepper.setMaxSpeed(rpm);
  stepper.setAcceleration(5000);
  // Set the target position:
  stepper.moveTo(location);
  // Run to target position with set speed and acceleration/deceleration:
  stepper.runToPosition();
  digitalWrite(ENA, HIGH);
}

void forwardslow()
{
  //one tooth forward
  digitalWrite(relay, LOW);
  digitalWrite(ENA, LOW);
  stepper.setMaxSpeed(rpm);
  stepper.setAcceleration(90000);
  // Set the target position:
  stepper.moveTo(location);
  // Run to target position with set speed and acceleration/deceleration:
  stepper.runToPosition();
  digitalWrite(ENA, HIGH);

}

[/code]

Wood_Stove_Blower_stepper_driver.ino (6.58 KB)

That is probably because the stepper library you're using can't use cooperative multitasking. There is no way to fix that in your code. You would need a non-blocking stepper library (if there is one).

I thought the accelstepper library was non blocking?

rlfairey:
I thought the library is non blocking?

If so, you can still break the multitasking by not running the update method every time through loop() - you might have placed it inside some looping construct.

Have you obeyed this rule about run(), from the docs?
“You must call this as frequently as possible, but at least once per minimum step time interval, preferably in your main loop.”

I call stepper.run and stepper.runToPosition when I need the motor to move. Otherwise I am only looking for button press and temperature.

I don't call a run() function in my main loop as I only need movement occasionally.

Wrong. This is what is killing you. run() doesn't do anything after a target position is reached. Again, you are using a non-blocking library in a blocking way.

holy cow! is it possible to stop the motor when using this library? If the motor stops, does the program freeze until the motor moves again?

Yes, you can fully control the motor. It will not freeze either. I guess you just don't understand how cooperative multitasking works. You need to bear down on that knowledge, or you won't get anywhere. Don't the library examples show how run() is supposed to be used?

I had a lousy C++ professor in 2004. This is my first dive back into C++ and my first dive into Arduino. So I don't understand a lot of the concepts, but I can manipulate code which is similar to what I want.

I appreciate your help and any reading/reference material you can point me to.

Thank you for the help!

This should give you some ideas...AccelStepper: Examples
This shows what I meant about run():

void setup()
{  
}
void loop()
{
    if (stepper.distanceToGo() == 0)
    {
        // Random change to speed, position and acceleration
        // Make sure we dont get 0 speed or accelerations
        delay(1000);
        stepper.moveTo(rand() % 200);
        stepper.setMaxSpeed((rand() % 200) + 1);
        stepper.setAcceleration((rand() % 200) + 1);
    }
    stepper.run();
}

This code is non-blocking and could be doing other things in loop() while something like moveTo() is running. Realize that moveTo() doesn't complete a stepper operation before the next statement, it only enables it. run() then does the work.

aarg - thank you for the advice. I was able to work out the blocking code sections. What I have now found is the commands for LCD and the thermocouples are slowing down the stepper motions. If I block the LCD and KTC the stepper runs quickly.

Is there suggested reading to slow down the polling rate for the display so I can free up some processor speed for the stepper?

Thanks for your help!

got it figured out. I used millis to call the temp and LCD functions every six seconds, that gives me a good enough screen refresh rate and lets the stepper make its moves without interruption