Fixing the text scrolling and display a value in real time at a fixed position on monitor screen

Continuing the discussion from Clearing the data in Serial monitor:

Can I fix the text scroll and display only the voltage values (Vin1, Vin2) in the real time (at same position) ? Is the Arduino code has the function goto(x,y) to display a text character at a specific position in monitor screen ?

Here is my code:

/*
Display list Testing
*/

#include <stdio.h>
#include <time.h>
#include <stdlib.h>


void setup() {
  // start serial connection
  Serial.begin(9600);

  const int Vin1 = 5;       // D2 pin
  const int Vin2 = 6;       // D3 pin

  pinMode(Vin1, INPUT);       
  pinMode(Vin2, INPUT);        
 
}

void loop() {
  // Starting TEST
  Serial.print("Voltages measued: ");
  Serial.println("  ");

  int Vin1 = digitalRead(5);
  
  // print out the value on monitor
    Serial.print("Votage Vin1: ");
    Serial.println(Vin1);
  delay(500);

  int Vin2 = digitalRead(6);
  
  // print out the value on monitor
    Serial.print("Votage Vin2: ");
    Serial.println(Vin2);
  delay (500);
  
  // Serial.write(0x0C);
  }

Think of the Serial Monitor as a less functional printer (not even a backspace! for tilde or strikeout), not a terminal.

I like to add bling to my output by only printing values that change, and pad the values for "right alignment"...

byte potpin = A0;
int pot, oldpot;

void setup() {
  Serial.begin(115200);
}

void loop() {
  pot = analogRead(potpin); // read pot value
  if (pot != oldpot) { // has the value changed
    oldpot = pot; // store new reading
    pad(pot); // right-align value
    Serial.println(pot); // print value
  }
}

void pad(int val) {
  for (int i = 1000; i > 1; i /= 10) { // count numeral places from four to one
    if (val < i) // value has fewer places than counter
      Serial.print(" "); // pad the left side
  }
}

Think of it as a TTY without a keyboard and with minimal features. To gain control of the monitor screen, you’ll need to load a terminal program.

Instead of the serial monitor, use a terminal program that emulates a VT100 or similar terminal. You will need to use the screen control codes, or an Arduino library for the selected terminal type.

2 Likes

I like it. Late 70's retro :laughing: :sweat_smile: :rofl:

what about in the same columns

