With Teensy-LC, each display.display() call scrolls static frame right 1 column

Yochanon

Member
// This code doesn't even write to the OLED; it displays the Adafruit logo screen;
// On a Nano, it remains static; On a Teensy-LC, it continually scrolls the whole frame to the right (with wraparound).
// Adding delays anywhere only slows it. I also tried swapping another OLED of the same type.

My Nano eats up half its memory with a single interactive text entry screen.
I just got a Teensy-LC and V4.0 and love the speed and capacity. Well done, PJRC!

I'm hoping someone has seen this before. (Something is too fast for something somewhere!)
Thanks - Mitch


Scroll bug.jpg

5 sec video:

Code:
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

void setup() {
     display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
     while (true){
         display.display();
         delay(1);
     }
}

void loop() {
}
 
Last edited:
New info - The SSD1306 is a 3.3v chip. It works well with 5v I2C.
These I2C are 3.3v. I note that putting a high impedance scope probe on the SDA changes the scrolling to a slight jitter!
I try running the OLED at 5 rather than 3.3 v. That does not fix it.
I don't have (so didn't) try level up shifters. Sorry.

So this OLED appears to be not 3.3v tolerant? Is that a thing? Tnx.
 
I tried your sketch on a T4 and the display was rock solid.

Tried it on T-LC and it is not moving like you saw, but I am seeing the screen be not rock solid but sort of moving a bit back and forth...

Will take a quick look, I suspect maybe the I2c (Wire) speed may be different.
 
I feel great having just discovered such real processing, I/O, and memory resource power.
I ordered just T-LC and T-4s. I've used ATtiny85s, Minis, Nanos and intend to use these Teensy's as much as possible.

Regarding the "I2c (Wire) speed", the T-LC does faithfully draw sophisticated graphics commands, i.e. the whole ssd1306-128x64 Example sketch. It is just scrolling or stability of the screen. I ordered some level shifters to try, just in case the OLED clones are 3.3v intolerant, and will share the results.

One would never restrict a creative writer to use only Post-it notes for paper!
Even more so a creative engineer whose "paper" is speed, memory, and I/O.
Life is too short! I will stay tuned. Thank you, Kurt!
 
I am curious about the differences in the Wire output between the T4 and the T-LC here.

The T4 Logic Analyzer looks good at 400khz and just the screens output...
screenshot.jpg

But when I look at the LC output which is at about 333khz.
There is a blurp that outputs just before the screen data:
screenshot2.jpg
There is about a 1ms gap between this one byte output and the main stuff.

Edit: On T4 there is a 1ms gap between page outputs like expected. With T-LC there is a roughly 16ms gap than the one byte than 1ms gap than display output.
Next up to instrument the code a little to see where this gap is added.
 
I don't know if any of this helps, but

1) there are 15 references to compiler #def CORE_TEENSY , or TEENSTDUINO, or (in a comment) "Teensy 4.x" in "Adafruit_SPITFT.cpp" in their GFX library.

2) In the very beginning and very end of the display() method (Adafruit_SSD1306.cpp, line 885) two interesting calls to a method "yield()" are added, especially for #if defined(ESP8266). The comment explains how it is for fast bit rates and speed-related reasons.
"ESP8266 needs a periodic yield() call to avoid watchdog reset."

Perhaps the T-LC also has a watchdog timer (?) and needs this for similar reasons.
The T-4, being much faster would not need interjected yield()s.
 
Thanks,

But it looks more like maybe some form of timing issue? Probably within Wire library.

That what I mentioned looks like a one byte output, is actually a reset of the buss.
in particular when the first endTransmission() call for the display update is called, the code calls into:

Code:
bool TwoWire::wait_idle(void)
{
	bool reset=false;
	uint32_t wait_begin = millis();

	//Serial.print("busy:");
	while (i2c_status() & I2C_S_BUSY) {
		//Serial.write('.') ;
		uint32_t waited = millis() - wait_begin;
#if 1
		if (waited > 15 && !reset) {
			reset = true;
			//Serial.println("attempt forced reset");
			uint8_t sda_pin = hardware.sda_pin[sda_pin_index];
			pinMode(sda_pin, INPUT_DISABLE);
			uint8_t scl_pin = hardware.scl_pin[sda_pin_index];
			pinMode(scl_pin, OUTPUT);
			for (int i=0; i < 9; i++) {
				digitalWrite(scl_pin, LOW);
				delayMicroseconds(5);
				digitalWrite(scl_pin, HIGH);
				delayMicroseconds(5);
			}
			uint32_t mux;
			volatile uint32_t *reg;
			reg = portConfigRegister(hardware.sda_pin[sda_pin_index]);
			mux = PORT_PCR_MUX(hardware.sda_mux[sda_pin_index]);
			*reg = mux|PORT_PCR_ODE|PORT_PCR_SRE|PORT_PCR_DSE;
			reg = portConfigRegister(hardware.scl_pin[scl_pin_index]);
			mux = PORT_PCR_MUX(hardware.scl_mux[scl_pin_index]);
			*reg = mux|PORT_PCR_ODE|PORT_PCR_SRE|PORT_PCR_DSE;
			delayMicroseconds(10);
			continue;
		}
#endif
		if (waited > 16) {
			// bus stuck busy too long
			port().C1 = 0;
			port().C1 = I2C_C1_IICEN;
			//Serial.println("abort");
			//return 4; // timeout waiting for bus
			return false;
		}
	}
	return true;
}
And after the 15ms it does the reset which is the sort of char output, and then it waits until the 16ms where it returns... Not sure why yet, thought maybe increase your delay to 5 still happens... But if I enable all of the debug code in endTransmission than I don't get this delay..
 
It is interesting with T3.6 it shows busy status for a real short period during start of the page, but clears quickly, like maybe a few microseconds... But with LC it holds on being busy.

I might not have much more time to debug this right now. I have not done much with an LC in awhile.
 
Kurt,
I mis-posted my forum reply yesterday. Today's reply is even better.

Thank you for trying out the I2C Oled bug on the T-4 and verifying [for me] that it didn't have the problem!
I made the future now and switched everything to the T-4. Problem solved. All runs smoothly, even at high graphics refresh rates.

After having the sketch not fit on the Nano, I was delighted to get this report of remaining elbow room!

Sketch uses 35280 bytes (1%) of program storage space. Maximum is 2031616 bytes.
Global variables use 45756 bytes (8%) of dynamic memory, leaving 478532 bytes for local variables. Maximum is 524288 bytes.

Someone should recommend that Arduino.cc format the numbers to use commas (or decimal points for Europe) for the remaining and Maximum memory amounts, even if mainly for the Teensy lines!

This particular project also includes a Nano and many Tiny85's.
I really hope the future is the Teency-4. It's got a lot of everything to spare!
Updating data on the high res OLED screen with a real font looks far better than doing the same on the 1602 LCD with its gross dot matrix text.

If anyone might be interested, I can include the snip of code that makes the clearing and updating easier.

Good work! Tnx.
Mitch
 
Last edited:
Back
Top