Mechatronics Exercises

Workspace Navigation

Photogrammetry based 3D scanner

Joose Lankia

1 Introduction

Photogrammetry is a 3D scanning method in which many photos are taken of an object from different directions and fed into a software that makes the 3D model based on the 3D depth information it is capable of calculating thanks to the photos taken from different angles. The goal for this project is to build a device that will rotate an object and move a smartphone around it to take pictures of the object from all the different directions. The data processing is then made by a smartphone app and a 3D model can be exported. 

2 Parts

For this project, the following critical parts have been bought:


NameUnitsPriceAvailable
AZ-Nano V3-Board with ATMEGA328 CH34019.99€https://www.az-delivery.de/en/collections/mikrocontroller/products/nano-v3-mit-ch340-arduino-kompatibel
MOTOU NEMA 17 Stepper Motor2

18.99€

(combined)

https://www.amazon.de/-/en/dp/B09XK65XXX?psc=1&ref=ppx_yo2ov_dt_b_product_details
A4988 Stepper Motor Driver2

5.29€

(per unit)

https://www.az-delivery.de/en/products/a4988-schrittmotor-modul

Ahorraluz Transformer 12V DC 2A 24W Power Supply

19.09€https://www.amazon.de/dp/B01G0Q3RWU?psc=1&ref=ppx_yo2ov_dt_b_product_details

HD44780 1602 LCD Module

&

I2C interface

111.99€https://www.az-delivery.de/en/products/bundlelcd-schnittstelle

Tooth belt and 2 pulleys 16T/5mm+GT2 


118.80€https://www.partco.fi/fi/mekaniikka/akselit/19877-elc-p3d0121gb2.html


3 Current progress (Pre Circus)


What has been done:

All the parts listed above has been ordered and they have arrived. Until now (16.3.2022), I have been focusing on getting the electronics working. The working principle can be seen in the following video. First of the stepper motors rotates a turntable where a scanned object is placed. The turntable rotates one full revolution by stopping after set intervals, so that a camera can take photos from all the different angles. After one full rotation, the second motor moves the camera in vertical direction and the turntable does new rotation and so on until all the angles have been captured on camera.

The lcd screen show the current progress of the scan by displaying how many pictures have already been taken. 




The Arduino code:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);

// Setting up pins for both of the motors
uint8_t M1_step = 2;
uint8_t M1_dir = 3;
uint8_t M2_step = 4;
uint8_t M2_dir = 5;

// This controls how many stops there will be for the turntable and the ring
int table_positions = 10;
int arc_positions = 5;

// This controls how much each motor will spin every time (needs to adjusted later)
int steps_M1 = 1000;
int steps_M2 = 1000;

int usDelay = 950;

// Counter for the progress that will be shown on the screen
int pictures_taken = 0;

void setup() { 
  lcd.init();
  lcd.backlight();  
  Serial.begin(9600); 
  pinMode(M1_step, OUTPUT); 
  pinMode(M1_dir, OUTPUT);
  pinMode(M2_step, OUTPUT);
  pinMode(M2_dir, OUTPUT);
}

