ThingPulse / esp8266-oled-ssd1306

Driver for the SSD1306 and SH1106 based 128x64, 128x32, 64x48 pixel OLED display running on ESP8266/ESP32
https://thingpulse.com
Other
2.02k stars 640 forks source link

how to clear current display font pixels when over-writing a line? #128

Closed tofrnr closed 4 years ago

tofrnr commented 7 years ago

hello, how s it possble to clear current font pixels when over-writing a line, without clearing the entire display? Currently all the new pixels are just added to the former ones, messing all up over the time. In other libs it is possible to do this by writing blanks or re-setting the font colors (white on black or normal), but neither method is working so far here:

while(1) {
  String cx_oled = "WiFi connected:" + (String)WiFi.RSSI()+" dBm";
  display.drawString( 0, 0, "                         "); // no effect
  display.display();                                     // no effect
  display.normalDisplay();                               // no effect
  display.drawString( 0, 0, cx_oled ); 
  display.display();
}

which method is working for this lib instead?

eqsone commented 7 years ago

display.clear(); display.setColor(BLACK);

works for me. Than after overwriting the last entry with the same data I set it back to white. Drawing a black rectangle in the size of the display works if the same data set can't be drawn twice.

tofrnr commented 7 years ago

As stated in my TOP,

how s it possble to clear current font pixels when over-writing a line, without clearing the entire display?

I do not want to clear the whole display and refresh all and everything anew, when just wanting to overwrite a couple of letters or numbers because that clearing and refreshing will need much too much time. e.g., I have 8 lines full of data and some of the data is changing very quickly, some others are mostly static or changing just very slowly (perhaps also some graphs), I want to update the display just for those specific quickly changing data and not all the others as well which still might have stayed unchanged so far, and so the major rest must not be cleared fom the screen. As also already stated, by other drivers that is possible (e.g. OLED drivers for a Raspberry Pi).

eqsone commented 7 years ago

Oops, I'm sorry. Overlooked that point.

beamzer commented 7 years ago

I played around with the library and also initially was surprised by the behavior. It seems that the way the functions work is like setting bit-flags for every pixel that should be lid, but they don't reset the pixels before writing so you should take care of that yourself. Painting with BLACK like eqsone suggests works. By using fillRect you can selectively blank the parts where you next want to write data; or specify a rectangle of all pixels and write everything again. It is key only to call the display function at the end when all pixels are defined, otherwise the display will flicker. You don't need the init or clear functions in your loop, those a called only once in setup.

squix78 commented 7 years ago

While you might use the library in this way it wasn't the intention of the creator and thus support is not very good. Unlike other libraries this library is built for the use case where you redraw the frame buffer with every iteration. This might be slower for some cases but also has its advantages: you don't have to worry about where you have to clear regions, you just make sure that you draw everything fresh in each separation....

tofrnr commented 7 years ago

yes, that's exactly the point: redrawing the entire display makes it extremely slow and additionally the whole screen is flickering then. Being able to overwrite and optionally completely clearing every old line would make it more valuable. BTW, the Adafruit libs work that way, and also a ESP8266 patch is available for them.

FelipeAlmirall commented 6 years ago

I was having the same problem and solved it by turning the area off with a filled rectangle!

You should try!

Use this code right above the line you are overwriting:

Display.fillRect(x0, y0, width, height, BLACK);

reivaxy commented 6 years ago

@tofmr I'm refreshing the whole screen when displaying only characters and do not get any flickering actually. You may need to have all the printable data ready before you refresh.

tofrnr commented 6 years ago

@ reivaxy : as already stated several times, a complete reflesh is no option at all

@ FelipeAlmirall: thanks, that may help, I'll try it ASAP and perhaps create some speed tests for just write-over, write by previous fill-rectangle and compare it to write by previous clear-all. Nonetheless the clear by fill-rectangle is cumbersome when using different font sizes at either line: better if it worked out of the box!

BNNorman commented 5 years ago

I know this thread is very old but I just tried display.setTextColor(WHITE,BLACK); and it worked for me.

tofrnr commented 5 years ago

I know this thread is very old but I just tried display.setTextColor(WHITE,BLACK); and it worked for me.

I actually doubt that that would work (writing 2 different strings like e.g., "old1234" and "new5678" shortly one after the other to the same coordinates, without any Clear-Screen cmd in between), given this lib has not been completely rewritten meanwhile what it is not supposed to be AFAIK...

BNNorman commented 5 years ago

Well, that's exactly how I displayed a time clock with incrementing seconds on a line of the OLED.

tofrnr commented 5 years ago

ok, that's new to me - of course then I stand corrected... Can you please post your entire code to check it?

BNNorman commented 5 years ago

Just checked this again: nodeMCU V1.0, Aliexpress SSD1306 OLED display: Clock ticks just fine.

include

include

include

include

include

define OLED_I2C_ADDR 0x3C

define SCREEN_WIDTH 128 // OLED display width, in pixels

define SCREEN_HEIGHT 64 // OLED display height, in pixels

define OLED_RESET -1 // SSD1306 doesn't have a reset pin

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// setupOLED should be called once from setup()

void setupOLED(void) { // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_I2C_ADDR)) { // Address 0x3C for SSD1306 128x64 Serial.println(F("SSD1306 allocation failed")); for(;;) yield(); // Don't proceed, loop forever }

}

void setup() { Serial.begin(9600); while(!Serial) yield(); Serial.println("OLED_DISPLAY starting");

setupOLED();

display.clearDisplay(); display.setCursor(0,0); display.print("Starting"); display.display();

}

void updateDisplay(char Temperature,char Humidity,char *Pressure) { char msg[50]="";

display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(WHITE,BLACK); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font

display.print("Temp (C): "); display.print(Temperature);

display.setCursor(0, 16); display.print("Humidity (%): "); display.print(Humidity);

display.setCursor(0,32); display.print("Press. (pa): "); display.print(Pressure);

snprintf(msg,sizeof msg,"Time: %0.2d:%0.2d:%0.2d",hour(),minute(),second()); display.setCursor(0,48); display.print(msg);

display.display(); }

void loop() {

updateDisplay((char )"23.0",(char )"80%",(char *)"1024kPa");

delay(1000);

}

BNNorman commented 5 years ago

IGNORE the temp/humidity stuff - I was just checking the OLED layout with this code.

tofrnr commented 5 years ago

well, you are using display.clearDisplay(); for either update., don't you?

but the issue here is to write new lines without using display.clearDisplay() every time before.

BNNorman commented 5 years ago

Ok, I chose a bad example - doing three things at once and my machine is running out of puff.

I've taken out the extra stuff and the clearDisplay() in updateDisplay() - still works

include

include

include

include

include

define OLED_I2C_ADDR 0x3C

define SCREEN_WIDTH 128 // OLED display width, in pixels

define SCREEN_HEIGHT 64 // OLED display height, in pixels

define OLED_RESET -1 // SSD1306 doesn't have a reset pin

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// setupOLED should be called once from setup()

void setupOLED(void) { // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if(!display.begin(SSD1306_SWITCHCAPVCC, OLED_I2C_ADDR)) { // Address 0x3C for SSD1306 128x64 Serial.println(F("SSD1306 allocation failed")); for(;;) yield(); // Don't proceed, loop forever }

}

void setup() { Serial.begin(9600); while(!Serial) yield(); Serial.println("OLED_DISPLAY starting");

setupOLED();

display.clearDisplay(); display.setCursor(0,0); display.print("Starting"); display.display();

}

void updateDisplay() { char msg[50]="";

display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(WHITE,BLACK); // Draw white text display.setCursor(0, 0); // Start at top-left corner display.cp437(true); // Use full 256 char 'Code Page 437' font

snprintf(msg,sizeof msg,"Time: %0.2d:%0.2d:%0.2d",hour(),minute(),second()); display.setCursor(0,48); display.print(msg);

display.display(); }

void loop() {

updateDisplay();

delay(1000);

}

tofrnr commented 5 years ago

thanks, I'll try to test it ASAP - currently I am using different libs in my projects (i.e., Adafruit, which also don't provide the clean overwrite feature. Perhaps I will have to change my programs then.

chimera786 commented 5 years ago

