Created
April 8, 2019 09:33
-
-
Save EDISON-SCIENCE-CORNER/73473a4c97b6499929e87c85c4bb2dff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Wire.h> | |
#include "LedControl.h" | |
LedControl lc=LedControl(12,10,11,4); // Pins: DIN,CLK,CS, # of Display connected | |
struct point | |
{ | |
int y, x; | |
int aX, aY; | |
}; | |
#define INIT_VALUE 32000 | |
#define NUMBEROFSAND 50 | |
point points[NUMBEROFSAND]; | |
char pointsCounter = 1; | |
//IMU adress | |
#define MPU 0x68 | |
//Used convertion ratio | |
#define A_R 16384.0 | |
#define G_R 131.0 | |
//Rad to degree convertion ratio 180/PI | |
#define RAD_A_DEG = 57.295779 | |
//MPU-6050 gives 16 bits integrer values | |
//Start values | |
int16_t AcX, AcY, AcZ, GyX, GyY, GyZ; | |
//Start values | |
float Acc[2]; //16 bits values of the acceleration | |
float Gy[2]; //16 bits values of the gyro | |
float Angle[2]; //16 bits values of the angle | |
void setup() | |
{ | |
randomSeed(analogRead(0)); | |
Wire.begin(); | |
Wire.beginTransmission(MPU); | |
Wire.write(0x6B); //i2c adress | |
Wire.write(0); | |
Wire.endTransmission(true); | |
Serial.begin(9600); | |
lc.shutdown(0,false); // Wake up displays | |
lc.shutdown(1,false); | |
lc.shutdown(2,false); | |
lc.shutdown(3,false); | |
lc.setIntensity(1,0); | |
lc.clearDisplay(0); // Clear Displays | |
lc.clearDisplay(1); | |
lc.clearDisplay(2); | |
lc.clearDisplay(3); | |
for(char i = 0; i < NUMBEROFSAND; i++) | |
{ | |
points[i].x = INIT_VALUE; | |
points[i].y = INIT_VALUE; | |
} | |
points[0].x = 10; | |
points[0].y = 4; | |
points[0].aX = 0; | |
points[0].aY = 0; | |
} | |
void loop() | |
{ | |
static long loopCounter = 0; | |
//We read the acceleration values from the module | |
Wire.beginTransmission(MPU); | |
Wire.write(0x3B); //we ask for 0x3B register - correspond to AcX | |
Wire.endTransmission(false); | |
Wire.requestFrom(MPU,6,true); //From 0x3B, we ask for 6 register | |
AcX=Wire.read()<<8|Wire.read(); //Each values ahs 2 bytes | |
AcY=Wire.read()<<8|Wire.read(); | |
AcZ=Wire.read()<<8|Wire.read(); | |
//We apply mathematics in order to calculate the acceleration | |
//This are the applied formulas | |
Acc[1] = atan(-1*(AcX/A_R)/sqrt(pow((AcY/A_R),2) + pow((AcZ/A_R),2)))*RAD_TO_DEG; | |
Acc[0] = atan((AcY/A_R)/sqrt(pow((AcX/A_R),2) + pow((AcZ/A_R),2)))*RAD_TO_DEG; | |
//We read data from the gyto register | |
Wire.beginTransmission(MPU); | |
Wire.write(0x43); | |
Wire.endTransmission(false); | |
Wire.requestFrom(MPU,4,true); //In this case we only ask for 4 register | |
GyX=Wire.read()<<8|Wire.read(); | |
GyY=Wire.read()<<8|Wire.read(); | |
//We calculate the angle | |
Gy[0] = GyX/G_R; | |
Gy[1] = GyY/G_R; | |
//We apply the complementary filter | |
Angle[0] = 0.98 *(Angle[0]+Gy[0]*0.010) + 0.02*Acc[0]; | |
Angle[1] = 0.98 *(Angle[1]+Gy[1]*0.010) + 0.02*Acc[1]; | |
//Printe the values using serial. Open serial monitor to see the values. | |
//Uncoment the values you want to serial print | |
//Serial.print("Y angle: "); Serial.print(Angle[1]); | |
//2//Serial.print(" "); Serial.print("X angle: "); Serial.print(Angle[0]); | |
Serial.print(" "); Serial.print("X acceleration: "); Serial.print(AcY); | |
//Serial.print(" "); Serial.print("Y acceleration: "); Serial.print(AcX); | |
//5//Serial.print(" "); Serial.print("Gyro X: "); Serial.print(GyX); | |
//6//Serial.print(" "); Serial.print("Gyro Y: "); Serial.print(GyY); | |
Serial.print("\n"); //jump a line | |
movePoints(); | |
drawPoints(); | |
flushMatrix(); | |
delay(50); //Use a delay if the serial is printing too fast | |
clearMatrix(); | |
if(pointsCounter < NUMBEROFSAND && loopCounter % 2) | |
{ | |
points[pointsCounter].x = 10; | |
points[pointsCounter].y = 4; | |
points[pointsCounter].aX = 0; | |
points[pointsCounter].aY = 0; | |
if(pointsCounter < NUMBEROFSAND )pointsCounter++; | |
} | |
loopCounter++; | |
} | |
void drawPoints() | |
{ | |
for(char i=0; i < NUMBEROFSAND; i++) | |
{ | |
if(points[i].x != INIT_VALUE) | |
{ | |
drawPoint(points[i].x, points[i].y); | |
} | |
} | |
} | |
char getPointMostLeftTopFromArray(point *points, char start, char sizeOfArray) | |
{ | |
char index; | |
char x = 32; | |
for(char i = start; i < sizeOfArray; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
if(points[i].x < x) | |
{ | |
x = points[i].x; | |
index = i; | |
} | |
} | |
for(char i = start; i < sizeOfArray; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
if(points[index].x == points[i].x) | |
{ | |
if(points[index].y > points[i].y) | |
{ | |
index = i; | |
} | |
} | |
} | |
return index; | |
} | |
char getPointMostRightTopFromArray(point *points, char start, char sizeOfArray) | |
{ | |
char index; | |
char x = 32; | |
char y = 0; | |
for(char i = start; i < sizeOfArray; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
if(points[i].x < x) | |
{ | |
x = points[i].x; | |
index = i; | |
} | |
} | |
for(char i = start; i < sizeOfArray; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
if(points[index].x == points[i].x) | |
{ | |
if(points[index].y < points[i].y) | |
{ | |
index = i; | |
} | |
} | |
} | |
return index; | |
} | |
char getPointMostRightBottomFromArray(point *points, char start, char sizeOfArray) | |
{ | |
char index; | |
char x = 0; | |
char y = 0; | |
for(char i = start; i < sizeOfArray; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
if(points[i].x > x) | |
{ | |
x = points[i].x; | |
index = i; | |
} | |
} | |
for(char i = start; i < sizeOfArray; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
if(points[index].x == points[i].x) | |
{ | |
if(points[index].y < points[i].y) | |
{ | |
index = i; | |
} | |
} | |
} | |
return index; | |
} | |
char getPointMostLeftBottomFromArray(point *points, char start, char sizeOfArray) | |
{ | |
char index; | |
char x = 0; | |
char y = 0; | |
for(char i = start; i < sizeOfArray; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
if(points[i].x > x) | |
{ | |
x = points[i].x; | |
index = i; | |
} | |
} | |
for(char i = start; i < sizeOfArray; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
if(points[index].x == points[i].x) | |
{ | |
if(points[index].y > points[i].y) | |
{ | |
index = i; | |
} | |
} | |
} | |
return index; | |
} | |
bool collision( point *pointsArray, point point) | |
{ | |
//Serial.print(point.y);Serial.print(" ");Serial.print(pointsArray[0].y);Serial.print(pointsArray[1].y);Serial.print(pointsArray[2].y); Serial.print("\n"); | |
for(char i = 0; i < NUMBEROFSAND; i++) | |
{ | |
if(point.x == pointsArray[i].x && point.y == pointsArray[i].y) | |
{ | |
return true; | |
} | |
} | |
return false; | |
} | |
void movePoints() | |
{ | |
point tempPoint; | |
if(AcY < 5000 && AcY > -5000) | |
{ | |
// sort points array | |
for(char i = 0; i < NUMBEROFSAND-1; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
char minIndex = getPointMostRightTopFromArray(points, i, NUMBEROFSAND); | |
if(i != minIndex) | |
{ | |
tempPoint.x = points[i].x; | |
tempPoint.y = points[i].y; | |
points[i].x = points[minIndex].x; | |
points[i].y = points[minIndex].y; | |
points[minIndex].x = tempPoint.x; | |
points[minIndex].y = tempPoint.y; | |
} | |
} | |
for(char i = 0; i < NUMBEROFSAND-1; i++) | |
{ | |
points[i].aX = 1; | |
points[i].aY = 0; | |
} | |
} | |
else if(AcY < -5000 && AcY > -10000) | |
{ | |
// sort points array | |
for(char i = 0; i < NUMBEROFSAND-1; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
char minIndex = getPointMostRightTopFromArray(points, i, NUMBEROFSAND); | |
if(i != minIndex) | |
{ | |
tempPoint.x = points[i].x; | |
tempPoint.y = points[i].y; | |
points[i].x = points[minIndex].x; | |
points[i].y = points[minIndex].y; | |
points[minIndex].x = tempPoint.x; | |
points[minIndex].y = tempPoint.y; | |
} | |
} | |
for(char i = 0; i < NUMBEROFSAND-1; i++) | |
{ | |
points[i].aX = 1; | |
points[i].aY = 1; | |
} | |
} | |
else if(AcY > 5000 && AcY < 10000) | |
{ | |
// sort points array | |
for(char i = 0; i < NUMBEROFSAND-1; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
char minIndex = getPointMostRightTopFromArray(points, i, NUMBEROFSAND); | |
if(i != minIndex) | |
{ | |
tempPoint.x = points[i].x; | |
tempPoint.y = points[i].y; | |
points[i].x = points[minIndex].x; | |
points[i].y = points[minIndex].y; | |
points[minIndex].x = tempPoint.x; | |
points[minIndex].y = tempPoint.y; | |
} | |
} | |
for(char i = 0; i < NUMBEROFSAND-1; i++) | |
{ | |
points[i].aX = 1; | |
points[i].aY = -1; | |
} | |
} | |
else if(AcY < -5000 ) | |
{ | |
// sort points array | |
for(char i = 0; i < NUMBEROFSAND-1; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
char minIndex = getPointMostLeftBottomFromArray(points, i, NUMBEROFSAND); | |
if(i != minIndex) | |
{ | |
tempPoint.x = points[i].x; | |
tempPoint.y = points[i].y; | |
points[i].x = points[minIndex].x; | |
points[i].y = points[minIndex].y; | |
points[minIndex].x = tempPoint.x; | |
points[minIndex].y = tempPoint.y; | |
} | |
} | |
for(char i = 0; i < NUMBEROFSAND-1; i++) | |
{ | |
points[i].aX = 0; | |
points[i].aY = 1; | |
} | |
} | |
else if(AcY > 5000 ) | |
{ | |
// sort points array | |
for(char i = 0; i < NUMBEROFSAND-1; i++) | |
{ | |
if(points[i].x == INIT_VALUE) continue; | |
char minIndex = getPointMostRightBottomFromArray(points, i, NUMBEROFSAND); | |
if(i != minIndex) | |
{ | |
tempPoint.x = points[i].x; | |
tempPoint.y = points[i].y; | |
points[i].x = points[minIndex].x; | |
points[i].y = points[minIndex].y; | |
points[minIndex].x = tempPoint.x; | |
points[minIndex].y = tempPoint.y; | |
} | |
} | |
for(char i = 0; i < NUMBEROFSAND-1; i++) | |
{ | |
points[i].aX = 0; | |
points[i].aY = -1; | |
} | |
} | |
for(char i = 0; i < NUMBEROFSAND; i++) | |
{ | |
if(points[i].x == INIT_VALUE)continue; | |
movePoint(&points[i]); | |
} | |
} | |
void movePoint(point *p) | |
{ | |
point newPoint; | |
if(p->aX == 1 && p->aY == 0) | |
{ | |
if((p->x+1) < 32) | |
{ | |
newPoint.x = p->x+1; | |
} | |
else return; | |
newPoint.y = p->y; | |
if(!collision(points, newPoint)) | |
{ | |
p->x = newPoint.x; | |
return; | |
} | |
else | |
{ | |
if((p->y+1) < 8) | |
{ | |
newPoint.y = p->y+1; | |
if(!collision(points, newPoint)) | |
{ | |
p->y = newPoint.y; | |
} | |
} | |
if((p->y-1) >= 0)newPoint.y = p->y-1; | |
else return; | |
if(!collision(points, newPoint)) | |
{ | |
if(random(2) == 0) | |
{ | |
p->y = newPoint.y; | |
} | |
} | |
} | |
} | |
else if(p->aX == 1 && p->aY == 1) | |
{ | |
if((p->x+1) < 32 && (p->y-1) >= 0) | |
{ | |
newPoint.x = p->x+1; | |
newPoint.y = p->y; | |
if(collision(points, newPoint)) | |
{ | |
newPoint.y = p->y-1; | |
if(!collision(points, newPoint)) | |
{ | |
p->x = newPoint.x; | |
p->y = newPoint.y; | |
return; | |
} | |
} | |
} | |
if((p->x+1) < 32) | |
{ | |
newPoint.x = p->x+1; | |
if(p->y+1 < 8) | |
{ | |
newPoint.y = p->y+1; | |
if(!collision(points, newPoint)) | |
{ | |
p->y = newPoint.y; | |
p->x = newPoint.x; | |
return; | |
} | |
} | |
else | |
{ | |
newPoint.y = p->y; | |
if(!collision(points, newPoint)) | |
{ | |
p->x = newPoint.x; | |
return; | |
} | |
} | |
} | |
if((p->y+1) < 8) | |
{ | |
newPoint.y = p->y+1; | |
newPoint.x = p->x; | |
if(!collision(points, newPoint)) | |
{ | |
p->y = newPoint.y; | |
return; | |
} | |
} | |
} | |
else if(p->aX == 1 && p->aY == -1) | |
{ | |
if((p->x+1) < 32 && (p->y+1) < 8) | |
{ | |
newPoint.x = p->x+1; | |
newPoint.y = p->y; | |
if(collision(points, newPoint)) | |
{ | |
newPoint.y = p->y+1; | |
if(!collision(points, newPoint)) | |
{ | |
p->x = newPoint.x; | |
p->y = newPoint.y; | |
return; | |
} | |
} | |
} | |
if((p->x+1) < 32) | |
{ | |
newPoint.x = p->x+1; | |
if(p->y-1 >= 0) | |
{ | |
newPoint.y = p->y-1; | |
if(!collision(points, newPoint)) | |
{ | |
p->y = newPoint.y; | |
p->x = newPoint.x; | |
return; | |
} | |
} | |
else | |
{ | |
newPoint.y = p->y; | |
if(!collision(points, newPoint)) | |
{ | |
p->x = newPoint.x; | |
return; | |
} | |
} | |
} | |
if((p->y-1) >= 0) | |
{ | |
newPoint.y = p->y-1; | |
newPoint.x = p->x; | |
if(!collision(points, newPoint)) | |
{ | |
p->y = newPoint.y; | |
return; | |
} | |
} | |
} | |
else if(p->aX == 0 && p->aY == 1) | |
{ | |
if((p->x-1) > 10 && (p->y+1) < 8) | |
{ | |
newPoint.x = p->x-1; | |
newPoint.y = p->y+1; | |
if(!collision(points, newPoint)) | |
{ | |
p->y = newPoint.y; | |
p->x = newPoint.x; | |
return; | |
} | |
} | |
if((p->y+1) < 8) | |
{ | |
newPoint.y = p->y+1; | |
newPoint.x = p->x; | |
if(!collision(points, newPoint)) | |
{ | |
p->y = newPoint.y; | |
return; | |
} | |
} | |
if((p->x+1) < 32) | |
{ | |
newPoint.x = p->x+1; | |
newPoint.y = p->y; | |
if(!collision(points, newPoint)) | |
{ | |
p->x = newPoint.x; | |
return; | |
} | |
} | |
} | |
else if(p->aX == 0 && p->aY == -1) | |
{ | |
if((p->x-1) > 10 && (p->y-1) >= 0) | |
{ | |
newPoint.x = p->x-1; | |
newPoint.y = p->y-1; | |
if(!collision(points, newPoint)) | |
{ | |
p->y = newPoint.y; | |
p->x = newPoint.x; | |
return; | |
} | |
} | |
if((p->y-1) >= 0) | |
{ | |
newPoint.y = p->y-1; | |
newPoint.x = p->x; | |
if(!collision(points, newPoint)) | |
{ | |
p->y = newPoint.y; | |
return; | |
} | |
} | |
if((p->x+1) < 32) | |
{ | |
newPoint.x = p->x+1; | |
newPoint.y = p->y; | |
if(!collision(points, newPoint)) | |
{ | |
p->x = newPoint.x; | |
return; | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment