MD_PAROLA change message in display when another animation is runing

Hello everyone. I'm making a project using a LED display with the MD_PAROLA lib and i'm having a little problem with the exibition of my messages.
My project is very simple, i have a sensor to check pressure. When the pessure changes, I show a message and then the value the sensor reads, and untill here, it's all ok. The problem is, when my sensor is idle, i show a placeholder message with the effect PA_SCROLL_LEFT and, sometimes, the sensor make reading while the placeholder is in the middle of the animation. So, I need to just stop the placeholder and it's animation and change the message on the display. But no matter what i try, nothing stops this animation to complete itself before change the message, and this way, sometimes, i lost my reading.
I've already tried the methods displayClear() and displayReset(), but nothing happens, the display keep show the placeholder. Can anyone help me?

void showMessage() {
  if (display.displayAnimate()) {
    if(reading == true) {
      display.displayText("Assopre!", PA_CENTER, 0, 500, PA_PRINT, PA_PRINT);
      delay(500);
    }
    else if (resultReady == true) {
      display.displayText("FODEU!", PA_CENTER, 0, 3000, PA_PRINT, PA_PRINT);
      display.displayAnimate();
      delay(3000);
      display.displayText(sensorValue, PA_CENTER, 100, 5000, PA_FADE, PA_FADE);
      display.displayAnimate();
      resultReady = false;
      maxReading = 0;
    }
    else {
      display.displayText("Barfometro       ", PA_CENTER, 0, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
    }
    display.displayAnimate();
  }
}

This is the code I'm using to control the display. I know it's not pretty yet, but my objective is make it work first and then I'll adjust the repetitions.
The "else" is my placeholder.

Hello @rcorradi - Posting your complete sketch will help with finding the solution.

1 Like

Sure, no problem. I saw a few posts with only part of the code and though it is more easy to see. Here is full sketch:

#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>
#include <Q2HX711.h>

// Matrix Led Display Config
#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
#define MAX_DEVICES 6
#define DATA_PIN 12
#define CLK_PIN 11
#define CS_PIN 10
MD_Parola display = MD_Parola(HARDWARE_TYPE, DATA_PIN, CLK_PIN, CS_PIN, MAX_DEVICES);

// MCA sensor config
const byte pressure_out = 2;
const byte pressure_sck = 3;
Q2HX711 pressureSensor(pressure_out,pressure_sck);

// Vars to read and update alcohol sensor
char sensorValue [20];
int maxReading;
const unsigned long period = 4000; // //period during alcohol sensor reading
const int threshold = 90000;
unsigned long startMillis; // initial millis
unsigned long currentMillis; // millis on the loop
boolean reading;  // check if we are reading
boolean firstReading; // config the first reading
boolean resultReady;
boolean displayMessage;

void setup() {
  Serial.begin(9600);
  display.begin();
  reading = false;
  firstReading = true;
}

void loop() {
  showMessage();

  if (isBlowing() || reading) {

    if (!startMillis) {
      startMillis = millis();
    }

    currentMillis = millis();

    if (currentMillis - startMillis <= period) {

      if (!reading) {
        reading = true;
      }

      setBlowingValue();
      Serial.println("Atualizando Valor:");
      Serial.println(maxReading);

    }
    else {

      if (reading) {
        Serial.println("Valor final:");
        Serial.println(maxReading);
        transformIntToChar();
        resultReady = true;
        displayMessage = true;
        resetParammeters();
      }

    }
  }
  
  if (firstReading) {
    firstReading = false;
  }

}

void resetParammeters() {
  firstReading = true;
  reading = false;
  startMillis = 0;
}

void transformIntToChar() {
  sprintf (sensorValue, "%4d", maxReading);
}

void showMessage() {
  if (display.displayAnimate()) {
    if(reading) {
      display.displayText("Assopre!", PA_CENTER, 0, 1000, PA_PRINT, PA_PRINT);
    }
    else if (resultReady) {
      if (displayMessage) {
        display.displayText("FODEU!", PA_CENTER, 0, 3000, PA_PRINT, PA_PRINT);
        displayMessage = false;
      } else {
        display.displayText(sensorValue, PA_CENTER, 100, 5000, PA_FADE, PA_FADE);
        resultReady = false;
        maxReading = 0;
      }
    }
    else {
      display.displayText("Barfometro       ", PA_CENTER, 50, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
    }
  }
}

bool isBlowing() {
  int aux = pressureSensor.read() / 100;
  return aux >= threshold;
}

void setBlowingValue() {
  if (maxReading < analogRead(0)) {
    maxReading = analogRead(0);
  }
}

One more thing I noticed. I know that the animation is not being canceled to start another animation with another sentence because of the if (display.displayAnimate()) { line. In Parola's doc it says that this method ensures that the current animation completes and then returns a true assertion. But without this line I can't make the display show anything.

I do not have a pressure meter, but I can use a button. What values are you expecting for the sensor to activate?

When I start your code, I see "Barfometro"... and if I make "isBlowing()" return a HIGH by pressing a button, I see in the Serial Monitor "Atualizando Valor: 1023"... and when I release the button I see Assopre! and FOUDEO on the LED matrix, then in the Serial Monitor "Valor final:1023" after which I see "Barfometro" in the LED matrix again. How is this supposed to work?

Not important, but "firstReading" does nothing...

boolean firstReading; // config the first reading
.
.
void setup() {
.
.
  firstReading = true;
.
.
 void loop() {
.
.
 if (firstReading) {
    firstReading = false;
  }
.
.
void resetParammeters() {
  firstReading = true;
.
.
}

The pressure meter is just a trigger to start all process. If it doesn't receive an interaction, it makes constant reading showing the atmosphere pressure, in the readings of the sensor, it brings values between 83.000 and 84.500. When someone blows it, the sensor read bigger values and show results abouve 90.000. So, this is the only thing the sensor does and it is the trigger to start everything. To you test, the button will work to.
About the "firstReading", thanks for remember me that. It's a remnant of code that was removed and I forgot to remove everything.

About my problem. When you see "Barfometro" into your display, if you press the button while it is running from the right to the left, you'll see the animation need to complete before it shows the next message "Assopre!" (this is an order in portuguese and it means "Keep Blowing!").
But, all my reading have a short time box, only 4 seconds, and depending on what point of the animation of "Barformetro" you trigger the sensor, it will take all the reading time to show another message and the comand "Assopre!" will not appear, going to the next one "Fodeu".

So, after all, what i need is to cancel the animation of "Barfometro" whenever the trigger happens. I don't want to wait all the animation to show the comand "Assopre!" because i can lost the timming to show it.

Try to trigger your button when the first column of the word "Barfometro" shows on your screen and you'll see what I'm talking about. And thanks for reading all this.

Yes, I see the display must finish "Barfometro" before "Assopre!!"... but in the Serial Monitor "Atualizando Valor: 1023" is seen immediately on the trigger (I am using a switch, which is ON/1023 or OFF/0).

Do I understand that you want "Assopre!" immediately on the trigger? In post #4 you mentioned Parola doc says displayAnimate() ensures current animation completes... so it sounds like you want to stop displayAnimate()...

Have you tried displayClear() or displayReset() when the trigger happens?

Yes, I did try these methods, but i didn't had sucsses. Also, i tried to remove the displayAnimate() and nothing is showed on the display. I don't know if i missed something on the doc or if it isn't possible.

I think it is time to ask @marco_c about interrupting a MD_Parola displayAnimate() function...

1 Like

@rcorradi

Hello,

It is indeed possible to do what you want. Please read my comments as you consider this wokwi

Excellent example. (upper case "S")

The OP raised this as an issue at the github repository (here). A solution was proposed and OP was unable to make it work for him. Good to see he has sought help from a more appropriate forum.

displayAnimate() does not need to be interrupted. To stop an animation just stop calling it and displayReset() to reset/restart the display state machine. displayAnimate() will only do the NEXT step in the animation it is time to do that step. For PRINT animations, everything happens in one step. For all other animations this is not true and displayAnimate() will need to be called many times for the animation to complete. The code structure adopted by OP does not work in the general case.

Hello guys, thanks for your attention.

@marco_c I really didn't know where to look for help, so i found that topic on github and asked there.

@indev2 and @marco_c I'm trying to use your solution and really not happens, the animation on "Barfometro" keep going untill the end, before change the message. I changed my method to the exact steps in the example of Wokwi, and I see it working on the simulator, but in my device, nothing happens.

I changed only the method showMessage(), calling displayReset() after i show the message "Barfometro", and calling displayClear() before i try to show the message "Assopre!". I think i followed the example but don't know if I having any problem with the loop.

void showMessage() {
  if (display.displayAnimate()) {
    if(reading) {
      display.displayClear();
      display.displayText("Assopre!", PA_CENTER, 0, 200, PA_PRINT, PA_PRINT);
      display.displayAnimate();
    }
    else if (resultReady) {
      if (displayMessage) {
        display.displayText(drunkMessages[i][z], PA_CENTER, 10, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
        displayMessage = false;
      } else {
        display.displayText(sensorValue, PA_CENTER, 100, 5000, PA_FADE, PA_FADE);
        resultReady = false;
        maxReading = 0;
      }
    }
    else {
      display.displayText("Barfometro       ", PA_LEFT, 50, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
      display.displayReset();
    }
  }
}

Let me ask one thing I was thinking... This call display.displayText("Barfometro ", PA_LEFT, 50, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT); is on a else, wich means while the if don't find any other condition, it always set this message. So, could it be just a problem of when i change the pressure, there is alredy another call of that ready to execute? Should I isolate this in another if and change the condition when it run the first time, and it keep showing because no other message was prepared to show? Or i'm saying somethin non sense?

I have said this before, but this line
if (display.displayAnimate()) {
stops anything from happening until the animation is finished. The code I proposed was different.

Guys, forget my last post. After i look a lot, I found my error. The problem was that I was ALWAYS validating display.displayAnimate(), but while "Barfometro" was running, it always return false, so it never get into the if(reading) condition. So, I looked again into the simulator that @indev2 sent and saw that only the main message is inside this check, the other message that cancel the animation, was outside. So, I did it in my code and worked.

Thanks you all for your help, and I'm sorry if any of you already said that and i didn't get it. As I said, I'm new and there are things i don't get it.

Here, the final method

void showMessage() {
  if(reading) {
    display.displayClear();
    display.displayText("Assopre!", PA_CENTER, 0, 200, PA_PRINT, PA_PRINT);
    display.displayAnimate();
  }
  else if (resultReady) {
    if (displayMessage) {
      display.displayText(drunkMessages[i][z], PA_CENTER, 10, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
      displayMessage = false;
    } else {
       if (display.displayAnimate()) {
        display.displayText(sensorValue, PA_CENTER, 100, 5000, PA_FADE, PA_FADE);
        resultReady = false;
        maxReading = 0;
      }
    }
  }
  else {
    if (display.displayAnimate()) {
      display.displayText("Barfometro       ", PA_LEFT, 50, 0, PA_SCROLL_LEFT, PA_SCROLL_LEFT);
      display.displayReset();
    }
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.