Scrolling Text on Ringo Display

Try:
mp.display.setTextWrap(false)
before your loop to override this.

So just to suggest how you might figure things like this out on your own, here is how I found the setTextWrap() function.

First I looked in TFT_eSPI.h to see where print() came from. Turns out that class TFT_eSPI is derived from base class Print, but then I found that it had a member function write() that was commented: “Used by print class to print text to cursor position”.

I then looked in TFT_eSPI.cpp at the TFT_eSPI::write() member function and saw that whether it moved down to the next line or not (when at the end of a line) was controlled by a flag called textwrapX. I searched for textwrapX and saw that it was initialized to true, but could be modified by the setTextWrap() member function. By setting it to false using that function, the text would simpy be written off the end of the display. Not quite sure what that does, as the drawChar() function is rather complex, but at least it shouldn’t go to the next line.

Experiment with this to see what happens. The whole idea of having text scroll off the right side and magically appear on the left may not be supported by the library. It’s all yours to explore and add capability if you see fit.

First, Although the text does continue on the next line. It only starts on the next line and then jumps up to the original line.

If I reduce the pixels in the second argument of the for loop function to 65 (i <65;) instead of the end of the screen at 160, I get a fairly good one line scroll.

Frank, here is the problem I have with your suggestion - when you first mentioned looking at the TFT_eSPI.h and TFT_eSPI.cpp source files, I looked everywhere for the function definitions and implementation that you referenced. I could not find them. I looked in the MAKERphone library and even tried google. Had a little luck, but not enough to provide any useful info. So please guide me to the location of this information.

I will try the suggestions you gave me, and do more research when I find the info you referenced.

Frank, the setTextWrap function works and I thank you. I have the scrolling the way I want it now with the end of screen 160 in the for loop as it should be.

Very interested in studying the source files you gave me, once I am able to access them.

The library is here:
https://github.com/CircuitMess/CircuitMess-Ringo

TFT_eSPI.h and TFT_eSPI.cpp are in the library - look in the src/TFT_eSPI directory. If you open TFT_eSPI.cpp in any text or code editor and search for TFT_eSPI::setCursor, you will find the function (which is pretty simple) and a comment directly above it describing the function and its arguments. Likewise you can search for TFT_eSPI::setTextWrap. Now if you try to search for TFT_eSPI.print or TFT_eSPI.pushSprite, you won’t find them because pushSprite is part of class eSprite which is another class derived from TFT_eSPI, so in this case, search for TFT_eSprite::pushSprite. To find print(), you need to look in TFT_eSPI.h and see that class TFT_eSPI is derived from base class Print, which is where the print() function is; but you really don’t need to go find the Print class because it defers to it’s virtual member function write() to do the actual work, and since TFT_eSPI provides a write() function, that is what does the printing. So you see it’s pretty convoluted to try to learn this way. Circuitmess folks really need to DOCUMENT the library API by class and member functions of each class; but though they’ve been promising to do that, it has yet to happen. So this hunting through the source files to figure out what each function of each class does is the next best thing. It’s a great learning experience but certainly can be frustrating.

Thank you so much Frank for your patience. I will follow your tutorial. Only been at this for a couple of months, so I really appreciate your help.

Frank, I find nothing that I can explore in the location you gave me.

When you go to that page, you click on the blue word “src” which takes you to the src directory. Then click on the blue word "TFT_eSPI, which takes you to the src/TFT_eSPI directory. Then click on the blue word “TFT_eSPI.cpp” if you want to see the source for TFT_eSPI.cpp (the implementation of classes TFT_eSPI and TFT_eSprite) or click on the underlined word “TFT_eSPI.h” if you want to see the source for TFT_eSPI.h (the specification of classes TFT_eSPI and TFT_eSprite). Since “display” is defined in MAKERphone.h (which can be found one directory level back) to be of type TFT_eSprite, these two files tell you everything you can possibly find out (lacking real documentation, i.e.: man pages) about the display member functions, which will be all the member functions of classes TFT_eSPI and TFT_eSprite plus all the member functions of base class Print from which class TFT_eSPI is derived (for those functions you would have to look elsewhere, probably in an Arduino library that defines class Print). In addition to the member functions, there may be public data members, flags/counts and such, that provide additional information for display (I haven’t gone hunting for these.)

If clicking your way through this directory structure is not working for you, I have no idea what the problem is, because all the project directories on GitHub are structured this way, and that is the normal way to explore a GitHub directory.

Thanks Frank. I think I will now be able to follow your instructions. I, of course, looked at src, but it made absolutely no sense to me. The description next to TFT_eSPI - fixed backslash character - kind of put me off. I will let you know how I make out. As you said, it’s a good learning experience.

@kfixman and @frankprindle thanks for being in this discussion - it’s where real learning happens!

Now back to the topic.

Since MAKERphone itself uses a few open-source libraries that are widely used (like the one for the display and for the buttons), they aren’t really CircuitMess’ libraries. Unfortunately, there isn’t an easy reference manual for these anywhere online, which makes it a bit tricky to figure out what they really do, especially for someone with little experience.

