SainSmart SPI_1.3_OLED

OP #4895673
Lesenswert?

Hallo
Versuche das OLED Display anzusteuern.
Prozessor Atmega 168

Leider funzt. da noch garnichts.
Laut Hersteller ist ein SH1106 Controller auf der Platine.

Hat jemand ein Projekt für AVR Studio mit dem Display ?

google kenne ich .
programmieren kann ich auch ein wenig.
Wenn jemand was passendes hat..
LG
Gast #4900063
Lesenswert?

Moin

Ich haben nun das Display angesteuert und es tut sich auch was.
Da gab es Probleme mit der SPI ansteuerung .



Nun mal eine Frage an die Experten.

Ist die SS1306 controller ansteuerung gleich der SH1106 ?

Hat jemand doch noch eine projekt für atmega ?

die u8glib Lib ist bischen übertrieben für das Display.

schon mal den besten .
#4901704
Lesenswert?

Hi,
wie wäre es denn mit einem Link zum Artikel?

Ich benutze auch OLED Displays mit einem SSD1306 Controller und verwende 
die u8glib. Übertrieben ist diese Bibliothek allemal NICHT. Sie kann 
lediglich einfache Funktionen, die für mich aber ausreichen.
Ich weiß nicht wie du dir eine Bibliothek mit noch weniger Funktionen 
vorstellst?
Was ist dir denn an der u8glib zu viel?

Such mal nach u8g2, dort gibt es eine neue Version die auch einen 
abgespeckten Modus ohne RAM Verbrauch unterstützt und lediglich Text 
erzeugen kann.

MfG Waldemar
OP #4903148
Lesenswert?

Hallo

Mit der u8glib habe ich probleme beim erstellen eines projektes unt
avr studio 4.

Komme aber schon weiter.
der 168er prozessor hatte probleme mit dem speicher so das er jedesmal 
restet wenn ich auf das display was schrieb.
habe nun einen 644er  mit dem ich das display ansteuern kann.

Ein byte senden geht.  " ssd1306_write_byte(x,y,wert)"


aber beim senden eines frame buffer von 128x8 byte erscheint nur was in 
der ersten zeile.

Muss da noch bei jeder zeile die adresse verändert werden ?



}
void
ssd1306_write_byte (const uint8_t x, const uint8_t page, const uint8_t 
byte)
{
  ssd1306_write_instruction (SSD1306_SET_PAGE_START_ADDR | page);
  ssd1306_write_instruction (SSD1306_SET_COL_LO_NIBBLE | (x & 0xF));
  ssd1306_write_instruction (SSD1306_SET_COL_HI_NIBBLE | (x >> 4));
  ssd1306_write_data(byte);
}

void
ssd1306_clear_screen (void)
{
  ssd1306_reset_cursor ();

  for (uint16_t byte = 0; byte < SSD1306_PIXEL_BYTES; byte++)
//  for (uint16_t byte = 0; byte < 8448; byte++)
    {
      ssd1306_write_data (0x00);
    }
}

/*  Transfer display buffer to LCD */
void
ssd1306_display_fb (void)
{
  ssd1306_reset_cursor ();

  for (uint8_t page = 0; page < SSD1306_PIXEL_PAGES; page++)
//  for (uint8_t page = 0; page < 3; page++)
    {
      for (uint8_t column = 0; column < SSD1306_X_PIXELS; column++)
//      for (uint8_t column = 0; column < 132; column++)
  {
    ssd1306_write_data (0x0f);

//    ssd1306_write_data (ssd1306_frame_buffer_g[page][column]);
  }
    }
}

void test_send()
{
uint16_t i;
    ssd1306_reset_cursor ();
  for(i=0;i<(128*8);i++)  ssd1306_write_data (0x0f);
}


void
ssd1306_clear_fb (void)
{
  memset(ssd1306_frame_buffer_g, 0, SSD1306_PIXEL_BYTES);
}

