FabScan - это open-source, DIY 3D лазерный сканер. Начало проекта было положено во время разработки бакалаврского проекта Франциска Энгелманна.
На основании этого проекта, разработан аналог, который и рассмотрен в статье. Для бокса используется мдф. Электронная начинка тоже несколько отличается.
Программа для Arduino взята с оригинального проекта. Так что спасибо команде FabScan за отличный open-source 3D сканер!
Итак, приступим.
Необходимые компоненты
![]() | ![]() |
---|---|
![]() | ![]() |
Детали и узлы для оригинального проекта FabScan:
- Arduino UNO;
- Драйвер шагового двигателя A4988;
- Шилд FabScan;
- Модуль лазера на 5 мВт - производитель Red Line;
- Биполярный шаговый двигатель NEMA 17 (200 шагов);
- Источник питания 12 В - 1 А;
- Веб-камера Logitech C270.
Для корпуса надо 4 листа из МДФ. Размеры - 600 мм на 300 мм. Толщина - 5 мм.
Детали и узлы, которые используются в этой инструкции:
- Arduino UNO;
- Шаговый двигатель NEMA 17 (200 шагов);
- Драйвер шагового двигателя L298N;
- Модуль лазера на 5 мВт - производитель Red Line;
- Источник питания 12 В - 2 А;
- Веб-камера Logiteck C270.
То есть мы просто не станем использовать шилд FabScan и используем другой модуль драйвера шагового двигателя
Разработка корпуса для 3D сканера
Процесс и результат разработки корпуса нашего 3D сканера показаны на фотографиях. Основная сложность - максимально точная установка камеры, модуля лазера и шагового двигателя.
![]() | ![]() |
---|---|
![]() | ![]() |
![]() | ![]() |
![]() | ![]() |
Подключение электрооборудования
Подключается все предельно просто. Особенно если вы закажете оригинальный шилд.
1. С шилдом.
Установите FabScan шилд на Arduino. Драйвер шагового двигателя A4988 устанавливается на предусмотренные рельсы. Шаговый двигатель подключается к соответствующим контактам на шилде. Модуль лазера подключается к аналоговому пину A4. После этого можете подключать питание и USB кабель.
2. Без шилда.
Если вы решили собрать сканер без использования шилда, подключите драйвер шагового двигателя L298 к контактам 10, 11, 9, 8 на Arduino (в принципе, эти контакты можно изменить с соответствующими правками в скетче). Модуль лазера подключается к пину A4 на Arduino. Все. Можно подключать питание и USB кабель.

Скетч для Arduino
// FabScan - http://hci.rwth-aachen.de/fabscan // // Created by Francis Engelmann on 7/1/11. // Copyright 2011 Media Computing Group, RWTH Aachen University. All rights reserved. // // Chngelog: // R. Bohne 29.01.2013: changed pin mapping to Watterott FabScan Arduino Shield // R. Bohne 30.12.2013: added pin definitions for stepper 4 --> this firmware supports the new FabScan Shield V1.1, minor syntax changes. Steppers are now disabled at startup. // R. Bohne 12.03.2014: renamed the pins 14..19 to A0..A5 (better abstraction for people who use Arduino MEGA, etc.) #define LIGHT_PIN A3 #define LASER_PIN A4 #define MS_PIN A5 //Stepper 1 as labeled on Shield, Turntable #define ENABLE_PIN_0 2 #define STEP_PIN_0 3 #define DIR_PIN_0 4 //Stepper 2, Laser Stepper #define ENABLE_PIN_1 5 #define STEP_PIN_1 6 #define DIR_PIN_1 7 //Stepper 3, currently unused #define ENABLE_PIN_2 11 #define STEP_PIN_2 12 #define DIR_PIN_2 13 //Stepper 4, currently unused #define ENABLE_PIN_3 A0 #define STEP_PIN_3 A1 #define DIR_PIN_3 A2 #define TURN_LASER_OFF 200 #define TURN_LASER_ON 201 #define PERFORM_STEP 202 #define SET_DIRECTION_CW 203 #define SET_DIRECTION_CCW 204 #define TURN_STEPPER_ON 205 #define TURN_STEPPER_OFF 206 #define TURN_LIGHT_ON 207 #define TURN_LIGHT_OFF 208 #define ROTATE_LASER 209 #define FABSCAN_PING 210 #define FABSCAN_PONG 211 #define SELECT_STEPPER 212 #define LASER_STEPPER 11 #define TURNTABLE_STEPPER 10 //the protocol: we send one byte to define the action what to do. //If the action is unary (like turnung off the light) we only need one byte so we are fine. //If we want to tell the stepper to turn, a second byte is used to specify the number of steps. //These second bytes are defined here below. #define ACTION_BYTE 1 //normal byte, first of new action #define LIGHT_INTENSITY 2 #define TURN_TABLE_STEPS 3 #define LASER1_STEPS 4 #define LASER2_STEPS 5 #define LASER_ROTATION 6 #define STEPPER_ID 7 int incomingByte = 0; int byteType = 1; int currStepper; //current motor: turn a single step void step() { if(currStepper == TURNTABLE_STEPPER){ digitalWrite(STEP_PIN_0, LOW); }else if(currStepper == LASER_STEPPER){ digitalWrite(STEP_PIN_1, LOW); } delay(3); if(currStepper == TURNTABLE_STEPPER){ digitalWrite(STEP_PIN_0, HIGH); }else if(currStepper == LASER_STEPPER){ digitalWrite(STEP_PIN_1, HIGH); } delay(3); } //step the current motor for <count> times void step(int count) { for(int i=0; i<count; i++){ step(); } } void setup() { // initialize the serial port Serial.begin(9600); pinMode(LASER_PIN, OUTPUT); pinMode(LIGHT_PIN, OUTPUT); pinMode(MS_PIN, OUTPUT); digitalWrite(MS_PIN, HIGH); //HIGH for 16microstepping, LOW for no microstepping pinMode(ENABLE_PIN_0, OUTPUT); pinMode(DIR_PIN_0, OUTPUT); pinMode(STEP_PIN_0, OUTPUT); pinMode(ENABLE_PIN_1, OUTPUT); pinMode(DIR_PIN_1, OUTPUT); pinMode(STEP_PIN_1, OUTPUT); pinMode(ENABLE_PIN_2, OUTPUT); pinMode(DIR_PIN_2, OUTPUT); pinMode(STEP_PIN_2, OUTPUT); pinMode(ENABLE_PIN_3, OUTPUT); pinMode(DIR_PIN_3, OUTPUT); pinMode(STEP_PIN_3, OUTPUT); //disable all steppers at startup digitalWrite(ENABLE_PIN_0, HIGH); //HIGH to turn off digitalWrite(ENABLE_PIN_1, HIGH); //HIGH to turn off digitalWrite(ENABLE_PIN_2, HIGH); //LOW to turn on digitalWrite(ENABLE_PIN_3, HIGH); //LOW to turn on digitalWrite(LIGHT_PIN, LOW); //turn light off digitalWrite(LASER_PIN, HIGH); //turn laser on Serial.write(FABSCAN_PONG); //send a pong back to the computer so we know setup is done and that we are actually dealing with a FabScan currStepper = TURNTABLE_STEPPER; //turntable is default stepper } void loop() { if(Serial.available() > 0){ incomingByte = Serial.read(); switch(byteType){ case ACTION_BYTE: switch(incomingByte){ //this switch always handles the first byte //Laser case TURN_LASER_OFF: digitalWrite(LASER_PIN, LOW); // turn the LASER off break; case TURN_LASER_ON: digitalWrite(LASER_PIN, HIGH); // turn the LASER on break; case ROTATE_LASER: //unused byteType = LASER_ROTATION; break; //TurnTable case PERFORM_STEP: byteType = TURN_TABLE_STEPS; break; case SET_DIRECTION_CW: if(currStepper == TURNTABLE_STEPPER){ digitalWrite(DIR_PIN_0, HIGH); }else if(currStepper == LASER_STEPPER){ digitalWrite(DIR_PIN_1, HIGH); } break; case SET_DIRECTION_CCW: if(currStepper == TURNTABLE_STEPPER){ digitalWrite(DIR_PIN_0, LOW); }else if(currStepper == LASER_STEPPER){ digitalWrite(DIR_PIN_1, LOW); } break; case TURN_STEPPER_ON: if(currStepper == TURNTABLE_STEPPER){ digitalWrite(ENABLE_PIN_0, LOW); }else if(currStepper == LASER_STEPPER){ digitalWrite(ENABLE_PIN_1, LOW); } break; case TURN_STEPPER_OFF: if(currStepper == TURNTABLE_STEPPER){ digitalWrite(ENABLE_PIN_0, HIGH); }else if(currStepper == LASER_STEPPER){ digitalWrite(ENABLE_PIN_1, HIGH); } break; case TURN_LIGHT_ON: byteType = LIGHT_INTENSITY; break; case TURN_LIGHT_OFF: digitalWrite(LIGHT_PIN, LOW); break; case FABSCAN_PING: delay(1); Serial.write(FABSCAN_PONG); break; case SELECT_STEPPER: byteType = STEPPER_ID; break; } break; case LIGHT_INTENSITY: //after this point we take care of the second byte if one is sent analogWrite(LIGHT_PIN, incomingByte); byteType = ACTION_BYTE; //reset byteType break; case TURN_TABLE_STEPS: step(incomingByte); byteType = ACTION_BYTE; break; case STEPPER_ID: Serial.write(incomingByte); currStepper = incomingByte; byteType = ACTION_BYTE; break; }
Скачайте плагин Codebender и нажмите кнопку "Run on Arduino", чтобы прошит ваш Arduino.
Все! Вы загрузили скетч на ваш Arduino напрямую из браузера!
Если вы не использовали шилд, нажмите кнопку Edit и:
- Добавьте строки
- Замените функцию step():
#include <Stepper.h>
const int stepsPerRevolution = 200; // измените этот параметр, чтобы настроить количество шагов на поворот вала вашего шагового мотора
Stepper myStepper(stepsPerRevolution, 10, 11,8,9);
void step() {
myStepper.setSpeed(1);
myStepper.step(1);
}
Программа для персонального компьютера
![]() | ![]() |
---|---|
![]() | ![]() |
![]() | ![]() |
Используется образ "FabScan Ubuntu Live DVD". На образе диска залито программное обеспечение FabScan. Можно записать образ на флэш-носитель с помощью Win32DiskImager и использовать его без установки linux os на ваш персональный компьютер.
Важное примечание! Если вы используете опцию "Try Ubuntu", убедитесь, что вы сохранили файлы перед тем как выключить персональный компьютер!
Следуйте инструкции, фотографии к которой приведены ниже:
- Выберите SerialPort;
- Выберите Camera;
- File - Control Panel;
- Нажмите detect laser (пока что не устанавливайте никаких объектов перед сканером) и выберите 'enable';
- Нажмите "Fetch Frame" и убедитесь, что синяя горизонтальная линия касается вершины вращающегося стола, а желтая горизонтальная линия касается нижней части вращающегося стола. Кроме того, желтая вертикальная линия должна совпадать с центром вращающегося стола. Если камера установлена некорректно, результат сканирования будет не четким!
После настройки закройте окно, установите объект в 3 D сканере и нажмите кнопку Start Scan.
Сохранение 3D изображения
Когда процесс 3Д сканирования завершится, вы сможете сохранить сканированный 3D объект с расширением .pcd или .ply. Можно сохранить и в формате 3D stl файла, но эта возможность доступна не на всех платформах. Открыть сканированный и сохраненный ранее объект можно, выбрав File - OpenPointCloud.
Что дальше?
Вы можете использовать MeshLab для обработки сканированного 3Д объекта и распечатать его на 3D принтере!
При обработке файла в MeshLab:
1. Убедитесь, что вы сохранили объект как .ply файл.
2. Откройте файл с помощью MeshLab.
3. В MeshLab рассчитайте нормали (Filters/Point Set/Compute normals).
4. После этого перестройте поверхность, используя Poisson reconstruction (Filters/Point Set/Surface Reconstruction: Poisson)
Все!
Окончательно собранная конструкция приведена на фото ниже.

Видео работы оригинального FabScan 3-Д сканера:
Огромное спасибо команде FabScan за потрясающий open-source сканер на Arduino!!!
Оставляйте Ваши комментарии, вопросы и делитесь личным опытом ниже. В дискуссии часто рождаются новые идеи и проекты!