output`

 V1  182, V2 1023
 V1  190, V2 1023
 V1  194, V2 1023
 V1  196, V2 1023
 V1  197, V2 1023
 V1  198, V2 1023
 V1  205, V2 1023
 V1  211, V2 1023
 V1  211, V2 1023
 V1  211, V2 1023
 V1  211, V2 1023
 V1  211, V2 1023
const int PinV1 = A0;
const int PinV2 = A2;

char s [90];

void setup() {
    Serial.begin (115200);
}

void loop()
{
    sprintf (s, " V1 %4d, V2 %4d", analogRead(PinV1), analogRead(PinV2));
    Serial.println (s);

    delay (500);
}
1 Like

I once wrote a program to monitor registers to learn how to use the CTSU library for the Arduino UNO R4, created by @Delta_G. (I miss him.)

UNO-R4-CTSI-registers

The program outputs to a VT100 terminal (TeraTerm in my case) via Serial1.

The "unchanging parts" that correspond to the table captions are output first, and then the "always changing" register values ​​are output at certain intervals.

Most of the program is a monster of escape sequences.

Looks good!

OP is using TeraTerm (not Serial monitor) which does, to my knowledge, support VT100 so the suggestion by @jremington in post #4 will do the job. Just a bit of studying by OP required :slight_smile:

I don't know about 70's, but it's a technique that still works today :grin:

I like it. How can I get more info about this interface display ? Thanks

Or, use an LCD.

1 Like

Study ansi escape sequence (ansi ecape sequences - Google Search). The wikipedia article is a good start.

Here's my repo:

Also here are some quick references:

https://espterm.github.io/docs/VT100%20escape%20codes.html

Name Description Esc Code Note
clearscreen ED2 Clear entire screen \e[2J \e can be replaced with \33
cursorpos(v,h) CUP Move cursor to screen location v,h \e[<v>;<h>H <v> and <h> start with 1

Combined with the input from Serial1, you can create a simple interactive monitor program that works like the vi editor.

Good luck!

There is one very simple solution:

printing more empty lines than your TeraTerm-Window is showing and then print new
If a new line is printed all the previous printed lines scroll one line up.

If you print 50 empty lines the screen is empty and the new printed data will always be at the bottom of the teraTerm-Window.

I coded some so called macros for debugging.
In the code is a link to where the macros are explained

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *

unsigned long MyTestTimer = 0;                   // Timer-variables MUST be of type unsigned long
const byte    OnBoard_LED = 2;     // onboard-LEDESP32 / ESP8266
//const byte    OnBoard_LED = 25;  // onboard-LED Raspberry Pi pico
//const byte    OnBoard_LED = 13;   // onboard-LED uno, mega

//  Display list Testing

/* I think you don't need these includes
  #include <stdio.h>
  #include <time.h>
  #include <stdlib.h>
*/

const int Vin1 = 5;       // D2 pin
const int Vin2 = 6;       // D3 pin

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  PrintFileNameDateTime();

  pinMode(Vin1, INPUT);
  pinMode(Vin2, INPUT);

}

void loop() {
  //BlinkHeartBeatLED(OnBoard_LED, 250);

  if ( TimePeriodIsOver(MyTestTimer,500) ) {
    printManyEmptyLines();
    dbg("01",digitalRead(Vin1) );
    dbg("02",digitalRead(Vin2) );
  }

  // Serial.write(0x0C);
}


void printManyEmptyLines() {

  // print many empty lines to "move out" the previous printing
  for (int i = 0; i < 50; i++) {
    Serial.println();
  }
}


// helper-functions
void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) );
}


// easy to use helper-function for non-blocking timing
// explanation see here
// https://forum.arduino.cc/t/example-code-for-timing-based-on-millis-easier-to-understand-through-the-use-of-example-numbers-avoiding-delay/974017
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}



void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);

  if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
    digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
  }
}

here is the variant that uses the macro dbgc where the "c" stands for Change
Only in case the value of the argument changes print one time

// MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START * MACRO-START *
// a detailed explanation how these macros work is given in this tutorial
// https://forum.arduino.cc/t/comfortable-serial-debug-output-short-to-write-fixed-text-name-and-content-of-any-variable-code-example/888298

#define dbg(myFixedText, variableName) \
  Serial.print( F(#myFixedText " "  #variableName"=") ); \
  Serial.println(variableName);

#define dbgi(myFixedText, variableName,timeInterval) \
  { \
    static unsigned long intervalStartTime; \
    if ( millis() - intervalStartTime >= timeInterval ){ \
      intervalStartTime = millis(); \
      Serial.print( F(#myFixedText " "  #variableName"=") ); \
      Serial.println(variableName); \
    } \
  }

#define dbgc(myFixedText, variableName) \
  { \
    static long lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }

#define dbgcf(myFixedText, variableName) \
  { \
    static float lastState; \
    if ( lastState != variableName ){ \
      Serial.print( F(#myFixedText " "  #variableName" changed from ") ); \
      Serial.print(lastState); \
      Serial.print( F(" to ") ); \
      Serial.println(variableName); \
      lastState = variableName; \
    } \
  }
// MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END * MACRO-END *

unsigned long MyTestTimer = 0;                   // Timer-variables MUST be of type unsigned long
const byte    OnBoard_LED = 13;     // onboard-LEDESP32 / ESP8266

const byte Vin1 = 5;       // D2 pin
const byte Vin2 = 6;       // D3 pin

void setup() {
  Serial.begin(115200);
  Serial.println("Setup-Start");
  PrintFileNameDateTime();

  pinMode(Vin1, INPUT_PULLUP);
  pinMode(Vin2, INPUT_PULLUP);

}

void loop() {
  //BlinkHeartBeatLED(OnBoard_LED, 250);

    //printManyEmptyLines();
    dbgc("01",digitalRead(Vin1) );
    dbgc("02",digitalRead(Vin2) );
    // short delay of 50 milliseconds for debouncing
    delay(50);
}


void printManyEmptyLines() {

  // print many empty lines to "move out" the previous printing
  for (int i = 0; i < 50; i++) {
    Serial.println();
  }
}


// helper-functions
void PrintFileNameDateTime() {
  Serial.println( F("Code running comes from file ") );
  Serial.println( F(__FILE__) );
  Serial.print( F("  compiled ") );
  Serial.print( F(__DATE__) );
  Serial.print( F(" ") );
  Serial.println( F(__TIME__) );
}


// easy to use helper-function for non-blocking timing
// explanation see here
// https://forum.arduino.cc/t/example-code-for-timing-based-on-millis-easier-to-understand-through-the-use-of-example-numbers-avoiding-delay/974017
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}



void BlinkHeartBeatLED(int IO_Pin, int BlinkPeriod) {
  static unsigned long MyBlinkTimer;
  pinMode(IO_Pin, OUTPUT);

  if ( TimePeriodIsOver(MyBlinkTimer, BlinkPeriod) ) {
    digitalWrite(IO_Pin, !digitalRead(IO_Pin) );
  }
}

With this second version the serial-monitor looks like this

"01" digitalRead(Vin1) changed from 1 to 0
"01" digitalRead(Vin1) changed from 0 to 1
"02" digitalRead(Vin2) changed from 1 to 0
"02" digitalRead(Vin2) changed from 0 to 1

The macro prints

  • a fixed text
  • the variable or expression that is evaluated
  • the value itself

and in case of macro dbgc() from what old value to what new the variable changed

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