SSD1306 I2C OLED - Muybridge Animation

Hi

Beautiful work

I Need your help, please:

I got a project that needs a simple animation, but the animation must have an option to rotate around the center of the screen due to a precise angle command

I'm sure there is a simple solution for it (animation and rotation) but I do not know where to look

Thanks a lot

Tal

TalBY:
Hi
I Need your help, please:

I got a project that needs a simple animation, but the animation must have an option to rotate around the center of the screen due to a precise angle command

I'm sure there is a simple solution for it (animation and rotation) but I do not know where to look

Tal

I am going to attempt to answer this with an animation that works with a loop and sin and cosine. I made another quick video of the outcome at: http://www.youtube.com/watch?v=AOkIm04BdFk

This animation is not done the with individual frames shown previously, but drawing lines and circles using the Adafruit drawing library. See attached code:

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

#define OLED_RESET 4

Adafruit_SSD1306 display(OLED_RESET);

int hSpin = 30;
int vSpin = 32;
int SpinRadius = 60;

void setup(){
  
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
}

void loop(){

  for(int i=60; i>0; i--){                       //Change loop to "for(int i=0; i<60; i++){" to spin clockwise
    display.fillRect(0, 0, 128, 64, BLACK);      //Blanks out last frame to black
    display.setTextColor(WHITE);
    display.setTextSize(3);
    display.setCursor(74,25);                                       // Position of text
    display.print(i);                                                
    display.fillCircle(hSpin, vSpin, SpinRadius / 2, WHITE);        // Draws a white filled circle
    display.fillCircle(hSpin, vSpin, (SpinRadius / 2) - 1 , BLACK); // draws a black circle to refresh line movement
 
    float SpinAngle = i * 6; 
    SpinAngle = SpinAngle / 57.296;                                 // converts degrees to radians
    int a = (hSpin + (sin(SpinAngle) * (SpinRadius / 2)));          //coordinate for end of line position horizontally
    int b = (vSpin - (cos(SpinAngle) * (SpinRadius / 2)));          //coordinate for end of line position vertically

    display.drawLine(hSpin,vSpin,a,b,WHITE); // draws rotating line from center out to horizontal and vertical position.
    display.display();                       // refresh screen
    delay(10);                               //Set delay to 1000 and mimick second hand movement
  }
}

I took that last example to a new personal height... I made the circular path and divided in half. Effectively making an elliptical path. I put a second elliptical path just below and made four equal distance points on each ellipse forming a square on each ellipse. I then connected the top and bottom squares forming a cube. So, now it's a rotating cube.

See cube rotating at: OLEDCube - SSD1306 I2C OLED Animation - YouTube

Extra code to be added to last example:

   float SpinAngle = i * 6; 
    SpinAngle = SpinAngle / 57.296;
    float SpinAngle2 = SpinAngle + 90 / 57.296;
    
    int a = (hSpin + (sin(SpinAngle) * (SpinRadius / 2)));
    int b = (vSpin - (cos(SpinAngle) * (SpinRadius / 2)))/2;
    int c = (hSpin - (sin(SpinAngle) * (SpinRadius / 2)));
    int d = (vSpin + (cos(SpinAngle) * (SpinRadius / 2)))/2;

    int a1 = (hSpin + (sin(SpinAngle2) * (SpinRadius / 2)));
    int b1 = (vSpin - (cos(SpinAngle2) * (SpinRadius / 2)))/2;
    int c1 = (hSpin - (sin(SpinAngle2) * (SpinRadius / 2)));
    int d1 = (vSpin + (cos(SpinAngle2) * (SpinRadius / 2)))/2;

    int e = (hSpin + (sin(SpinAngle) * (SpinRadius / 2)));
    int f = (vSpin2 - (cos(SpinAngle) * (SpinRadius / 2)))/2;
    int g = (hSpin - (sin(SpinAngle) * (SpinRadius / 2)));
    int h = (vSpin2 + (cos(SpinAngle) * (SpinRadius / 2)))/2;

    int e1 = (hSpin + (sin(SpinAngle2) * (SpinRadius / 2)));
    int f1 = (vSpin2 - (cos(SpinAngle2) * (SpinRadius / 2)))/2;
    int g1 = (hSpin - (sin(SpinAngle2) * (SpinRadius / 2)));
    int h1 = (vSpin2 + (cos(SpinAngle2) * (SpinRadius / 2)))/2;
    
    display.drawLine(a,b,a1,b1,WHITE);
    display.drawLine(a1,b1,c,d,WHITE);
    display.drawLine(c,d,c1,d1,WHITE);
    display.drawLine(c1,d1,a,b,WHITE);

    display.drawLine(e,f,e1,f1,WHITE);
    display.drawLine(e1,f1,g,h,WHITE);
    display.drawLine(g,h,g1,h1,WHITE);
    display.drawLine(g1,h1,e,f,WHITE);
    
    display.drawLine(a,b,e,f,WHITE);
    display.drawLine(g,h,c,d,WHITE);
    display.drawLine(a1,b1,e1,f1,WHITE);
    display.drawLine(g1,h1,c1,d1,WHITE);

A second version with the ellipses turn opposite to each other causing the cube animation to have depth or perspective.

See cube with perspective rotating at: OLEDDepth - SSD1306 I2C OLED Animation - YouTube

Revised addition code:

   SpinAngle = SpinAngle / 57.296;
    float SpinAngle2 = SpinAngle + 90 / 57.296;
    
    int a = (hSpin - (sin(SpinAngle) * (SpinRadius / 2)));
    int b = (vSpin - (cos(SpinAngle) * (SpinRadius / 2)))/2;
    int c = (hSpin + (sin(SpinAngle) * (SpinRadius / 2)));
    int d = (vSpin + (cos(SpinAngle) * (SpinRadius / 2)))/2;

    int a1 = (hSpin + (sin(SpinAngle2) * (SpinRadius / 2)));
    int b1 = (vSpin + (cos(SpinAngle2) * (SpinRadius / 2)))/2; 
    int c1 = (hSpin - (sin(SpinAngle2) * (SpinRadius / 2)));  
    int d1 = (vSpin - (cos(SpinAngle2) * (SpinRadius / 2)))/2;

    int e = (hSpin + (sin(SpinAngle) * (SpinRadius / 2)));
    int f = (vSpin2 - (cos(SpinAngle) * (SpinRadius / 2)))/2;
    int g = (hSpin - (sin(SpinAngle) * (SpinRadius / 2)));
    int h = (vSpin2 + (cos(SpinAngle) * (SpinRadius / 2)))/2;

    int e1 = (hSpin - (sin(SpinAngle2) * (SpinRadius / 2)));
    int f1 = (vSpin2 + (cos(SpinAngle2) * (SpinRadius / 2)))/2;
    int g1 = (hSpin + (sin(SpinAngle2) * (SpinRadius / 2)));
    int h1 = (vSpin2 - (cos(SpinAngle2) * (SpinRadius / 2)))/2;
    
    display.drawLine(a,b,a1,b1,WHITE);
    display.drawLine(a1,b1,c,d,WHITE);
    display.drawLine(c,d,c1,d1,WHITE);
    display.drawLine(c1,d1,a,b,WHITE);

    display.drawLine(e,f,e1,f1,WHITE);
    display.drawLine(e1,f1,g,h,WHITE);
    display.drawLine(g,h,g1,h1,WHITE);
    display.drawLine(g1,h1,e,f,WHITE);
    
    display.drawLine(a,b,g,h,WHITE);
    display.drawLine(a1,b1,g1,h1,WHITE);
    display.drawLine(c,d,e,f,WHITE);
    display.drawLine(c1,d1,e1,f1,WHITE);

The old TVout library has a demo of a spinning 3D wireframe cube

zoomx:
The old TVout library has a demo of a spinning 3D wireframe cube
arduino-tvout/examples/DemoPAL/DemoPAL.pde at master · cbmeeks/arduino-tvout · GitHub

I'll bet your library doesn't have a wireframe of a spinning dodecahedron...

See spinning dodecahedron animation at: http://youtu.be/y-KIPsp4hps

I made a second dodecahedron animation with perspective by rotating the bottom elliptical path opposite to the top three paths.

Dodecahedron animation with perspective at: https://youtu.be/VPEzzP9_Wyc

Well done!

It's not my library. I have a copy of it in github (but the link is not my copy) because the original repository is on Google Code that has closed.

Anyway Claus Ilginnis made a better work fixing more bugs here

But there is not any spinning dodecahedron!
See the spinning cube here

from 0:55. The rotation is not limited on one axis.

I just started exploring this subject and decided to go in a different direction. I created a Mac/Linux program to take animated GIFs and turn them into a compact form that's easy to play back (my own byte oriented compression). The player code doesn't need any RAM and runs well on an ATtiny85. I'm currently documenting everything and will release it as open source soon. Anyone interested can contact me with suggestions/requests before I publish it.

Here's a video of it running a short animation on an ATtiny85:

Youtube Video

I just added a blog post about it:

Practical animation on I2C SSD1306 displays

Interesting!

Maybe you can consider cheap MCU like the STM32F103 (bluepill but STM32F4 series also!) or the ESP8266 for bigger animations!

I am very impressed with decoding a GIF with a tiny85.

We look forward to your posts.

David.

It does not decode a GIF but a format developed by him.

bitbank:
I created a Mac/Linux program to take animated GIFs and turn them into a compact form that's easy to play back (my own byte oriented compression). The player code doesn't need any RAM and runs well on an ATtiny85.

Yes, I am aware of that. But I suspect that he has a pretty good knowledge of how to decode a regular GIF.

It would be interesting to know if it can be done with Uno-size SRAM.

Yes, I am sure that you can invent a special format. But you would need to process every standard GIF into this special format before you use it. Not as convenient as using standard PC tools like IrfanView.

David.

david_prentice:
Yes, I am aware of that. But I suspect that he has a pretty good knowledge of how to decode a regular GIF.

It would be interesting to know if it can be done with Uno-size SRAM.

Yes, I am sure that you can invent a special format. But you would need to process every standard GIF into this special format before you use it. Not as convenient as using standard PC tools like IrfanView.

David.

As I state in my blog post. No AVR MCU has enough RAM to decode a GIF. LZW compression needs a dynamic dictionary with 4096 entries and multiple pointers/flags for each entry. Animated GIF requires additional RAM to hold the previous frame. Neither of which is possible with less than 32-64k of RAM. My solution is a practical way to leverage the numerous animated GIF tools to easily create complex animations to run on AVRs. The other side of my project is that my code allows the "slow+cheap" I2C version of the SSD1306 to become practical for doing fast animations.

It is the same also for small GIF?
Because Bodmer was able to decode JPEG on a Mega (SRAM 8Kb)

and I used his library on a STM32F103 with 20Kb SRAM.

Anyway maybe an ESP8266 or an ESP32 can do that?

zoomx:
It is the same also for small GIF?
Because Bodmer was able to decode JPEG on a Mega (SRAM 8Kb)
GitHub - Bodmer/JPEGDecoder: A JPEG decoder library
and I used his library on a STM32F103 with 20Kb SRAM.

Anyway maybe an ESP8266 or an ESP32 can do that?

JPEG and GIF compression have nothing to do with each other. Yes, it's possible to decode a JPEG with less RAM than a GIF. The problem with GIF decoding is that the dictionary grows as you decode the image. You may be able to decode a tiny image, but then a slightly larger one will need more room to decode. It would be a "half-baked" solution that would fail frequently. An ESP32 could certainly handle GIF decoding. This topic is about animating images on much more constrained MCUs like the AVR series.

stievenart:
....
I have attached an image of a Star Wars AT-AT that someone might animate:
.....

Done.

at80.c (99.3 KB)

Thanks. It seems that frame 14 (img14) was lost.

@dm3942,

There are three types of monochrome bitmap:

  1. MSB first. 8-bits across a row per byte. Used by Adafruit drawBitmap()
  2. LSB first. 8-bits across a row. Used by Adafruit drawXBitmap() and U8g2lib
  3. KS0108 style. 8 vertical bits per byte. Draw an 8-bit deep stripe across the screen. Called a page.

Method (3) is native to the SSD1306, KS0108, ... controller. And is the format used by Adafruit and U8g2lib for RAM buffers.

I found Image2GLCD on the Internet. It appears to be capable of generating all three styles.
I could not get it to work properly. The program is Chinese. I don't know how to register in Chinese. I can't read Chinese Help files.

Image2GLCD can resize to fit your GLCD / OLED
Image2GLCD can alter colour depth / contrast.

Your bitmaps were made for (2) with default depth. You could get better images if you adjust the depth.

I suspect that some programs can extract multiple frames from an animated GIF. Which would be nice.

Anyway, I have adapted your arrays to suit a Uno.
And converted them to (3) format.

A Uno can achieve about 15 FPS with I2C and drawBitmap() or 30FPS with the native KS0108 format.

If you use SPI, you can get 30FPS and 285 FPS on a Uno.

Can anyone recommend an Image program that work properly?
It would be nice to generate multiple C arrays directly from animated GIF.

David.

OLED_at80s.zip (29.2 KB)

I found Image2GLCD here
http://www.ablab.in/image2glcd-software/
it is in english not chinese!
I found also this one

and this one
http://bitmap2lcd.com/blog/
No one works with animated gif.
I believe that it can be done using multiple programs, one for splitting gif and one for converting, with a third program that automate the process.

I will wait to hear from someone that has a positive experience with a PC app.

I do not want to "register" with an Indian website.
I do not mind paying a modest contribution to the real author.

David.