mohamedalimani
Published © Apache-2.0

3D Scanner

A 3D scanner that makes 3d models in a graphic interface .

AdvancedShowcase (no instructions)7,700
3D Scanner

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
sharp distance sensor
×1
Stepper Motor, Mini Step
Stepper Motor, Mini Step
×2
Stepper motor driver board A4988
SparkFun Stepper motor driver board A4988
×1
power supply 12V AC/DC
×1

Software apps and online services

Processing
The Processing Foundation Processing
Arduino IDE
Arduino IDE

Story

Read more

Schematics

3d scanner schema

NOTE (very important) : there isn't a4988 driver in proteus 8 so i replaced it with l298 in simulation .

Code

arduino.exe

Arduino
 char val; // Data received from the serial port
 int ledPin = 13; // Set the pin to digital I/O 13
 boolean startCalculatingPointsCoordinations ; 
 const int stepPiny = 13 ; 
const int dirPiny   =  12  ;   
const int stepPinx  = 6 ;
const int dirPinx  = 7 ; 
int motorStepsX = 36 ; //  it will take 36 points in each full rotation
int motorStepsY = 36 ; //  the more you make points the better picture                               //  resolution you get
float maxDistance = 150 ;  
#define sensor A0 
 void setup() {
  pinMode(stepPiny,OUTPUT) ; 
pinMode(dirPiny, OUTPUT) ;
pinMode(stepPinx,OUTPUT) ; 
pinMode(dirPinx, OUTPUT) ;
   pinMode(ledPin, OUTPUT); 
   Serial.begin(9600);
 startCalculatingPointsCoordinations = false ; 
 }
 void loop() {
   if (Serial.available()){ // If data is available to read, 
     val = Serial.read(); // read it and store it in val
   }
   if (val == '1') 
   { // If 1 was received
     digitalWrite(ledPin, HIGH); // turn the LED on
     startCalculatingPointsCoordinations = true ; 
   } else {
     digitalWrite(ledPin, LOW); // otherwise turn it off
   }
   if(startCalculatingPointsCoordinations){
//--------------------moving motors--------------------------------------
    for(int y = 0 ; y < motorStepsY ; y++){
// horizental axe
for(int x = 0 ; x < motorStepsX ; x++){
calculateDistance() ;
moveMotorX() ; 
}
moveMotorY() ;
float actualDistance = calculateDistance() ;
if ((actualDistance > maxDistance)&&(y > 40)){
stopMotors() ; 
}
}
//----------------------------------------------------------------
    }
delay(10); // Wait 10 milliseconds for next reading
}

void moveMotorX(){
digitalWrite(dirPiny,HIGH) ;
digitalWrite(stepPinx,HIGH); 
delay(200); 
digitalWrite(stepPinx,LOW); 
delay(200); 
}

void moveMotorY(){
  for (int i = 0 ; i <120; i++){
  digitalWrite(dirPiny,HIGH) ;
digitalWrite(stepPiny,HIGH) ;
delay(50) ;
digitalWrite(stepPiny,LOW) ; 
delay(50) ;
  }
}

void stopMotors(){
digitalWrite(stepPinx,LOW); 
digitalWrite(stepPinx,LOW); 
}

float calculateDistance(){
  float volts = analogRead(sensor)*0.0048828125;  
  int distance1 = 13*pow(volts, -1); 
  distance1 = map(distance1,4,45,0,200) ;
  int distance2 = constrain(distance1,0,200) ; 
  delay(200);  // 200
    Serial.println(distance2);
  Serial.flush() ;  
  return distance2 ;
}

pfa2.pde

