alexpikkert
Published © GPL3+

Sand Art Display

A Japanese zen garden built into a glass-covered picture frame.

IntermediateFull instructions provided2,584
Sand Art Display

Things used in this project

Hardware components

Arduino UNO & Genuino UNO
Arduino UNO & Genuino UNO
see the construction manual PDF for all components.
×1
5 V stepper motor 28BYJ-48 with driver board ULN2003.
×2

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)
see the construction manual PDF for all tools needed.

Story

Read more

Custom parts and enclosures

construction manual

construction manual

Schematics

Sand Art Display wiring diagram

Code

Display3

Arduino
6 patterns.
The selection leds will light up every 5 seconds. When you press a button when the leds are OFF you select a pattern (Sine, Hello World or Mad Ant), when you press a button when the selection leds are ON you select a different set of patterns (Waffle, Plough or Pong).
/*
Display3: this is a combined program for 6 patterns.
For the first set of three patterns press a button when alle select leds are OFF.
For the second set of three patterns press a button when alle select leds are ON.
These leds will be OFF or ON every 5 seconds.

Stepper Motor Control progam for an X-Y table named "Sand Art Display".
This program drives two unipolar 5V DC stepper motors type 28BYJ-48.
The motors are attached to digital pins 4,5,6,7 and 8,9,10 and 11 of the Arduino UNO, 
via a driver board with IC ULN2003.
The motor power supply on this board is a separate 5V DC supply. 
GND is connected to the GND of the Arduino. 
The motors drive both axis of the sand art table with a 250 mm rack gear.
It starts the movement blue, yellow or white when the motors are resting in the full left & up position.
See www.apinventions.wordpress.com for the Sand Art Display building instructions.
Created March 12 2020 by Alex Pikkert.
*/

#include <Stepper.h>
//this sequence is special for the 28BYJ-48 stepper motor.
Stepper myStepperX(1024, 8,10,9,11);Stepper myStepperY(1024, 4,6,5,7);

int button    = A1; // analog button value 736(white)/451(yellow)/14(blue)
int select    = 0;  // select which road to follow... 
int resetled  = A2; // green led ready for instructions
int whiteled  = A3; // path 1
int yellowled = A4; // path 2
int blueled   = A5; // path 3
int xstop     = 12; // port end position left or right
int ystop     = 3;  // port end position up or down
int speed1    = 10; // slow speed
int speed2    = 15; // medium speed 
int speed3    = 25; // fast speed
int speed4    = 30; // super fast speed
int up        = 50; // length of standard step up
int down      = -50;// length of standard step down  
int left      = 50; // length of standard step left
int right     = -50;// length of standard step right
int n=0;            // counter flag up/down
int m=0;            // counter flag left/right
int x=0;            // left/right number of steps
int y=0;            // up/down number of steps
int d=0;            // counter for step difference
long randNumber;    // counter for random steps
double sinus;       // sine value for Y
int i;              // steps counter
int ystep;          // Y step increment
int yprev;          // Y step store in memory 
int ymax;           // Y max amplitude 
int a;              // select which set is active (select1 or select2)

void setup() {
myStepperX.setSpeed(speed3);myStepperY.setSpeed(speed3);
pinMode(3,INPUT_PULLUP);pinMode(12,INPUT_PULLUP);pinMode(A1,INPUT_PULLUP);
pinMode(A2,OUTPUT);pinMode(A3,OUTPUT);pinMode(A4,OUTPUT);pinMode(A5,OUTPUT);
myStepperX.step(5*left);myStepperY.step(5*up);// always move to left/up corner start position
}