void
ssd1306_set_pixel_fb (const uint8_t x, const uint8_t y, const 
pixel_state_t pixel_state)
{
  switch (pixel_state)
    {
    case PIXEL_STATE_ON:
      ssd1306_frame_buffer_g[y / SSD1306_PIXEL_PAGES][x] |= (1 << y % 
SSD1306_PIXEL_PAGES);
      break;
    case PIXEL_STATE_OFF:
      ssd1306_frame_buffer_g[y / SSD1306_PIXEL_PAGES][x] &= ~(1 << y % 
SSD1306_PIXEL_PAGES);
      break;
    default:
      break;
    }
}

/* Writes a run length encoded image to the display buffer */
void
ssd1306_write_image_fb (const uint8_t * image)
{
  uint8_t image_byte = 0, next_image_byte, write_byte_count = 0;

  for (uint8_t page = 0; page < SSD1306_PIXEL_PAGES; page++)
    {
      for (uint8_t column = 0; column < SSD1306_X_PIXELS; column++)
  {
    if (!write_byte_count)
      {
        image_byte = pgm_read_byte_near (image++);
        next_image_byte = pgm_read_byte_near (image++);
        if (image_byte == next_image_byte)
    {
      write_byte_count = pgm_read_byte_near (image++);
    }
        else
    {
      write_byte_count = 1;
      image--;
    }
      }
Gast #4903292
Lesenswert?

Eigentlich ist das nur ein Probem mit dem Verständnisses des Speicher 
vom Display.
Wenn ich ein Reset Cursor mache und dann 128x 8 Byte in dem Display 
Speicher schreibe wird nur in der ersten Page was angezeigt.
 Nach dem Original sourcen wird auch nur ein Speicher abgelegt ( FB) und 
dann zum Display gesendet.

Wie schreibe ich in die nächste Page .Also 1-7 ?
Oder gibt es ein Register für autoincrement ?
#4903744
Lesenswert?

Juppo N. schrieb:
> Moin
> Anbei mein Test Projekt für das OLED Display
>
> Wie schon beschrieben wird immer nur die erste Page beschrieben.

mach doch bitte einen Screenshot davon und hänge ihn an. Wir können dir 
hier erst helfen, (ich zumindest), wenn ich das Problem vollends 
verstehen und nachvollziehen kann!
Wenn du schreibst, es wird nur die erste Page beschrieben, weiß trotzdem 
niemand, wie das Endergebnis auf dem Display aussieht...

MfG Waldemar
#4903864
Lesenswert?

jupp schrieb:
> Ist die SS1306 controller ansteuerung gleich der SH1106 ?
>
> Hat jemand doch noch eine projekt für atmega ?

Für I2C hab ich eine Lösung: 
Beitrag "SSD1306/1309 Library zum Darstellen von Text auf OLED Displays"

Siehe dort meinen letzten Eintrag, da ist die Lib mit angehangen.

Stellst du auf I2C um kannst du die Lib direkt benutzten, willst du SPI 
weiterhin verwenden musst du alle i2c-Funktionen entsprechend anpassen.
Wirklich schwer ist das nicht.

Juppo N. schrieb:
> was passiert wenn ich das pixel 129 schreibe ?
> muss dann der cursor auf page 1 gesetzt werden ?

Wenn du in die Nächste Zeile willst musst du den Cursor auf die nächste 
Page und X wieder auf 2 setzen.

Der RAM-Inhalt ist wie folgt:

es gibt 132 Columns von denen die Column 2 bis 128 der Displayanzeige 
entspricht. Die Column 0 & 1 ist links außerhalb des Displays, die 
Column 131 & 132 ist rechts außerhalb des Displays. Läuft der Cursor aus 
dem Bereich heraus wird er automatisch wieder auf Column 0 gesetzt, die 
Page wird (im Gegensatz zum SSD1306) nicht geändert.

Die Pages werden alle auf dem Display da gestellt, hier gibt es keine 
außerhalb des Anzeigenbereichs des Displays.
#4903932
Lesenswert?

Juppo N. schrieb:
> Wie schon beschrieben wird immer nur die erste Page beschrieben.

vielleicht hilft dir das?

mit der U8GLIB auf Arduino sollte aber auch passend umzubauen sein für 
pur AVR

im loop (natürlich nur alle 250ms)
1
  if ( u8g.getMode() == U8G_MODE_BW ) 
2
  { u8g.setColorIndex(1);         // pixel on
3
  }
4
  u8g.firstPage();  
5
  do 
6
  { draw(_txt);
7
  } while( u8g.nextPage() );


1
#include "U8glib.h"
2
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NONE);  // I2C / TWI 
3
//U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_FAST);  // Dev 0, Fast I2C / TWI
4
U8GLIB_SH1106_128X64 u8g(U8G_I2C_OPT_NO_ACK);  // Display which does not send ACK
5

6
char _txt[15]={0};
7
char start[]="Tach auch";
8

9
void draw(char *txt) 
10
{
11
  // graphic commands to redraw the complete screen should be placed here  
12
  
13
  u8g.setFont(u8g_font_unifont);
14
  //u8g.setFont(u8g_font_5x7);
15
  //u8g.setFont(u8g_font_osb21); // viel Platz im Sketch
16

17
/*
18
  uint8_t font_high = 0.9 * u8g.getFontLineSpacing();
19
  u8g.drawStr( 0, 1 * font_high, txt);
20
  u8g.drawStr( 0, 3 * font_high, lefts(r_date_str, 14));
21
  u8g.drawStr( 0, 4 * font_high, lefts(r_time_str, 14));
22
  u8g.drawStr( 0, 5 * font_high, "123456789012345678901234567890");
23
*/
24
  u8g.drawStr( 0, 11, txt);
25
  u8g.drawStr( 0, 33, lefts(r_date_str, 14));
26
  u8g.drawStr( 0, 44, lefts(r_time_str, 14));
27
  u8g.drawStr( 0, 55, "Line 5");
28
  u8g.setFont(u8g_font_5x7);
29
  u8g.drawStr( 0, 64, "1234567890123456789012345");
30
}
#4904025
Lesenswert?

Juppo N. schrieb:
> Mal ne frage zu adruino.
> sind die lib's kompatible zu avr c ?

Nein, die müssen umgeschrieben werden da die Arduino Libraries in C++ 
geschrieben sind. C kann damit nichts anfangen.

Der Umfang der bekannten Libraries (Adafruit, u8g) war meine Intention 
mir für den SSD1306 für I2C selbst eine (bzw. zwei) Library zu 
schreiben. Auf Nachfrage hier im Forum habe ich dann noch die 
SH1106-Kompatibilität hergestellt.
Meine Lib nur für Text-Darstellung benötigt keinen statischen RAM und 
"nur" ca. 1500 kByte Flash, die Lib für Grafik benötigt ca. 1900 kByte 
Flash und 1027 byte statischen RAM. Als Gegenvergleich: Ich mein die u8g 
braucht etwas über 4 kByte Flash, die von Adafruit hab ich was mit 10 
kByte im Kopf und beide brauchen etwas über 1kByte statischen RAM.
#4904027
Lesenswert?

also alle meine C zu Ino umbenennen klappte

Der andere Weg sollte auch funktionieren, nur kann ich kein cpp

Aber im cpp File auch c-code oder preprozessor statements einfügen 
klappt

Es wäre auszuprobieren

Notfalls geht man nicht über die IDE vom Arduino und lässt setup und 
loop weg, dann ist die fast wie AVR nur muss man dann die Make wohl 
passend machen oder gleich den gcc aufrufen, aber da schwimme ich 
gerade, brauchte ich ja nie
#4904077
Lesenswert?

Joachim B. schrieb:
> also alle meine C zu Ino umbenennen klappte
>
> Der andere Weg sollte auch funktionieren, nur kann ich kein cpp

C zu C++ zu konvertieren geht daher, da C eine Teilmenge von C++ 
darstellt. Der andere Weg geht aber nicht da C++ schlicht keine 
Teilmenge von C ist. Woher soll z.B. C wissen was ein Konstruktor ist? 
Schon die Symantik würde der C-Compiler anmeckern.
Also der C++-Quellcode müsste dann schon sehr speziell sein, nur C-Code 
enthalten aber nichts aus dem C++ Pool, und das ist eben sehr 
unwahrscheinlich.
#4904363
Lesenswert?

M. K. schrieb:
> C zu C++ zu konvertieren geht daher, da C eine Teilmenge von C++
> darstellt. Der andere Weg geht aber nicht da C++ schlicht keine
> Teilmenge von C ist.

übersiehst du dabei nicht das Arduino und A-Studio 4 auf GCC aufsetzen?

Damit sollte die Verwendbarkeit von cpp möglich sein.

Juppo N. schrieb:
> Hat jemand ein Projekt für AVR Studio

OK welches Studio wird nicht benannt, ich nutze 4.18 mit gcc
#4904371
Lesenswert?

Joachim B. schrieb:
> übersiehst du dabei nicht das Arduino und A-Studio 4 auf GCC aufsetzen?
>
> Damit sollte die Verwendbarkeit von cpp möglich sein.

Aber nicht in C, das war ja die Frage. Probiere es einfach mal aus. 
Schreibe dir eine Standard-C++-Klasse und versuche sie in C zu benutzen. 
Der C-Compiler wird hier meckern weil er u.a. mit den 
Constructor/Destructor nichts anzufangen weis.
OP #4904380
Lesenswert?

Ich benutze AVR Studio 4

Beim Schreiben muss der x wert +2 genommen werden.
Dann passt es.
Hab nun einen buffer angelegt der das ganze Display beschreibt.
in diesen buffer kann ich dann hinein schreiben.
Funktioniert.

Asccii Zeichensatz mit 8 pixel höhe und 5 pixel breite geht auch.
Weiter gehts dann mit große Zeichen und funktionen für rahmen und usw.

Besten Dank an alle.
#4904383
Lesenswert?

Juppo N. schrieb:
> Ich benutze AVR Studio 4

Warum eigentlich diese alte Gurke? Etabliertes System?

Juppo N. schrieb:
> Beim Schreiben muss der x wert +2 genommen werden.

Ja, das habe ich oben geschrieben. ;)
Grund ist, dass links und rechts vom sichtbaren Bereichs des Display 
jeweils zwei Spalten sind, die man nicht sieht. Wahrscheinlich um das 
Scrolling Smoother aussehen zu lassen.

Juppo N. schrieb:
> Weiter gehts dann mit große Zeichen und funktionen für rahmen und usw.

Wie geschrieben, schau dir mal meine Lib ruhig an wie ich es löste. Das 
hilft dir sicher auch ;)

