LCD slowness degrade all the process

Hi all,
In my current project (CNC coil winder) I want to display the turns count during winding.
As I need synchronized movements of 2 steppers, I do not use a special library to move my steppers and I use micros() with time value from 4000 (slower speed) to 350 (higher speed)

…
if ((micros() - YpreviousMicros) >= customDelayMapped && YpinState == LOW){
            digitalWrite(YstepPin,HIGH) ; 
            YpreviousMicros = micros();
            YpinState = HIGH ;
        }   
        if ( (micros() - YpreviousMicros) >= customDelayMapped && YpinState == HIGH) {
            digitalWrite(YstepPin,LOW) ;
            YpreviousMicros =  micros() ;
            YpinState = LOW ;
            // Update counters----------
            ++YstepsCount;      // +1
            ++YstepsQtyCount ;  // +1
            Xcount += XYratio ;
        }  
…

Each 200 steps (=1 turn) I want to actualize the counter value on LCD. The problem is that my LCD is in I2C and is so slow that updating the counter value slow down all the process…

Do you know a method to solve (or at least improve) this issue ?

Thanks for your help :wink:

The problem is that my LCD is in I2C and is so slow that updating the counter value slow down all the process…

No, the problem is that you haven't posted the code that deals with the LCD. Sending a short string of text to the LCD, with the new count, should not take that long.

PaulS:
No, the problem is that you haven't posted the code that deals with the LCD. Sending a short string of text to the LCD, with the new count, should not take that long.

Ooops...

void refreshCount(){
    activeLayerNbr = YstepsCount / YstepsPerLayer ; 
    if (activeLayerNbrLastValue < activeLayerNbr){
        activeLayerNbrLastValue = activeLayerNbr ;
        lcd.setCursor(8,1) ;
        lcd.print(activeLayerNbr) ;
    }
    activeTurnsNbr = YstepsCount / YstepsNbr ;
    if (activeTurnsNbrLastValue < activeTurnsNbr){
        activeTurnsNbrLastValue = activeTurnsNbr ;
        lcd.setCursor(6,2) ;
        lcd.print(activeTurnsNbr) ;
    }
}

In winding mode, refreshCount() was called every loop (just after windingMove() )

I have joined all the code in attachment.

CNC_coil_winder_0_61.ino (41.8 KB)

            switch (b) {
                VERBOSECASE(ClickEncoder::Pressed) ;
                VERBOSECASE(ClickEncoder::Held)

There should not be any code in a switch statement that is not part of a case.

Frankly, I don't think your problem is that printing the number of turns is causing problems. It is that you are printing to the LCD on every pass through loop(), even if nothing has changed.

The magic numbers in the code do not make for readable code.

The menu handling should be in a function, not in loop().

PaulS:

            switch (b) {

VERBOSECASE(ClickEncoder::Pressed) ;
                VERBOSECASE(ClickEncoder::Held)



There should not be any code in a switch statement that is not part of a case.--> Ok, this is now fixed.

Frankly, I don't think your problem is that printing the number of turns is causing problems. It is that you are printing to the LCD on every pass through loop(), even if nothing has changed.--> Really !? I was thinking that as activeLayerNbr, activeLayerNbrLastValue, activeTurnsNbr, activeTurnsNbrLastValue are unsigned integer, the result of activeLayerNbr = YstepsCount / YstepsPerLayer and activeTurnsNbr = YstepsCount / YstepsNbr will be integer and so lcd wrinting will be allowed only for increment of 1 and not every loop.

The magic numbers in the code do not make for readable code.--> sorry for that ... I try to improve my code, but programming is not my strong point.

The menu handling should be in a function, not in loop(). --> Again sorry for that ... if I had been able to do, I would have gladly

so lcd wrinting will be allowed only for increment of 1 and not every loop.

Really? What about all the other places where you write to the LCD? Like, the menu seems to be written on every pass.

PaulS:
Really? What about all the other places where you write to the LCD? Like, the menu seems to be written on every pass.

No, the LCD is written only once at each level change e.g. (it's the reason I use level and levelLastValue )

        if (levelLastValue != level){
                    levelLastValue = level ;    // Store the last level nbr
                    displayLevel(level) ;       // Display level 11
                    activateSteppers (LOW);
                    cursorPos = 0 ;
                    updateCoilData();   // update coil data
                    // Display actual coil values
                    lcd.setCursor(13,1) ;
                    lcd.print(coilWidth) ;
                    lcd.setCursor(13,2) ;
                    lcd.print(wireDia,3) ;
                    lcd.setCursor(13,3) ;
                    lcd.print(totalTurnsNbr) ;
                    tblWidth = sizeof(tabLocation11)/sizeof(uint8_t) ;
                }

No, the LCD is written only once at each level change e.g. (it's the reason I use level and levelLastValue )

It would be clearer if loop() didn't read like the Encyclopedia Britannica. Use some functions to handle the load.

scarou:
No, the LCD is written only once at each level change e.g. (it's the reason I use level and levelLastValue )

Pick a refresh rate on your LCD monitor and use that.

can you process at faster than once every 100-250milliseconds? If the user isn't responsible to interact based on the output to the LCD, then the answer is that refresh rates can be slower.

if(millis() - lastDisplayUpdateTime > SCREEN_UPDATE_INTERVAL)
{
  refreshLCD();
  lastDisplayUpdateTime += SCREEN_UPDATE_INTERVAL;
}