OLED Display SSD1306 i2c 128x64 demo

From Public Wiki
Revision as of 03:52, 1 November 2020 by Legg (talk | contribs) (Created page with "==Synopsis== Demo of different graphics and test modes of SSD1306. ==Code== <syntaxhighlight lang="C++" line='line'> //Arduino UNO //SSD1306 ////Pin A4 SDA ////Pin A5 SCL /**...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Synopsis

Demo of different graphics and test modes of SSD1306.

Code

  1 //Arduino UNO
  2 //SSD1306
  3 ////Pin A4 SDA
  4 ////Pin A5 SCL
  5 
  6 /**************************************************************************
  7  This is an example for our Monochrome OLEDs based on SSD1306 drivers
  8 
  9  Pick one up today in the adafruit shop!
 10  ------> http://www.adafruit.com/category/63_98
 11 
 12  This example is for a 128x64 pixel display using I2C to communicate
 13  3 pins are required to interface (two I2C and one reset).
 14 
 15  Adafruit invests time and resources providing this open
 16  source code, please support Adafruit and open-source
 17  hardware by purchasing products from Adafruit!
 18 
 19  Written by Limor Fried/Ladyada for Adafruit Industries,
 20  with contributions from the open source community.
 21  BSD license, check license.txt for more information
 22  All text above, and the splash screen below must be
 23  included in any redistribution.
 24  **************************************************************************/
 25 
 26 #include <SPI.h>
 27 #include <Wire.h>
 28 #include <Adafruit_GFX.h>
 29 #include <Adafruit_SSD1306.h>
 30 
 31 #define SCREEN_WIDTH 128 // OLED display width, in pixels
 32 #define SCREEN_HEIGHT 64 // OLED display height, in pixels
 33 
 34 // Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
 35 #define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
 36 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 37 
 38 #define NUMFLAKES     10 // Number of snowflakes in the animation example
 39 
 40 #define LOGO_HEIGHT   16
 41 #define LOGO_WIDTH    16
 42 static const unsigned char PROGMEM logo_bmp[] =
 43 { B00000000, B11000000,
 44   B00000001, B11000000,
 45   B00000001, B11000000,
 46   B00000011, B11100000,
 47   B11110011, B11100000,
 48   B11111110, B11111000,
 49   B01111110, B11111111,
 50   B00110011, B10011111,
 51   B00011111, B11111100,
 52   B00001101, B01110000,
 53   B00011011, B10100000,
 54   B00111111, B11100000,
 55   B00111111, B11110000,
 56   B01111100, B11110000,
 57   B01110000, B01110000,
 58   B00000000, B00110000 };
 59 
 60 void setup() {
 61   Serial.begin(9600);
 62 
 63   // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
 64   if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
 65     Serial.println(F("SSD1306 allocation failed"));
 66     for(;;); // Don't proceed, loop forever
 67   }
 68 
 69   // Show initial display buffer contents on the screen --
 70   // the library initializes this with an Adafruit splash screen.
 71   display.display();
 72   delay(2000); // Pause for 2 seconds
 73 
 74   // Clear the buffer
 75   display.clearDisplay();
 76 
 77   // Draw a single pixel in white
 78   display.drawPixel(10, 10, SSD1306_WHITE);
 79 
 80   // Show the display buffer on the screen. You MUST call display() after
 81   // drawing commands to make them visible on screen!
 82   display.display();
 83   delay(2000);
 84   // display.display() is NOT necessary after every single drawing command,
 85   // unless that's what you want...rather, you can batch up a bunch of
 86   // drawing operations and then update the screen all at once by calling
 87   // display.display(). These examples demonstrate both approaches...
 88 
 89   testdrawline();      // Draw many lines
 90 
 91   testdrawrect();      // Draw rectangles (outlines)
 92 
 93   testfillrect();      // Draw rectangles (filled)
 94 
 95   testdrawcircle();    // Draw circles (outlines)
 96 
 97   testfillcircle();    // Draw circles (filled)
 98 
 99   testdrawroundrect(); // Draw rounded rectangles (outlines)
100 
101   testfillroundrect(); // Draw rounded rectangles (filled)
102 
103   testdrawtriangle();  // Draw triangles (outlines)
104 
105   testfilltriangle();  // Draw triangles (filled)
106 
107   testdrawchar();      // Draw characters of the default font
108 
109   testdrawstyles();    // Draw 'stylized' characters
110 
111   testscrolltext();    // Draw scrolling text
112 
113   testdrawbitmap();    // Draw a small bitmap image
114 
115   // Invert and restore display, pausing in-between
116   display.invertDisplay(true);
117   delay(1000);
118   display.invertDisplay(false);
119   delay(1000);
120 
121   testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT); // Animate bitmaps
122 }
123 
124 void loop() {
125 }
126 
127 void testdrawline() {
128   int16_t i;
129 
130   display.clearDisplay(); // Clear display buffer
131 
132   for(i=0; i<display.width(); i+=4) {
133     display.drawLine(0, 0, i, display.height()-1, SSD1306_WHITE);
134     display.display(); // Update screen with each newly-drawn line
135     delay(1);
136   }
137   for(i=0; i<display.height(); i+=4) {
138     display.drawLine(0, 0, display.width()-1, i, SSD1306_WHITE);
139     display.display();
140     delay(1);
141   }
142   delay(250);
143 
144   display.clearDisplay();
145 
146   for(i=0; i<display.width(); i+=4) {
147     display.drawLine(0, display.height()-1, i, 0, SSD1306_WHITE);
148     display.display();
149     delay(1);
150   }
151   for(i=display.height()-1; i>=0; i-=4) {
152     display.drawLine(0, display.height()-1, display.width()-1, i, SSD1306_WHITE);
153     display.display();
154     delay(1);
155   }
156   delay(250);
157 
158   display.clearDisplay();
159 
160   for(i=display.width()-1; i>=0; i-=4) {
161     display.drawLine(display.width()-1, display.height()-1, i, 0, SSD1306_WHITE);
162     display.display();
163     delay(1);
164   }
165   for(i=display.height()-1; i>=0; i-=4) {
166     display.drawLine(display.width()-1, display.height()-1, 0, i, SSD1306_WHITE);
167     display.display();
168     delay(1);
169   }
170   delay(250);
171 
172   display.clearDisplay();
173 
174   for(i=0; i<display.height(); i+=4) {
175     display.drawLine(display.width()-1, 0, 0, i, SSD1306_WHITE);
176     display.display();
177     delay(1);
178   }
179   for(i=0; i<display.width(); i+=4) {
180     display.drawLine(display.width()-1, 0, i, display.height()-1, SSD1306_WHITE);
181     display.display();
182     delay(1);
183   }
184 
185   delay(2000); // Pause for 2 seconds
186 }
187 
188 void testdrawrect(void) {
189   display.clearDisplay();
190 
191   for(int16_t i=0; i<display.height()/2; i+=2) {
192     display.drawRect(i, i, display.width()-2*i, display.height()-2*i, SSD1306_WHITE);
193     display.display(); // Update screen with each newly-drawn rectangle
194     delay(1);
195   }
196 
197   delay(2000);
198 }
199 
200 void testfillrect(void) {
201   display.clearDisplay();
202 
203   for(int16_t i=0; i<display.height()/2; i+=3) {
204     // The INVERSE color is used so rectangles alternate white/black
205     display.fillRect(i, i, display.width()-i*2, display.height()-i*2, SSD1306_INVERSE);
206     display.display(); // Update screen with each newly-drawn rectangle
207     delay(1);
208   }
209 
210   delay(2000);
211 }
212 
213 void testdrawcircle(void) {
214   display.clearDisplay();
215 
216   for(int16_t i=0; i<max(display.width(),display.height())/2; i+=2) {
217     display.drawCircle(display.width()/2, display.height()/2, i, SSD1306_WHITE);
218     display.display();
219     delay(1);
220   }
221 
222   delay(2000);
223 }
224 
225 void testfillcircle(void) {
226   display.clearDisplay();
227 
228   for(int16_t i=max(display.width(),display.height())/2; i>0; i-=3) {
229     // The INVERSE color is used so circles alternate white/black
230     display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
231     display.display(); // Update screen with each newly-drawn circle
232     delay(1);
233   }
234 
235   delay(2000);
236 }
237 
238 void testdrawroundrect(void) {
239   display.clearDisplay();
240 
241   for(int16_t i=0; i<display.height()/2-2; i+=2) {
242     display.drawRoundRect(i, i, display.width()-2*i, display.height()-2*i,
243       display.height()/4, SSD1306_WHITE);
244     display.display();
245     delay(1);
246   }
247 
248   delay(2000);
249 }
250 
251 void testfillroundrect(void) {
252   display.clearDisplay();
253 
254   for(int16_t i=0; i<display.height()/2-2; i+=2) {
255     // The INVERSE color is used so round-rects alternate white/black
256     display.fillRoundRect(i, i, display.width()-2*i, display.height()-2*i,
257       display.height()/4, SSD1306_INVERSE);
258     display.display();
259     delay(1);
260   }
261 
262   delay(2000);
263 }
264 
265 void testdrawtriangle(void) {
266   display.clearDisplay();
267 
268   for(int16_t i=0; i<max(display.width(),display.height())/2; i+=5) {
269     display.drawTriangle(
270       display.width()/2  , display.height()/2-i,
271       display.width()/2-i, display.height()/2+i,
272       display.width()/2+i, display.height()/2+i, SSD1306_WHITE);
273     display.display();
274     delay(1);
275   }
276 
277   delay(2000);
278 }
279 
280 void testfilltriangle(void) {
281   display.clearDisplay();
282 
283   for(int16_t i=max(display.width(),display.height())/2; i>0; i-=5) {
284     // The INVERSE color is used so triangles alternate white/black
285     display.fillTriangle(
286       display.width()/2  , display.height()/2-i,
287       display.width()/2-i, display.height()/2+i,
288       display.width()/2+i, display.height()/2+i, SSD1306_INVERSE);
289     display.display();
290     delay(1);
291   }
292 
293   delay(2000);
294 }
295 
296 void testdrawchar(void) {
297   display.clearDisplay();
298 
299   display.setTextSize(1);      // Normal 1:1 pixel scale
300   display.setTextColor(SSD1306_WHITE); // Draw white text
301   display.setCursor(0, 0);     // Start at top-left corner
302   display.cp437(true);         // Use full 256 char 'Code Page 437' font
303 
304   // Not all the characters will fit on the display. This is normal.
305   // Library will draw what it can and the rest will be clipped.
306   for(int16_t i=0; i<256; i++) {
307     if(i == '\n') display.write(' ');
308     else          display.write(i);
309   }
310 
311   display.display();
312   delay(2000);
313 }
314 
315 void testdrawstyles(void) {
316   display.clearDisplay();
317 
318   display.setTextSize(1);             // Normal 1:1 pixel scale
319   display.setTextColor(SSD1306_WHITE);        // Draw white text
320   display.setCursor(0,0);             // Start at top-left corner
321   display.println(F("Hello, world!"));
322 
323   display.setTextColor(SSD1306_BLACK, SSD1306_WHITE); // Draw 'inverse' text
324   display.println(3.141592);
325 
326   display.setTextSize(2);             // Draw 2X-scale text
327   display.setTextColor(SSD1306_WHITE);
328   display.print(F("0x")); display.println(0xDEADBEEF, HEX);
329 
330   display.display();
331   delay(2000);
332 }
333 
334 void testscrolltext(void) {
335   display.clearDisplay();
336 
337   display.setTextSize(2); // Draw 2X-scale text
338   display.setTextColor(SSD1306_WHITE);
339   display.setCursor(10, 0);
340   display.println(F("scroll"));
341   display.display();      // Show initial text
342   delay(100);
343 
344   // Scroll in various directions, pausing in-between:
345   display.startscrollright(0x00, 0x0F);
346   delay(2000);
347   display.stopscroll();
348   delay(1000);
349   display.startscrollleft(0x00, 0x0F);
350   delay(2000);
351   display.stopscroll();
352   delay(1000);
353   display.startscrolldiagright(0x00, 0x07);
354   delay(2000);
355   display.startscrolldiagleft(0x00, 0x07);
356   delay(2000);
357   display.stopscroll();
358   delay(1000);
359 }
360 
361 void testdrawbitmap(void) {
362   display.clearDisplay();
363 
364   display.drawBitmap(
365     (display.width()  - LOGO_WIDTH ) / 2,
366     (display.height() - LOGO_HEIGHT) / 2,
367     logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
368   display.display();
369   delay(1000);
370 }
371 
372 #define XPOS   0 // Indexes into the 'icons' array in function below
373 #define YPOS   1
374 #define DELTAY 2
375 
376 void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
377   int8_t f, icons[NUMFLAKES][3];
378 
379   // Initialize 'snowflake' positions
380   for(f=0; f< NUMFLAKES; f++) {
381     icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
382     icons[f][YPOS]   = -LOGO_HEIGHT;
383     icons[f][DELTAY] = random(1, 6);
384     Serial.print(F("x: "));
385     Serial.print(icons[f][XPOS], DEC);
386     Serial.print(F(" y: "));
387     Serial.print(icons[f][YPOS], DEC);
388     Serial.print(F(" dy: "));
389     Serial.println(icons[f][DELTAY], DEC);
390   }
391 
392   for(;;) { // Loop forever...
393     display.clearDisplay(); // Clear the display buffer
394 
395     // Draw each snowflake:
396     for(f=0; f< NUMFLAKES; f++) {
397       display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
398     }
399 
400     display.display(); // Show the display buffer on the screen
401     delay(200);        // Pause for 1/10 second
402 
403     // Then update coordinates of each flake...
404     for(f=0; f< NUMFLAKES; f++) {
405       icons[f][YPOS] += icons[f][DELTAY];
406       // If snowflake is off the bottom of the screen...
407       if (icons[f][YPOS] >= display.height()) {
408         // Reinitialize to a random position, just off the top
409         icons[f][XPOS]   = random(1 - LOGO_WIDTH, display.width());
410         icons[f][YPOS]   = -LOGO_HEIGHT;
411         icons[f][DELTAY] = random(1, 6);
412       }
413     }
414   }
415 }