void loop() {
  for (int i = 0; i < arc_positions; i++) {
    for (int j = 0; j < table_positions; j++) {
      lcd.setCursor(0, 0);
      lcd.print("Pictures taken:");
      lcd.setCursor(0, 1);
      lcd.print(String(pictures_taken++) + String("
/ 100"));

      take_steps(steps_M1, usDelay, M1_step, M1_dir);
      delay(1000);
    }
    
    take_steps(steps_M2, usDelay, M2_step, M2_dir);
    delay(1000);
  }
}

// Function for spinning a motor
void take_steps(int steps, int usDelay, uint8_t step_pin, uint8_t dir_pin) {
  digitalWrite(dir_pin, HIGH);
  for (int i = 0; i < steps; i++) {
    digitalWrite(step_pin, HIGH);
    delayMicroseconds(usDelay);
    digitalWrite(step_pin, LOW);
    delayMicroseconds(usDelay);
  }
}


What needs to be done next:

On the electronics side, the whole system will be controlled with couple of buttons and that action is yet to be done. Also, the Arduino needs to be controlled by external power source. The action of taking the pictures is also yet to be done and so is the led lights which will provide uniform lighting to the object. In the end, all the electronics will be semi-permanently soldered so that there is no risk of messing up the wirings afterwards. 

On the mechanical side, almost everything needs to be still done. The contraption will be mounted on a plywood base board and the ring will probably be made of aluminium. The ring will be mounted on 3D printed rollers. The mount connecting the mobile camera to the ring will either be bought or made by myself. The next step is to start working on the ring and the mounts for it. Planning and 3D modeling for the mounting mechanism has been started, but there is yet very little to show. 


Current problems: 

The main problem would have to be the lack of time. Until now, not much time has been available but hopefully next week I will start working on the mechanical parts. There were some problems with the electronics, but they have been overcome, so hopefully on that side there should not be any more major problems. 


4 Mechanical assembly

The base was made out of plywood and bicycle wheel was used for the ring on which smartphone was connected. The job started by designing the mounting mechanism for the ring and smartphone. The ring was mounted between 3D-printed rollers and a mounting mechanism for the smartphone was assembled from 3D-printed parts.

Assembly of the phone mount:


The plywood base:


Each of the rollers were 3D-printed in two parts ensuring nice surface finish for the inner walls. Ball bearings were fitted inside them. Threaded rod was used as axel and the rollers were secured with locknuts. Note that one of the rollers has an integrated pulley for tooth belt.


A mount for the motor that drives the ring and a properly sized belt that was glued together:


The assembly for the ring: 


Next the job was to make the horizontal turntable on which an object can be placed. I used extruded aluminium profile and 3D-printed supports and rollers to mount it and a second stepper motor to drive it. 


3D-printed supports for mounting the aluminium profiles. Note the small green 3D-printed piece that goes around the nut preventing it from spinning inside the aluminium profile making fastening easy. 


Attaching horizontal profiles with the same 3D-printed supports and second motor..


Rollers for the turntable. Again one of them having toothed pulley for the belt drive. 


All the mechanical parts put together. Transparent plexiglass sheet was used as the platform. 



5 Electronics and code

Unfortunately due to time restrictions and last minute soldering problems I was not able to get the project into working condition. The idea was to solder most of the components together and put all the electronics in a 3D-printed housing:

 Like in the pictures, there are two buttons and hole for a potentiometer. Those was meant to be used for selecting the amount of photos the user want's the scanner to take. Another button was meant to force the scanning to stop. 

A cheap wireless remote control for taking pictures was bought and taken apart. I was able to control it by using the Arduino to send a command to smartphone to take a picture. The remote works via Bluetooth. Unfortunately I have no pictures of that at the moment. 

The working principle of the motors remained the same as in the video in the section 2 with the exception that the motors use now so called trapezoidal acceleration, meaning they accelerate and decelerate more smoothly to avoid really high accelerations. 


Updated Arduino code. Here it is worth noting that the motor speeds and steps would need to be configured based on testing the device. As I was not able to finish it on time, I did not yet set those properly.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);

// Setting up pins for both of the motors
uint8_t M1_step = 3;
uint8_t M1_dir = 4;
uint8_t M2_step = 5;
uint8_t M2_dir = 6;
uint8_t engage_motor = 7;

// the pin controlling the remote for taking pictures
uint8_t take_picture = 8;

uint8_t button = 9;
uint8_t reset = 2;
int selector; 

// This controls how much each motor will spin every time (needs to adjusted later)
int steps_M1 = 1000;
int steps_M2 = 1000;

int usDelay = 950;

// Counter for the progress that will be shown on the screen
int* scan_options[] = {20, 40, 60, 80, 100, 150, 200, 200};
int selected_amount; 
int pictures_taken = 0;
int current = 0;

// This controls how many stops there will be for the turntable and the ring
int table_positions = selected_amount / 3;
int arc_positions = 3;

uint8_t gotInterrupt = false;

void setup() { 
  lcd.init();
  lcd.backlight();  
  Serial.begin(9600); 
  pinMode(M1_step, OUTPUT); 
  pinMode(M1_dir, OUTPUT);
  pinMode(M2_step, OUTPUT);
  pinMode(M2_dir, OUTPUT);
  pinMode(engage_motor, OUTPUT);
  pinMode(take_picture, OUTPUT);

  pinMode(button, INPUT);
  pinMode(reset, INPUT);

  attachInterrupt(digitalPinToInterrupt(reset), resetFunction, LOW);

  lcd.setCursor(3, 0);
  lcd.print("Welcome!");
  delay(2000);
}

void loop() {
  selector = analogRead(A1);
  selected_amount = scan_options[map(selector, 0, 1023, 0, 7)];
  if (current != selected_amount) {
    current = selected_amount;
    lcd.clear();
    lcd.setCursor(0, 0);  
    lcd.print("Amount of photos:");
    lcd.setCursor(0, 1);
    lcd.print(selected_amount);
  }
  if (digitalRead(button) == LOW) {
    lcd.clear();
    scan(selected_amount);
  }
  delay(10);
}

void scan(int amount) {
  digitalWrite(engage_motor, HIGH);
  lcd.setCursor(1, 0);
  lcd.print("Scanning");
  lcd.setCursor(7, 1);
  lcd.print("starting");
  delay(2000);
  lcd.clear();

  for (int i = 0; i < arc_positions; i++) {
      for (int j = 0; j < table_positions; j++) {
        lcd.setCursor(0, 0);
        lcd.print("Pictures taken:");
        lcd.setCursor(0, 1);
        lcd.print(String(pictures_taken++) + String(" / ") + String(amount));
        if (gotInterrupt == true) {
          break;
        }
        LSPD(M1_dir, M1_step, 1, 200, 200, 1500, 800);
        delay(500);
        digitalWrite(take_picture, HIGH);
        delay(5);
        digitalWrite(take_picture, LOW);
        delay(500);
      }
      if (gotInterrupt == true) {
        break;
      }
      LSPD(M2_dir, M2_step, 1, 200, 200, 1500, 800);
      delay(1000);
    }

  lcd.clear();
  lcd.setCursor(1, 0);
  lcd.print("Ending the");
  lcd.setCursor(7, 1);
  lcd.print("scan...");
  digitalWrite(engage_motor, LOW);
  delay(3000);
  current = 0;
  gotInterrupt = false;
  pictures_taken = 0;
  return;
}

void LSPD(int dir_pin, int step_pin, int dir, int acc_steps, int const_steps, int startDelay, int targetDelay) {
  digitalWrite(dir_pin, dir);
  int step_size = round(float(startDelay - targetDelay)/float(acc_steps));
  int currDelay = startDelay;
  for (int steps = 0; steps < acc_steps; steps++) {
    digitalWrite(step_pin, HIGH);
    delayMicroseconds(currDelay);
    digitalWrite(step_pin, LOW);
    delayMicroseconds(currDelay);
    currDelay -= step_size;
  }
  for (int steps = 0; steps < const_steps; steps++) {
    digitalWrite(step_pin, HIGH);
    delayMicroseconds(targetDelay);
    digitalWrite(step_pin, LOW);
    delayMicroseconds(targetDelay);
    }
  for (int steps = 0; steps < acc_steps; steps++) {
    digitalWrite(step_pin, HIGH);
    delayMicroseconds(currDelay);
    digitalWrite(step_pin, LOW);
    delayMicroseconds(currDelay);
    currDelay += step_size;
  }
}

void resetFunction() {
  gotInterrupt = true;
}


6 Next steps

As I was not able to get the device working on time, the next steps would naturally be to fix the electrical problems and complete the project. Also some adjustments to the design:

  • the friction between the rollers and the wheel/the turntable is not probably high enough to prevent slipping. Atm I have large heat-shrink tubing on the surface but something like bicycle inner tire or some other rubbery material would probably be better
  • in order to assist the reconstruction of the 3D-model, uniform background would be nice. Adding a black or white background to the other side of the wheel would be worth building.
  • also to have nicer results, uniform lighting is essential. I ordered high power white LED's but did not have time to build a ring light around the phone holder. 
  • No labels
  File Modified
Multimedia File IMG_2197.MOV Apr 24, 2023 by Joose Lankia
JPEG File IMG_2315 Normaali.jpeg Apr 24, 2023 by Joose Lankia
File IMG_2321.HEIC Apr 24, 2023 by Joose Lankia
JPEG File IMG_2321 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2324 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2345 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2347 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2352 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2353 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2354 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2360 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2362 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2367 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2371 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2373 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2376 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2377 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2381 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2383 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2394 Normaali.jpeg Apr 24, 2023 by Joose Lankia
JPEG File IMG_2396 Normaali.jpeg Apr 24, 2023 by Joose Lankia
PNG File Näyttökuva 2023-2-22 kello 0.56.10.png Feb 21, 2023 by Joose Lankia