The way Frank described it is the only one - just looking through the code and trying to figure out what does what. Also, testing every function just to see what it does is the way to go. It’s a slow process, but ultimately it will teach you how do functions like these really work and how are these libraries being written. :smiley:

Glad to see you finding a solution.

Cheers,
Robert

I would have used the Adafruit library…it should be compatible…

Thanks to Frank, Robert, and the examples from 8bitRobert, I have my program running pretty much as I want it. It is simply an app selected with my initials in a .bmp file and two loops that say this phone belongs to me with my name scrolling, and the LEDs flashing . I can return the phone to its firmware by pushing the home button. To complete the app, I will add another loop for sounds (right now it’s the happy birthday tune) from the oscillator. I will post the code when I am done, and it is at least presentable.

Unfortunately, the processor is designed to run the loops sequentially in core 1 . I want to be able to run the two loops in parallel, using core 0 as well as core 1. I have played with the following:

TaskHandle_t Task1;

xTaskCreatePinnedToCore(
Task1code,
“Task1”,
10000,
NULL,
1,
&Task1,
0);

void Task1code( void * pvParameters )

But my code with the Task() functions added won’t compile for the Ringo.

I have incorporated the Adafruit library for Arduino but I might not have the right library to use both cores of the ESP32 processor. I am thinking I need mp. functions to make it work.

I really don’t have the experience, although I have tried, to search existing code, as Frank suggested.

Any help much appreciated.

I’ve never been very good at running parallel tasks using C.
From what I’ve encountered, it is an unregistered skill.
I’m sure there is at least one video on the subject. However, I have seen many come forth on such an objective. I would think there would be more public concern on the matter.

Hey Kent,

Yes, tasks aren’t really something we have focused on during Ringo development. Therefore, there aren’t any “easy way” functions implemented.

As we’re making some of the new products, we have discovered great value of tasks and have implemented them in pretty much everything. They are somewhat limited since the ESP32 itself has its physical limitations, but at least you can control some parts of your work.

If you can send me a more detailed error report along with some explanation of what you’re really trying to do, I might be able to help more and we might get to the solution in one way or another. :slight_smile:

Cheers,
Robert

1 Like

Robert, here is a little project I have been working on, made up of code from you, Frank, and 8bitRobot. It is intended to be an app on the SD card that just shows who’s phone it is. I am sure the code can be refined and condensed, but it works.

#include <MAKERphone.h>
#include <FastLED/FastLED.h>
#include <FastLED/pixeltypes.h>

CRGB leds[8];
MAKERphone mp;

void setup(){

Serial.begin(115200);
mp.begin(0);
mp.pixelsBrightness = 2;

}

void loop() {

for(int i = 0; i < 8; i++){
for(int j = 0; j <= i; j++){
mp.leds[j] = CRGB(random(0,255),random(0,255),random(0,255));
}
   delay(500);

mp.update();

}

mp.display.setTextWrap(false);

for(int i = 0; i < 160; i++){

mp.display.fillScreen(TFT_BLACK);
mp.display.fillCircle(80, 64, 63, TFT_WHITE);
mp.display.setTextColor(TFT_RED);
mp.display.setCursor(50, 15);
mp.display.setTextFont(2);
mp.display.setTextSize(2);
mp.display.print(“JOE”);

mp.display.setCursor(40, 85);
mp.display.setTextColor(TFT_GREEN);
mp.display.print(“PHONE”);

if(mp.buttons.released(BTN_HOME)) mp.loader();

mp.display.setCursor(i, 50);
mp.display.setTextColor(TFT_BLUE);
mp.display.setTextFont(2);
mp.display.setTextSize(2);
mp.display.print(“RINGO’S”);
mp.display.pushSprite(0, 0);

 delay(25);

mp.buttons.update(); while(mp.buttons.states[BTN_HOME]) mp.update();

}

}

I would like to run each of the two loops in a separate core of the processor because I think it would look better, and just because it can be done. The following is my attempt to run one of the loops in core 0 instead of the default core 1. It gets pretty far through the process, but won’t complete the compile.

#include <Arduino.h>
#include <MAKERphone.h>

TaskHandle_t Task1;
MAKERphone mp;

void setup() {

Serial.begin(115200);

xTaskCreatePinnedToCore(
Task1code,
“Task1”,
10000,
NULL,
1,
&Task1,
0);

delay(500);
}

void Task1code( void * pvParameters ){

mp.display.setTextWrap(false);

for(int i = 0; i < 160; i++){

mp.display.fillScreen(TFT_BLACK);
mp.display.fillCircle(80, 64, 63, TFT_WHITE);
mp.display.setTextColor(TFT_RED);
mp.display.setCursor(50, 15);
mp.display.setTextFont(2);
mp.display.setTextSize(2);
mp.display.print(“JOE”);
mp.display.setCursor(40, 85);
mp.display.setTextColor(TFT_GREEN);
mp.display.print(“PHONE”);

if(mp.buttons.released(BTN_HOME)) mp.loader();

mp.display.setCursor(i, 50);
mp.display.setTextColor(TFT_BLUE);
mp.display.setTextFont(2);
mp.display.setTextSize(2);
mp.display.print(“RINGO’S”);
mp.display.pushSprite(0, 0);

 delay(25);

mp.buttons.update(); while(mp.buttons.states[BTN_HOME]) mp.update();

}

}