void loop() {
randomSeed(analogRead(A0));
myStepperX.setSpeed(speed3);myStepperY.setSpeed(speed3);
digitalWrite(whiteled,LOW);digitalWrite(yellowled,LOW);digitalWrite(blueled,LOW);
y = digitalRead(ystop);if(y==HIGH) {myStepperY.step(4*up);}
x= digitalRead(xstop);if(x==HIGH) {myStepperX.step(4*left);}

if (y==LOW && x==LOW) // left/up start position
{ digitalWrite(resetled,HIGH);

// select which set is active (select1 or select2)  
a=a+1;
if (a <= 10000){select1();}
if (a> 10000 && a <= 20000){select2();}
if (a > 20000) {a=0;}
}
}

void select1()
{  
  digitalWrite(whiteled,LOW);digitalWrite(yellowled,LOW);digitalWrite(blueled,LOW);
  select = analogRead(button);
  if (select <50){digitalWrite(blueled,HIGH);blue1();}
  if (select >50 && select <600){digitalWrite(yellowled,HIGH);yellow1();}
  if (select >600 && select <800){digitalWrite(whiteled,HIGH);white1();}
}

void select2()
{  
  digitalWrite(whiteled,HIGH);digitalWrite(yellowled,HIGH);digitalWrite(blueled,HIGH);
  select = analogRead(button);
  if (select <50){digitalWrite(whiteled,LOW);digitalWrite(yellowled,LOW);blue2();}
  if (select >50 && select <600){digitalWrite(whiteled,LOW);digitalWrite(blueled,LOW);yellow2();}
  if (select >600 && select <800){digitalWrite(yellowled,LOW);digitalWrite(blueled,LOW);white2();}
}


//MAD ANT
void blue1(){
myStepperX.setSpeed(speed4);myStepperY.setSpeed(speed4);
digitalWrite(resetled,LOW);
if (d==0)
{myStepperX.step(10*right);myStepperY.step(10*down);}
d=1;
randNumber= random(-10,10);myStepperX.step(randNumber*left);
x= digitalRead(xstop);if(x==LOW) 
{myStepperX.step(5*left);
x= digitalRead(xstop);if(x==HIGH) {myStepperX.step(15*left);}
else{myStepperX.step(15*right);}
}

randNumber= random(-10,10);myStepperY.step(randNumber*down);
y= digitalRead(ystop);if(y==LOW) 
{myStepperY.step(5*down);
y= digitalRead(ystop);if(y==HIGH) {myStepperY.step(15*down);}
else{myStepperY.step(15*up);}
}

blue1();
}

//MESSAGE HELLO WORLD
void yellow1(){
x=9;y=12;
myStepperX.setSpeed(speed4);myStepperY.setSpeed(speed4);
digitalWrite(resetled,LOW);
//H
myStepperY.step(2*y*down);
myStepperY.step(y*up);
myStepperX.step(x*right);
myStepperY.step(y*up);
myStepperY.step(2*y*down);

//E
myStepperX.step(x*right);
myStepperY.step(y*up);
myStepperX.step(x*right);
myStepperX.step(x*left);
myStepperY.step(y*down/2);
myStepperX.step(x*right);
myStepperX.step(x*left);
myStepperY.step(y*down/2);
myStepperX.step(2*x*right);

//LL
myStepperY.step(2*y*up);
myStepperY.step(2*y*down);
myStepperX.step(x*right);
myStepperY.step(2*y*up);
myStepperY.step(2*y*down);

//O
myStepperX.step(x*right);
myStepperY.step(y*up);
myStepperX.step(x*right);
myStepperY.step(y*down);
myStepperX.step(1.3*x*left);
myStepperX.step(2.3*x*right);
myStepperY.step(2.8*y*down);
myStepperX.step(8*x*left);

//W
myStepperY.step(y*up);
myStepperY.step(y*down);
myStepperX.step(0.6*x*right);
myStepperY.step(0.5*y*up);
myStepperY.step(0.5*y*down);
myStepperX.step(0.6*x*right);
myStepperY.step(y*up);
myStepperY.step(y*down);

//O
myStepperX.step(x*right);
myStepperY.step(y*up);
myStepperX.step(x*right);
myStepperY.step(y*down);
myStepperX.step(1.3*x*left);
myStepperX.step(2.3*x*right);

//R
myStepperY.step(y*up);
myStepperX.step(x*right);
myStepperX.step(x*left);
myStepperY.step(y*down);

//L
myStepperX.step(1.8*x*right);
myStepperY.step(2*y*up);
myStepperY.step(2*y*down);

//D
myStepperX.step(x*right);
myStepperY.step(y*up);
myStepperX.step(x*right);
myStepperY.step(y*down);
myStepperX.step(0.3*x*right);
myStepperX.step(0.3*x*left);

while(x==9){};
}