Processing
first , all distance measures will be saved in an array list then processing will use it to draw many points that will form our objects 3d model
/*
i have plenty of ideas to make this code better and easier to use but unfortunately i can't find enough time for that because of study but it's functional so i will be glad to see what is the changes you made 
*/
import processing.serial.*;
boolean startScanButtonPressed ;
Serial myPort;  
PShape button ;
float y ;
float f ;
float maxVirtualHigh = -40 ; 
float stepHigh = 5 ;
float distance ;  
int secPass ; 
ArrayList <PVector> twod = new ArrayList<PVector>() ;
ArrayList <PVector> threed = new ArrayList<PVector>() ; 
int pointIndex ;
float angle ;
float oneStepDegree = 10 ;
boolean startDrawing ; 
boolean viewModeOn ; 
boolean changeBg ; 
void setup() 
{
  size(800,700,P3D); 
  myPort = new Serial(this, "COM4", 9600);
  angle = 0 ; 
  startDrawing = false ;
  myPort.bufferUntil('\n'); 
  startScanButtonPressed = false ;
  viewModeOn = false ; 
  changeBg = false ;
button() ; 
}

void draw() {
  if (startScanButtonPressed == true) {  //if we clicked in the window
   myPort.write('1');         //send a 1
   println("receiving data from arduino ...");  
   delay(200) ;
   changeBg = true ;
    startScanButtonPressed = false ;
  } 
  else {                   
if (changeBg){ 
background(0) ;
}
  println("press button to start ...") ;
  if ((y<=-20)&&(startDrawing == true))
viewModeOn = true ;
  pushMatrix() ; 
translate(250,400,f)  ;
  if (startDrawing == true){
myPort.stop();                // seeME PLEASE
mouseDragged() ;
drawMe() ;
  }
popMatrix() ;
programControl(secPass) ;
save("Object.OBG") ;
  }   
}

//----------------------------------------------------------------------
void mousePressed(){
if ((150 <= mouseX)&&(mouseX <= 350)&&(220 <= mouseY)
&&(mouseY <= 260)){
startScanButtonPressed = true ;  
}
else startScanButtonPressed = false ;
}

void button(){
button = createShape() ;
button.beginShape() ; 
fill(0,0,250) ;
rect(150,220,200,40) ;
fill(255) ;
textSize(18) ;
text("Start Scanning",190,245) ;
button.endShape() ; 
}

float serialEvent(Serial myPort){  
  distance = float(myPort.readStringUntil('\n')) ;
  secPass++ ;
 threed.add(new PVector()) ; 
    twod.add(new PVector()) ;
    twod.get(pointIndex).y = distance ;
    twod.get(pointIndex).rotate(angle) ;
    threed.get(pointIndex).z = twod.get(pointIndex).y ; 
    threed.get(pointIndex).x = twod.get(pointIndex).x ;
    threed.get(pointIndex).y = y ;
angle = oneStepDegree+angle ;
 if (angle >= 360)
 {
  y-=stepHigh ;
  angle = 0 ;
  if (y <= maxVirtualHigh){   
  startDrawing = true ;
  }
}
pointIndex++ ;  
return distance ;
  }

void drawMe(){
  stroke(255) ;
beginShape(POINTS) ; // QUADS LINES
  for(int j = 0 ; j<threed.size() ; j++){
vertex(threed.get(j).x,threed.get(j).y,threed.get(j).z) ;
}
endShape(CLOSE) ; // CLOSE
}

// WATCH DATA
void programControl(int onePercent){
  String msg ;
println(" angle = ",angle) ;
println(" startDrawing =",startDrawing) ; 
text("pixel number = " + pointIndex,20,20) ;
println("viewModeOn =",viewModeOn) ;
println("distance =",distance) ; 
msg = "uploading ... "+percentage(onePercent)+" %" ;
if (percentage(onePercent)>100){ 
  onePercent = 0 ;
  msg = "" ;  
  }
text(msg,20,45) ;  
save("model.tif") ;
}
// CAMERA ROTATION
void mouseDragged(){
  if (viewModeOn == true){
rotateX(mouseX*0.1) ; 
rotateY(mouseY*0.1) ;
}
}

void mouseWheel(MouseEvent event){
float e = event.getCount() ;
f += e*(6) ; 
}

int percentage(int secPass){
 float huPer = ((360/oneStepDegree)*(-maxVirtualHigh/stepHigh)) ; //100%
 int percentage = int((100/huPer)*secPass) ;
return percentage ;
}

Credits

mohamedalimani

mohamedalimani

1 project • 1 follower

Comments