void loop() {

}

1 Like

Okay, I’ve got everything now - except the error!

Please, send me the full error report so I can tell you what to do next. :slight_smile:

Robert

1 Like

The file is too big to upload with the Arduino - “Show verbose output during compilation” checked, so here it is without that additional information.

Arduino: 1.8.12 (Windows 10), Board: “Ringo by CircuitMess, Minimal SPIFFS (Large APPS with OTA), 80MHz, 921600, None”

In file included from C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src/MAKERphone.h:31:0,

             from C:\Kent's .INO Code\Combo2_task\Combo2_task.ino:3:

C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src/FastLED/FastLED.h:14:21: note: #pragma message: FastLED version 3.002.001

pragma message “FastLED version 3.002.001”

                 ^

In file included from C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src/FastLED/FastLED.h:65:0,

             from C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src/MAKERphone.h:31,

             from C:\Kent's .INO Code\Combo2_task\Combo2_task.ino:3:

C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src/FastLED/fastspi.h:110:23: note: #pragma message: No hardware SPI pins defined. All SPI access will default to bitbanged output

pragma message “No hardware SPI pins defined. All SPI access will default to bitbanged output”

                   ^

In file included from C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src\MAKERphone.h:31:0,

             from C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src\MAKERphone.cpp:20:

C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src\FastLED/FastLED.h:14:21: note: #pragma message: FastLED version 3.002.001

pragma message “FastLED version 3.002.001”

                 ^

In file included from C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src\FastLED/FastLED.h:65:0,

             from C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src\MAKERphone.h:31,

             from C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src\MAKERphone.cpp:20:

C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src\FastLED/fastspi.h:110:23: note: #pragma message: No hardware SPI pins defined. All SPI access will default to bitbanged output

pragma message “No hardware SPI pins defined. All SPI access will default to bitbanged output”

                   ^

libraries\Ringo\MAKERphone.cpp.o: In function `Task1code(void*)’:

C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src/MAKERphone.cpp:71: multiple definition of `Task1code(void*)’

sketch\Combo2_task.ino.cpp.o:C:\Kent’s .INO Code\Combo2_task/Combo2_task.ino:24: first defined here

libraries\Ringo\MAKERphone.cpp.o:(.bss.Task1+0x0): multiple definition of `Task1’

sketch\Combo2_task.ino.cpp.o:(.bss.Task1+0x0): first defined here

collect2.exe: error: ld returned 1 exit status

Multiple libraries were found for “WiFi.h”
Used: C:\Users\Nicholson\AppData\Local\Arduino15\packages\cm\hardware\esp32\1.0.5\libraries\WiFi
Not used: C:\Program Files (x86)\Arduino\libraries\WiFi
Multiple libraries were found for “MAKERphone.h”
Used: C:\Users\Nicholson\Documents\Arduino\libraries\Ringo
Not used: C:\Users\Nicholson\Documents\Arduino\libraries\Ringo_by_CircuitMess_Library
Multiple libraries were found for “SD.h”
Used: C:\Users\Nicholson\AppData\Local\Arduino15\packages\cm\hardware\esp32\1.0.5\libraries\SD
Not used: C:\Program Files (x86)\Arduino\libraries\SD
Not used: C:\Users\Nicholson\Documents\Arduino\libraries\SD
exit status 1
Error compiling for board Ringo by CircuitMess.

This report would have more information with
“Show verbose output during compilation”
option enabled in File -> Preferences.

1 Like

Hey Kent,

I’ve done a bit of snooping around it and fixed your problem.

Most of these are not errors, but warnings, and they actually don’t effect anything. The thing that is actually stopping your program is this

C:\Users\Nicholson\Documents\Arduino\libraries\Ringo\src/MAKERphone.cpp:71: multiple definition of `Task1code(void*)’

Somewhere in the Makerphone.h there is already defined Task1code(void*) and Task1, so when you’re trying to re-define it, it throws out an error.

I’ve fixed your errors and it is all working now, not ideal, but enough for you to continue working on it if you want to.

KentProgram.zip (799 Bytes)

It’s important to look at this function vTaskDelay(1) - this has to be in there because it allows other processes to run inside of that same core when this task is not doing anything (either waiting or something passive). Also, when limiting how many times something is called or just when you want to create a delay, it’s much better to use millis() than delay, since it doesn’t stop the whole flow of the program. If you’re unfamiliar with this technique, please tell me so I can show you a few examples. :slight_smile:

Hope this helps,
Robert

1 Like

Thank you Robert. Now I can get back to playing/learning. I am familiar with millis() and have used it in this same program when trying to speed everything up, but it didn’t make a difference. I will put it back instead of the delay.

Thanks again, and stay safe.

2 Likes

I have the little two core program working pretty well thanks to all you guys that helped. It is fast, and both programs ( scrolling text and pulsating LEDs) run at the same time instead of sequentially like they did when they both were running in core 1.

I have been able to find out about the vTaskDelay() function, but I am at a loss about the doo() function. What doo it do?