//SINE SHAPE
void white1(){
myStepperX.setSpeed(speed4);myStepperY.setSpeed(speed4);
digitalWrite(resetled,LOW);
if (d==0)
{myStepperY.step(60*down);myStepperY.step(30*up);
myStepperX.step(76*right);myStepperX.step(76*left);
d=1;delay(500);}
ymax=1400;drawsinus();
ymax=900;drawsinus();
ymax=400;drawsinus();
ymax=-1400;drawsinus();
ymax=-900;drawsinus();
ymax=-400;drawsinus();
while(i>360){};
}

void drawsinus(){
for (i = 1; i <= 360; i=i+2)
 {sinus = sin(i*0.0175);
 y=(sinus*ymax);
 ystep=(y-yprev);
 myStepperY.step(ystep);
 myStepperX.step(0.44*right);
 yprev=y;}
 myStepperX.step(76*left);
}

//PONG
void blue2(){
myStepperX.setSpeed(speed4);myStepperY.setSpeed(speed4);
digitalWrite(resetled,LOW);

y = digitalRead(ystop);if(y==LOW && n==0){myStepperY.step(4*down);n=1;}
y = digitalRead(ystop);if(y==HIGH && n==1){myStepperY.step(2*down);}
y = digitalRead(ystop);if(y==LOW && n==1){myStepperY.step(4*up);n=0;} 
y = digitalRead(ystop);if(y==HIGH && n==0){myStepperY.step(2*up);}

x = digitalRead(xstop);if(x==LOW && m==0){myStepperX.step(4*right);m=1;}
x = digitalRead(xstop);if(x==HIGH && m==1){myStepperX.step(2*right);}
x = digitalRead(xstop);if(x==LOW && m==1){myStepperX.step(4*left);m=0;} 
x = digitalRead(xstop);if(x==HIGH && m==0){myStepperX.step(2*left);}
blue2();
}

//PLOUGH
void yellow2(){
myStepperX.setSpeed(speed4);myStepperY.setSpeed(speed4);
digitalWrite(resetled,LOW);
x=73-d;myStepperX.step(x*right);
y=56-d;myStepperY.step(y*down);
d=d+3;
x=73-d;myStepperX.step(x*left);
y=56-d;myStepperY.step(y*up);
d=d+3;
while(y<5 || x< 5){} ;
yellow2();
}

//WAFFLE 
void white2(){
myStepperX.setSpeed(speed4);myStepperY.setSpeed(speed4);
digitalWrite(resetled,LOW);
if(d==0){
if(n==0){myStepperY.step(5*down);}
y = digitalRead(ystop);if(y==LOW && n==0){myStepperX.step(11*right);n=1;x=x+1;}
if(n==1){myStepperY.step(5*up);}
y = digitalRead(ystop);if(y==LOW && n==1){myStepperX.step(11*right);n=0;x=x+1;}
if(x >7){d=1;y=0;n=0;}
}
if (d==1){
if(n==0){myStepperX.step(5*left);}
x = digitalRead(xstop);if(x==LOW && n==0){myStepperY.step(11*down);n=1;y=y+1;}
if(n==1){myStepperX.step(5*right);}
x = digitalRead(xstop);if(x==LOW && n==1){myStepperY.step(11*down);n=0;y=y+1;}
while(y >5){};
}
white2();
}

Credits

alexpikkert

alexpikkert

1 project • 4 followers

Comments