Viel Spass mit dem Display ;)
#4904427
Lesenswert?

Juppo N. schrieb:
> Asccii Zeichensatz mit 8 pixel höhe und 5 pixel breite geht auch.
> Weiter gehts dann mit große Zeichen und funktionen für rahmen und usw.

ich gebe hier nochmal den Hinweis, dass die u8glib (bzw. mittlerweile 
u8g2) das alles kann. Und die Lib kann auch nicht besonders viel mehr, 
bzw. sie ist nicht überladen und auch nicht übertrieben!

Dafür ist die Lib gut strukturiert, hat sehr viele Fonts in allen 
erdenklichen Größen und funktioniert einfach gut!

Überleg dir nochmal ob du alles selber programmieren willst, obwohl es 
das schon fertig gibt!?

Wenn du mit der u8glib / u8g2 nicht auf Anhieb klar kommst, kann ich dir 
nur sagen: Es lohnt sich, dort eine halbe Stunde zu investieren und die 
Lib kennenzulernen.

Damit kannst du nämlich auch sehr sehr viele andere Displays ansteuern, 
und brauchst, wenn du mal das Display wechselst, keine neue Lib zu 
"erlernen"...

Ist nur so ein Hinweis...

MfG Waldemar
(Firma: privat) #5503618
Lesenswert?

Hallo,
ich brüte gerade über der Umsetzung mit der u8h2 Lib ein I2C Display 
anzusteuern. Ein SSD1306 soll mit HW TWI des Atmega 328P angesteuert 
werden.
Ich finde aber nichts für das Setup in der Form: 
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2 für ein HW I2C.
Beinhaltet die Bibliothek schon die HW I2C Ansteuerung?
Gruß
Reinhard
#5503670
Lesenswert?

Reinhard O. schrieb:
> u8h2

?

ich habe gerade noch mal geschaut
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0);  // I2C 
/ TWI
//U8GLIB_SSD1306_128X64 
u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);  // Fast I2C 
/ TWI
//U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NO_ACK);  // Display which does 
not send AC

alles da, ist aber eine ältere Version

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren