Creating moving object on MicroView display

Hi there everyone,
I want to create a moving spot (later even a group of pixels), that will follow given path. Program is controlled by UNO and the display is MicroOled from SparkFun ( GitHub - sparkfun/SparkFun_Micro_OLED_Arduino_Library: Arduino library for the SparkFun Micro OLED - a breakout board for a monochrome, 0.66", 64x48 OLED display. ). I successfully managed to create vertical or horizontal moving pixel by this code:

void verticalMov()       //pixel by pixel movement of a pixel:)
{
  for (int y=19; y<29; y++)  //starts in position 19, finishes in position 29
  {
  oled.clear(PAGE);              //clears the displays buffer to erase previous pixels
  oled.pixel(32,y);               //buffers of pixel with fixed column in position 32 
  oled.display();                  //prints pixel on display
  delay(200);                      //delay, to control the movement speed
  } 
}

However in case of movement with an angle, I have to control two integers (x and y). And I can't do that by this code below, because nested FOR loop is counting first x and then y. I realize that the answer may be very simple, but I am not the programmer, just self teaching biologist:).

void angleMov()
{
  for (int y=19; y<29; y++)      
    {
    for (int x=35; x>30; x--) 
      {
      oled.clear(PAGE);
      oled.pixel(x,y);
      oled.display();
      delay(200);  
      }
    }
}

So my questions are:

  1. How to incorporate two integers into one loop?
  2. How to program such movements (both, horizontal and angled) with not just one pixel, but with set of couple pixels (like custom shape of i.e. 5 pixels).

This animation will be used to animate artificial prey in behavioral studies.
Thank you in advance for any help.

Not quite sure what you mean by angled movement but what you can do is this:

float x = 0;
float y = 0;
float dt = 0.01;
float moveN = 1; // You can change this to negative to move left or positive to move right


void Mov(){
 x += moveN * dt;
y += moveN * dt;
}

I guess by angled you mean this:

float x = 0;
float y = 0;
float dt = 0.01;
float moveN = 1; // You can change this to negative to move left or positive to move right
float angle = 90;

void angledMove(){
x+= moveN * math.cos(angle) * dt;
y += moveN * math.sin(angle) * dt
}

You would need to execute the angledMove method in a loop.
In the case your OLED.pixel() function doesn't take in floats You have to cast them by doing this:

oled.pixel((int)x,(int)y);

Thank you Bruce. By angle movement I meant other movements than horizontal and vertical (when both x and y coordinates are changed). I think that 45deg angle will be fine. I will check your ideas as soon as I get back to wires.

void setup() {
 Serial.begin(9600); 
}

float x = 0;
float y = 0;
float dt = 0.01;
float moveN = 10;
float angle = 45;

void angledMove(){
  x += moveN * cos(angle) * dt;
  y += moveN * sin(angle) * dt;
}

void loop() {
  delay(100);
  angledMove();
  Serial.println((int)x);
  Serial.print((int)y);
}

This seems to work for the Arduino IDE. You're best bet for representing Entities is to create a class. I'm aware that you don't know much about coding but I can help you.

OK, It works, I implemented it with a bit change, and the result looks like this:

There are 15 different paths in the animation, so the code got fatty.
But I still have no idea how to animate more complicated shapes on this pathway:(.

#include <Wire.h>  // Include Wire if you're using I2C
#include <SPI.h>  // Include SPI if you're using SPI
#include <SFE_MicroOLED.h>  // Include the SFE_MicroOLED library


#define PIN_RESET 9  // Connect RST to pin 9 (req. for SPI and I2C)
#define PIN_DC    8  // Connect DC to pin 8 (required for SPI)
#define PIN_CS    10 // Connect CS to pin 10 (required for SPI)
#define DC_JUMPER 0
// Also connect pin 13 to SCK and pin 11 to MOSI

//////////////////////////////////
// MicroOLED Object Declaration //
//////////////////////////////////
// Declare a MicroOLED object. The parameters include:
// 1 - Reset pin: Any digital pin
// 2 - D/C pin: Any digital pin (SPI mode only)
// 3 - CS pin: Any digital pin (SPI mode only, 10 recommended)
MicroOLED oled(PIN_RESET, PIN_DC, PIN_CS);
//MicroOLED oled(PIN_RESET, DC_JUMPER); // Example I2C declaration

// I2C is great, but will result in a much slower update rate. The
// slower framerate may be a worthwhile tradeoff, if you need more
// pins, though.

void setup()
{
  // These three lines of code are all you need to initialize the
  // OLED and print the splash screen.
  
  // Before you can start using the OLED, call begin() to init
  // all of the pins and configure the OLED.
  oled.begin();
  // clear(ALL) will clear out the OLED's graphic memory.
  // clear(PAGE) will clear the Arduino's display buffer.
  oled.clear(ALL);  // Clear the display's memory (gets rid of artifacts)
  // To actually draw anything on the display, you must call the
  // display() function. 
  //oled.display();   
}

float jumpSpeed = 200;
void loop()
{
oled.invert(false);
oled.clear(PAGE);//clear the screen before we draw our image
VertUpCent();
Turn1();
HorizUpRight();
Turn2();
VertDownRight();
Turn3();
HorizDownRight();
Turn4();
VertUpCent();
Turn5();
HorizUpLeft();
Turn6();
VertDownLeft();
Turn7();
HorizDownLeft();
Turn8();
}
void VertUpCent() //vertical up center
{
float x1 = 32; //x start point
float y1 = 18; //y start point
float dt1 = 1; //distance

for (int n=1; n<12; n++) 
  {
  //x1 +=  dt1;
  y1 +=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void VertDownRight() //vertical down right
{
float x1 = 10; //x start point
float y1 = 30; //y start point
float dt1 = -1; // pos=up, neg=down

for (int n=1; n<12; n++) 
  {
  //x1 +=  dt1;
  y1 +=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void VertDownLeft() //vertical down left
{
float x1 = 54; //x start point
float y1 = 30; //y start point
float dt1 = -1; //distance

for (int n=1; n<12; n++) //number of steps
  {
  //x1 +=  dt1;
  y1 +=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void Turn1() // turn
{
float x1 = 32; //x start point
float y1 = 30; //y start point
float dt1 = 1; //distance

for (int n=1; n<5; n++) 
  {
  x1 -=  dt1;
  y1 +=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void HorizUpRight() //horizontal up right
{
float x1 = 27; //x start point
float y1 = 35; //y start point
float dt1 = 1; // pos=up, neg=down

for (int n=1; n<12; n++) 
  {
  x1 -=  dt1;
  //y1 +=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void Turn2() // turn
{
float x1 = 15; //x start point
float y1 = 35; //y start point
float dt1 = 1; //distance

for (int n=1; n<5; n++) 
  {
  x1 -=  dt1;
  y1 -=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void Turn3() // turn
{
float x1 = 10; //x start point
float y1 = 18; //y start point
float dt1 = 1; //distance

for (int n=1; n<5; n++) 
  {
  x1 +=  dt1;
  y1 -=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void HorizDownRight() //horizontal down right
{
float x1 = 15; //x start point
float y1 = 13; //y start point
float dt1 = 1; // pos=up, neg=down

for (int n=1; n<12; n++) 
  {
  x1 +=  dt1;
  //y1 +=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void Turn4() // turn
{
float x1 = 27; //x start point
float y1 = 13; //y start point
float dt1 = 1; //distance

for (int n=1; n<5; n++) 
  {
  x1 +=  dt1;
  y1 +=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void Turn5() // turn
{
float x1 = 32; //x start point
float y1 = 30; //y start point
float dt1 = 1; //distance

for (int n=1; n<5; n++) 
  {
  x1 +=  dt1;
  y1 +=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void HorizUpLeft() //horizontal up left
{
float x1 = 37; //x start point
float y1 = 35; //y start point
float dt1 = 1; // pos=up, neg=down

for (int n=1; n<12; n++) 
  {
  x1 +=  dt1;
  //y1 +=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void Turn6() // turn
{
float x1 = 49; //x start point
float y1 = 35; //y start point
float dt1 = 1; //distance

for (int n=1; n<5; n++) 
  {
  x1 +=  dt1;
  y1 -=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void Turn7() // turn
{
float x1 = 54; //x start point
float y1 = 18; //y start point
float dt1 = 1; //distance

for (int n=1; n<5; n++) 
  {
  x1 -=  dt1;
  y1 -=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void HorizDownLeft() //horizontal down left
{
float x1 = 49; //x start point
float y1 = 13; //y start point
float dt1 = 1; // pos=up, neg=down

for (int n=1; n<12; n++) 
  {
  x1 -=  dt1;
  //y1 +=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}
void Turn8() // turn
{
float x1 = 37; //x start point
float y1 = 13; //y start point
float dt1 = 1; //distance

for (int n=1; n<5; n++) 
  {
  x1 -=  dt1;
  y1 +=  dt1;
  oled.clear(PAGE);
  oled.pixel(x1,y1);
  oled.display();
  delay(jumpSpeed);  
  }
}

Did you try using the angledMove function I made?

You can simulate complex paths with mathematical functions. For example here is an elliptical orbit:

float angle = 0;
float x = 30;
float y = 30;
float moveFactor = 10;
float dt = 0.01;

void orbit(){
 
angle = angle + dt;
x = x + moveFactor * math.cos(angle) * dt;
y = y - moveFactor * math.sin(angle) * dt 

}

If you could specify the complex paths you're trying to achieve it would help.

Floating-point calculations are relatively slow. If that's all that your Arduino is doing, then that's a good way to do it. If you need it to do other time-sensitive things simultaneously, then you may find that the FP calculations are the bottleneck.

One alternative for straight lines is called Bressenham's Algorithm. It is also relatively easy to make circles and ellipses but segments of circles and ellipses (like making a smooth turn between two straights) can get complex. Then you will probably end up back at the FP calculations again.

Hi guys,
indeed, making ellipses like these below is much more effortless in code than drawing single lines. I used shapes that were build into the display's library, and animated them along the pathway created with sin/cos function (and had to remind classes about trigonometry from 90ties:))). Thank you!

void OrbitLeft_1_pix()
{
float moveFactor = 13; 
float x1 = 32; //x start point
float y1 = 30; //y start point
float dt1 = 0.12; //density
float angle=90;  //start angle
for (int n=1; n<46; n++) //leght of the pathway
{
angle = angle + dt1;
x1 = x1 - moveFactor * cos(angle) * dt1;  //up or down
y1 = y1 + moveFactor * sin(angle) * dt1;  //up or down
oled.clear(PAGE);
oled.pixel(x1,y1);
oled.display();
delay(jumpSpeed);
}
}
void OrbitRight_1_pix()
{
float moveFactor = 13; 
float x1 = 32; //x start point
float y1 = 30; //y start point
oled.clear(PAGE);
float dt1 = 0.12; //density
float angle=30.3;
for (int n=1; n<46; n++) //leght of the pathway
{
angle = angle + dt1;
x1 = x1 - moveFactor * cos(angle) * dt1;
y1 = y1 - moveFactor * sin(angle) * dt1;
oled.clear(PAGE);
oled.pixel(x1,y1);
oled.display();
delay(jumpSpeed);
}
}