thanks, I'll try to test it ASAP - currently I am using different libs in my projects (i.e., Adafruit, which also don't provide the clean overwrite feature. Perhaps I will have to change my programs then.

Hey! I am having the same issue: trying to update only a select portion of the OLED screen (using Adafruit lib). Did you ever figure out a work around for it?

EDIT:

Well I did figure it out. Its basically overwriting that particular location with a blank image (or shape). In my case, I just placed a rectangle shape to clear the location I wanted to update.

What this means is that: For OLEDs and LCD screens, its important to designate locations of certain items that you may want to display on the screen. For example, if you want to display a clock and keep updating it every second, you'll have to designate a corner of the screen to that clock and come up with a blank shape to replace the current clock display(or part of the clock display) and then update it with the new value.

Is it elegant? No but it is functional.

If anyone else has a better way to update specific portions of an OLED screen using adafruit SSD1306 library, please post here.

BNNorman commented 5 years ago

Thats the way most GUI screen drivers work.

dpharris commented 5 years ago

Often, one can select to write either both the foreground and background, or just the foreground (ie the background is invisible). That way thd characters appear to float over the background image or teplacr thr background image.

Using a rectangular area to 'clear' the area works ok in this case, though.

David

On Sun, Jun 30, 2019, 22:53 Brian notifications@github.com wrote:

Thats the way most GUI screen drivers work.

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/ThingPulse/esp8266-oled-ssd1306/issues/128?email_source=notifications&email_token=AAEDQSVFNWPCSPSAQ2EDIBLP5GLUDA5CNFSM4DOBKEC2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODY5B5DY#issuecomment-507125391, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEDQSXWUUFDHKFDQTUSJ53P5GLUDANCNFSM4DOBKECQ .

BNNorman commented 5 years ago

Ok, transparency is, I think, what you are talking about. I seem to remember, when I was first working with the OLED that text did overwrite with transparency but it quickly became rubbish - I think you just don't set a background colour IIRC

display.setTextColor(WHITE); // Draw white text

I have written animated LED displays using Python before now and to handle what you are describing required me to created image layers and render them back to front into a buffer which was then written to the LED display. Of course, if the display has it's own buffers that's easier to handle. But I don't think the OLED displays have that. Currently I just use OLED for text display so clearing the display then writing works for me, it's fast enough not to suffer from visible flicker.

chimera786 commented 5 years ago

@dpharris

I don't fully understand what you mean. Can you please clarify a bit more?

Thanks!

dpharris commented 5 years ago

Sorry for the confusion. I was just musing on different techniques.

What I do presently is to have a display routine that clears the screen and rewrites the display. However, the technique of overwriting a rectangle to clear a portion of the screen works fine.

David

On Mon, Jul 1, 2019, 08:15 chimera786 notifications@github.com wrote:

@dpharris https://github.com/dpharris

I don't fully understand what you mean. Can you please clarify a bit more?

Thanks!

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ThingPulse/esp8266-oled-ssd1306/issues/128?email_source=notifications&email_token=AAEDQSRQ7AKQ2RAHJB66KCTP5INQJA5CNFSM4DOBKEC2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODY6OLTI#issuecomment-507307469, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEDQSX77GBR37QEUP755ITP5INQJANCNFSM4DOBKECQ .

BNNorman commented 5 years ago

That's about all you can do. However, with the Adafruit SSD1306 library there's a call getBuffer() which returns a pointer to the driver's buffer. That means you could blit an image directly onto it, which would be fun.

dpharris commented 5 years ago

As in blitbit from Smalltak? Maybe a bitblib library would be useful for esp8266/32?

David

On Mon, Jul 1, 2019, 09:52 Brian notifications@github.com wrote:

That's about all you can do. However, with the Adafruit SSD1306 library there's a call getBuffer() which returns a pointer to the driver's buffer. That means you could blit an image directly onto it, which would be fun.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ThingPulse/esp8266-oled-ssd1306/issues/128?email_source=notifications&email_token=AAEDQSSZJG6CJ2CC4AROE6TP5IY6TA5CNFSM4DOBKEC2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODY6XJXY#issuecomment-507344095, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEDQSSISIXI6EVQR2MEDG3P5IY6TANCNFSM4DOBKECQ .

BNNorman commented 5 years ago

Not sure of the origin but blitbit is the full name I think - fast binary data transfer as in memcpy()? The adafruit GFX library has methods to load images from SD card- not tried them. The Adafruit logo (see logo.h in the SD1306 librray) is held in PROGMEM so the library must contain code to render that to the buffer.

dpharris commented 5 years ago

Bitblit was developed at Xerox Parc by the Smalltalk team. It uses logic operationx to combine the source and destination bit fields.

Good write up in Wikipedia: https://en.m.wikipedia.org/wiki/Bit_blit

David

On Mon, Jul 1, 2019, 11:24 Brian notifications@github.com wrote:

Not sure of the origin but blitbit is the full name I think - fast binary data transfer as in memcpy()? The adafruit GFX library has methods to load images from SD card- not tried them. The Adafruit logo (see logo.h in the SD1306 librray) is held in PROGMEM so the library must contain code to render that to the buffer.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ThingPulse/esp8266-oled-ssd1306/issues/128?email_source=notifications&email_token=AAEDQSWQFIACL2FENAGE2R3P5JDUHA5CNFSM4DOBKEC2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODY66LIQ#issuecomment-507372962, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEDQSWX3AICOTCTAQMUKDLP5JDUHANCNFSM4DOBKECQ .

dpharris commented 5 years ago

I looked at the code at: https://github.com/ThingPulse/esp8266-oled-ssd1306/blob/master/src/OLEDDisplay.cpp and its seems that we could add an 'overwrite' option, in several places, eg: switch (this->color) { case WHITE: buffer[dataPos] |= currentByte << yOffset; break; case BLACK: buffer[dataPos] &= ~(currentByte << yOffset); break; case INVERSE: buffer[dataPos] ^= currentByte << yOffset; break; } becomes: switch (this->color) { case WHITE: if(overwrite) buffer[dataPos] = currentByte << yOffset; else buffer[dataPos] |= currentByte << yOffset; break; case BLACK: if(overwrite) buffer[dataPos] = ~(currentByte << yOffset); buffer[dataPos] &= ~(currentByte << yOffset); break; case INVERSE: buffer[dataPos] ^= currentByte << yOffset; break; } This would work well for individual characters, but if one was writing strings, then shorter strings would not overwrite previous longer strings. Of course, one could pad the strings to be a constant length.

Not sure this is worthwhile, but if there is interest, we could implement that. I would need to test it first, of course.

We could also generalize the code to do blitbit type operations, if there is interest. This would let you do operations like: write all-black, all-white, source AND destination, source NOR destination, etc. I will explore whether this is worthwhile, and publish a library if it looks ok.

David

On Mon, Jul 1, 2019 at 12:02 PM David Harris drdpharris@gmail.com wrote:

Bitblit was developed at Xerox Parc by the Smalltalk team. It uses logic operationx to combine the source and destination bit fields.

Good write up in Wikipedia: https://en.m.wikipedia.org/wiki/Bit_blit

David

On Mon, Jul 1, 2019, 11:24 Brian notifications@github.com wrote:

Not sure of the origin but blitbit is the full name I think - fast binary data transfer as in memcpy()? The adafruit GFX library has methods to load images from SD card- not tried them. The Adafruit logo (see logo.h in the SD1306 librray) is held in PROGMEM so the library must contain code to render that to the buffer.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/ThingPulse/esp8266-oled-ssd1306/issues/128?email_source=notifications&email_token=AAEDQSWQFIACL2FENAGE2R3P5JDUHA5CNFSM4DOBKEC2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODY66LIQ#issuecomment-507372962, or mute the thread https://github.com/notifications/unsubscribe-auth/AAEDQSWX3AICOTCTAQMUKDLP5JDUHANCNFSM4DOBKECQ .

BNNorman commented 5 years ago

That might be useful.

stale[bot] commented 4 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

xilef111 commented 4 years ago

I looked at the code at: https://github.com/ThingPulse/esp8266-oled-ssd1306/blob/master/src/OLEDDisplay.cpp and its seems that we could add an 'overwrite' option, in several places[...]

That might be useful.

I would find that very usefult too.

Is there any progress of implementing that?

regards xilef111