Forum: Mikrocontroller und Digitale Elektronik SSD1306 Arduino I2C nur 30kHz?


von Paul G. (paul_g210) Benutzerseite


Angehängte Dateien:

Lesenswert?

Hallo

Zur Vorgeschichte:
Ich experimentiere gerade mit meinem Atmega328 (internal 1Mhz) und dem 
SSD1306 128x64 OLED. Dabei musste ich feststellen das mit der aktuellen 
Adafruit SSD1306 Library mein Display fast 7 Sekunden bracuht um das 
Display zu füllen oder zu leeren. Dann dachte ich mir schau doch mal wie 
der I2C Clock aussieht und bei meiner ersten Messung stellte ich fest 
dass da nur ~2-3kHz am SCK ankommen... ich hab noch nie einen so 
niedrigen Clock gesehen und das für I2C? Ich wollte es nicht glauben und 
denke mir das liegt zum Teil daran das mein atmega mit 1Mhz läuft..

Um zu sehen wie sich ein normaler Arduino Nano mit 16Mhz verhält habe 
ich das Display an diesen angeschlossen und zum testen erstmal den 
Sketch i2cdetect laufen gelassen und dann mit dem Osszi SCK angeschaut. 
Um alles richtig zu machen habe ich noch jeweils ein Pullup Widerstand 
von 1k zischen SDA-5V und SCK-5V gemacht, hat aber eigentlich nix mit 
dem ganzen zu tun, nur sehen jetzt die Bit's wieder schön rechtwinklig 
aus und nicht mehr so rund vorn...
Ich ich bekam meine erwarteten 100kHz.

Nun habe ich einen Sketch hochgeladen der einfach nur eine Zahl 
hochzählt und diese jedes mal auf dem Display ausgibt:
1
#include <SPI.h>
2
#include <Wire.h>
3
#include <Adafruit_GFX.h>
4
#include <Adafruit_SSD1306.h>
5
#define OLED_RESET 4
6
7
Adafruit_SSD1306 display(OLED_RESET);
8
9
int c = 0;
10
11
void setup()   {                
12
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
13
  display.clearDisplay();
14
}
15
16
void loop() {
17
    c = 0;
18
    for(int i=0;i<100;i++){
19
    display.setTextSize(1);
20
    display.setTextColor(WHITE);
21
    display.setCursor(0,0);
22
    display.print(c);
23
    display.display();
24
    display.clearDisplay();
25
    c++;
26
    }
27
}

Während dieser Sketch läuft finde ich am SCK nur noch so um die 
28-31kHz...
Hat jemand eine Idee warum? Sollte der Sketch nicht auch mit 100kHz 
laufen?
Oder messe ich evtl etwas falsch? Oder handelt die SSD1306 library eine 
niedrigere Geschwindigkeit aus? Ich kenne mich mit I2C leider überhaupt 
nicht aus...

von Mick (Gast)


Lesenswert?

Versuch mal
1
Wire.setClock(400000);
nach
1
display.begin

von Mick (Gast)


Lesenswert?

Falls beim Kompilieren ein Fehler auftritt:
1
Wire.setClock(400000L);

von Paul G. (paul_g210) Benutzerseite


Angehängte Dateien:

Lesenswert?

Danke dir, das hätte ich als nächstes probiert.
Ich habe gerade festgestellt das sich wohl der Constructor der SSD1306 
library seit Version 1.2 (November 2018) geändert hat.

Man kann jetzt die Frequenz "wärend" und "danach" angeben:

Adafruit_SSD1306(uint8_t w, uint8_t h, TwoWire *twi=&Wire, int8_t 
rst_pin=-1, uint32_t clkDuring=400000UL, uint32_t clkAfter=100000UL);

Mein Display lief sogar noch mit 800000.

Ich werde morgen mal meinen 1MHz Atmega mit dem neuen Sketch laufen 
lassen und mal sehen wie hoch er SCL takten kann.

Warum ich aber ständig die 30kHz bekommen habe erschließt sich mir immer 
noch nicht wenn der default Wert eigentlich so ziemlich überall 100kHz 
ist... naja egal :)

von Paul G. (paul_g210) Benutzerseite


Angehängte Dateien:

Lesenswert?

Okay, das hat nicht geklappt, ich bekomme immer noch nur 2kHz mit meinem 
Atmel328@1Mhz.

Das Problem ist wohl in der Wire library und dort die einzige Stelle die 
ich gefunden habe ist in zwei Funktionen der twi.c. Ich weiß das der 
Prescaler wohl auf 1 steht und TWBR so definiert ist:
1
void twi_init(void)
2
...
3
TWBR = ((F_CPU / TWI_FREQ) - 16) / 2;
4
...
5
6
void twi_setFrequency(uint32_t frequency)
7
...
8
TWBR = ((F_CPU / frequency) - 16) / 2;
Wenn F_CPU 1Mhz ist würde da theoretisch eine negative Zahl 
rauskommen...
Ich habe versucht beide zuweisungen von TWBR mit
1
TWBR = 1
zu ersetzen, das hat aber eigenartigerweise überhaupt keinen Einfluss.
Immer noch 2kHz, und wenn ich in meinem Sketch TWBR mit
1
Serial.println("TWBR= " + String(TWBR,BIN) + " = " + String(TWBR));
ausgebe bekomme ich immer
1
TWBR= 11111101 = 253

Dann habe ich weiter vorne in der Adafruit_SSD1306.cpp gesucht und 
brutalo nach jeder "wire->begin..." Anweisung mein "TWBR = 1" eingefügt 
und TADA ich hatte meine 55kHz und bei "TWBR = 0" sogar um die 65kHz und 
mein Display refreshd jetzt wieder erträglich. Ich weiß das TWBR < 10 
außerhalb der Empfehlung liegt aber es geht :)

Eigenartigerweise zeigt er mir die Ausgabe des Registers immer noch 
diese ominöse 253 an. Ich habe absolut keinen Plan wo die herkommt und 
warum das ändern der twi.c überhaupt keinen Einfluss hat...

: Bearbeitet durch User
von M. K. (sylaina)


Lesenswert?

Ich mach mal ein wenig Eigenwerbung:

https://github.com/Sylaina/oled-display

Das ist meine Library für I2C Displays mit SSD1306 bzw. SH1106 
Controller. Ist etwas schneller als die Adafruit-Library und braucht 
auch weniger Speicher. Ist halt dafür nicht ganz so 
flexibel/umfangreich.
Einstellungen werden fürs LCD werden in der lcd.h gemacht, für I2C 
werden die Einstellungen in i2c.h vorgenommen.

: Bearbeitet durch User
von Paul G. (paul_g210) Benutzerseite


Lesenswert?

Danke, werde ich mal probieren.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.