├── .github └── FUNDING.yml ├── .gitignore ├── Bitmaps ├── Bitmap_cancel_selected.bmp ├── Bitmap_gradient.bmp ├── Bitmap_lines.bmp ├── Bitmap_no_selected.bmp ├── Bitmap_ok_selected.bmp ├── Bitmap_yes_selected.bmp └── LICENSE.md ├── Firmware ├── EEPROM.ino ├── Encoder.ino ├── Firmware.ino ├── LICENSE.md ├── Lights.ino ├── Menu.ino ├── Nokia5110-Display.ino ├── Remote-Shutter.ino ├── Scan.ino ├── State_Change_Contrast.ino ├── State_Menu.ino ├── State_Scan_Configure.ino ├── State_Scan_Confirm.ino ├── State_Set_12Bit.ino ├── State_Set_16Bit.ino ├── Status-LED.ino ├── Stepper-Rotor.ino └── Stepper-Turntable.ino ├── Gear_Settings ├── LICENSE.md ├── Spur_gear_3d_scanner_gear.PNG └── Spur_gear_3d_scanner_pinion.PNG ├── LICENSE.md ├── Manual ├── AppendixPCB.tex ├── BuildInstructions.tex ├── Commands.tex ├── Introduction.tex ├── LICENSE.md ├── Manual.pdf ├── Manual.tex ├── PerformingScans.tex ├── References.tex ├── RelatedProjects.tex ├── Requirements.tex ├── UserGuide.tex └── images │ ├── 3DTurntable.png │ ├── Assembly1.png │ ├── Assembly10.png │ ├── Assembly11.png │ ├── Assembly12.png │ ├── Assembly13.png │ ├── Assembly14.png │ ├── Assembly15.png │ ├── Assembly16.png │ ├── Assembly17.png │ ├── Assembly18.png │ ├── Assembly2.png │ ├── Assembly3.png │ ├── Assembly4.png │ ├── Assembly5.png │ ├── Assembly6.png │ ├── Assembly7.png │ ├── Assembly8.png │ ├── Assembly9.png │ ├── Breadboard.jpg │ ├── Ciclop.jpg │ ├── DisplayCable.jpg │ ├── DualColorLedCable.jpg │ ├── EncoderCable.jpg │ ├── HeatSink.jpg │ ├── LCDAssistant.png │ ├── LedStrip.jpg │ ├── LedStripAssembly.jpg │ ├── LedStripCable.jpg │ ├── LedStripGlue.jpg │ ├── OpenScan.png │ ├── PCB.png │ ├── PcbSeries1.jpg │ ├── PcbSeries2.jpg │ ├── PcbSeries3.jpg │ ├── PcbSeries4.jpg │ ├── PcbSeries5.jpg │ ├── PcbSeries6.jpg │ ├── PcbSeries7.jpg │ ├── PinHeader.jpg │ ├── PinSocket.jpg │ ├── PowerCable.jpg │ ├── Render.png │ ├── Schematic.png │ ├── Spur_gear_3d_scanner_gear.png │ ├── ThermalPaste.jpg │ ├── UsbCable.jpg │ ├── cover.png │ └── gimp │ ├── Assembly1.xcf │ ├── Assembly10.xcf │ ├── Assembly11.xcf │ ├── Assembly12.xcf │ ├── Assembly13.xcf │ ├── Assembly14.xcf │ ├── Assembly15.xcf │ ├── Assembly16.xcf │ ├── Assembly17.xcf │ ├── Assembly18.xcf │ ├── Assembly2.xcf │ ├── Assembly3.xcf │ ├── Assembly4.xcf │ ├── Assembly5.xcf │ ├── Assembly6.xcf │ ├── Assembly7.xcf │ ├── Assembly8.xcf │ ├── Assembly9.xcf │ ├── DisplayCable.xcf │ ├── DualColorLedCable.xcf │ ├── EncoderCable.xcf │ ├── LedStripAssembly.xcf │ ├── LedStripCable.xcf │ ├── PowerCable.xcf │ └── UsbCable.xcf ├── PCB ├── 3D Models │ ├── CUI_TB002-500-02BE.step │ ├── ESP32-DEVKITC-32D--3DModel-STEP-56544.STEP │ ├── a4988-stepper-motor-driver-carrier.step │ └── fk_245_mi_247_o.stp ├── 3D Scanner.kicad_pcb ├── 3D Scanner.pro ├── 3D Scanner.sch ├── Footprints │ ├── Nazrim.bck │ ├── Nazrim.dcm │ ├── Nazrim.lib │ └── Nazrim.pretty │ │ ├── A4988.kicad_mod │ │ ├── AZDelivery-ESP32_NodeMCU.kicad_mod │ │ ├── QR-Code_MyMiniFactory_Profile.kicad_mod │ │ ├── Rotary_Encoder_Switch.kicad_mod │ │ ├── TO-220-3_Vertical_Cooler.kicad_mod │ │ └── TerminalBlock_2_P5.08mm.kicad_mod ├── Gerber Files │ ├── 3D Scanner-B_Cu.gbr │ ├── 3D Scanner-B_Mask.gbr │ ├── 3D Scanner-B_SilkS.gbr │ ├── 3D Scanner-Edge_Cuts.gbr │ ├── 3D Scanner-F_Cu.gbr │ ├── 3D Scanner-F_Mask.gbr │ ├── 3D Scanner-F_SilkS.gbr │ └── 3D Scanner.drl └── LICENSE.md ├── README.md ├── STLs ├── Backplate-Holder_v1.stl ├── Cable-Holder_v1.stl ├── Foot-Holder-Clamp_v1.stl ├── Housing │ ├── Encoder-Holder_v1.stl │ ├── Housing-Main_v1.stl │ ├── Housing-Plate_v1.stl │ ├── Housing-Top_v1.stl │ ├── Knob_v1.stl │ ├── LCD-Holder_v1.stl │ ├── LED-Holder_v1.stl │ ├── MicroFit-Holder-P1_v1.stl │ └── MicroFit-Holder-P2_v1.stl ├── LICENSE.md ├── Passive-Stand_v1.stl ├── Rotor-Arm_v1.stl ├── Rotor-Gear_v1.stl ├── Rotor-Pinion_v1.stl ├── Rotor-Stand_v1.stl ├── Spotligt-Frame_v1.stl ├── Spotligt-Stand_v1.stl ├── Turntable-Arm_v1.stl └── Turntable-Medium_v1.stl └── images ├── LICENSE.md └── logo.png /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: nazrim 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Manual/*.aux 2 | Manual/*.idx 3 | Manual/*.log 4 | Manual/*.out 5 | Manual/*.ilg 6 | Manual/*.ind 7 | Manual/*.ptc 8 | Manual/*.toc 9 | Manual/*.gz 10 | PCB/fp-info-cache 11 | PCB/fp-lib-table 12 | PCB/sym-lib-table 13 | PCB/*.kicad_pcb-bak 14 | PCB/*.bak 15 | PCB/Gerber Files/Gerber Files.zip 16 | PCB/3D Scanner-cache.lib 17 | PCB/3D Scanner.step 18 | -------------------------------------------------------------------------------- /Bitmaps/Bitmap_cancel_selected.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Bitmaps/Bitmap_cancel_selected.bmp -------------------------------------------------------------------------------- /Bitmaps/Bitmap_gradient.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Bitmaps/Bitmap_gradient.bmp -------------------------------------------------------------------------------- /Bitmaps/Bitmap_lines.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Bitmaps/Bitmap_lines.bmp -------------------------------------------------------------------------------- /Bitmaps/Bitmap_no_selected.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Bitmaps/Bitmap_no_selected.bmp -------------------------------------------------------------------------------- /Bitmaps/Bitmap_ok_selected.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Bitmaps/Bitmap_ok_selected.bmp -------------------------------------------------------------------------------- /Bitmaps/Bitmap_yes_selected.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Bitmaps/Bitmap_yes_selected.bmp -------------------------------------------------------------------------------- /Firmware/EEPROM.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * The EEPROM provides persistent memory to this application and is used to store configurations. 5 | * 6 | * EEPROM size in bytes 7 | * 1 byte indicator if initialization is needed 8 | * 1 byte lcd backgroundlight [bit 7] lcd contrast [bit 0-6] 9 | * 1 byte determining the used camera type (0x1 = Android Device; 0x2 = iOS Device) 10 | * 2 bytes for rotor stepper RPM and microstepping (12 bits for rpm with rotor_rpm = byte_n byte_n+1[0:3] [4096 different settings] and 11 | * byte_n+1[4:7] = 0 --> microstepping = full step 12 | * byte_n+1[4:7] = 1 --> microstepping = half step 13 | * byte_n+1[4:7] = 2 --> microstepping = quarter step 14 | * byte_n+1[4:7] = 4 --> microstepping = eighth step 15 | * byte_n+1[4:7] = 8 --> microstepping = sixteenth step) 16 | * 3 bytes for rotor acceleration and deceleration (1.5 bytes/12 bits each) with 17 | * accel = byte_n+2 & 0x0F << 8 | byte_n 18 | * decel = byte_n+2 & 0xF0 << 4 | byte_n+1 19 | * 1 byte for a shared stepper bitmask. bit 0 to 3 apply to rotor while 4 to 7 aply to the roll stepper. 20 | * The interpretation for each stepper is identical. So 21 | * semantic wise the following pairs are identically (0,4), (1,5), (2,6), (3,7). 22 | * Bit 0 determines the acceleration type (0 = constant speed; 1 = linear speed) 23 | * Bit 1 determines motor direction (0 = normal; 1 = inverted) 24 | * 2 bytes for turntable stepper RPM and microstepping 25 | * 3 bytes for turntable stepper acceleration and deceleration 26 | * 2 bytes for time between to photos during a scan 27 | * 2 bytes for delay after a stepper was moved during a print 28 | * 2 bytes for photos per revolution during a custom scan 29 | * 2 bytes for rotation during a custom scan 30 | * 2 bytes for rotation steps during a custom scan 31 | * 32 | * Bitorder within a byte: 33 | * Value | 2^7 | 2^6 | 2^5 | 2^4 | 2^3 | 2^2 | 2^1 | 2^0 34 | * Index | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 35 | * Most significant <-----------------> Least significant 36 | */ 37 | const uint8_t EEPROM_SIZE = 24; 38 | 39 | const uint8_t EEPROM_INITIALIZED_POS = 0x00; 40 | const uint8_t EEPROM_LCD_BL_CONTRAST_POS = 0x01; 41 | const uint8_t EEPROM_CAMERA_TYPE_POS = 0x02; 42 | const uint8_t EEPROM_STEPPER_ROTOR_RPM_POS = 0x03; 43 | const uint8_t EEPROM_STEPPER_ROTOR_RPM_MS_POS = 0x04; 44 | const uint8_t EEPROM_STEPPER_ROTOR_ACCEL_POS = 0x05; 45 | const uint8_t EEPROM_STEPPER_ROTOR_DECEL_POS = 0x06; 46 | const uint8_t EEPROM_STEPPER_ROTOR_ACCEL_DECEL_POS = 0x07; 47 | const uint8_t EEPROM_STEPPER_BITMASK_POS = 0x08; 48 | const uint8_t EEPROM_STEPPER_TURNTABLE_RPM_POS = 0x09; 49 | const uint8_t EEPROM_STEPPER_TURNTABLE_RPM_MS_POS = 0x0A; 50 | const uint8_t EEPROM_STEPPER_TURNTABLE_ACCEL_POS = 0x0B; 51 | const uint8_t EEPROM_STEPPER_TURNTABLE_DECEL_POS = 0x0C; 52 | const uint8_t EEPROM_STEPPER_TURNTABLE_ACCEL_DECEL_POS = 0x0D; 53 | const uint8_t EEPROM_TIME_BETWEEN_PHOTO_LOW_POS = 0x0E; 54 | const uint8_t EEPROM_TIME_BETWEEN_PHOTO_HIGH_POS = 0x0F; 55 | const uint8_t EEPROM_TIME_AFTER_MOVE_LOW_POS = 0x10; 56 | const uint8_t EEPROM_TIME_AFTER_MOVE_HIGH_POS = 0x11; 57 | const uint8_t EEPROM_CUSTOM_SCAN_PHOTOS_PER_REVOLUTION_LOW_POS = 0x12; 58 | const uint8_t EEPROM_CUSTOM_SCAN_PHOTOS_PER_REVOLUTION_HIGH_POS = 0x13; 59 | const uint8_t EEPROM_CUSTOM_SCAN_ROTATION_LOW_POS = 0x14; 60 | const uint8_t EEPROM_CUSTOM_SCAN_ROTATION_HIGH_POS = 0x15; 61 | const uint8_t EEPROM_CUSTOM_SCAN_ROTATION_DIVISIONS_LOW_POS = 0x16; 62 | const uint8_t EEPROM_CUSTOM_SCAN_ROTATION_DIVISIONS_HIGH_POS = 0x17; 63 | 64 | /** 65 | * Define values for (e.g.) bitmask to simplify the usage. 66 | * This contains also default values. 67 | */ 68 | const uint8_t EEPROM_CAMERA_TYPE_ANDROID_DEVICE = 0x01; 69 | const uint8_t EEPROM_CAMERA_TYPE_IOS_DEVICE = 0x02; 70 | const uint8_t EEPROM_STEPPER_FULL_STEP = 0x00; 71 | const uint8_t EEPROM_STEPPER_HALF_STEP = 0x01; 72 | const uint8_t EEPROM_STEPPER_QUARTER_STEP = 0x02; 73 | const uint8_t EEPROM_STEPPER_EIGHTH_STEP = 0x04; 74 | const uint8_t EEPROM_STEPPER_SIXTEENTH_STEP = 0x08; 75 | const uint8_t EEPROM_STEPPER_CONSTANT_SPEED = 0x00; 76 | const uint8_t EEPROM_STEPPER_LINEAR_SPEED = 0x01; 77 | const uint8_t EEPROM_STEPPER_DIR_NORMAL = 0x00; 78 | const uint8_t EEPROM_STEPPER_DIR_INVERTED = 0x01; 79 | 80 | const unsigned short EEPROM_STEPPER_ROTOR_DEFAULT_RPM = 999; 81 | const uint8_t EEPROM_STEPPER_ROTOR_DEFAULT_MS = EEPROM_STEPPER_SIXTEENTH_STEP; 82 | const unsigned short EEPROM_STEPPER_ROTOR_DEFAULT_ACCEL = 900; 83 | const unsigned short EEPROM_STEPPER_ROTOR_DEFAULT_DECEL = 900; 84 | const uint8_t EEPROM_STEPPER_ROTOR_DEFAULT_SPEED_TYPE = EEPROM_STEPPER_LINEAR_SPEED; 85 | 86 | const unsigned short EEPROM_STEPPER_TURNTABLE_DEFAULT_RPM = 999; 87 | const uint8_t EEPROM_STEPPER_TURNTABLE_DEFAULT_MS = EEPROM_STEPPER_SIXTEENTH_STEP; 88 | const unsigned short EEPROM_STEPPER_TURNTABLE_DEFAULT_ACCEL = 900; 89 | const unsigned short EEPROM_STEPPER_TURNTABLE_DEFAULT_DECEL = 900; 90 | const uint8_t EEPROM_STEPPER_TURNTABLE_DEFAULT_SPEED_TYPE = EEPROM_STEPPER_LINEAR_SPEED; 91 | 92 | const short EEPROM_DEFAULT_TIME_BEETWEEN_PHOTO = 3000; 93 | const short EEPROM_DEFAULT_TIME_AFTER_MOVE = 1000; 94 | const short EEPROM_DEFAULT_PHOTOS_PER_REVOLUTION = 32; 95 | const short EEPROM_DEFAULT_ROTATION = 90; 96 | const short EEPROM_DEFAULT_ROTATION_DIVISIONS = 3; 97 | 98 | /** 99 | * Change this value to anything within the range of 0 to 254 to trigger an EEPROM initialization on next startup. 100 | * 101 | * CAUTION: Do not use this inflationary since the flash cells have a limited amount of write cycles before 102 | * thes stop working. 103 | */ 104 | #define EEPROM_INITIALIZED_VALUE 128 105 | 106 | /** 107 | * If the controller is started for the first time, the EEPROM needs to be filled with 108 | * meaningful values. 109 | */ 110 | void load_default_EEPROM_data() { 111 | EEPROM.write(EEPROM_INITIALIZED_POS, EEPROM_INITIALIZED_VALUE); 112 | EEPROM.write(EEPROM_LCD_BL_CONTRAST_POS, 0xBC); 113 | EEPROM.write(EEPROM_CAMERA_TYPE_POS, EEPROM_CAMERA_TYPE_ANDROID_DEVICE); 114 | EEPROM.write(EEPROM_STEPPER_ROTOR_RPM_POS, EEPROM_STEPPER_ROTOR_DEFAULT_RPM & 0xFF); 115 | EEPROM.write(EEPROM_STEPPER_ROTOR_RPM_MS_POS, (EEPROM_STEPPER_ROTOR_DEFAULT_MS << 4) | ((EEPROM_STEPPER_ROTOR_DEFAULT_RPM >> 8) & 0x0F)); 116 | EEPROM.write(EEPROM_STEPPER_ROTOR_ACCEL_POS, EEPROM_STEPPER_ROTOR_DEFAULT_ACCEL & 0xFF); 117 | EEPROM.write(EEPROM_STEPPER_ROTOR_DECEL_POS, EEPROM_STEPPER_ROTOR_DEFAULT_DECEL & 0xFF); 118 | EEPROM.write(EEPROM_STEPPER_ROTOR_ACCEL_DECEL_POS, (((EEPROM_STEPPER_ROTOR_DEFAULT_ACCEL >> 8) & 0x0F) << 4) | ((EEPROM_STEPPER_ROTOR_DEFAULT_ACCEL >> 8) & 0x0F)); 119 | EEPROM.write(EEPROM_STEPPER_BITMASK_POS, 120 | // turntable 121 | (EEPROM_STEPPER_DIR_NORMAL << 5) | (EEPROM_STEPPER_TURNTABLE_DEFAULT_SPEED_TYPE << 4) 122 | // rotor 123 | | (EEPROM_STEPPER_DIR_INVERTED << 1) | EEPROM_STEPPER_ROTOR_DEFAULT_SPEED_TYPE); 124 | EEPROM.write(EEPROM_STEPPER_TURNTABLE_RPM_POS, EEPROM_STEPPER_TURNTABLE_DEFAULT_RPM & 0xFF); 125 | EEPROM.write(EEPROM_STEPPER_TURNTABLE_RPM_MS_POS, (EEPROM_STEPPER_TURNTABLE_DEFAULT_MS << 4) | ((EEPROM_STEPPER_TURNTABLE_DEFAULT_RPM >> 8) & 0x0F)); 126 | EEPROM.write(EEPROM_STEPPER_TURNTABLE_ACCEL_POS, EEPROM_STEPPER_TURNTABLE_DEFAULT_ACCEL & 0xFF); 127 | EEPROM.write(EEPROM_STEPPER_TURNTABLE_DECEL_POS, EEPROM_STEPPER_TURNTABLE_DEFAULT_DECEL & 0xFF); 128 | EEPROM.write(EEPROM_STEPPER_TURNTABLE_ACCEL_DECEL_POS, (((EEPROM_STEPPER_TURNTABLE_DEFAULT_ACCEL >> 8) & 0x0F) << 4) | ((EEPROM_STEPPER_TURNTABLE_DEFAULT_ACCEL >> 8) & 0x0F)); 129 | EEPROM.write(EEPROM_TIME_BETWEEN_PHOTO_LOW_POS, EEPROM_DEFAULT_TIME_BEETWEEN_PHOTO & 0xFF); 130 | EEPROM.write(EEPROM_TIME_BETWEEN_PHOTO_HIGH_POS, (EEPROM_DEFAULT_TIME_BEETWEEN_PHOTO >> 8) & 0xFF); 131 | EEPROM.write(EEPROM_TIME_AFTER_MOVE_LOW_POS, EEPROM_DEFAULT_TIME_AFTER_MOVE & 0xFF); 132 | EEPROM.write(EEPROM_TIME_AFTER_MOVE_HIGH_POS, (EEPROM_DEFAULT_TIME_AFTER_MOVE >> 8) & 0xFF); 133 | EEPROM.write(EEPROM_CUSTOM_SCAN_PHOTOS_PER_REVOLUTION_LOW_POS, EEPROM_DEFAULT_PHOTOS_PER_REVOLUTION & 0xFF); 134 | EEPROM.write(EEPROM_CUSTOM_SCAN_PHOTOS_PER_REVOLUTION_HIGH_POS, (EEPROM_DEFAULT_PHOTOS_PER_REVOLUTION >> 8) & 0xFF); 135 | EEPROM.write(EEPROM_CUSTOM_SCAN_ROTATION_LOW_POS, EEPROM_DEFAULT_ROTATION & 0xFF); 136 | EEPROM.write(EEPROM_CUSTOM_SCAN_ROTATION_HIGH_POS, (EEPROM_DEFAULT_ROTATION >> 8) & 0xFF); 137 | EEPROM.write(EEPROM_CUSTOM_SCAN_ROTATION_DIVISIONS_LOW_POS, EEPROM_DEFAULT_ROTATION_DIVISIONS & 0xFF); 138 | EEPROM.write(EEPROM_CUSTOM_SCAN_ROTATION_DIVISIONS_HIGH_POS, (EEPROM_DEFAULT_ROTATION_DIVISIONS >> 8) & 0xFF); 139 | 140 | EEPROM.commit(); 141 | } 142 | 143 | /** 144 | * Start the EEPROM and check if it is already initialized. 145 | */ 146 | void initialize_EEPROM() { 147 | EEPROM.begin(EEPROM_SIZE); 148 | // determine if the EEPROM needs to be initialized 149 | if (EEPROM.read(EEPROM_INITIALIZED_POS) != EEPROM_INITIALIZED_VALUE) { 150 | Serial.println("This is the first run of the application. Going to initialize the EEPROM now."); 151 | load_default_EEPROM_data(); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /Firmware/Encoder.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * The used encoder does provide a button in addition to the standard encoder functionality 5 | * (detecting rotation). The encoder is used for all user input. 6 | */ 7 | 8 | /** 9 | * This is the minimal time (in ms) the encoder button can not be triggered (software side) 10 | * after the triggering was consumed and resulted in some kind of action. 11 | * This prevents "flickering" on the encoder button. 12 | */ 13 | #define ENCODER_BUTTON_DEBOUNCE_TIME 350 14 | 15 | // Time since startup since the encoder button was pressed the last time 16 | volatile unsigned long encoder_button_last_state_change = 0; 17 | 18 | // Encoder used for user input 19 | ESP32Encoder encoder; 20 | 21 | // State of the encoder button 22 | volatile boolean encoder_button_pressed = false; 23 | 24 | /** 25 | * Set encoder button to not pressed and store curren time. 26 | */ 27 | void consume_encoder_button() { 28 | encoder_button_last_state_change = millis(); 29 | encoder_button_pressed = false; 30 | } 31 | 32 | /** 33 | * Interrupt service function for the encoder button. 34 | * Ensures that the pressed encoder button is only registered 35 | * after ENCODER_BUTTON_DEBOUNCE_TIME ms after the button was 36 | * pressed the last time or an action was triggered because of 37 | * the encoder button press. 38 | * 39 | * Stored in RAM instead of normal flash storage. 40 | */ 41 | void IRAM_ATTR encoder_button_isr() { 42 | if (digitalRead (ENCODER_BUTTON) == LOW) { 43 | unsigned long current_millis = millis(); 44 | if (current_millis - encoder_button_last_state_change > ENCODER_BUTTON_DEBOUNCE_TIME) { 45 | encoder_button_pressed = true; 46 | encoder_button_last_state_change = current_millis; 47 | } 48 | } else { 49 | encoder_button_pressed = false; 50 | } 51 | } 52 | 53 | /** 54 | * Bind defined keys to encoder logic and setup the bin which is defined for the encoder button. 55 | * 56 | * Currently the encoder button pin is not registered for interrupts because the BLE functionality 57 | * somewhat messes up the interrupt handling because it disables interrupt handling internally. 58 | */ 59 | void initialize_encoder() { 60 | encoder.attachHalfQuad(ENCODER_PHASE_A, ENCODER_PHASE_B); 61 | encoder.setCount(0); 62 | pinMode(ENCODER_BUTTON, INPUT_PULLUP); 63 | attachInterrupt(ENCODER_BUTTON, encoder_button_isr, CHANGE); 64 | } 65 | -------------------------------------------------------------------------------- /Firmware/Firmware.ino: -------------------------------------------------------------------------------- 1 | #include // Arduino 2 | #include // Arduino 3 | #include // Arduino 4 | #include // Arduino (https://github.com/nkolban/ESP32_BLE_Arduino) 5 | #include // Arduino (https://github.com/nkolban/ESP32_BLE_Arduino) 6 | #include // Arduino (https://github.com/nkolban/ESP32_BLE_Arduino) 7 | #include "BLE2902.h" // Arduino (https://github.com/nkolban/ESP32_BLE_Arduino) 8 | #include "BLEHIDDevice.h" // Arduino (https://github.com/nkolban/ESP32_BLE_Arduino) 9 | #include "HIDTypes.h" // Arduino (https://github.com/nkolban/ESP32_BLE_Arduino) 10 | #include "HIDKeyboardTypes.h" // Arduino (https://github.com/nkolban/ESP32_BLE_Arduino) 11 | #include // https://github.com/espressif/esp-idf 12 | #include "soc/timer_group_struct.h" // https://github.com/espressif/esp-idf 13 | #include "soc/timer_group_reg.h" // https://github.com/espressif/esp-idf 14 | #include // https://github.com/platisd/nokia-5110-lcd-library 15 | #include // https://github.com/laurb9/StepperDriver 16 | #include // https://github.com/madhephaestus/ESP32Encoder/ 17 | #include // https://github.com/jonblack/arduino-menusystem 18 | 19 | /** 20 | * Begin of pin definitions 21 | */ 22 | 23 | /** 24 | * Free GPIOs: 25 | * - GPIO 0 (G0 - outputs PWM signal at boot) 26 | * - GPIO 3 (RX0 - HIGH at boot) 27 | */ 28 | 29 | /** 30 | * Note: Because of the limited amount of GPIO Pins on the ESP32 31 | * the microstepping functionality is not used within the application. 32 | * Instead sixteenth microstepping is used by default for both steppers. 33 | * 34 | * If in a future version a better solution is found the functionality 35 | * is added again. No code was removed, only outcommented. 36 | * 37 | * If you want to ommit on some parts in favor of microstepping you can 38 | * return to the "old" state. 39 | * 40 | * Relevant changes are in ESP32-3D_Scanner_-_Menu (microstepping submenues are not inserted into menu structure), 41 | * ESP32-3D_Scanner_-_Stepper-Rotor/Turntable (Microstepping function always returns sixteenth stepping and constructor 42 | * does not use microstepping pins anymore) 43 | */ 44 | 45 | // Pins used by the Nokia 5110 LCD Display 46 | const uint8_t DISPLAY_RST = 13; // reset pin 47 | const uint8_t DISPLAY_CE = 33; // chip enable pin 48 | const uint8_t DISPLAY_DC = 27; // data/command selection pin 49 | const uint8_t DISPLAY_DIN = 26; // serial input pin 50 | const uint8_t DISPLAY_CLK = 25; // clock pin 51 | const uint8_t DISPLAY_BL = 12; // background light pin 52 | 53 | // Encoder pins used by Encoder STEC12E08 54 | const uint8_t ENCODER_PHASE_A = 23; // bottom right pin 55 | const uint8_t ENCODER_PHASE_B = 22; // bottom left pin 56 | const uint8_t ENCODER_BUTTON = 34; // top left pin 57 | 58 | // Pins used by the A4988 driving the rotor stepper 59 | //uint8_t ROTOR_MS1 = 15; 60 | //uint8_t ROTOR_MS2 = 2; 61 | //uint8_t ROTOR_MS3 = 4; 62 | const uint8_t ROTOR_ENABLE = 18; 63 | const uint8_t ROTOR_STEP = 17; 64 | const uint8_t ROTOR_DIR = 16; 65 | 66 | // Pins used by the A4988 driving the turntable stepper 67 | //uint8_t TURNTABLE_MS1 = 5; 68 | //uint8_t TURNTABLE_MS2 = 18; 69 | //uint8_t TURNTABLE_MS3 = 19; 70 | const uint8_t TURNTABLE_ENABLE = 5; 71 | const uint8_t TURNTABLE_STEP = 14; 72 | const uint8_t TURNTABLE_DIR = 19; 73 | 74 | // Pins used by the bi-color status LED 75 | const uint8_t STATUS_LED_GREEN = 2; 76 | const uint8_t STATUS_LED_RED = 4; 77 | 78 | // The transistor which switches light on/off needs a pin to drive the gate 79 | const uint8_t LIGHT_SWITCH = 32; 80 | 81 | // This is the number of scan presets defined in Scan.ino; information needed here since it is used in Menu.ino to build the correct menu structure 82 | #define NUMBER_OF_SCAN_PRESETS 4 83 | 84 | /** 85 | * End of pin definitions 86 | */ 87 | 88 | /** 89 | * Relevant data to keep track of the current application status. 90 | * Required for e.g. user input handling 91 | */ 92 | enum State { 93 | MENU, // state for general menu navigation 94 | MENU_CHANGE_CONTRAST, // state for changing the contrast settings 95 | MENU_CHANGE_RPM_ROTOR, // state for changing target RPM for rotor stepper 96 | MENU_CHANGE_ACCELERATION_ROTOR, // state for changing acceleration for rotor stepper 97 | MENU_CHANGE_DECELERATION_ROTOR, // state for changing deceleration for rotor stepper 98 | MENU_CHANGE_RPM_TURNTABLE, // state for changing target RPM for turntable stepper 99 | MENU_CHANGE_ACCELERATION_TURNTABLE, // state for changing acceleration for turntable stepper 100 | MENU_CHANGE_DECELERATION_TURNTABLE, // state for changing deceleration for turntable stepper 101 | MENU_CHANGE_PHOTO_DELAY, // state for changing the delay after a photo was taken 102 | MENU_CHANGE_MOVE_DELAY, // state for changing the delay after a stepper was moved 103 | SCAN_CONFIGURE, // state for defining a custom scan 104 | SCAN_CONFIRM, // state for confirming chosen scan settings 105 | SCAN, // state for scanning 106 | }; 107 | 108 | // This is the current state of the application. 109 | State current_state; 110 | 111 | /** 112 | * This enum contains the valid microstepping values for the used A4988 drivers 113 | */ 114 | enum MicroStepping { 115 | FULL_STEP = 1, 116 | HALF_STEP = 2, 117 | QUARTER_STEP = 4, 118 | EIGHTH_STEP = 8, 119 | SIXTEENTH_STEP = 16 120 | }; 121 | 122 | /** 123 | * Possible colors for the status LED. 124 | */ 125 | enum StatusLedColor : uint8_t { 126 | RED = 0, 127 | YELLOW = 1, 128 | GREEN = 2 129 | }; 130 | 131 | /** 132 | * Possible blinking speeds for the status LED. 133 | */ 134 | enum StatusLedSpeed : uint8_t { 135 | SLOW = 0, 136 | FAST = 1, 137 | EXTRA_SLOW = 2 138 | }; 139 | 140 | /** 141 | * The struct contains all settings which are required to perform a full scan. 142 | */ 143 | struct Scan { 144 | short photos_per_revolution; // maximum "reasonable" value is rotor.microstepping * rotor.steps_per_revolution 145 | short rotation; // maximum "reasonable" value is 360 since this setting is interpreted as degree value 146 | short rotation_divisions; // maximum "reasonable" value is (rotor.microstepping * rotor.steps_per_revolution) / (rotation/360), while minimum value is 1 (start only) 147 | }; 148 | 149 | /** 150 | * Scan presets are predefined scan objects with a name and scan settings which can be chosen from the menu. 151 | */ 152 | struct ScanPreset { 153 | char const* display_name; 154 | Scan preset; 155 | }; 156 | 157 | 158 | // Used during MENU_CHANGE_CONTRAST state to store the current contrast value 159 | uint8_t menu_change_contrast_current_value = 0; 160 | 161 | // Used during MENU_CHANGE_CONTRAST state to store the current backlight state 162 | uint8_t menu_change_contrast_backlight_state = 0; 163 | 164 | // Used during ALL states which use the set min/max 12 bit function 165 | unsigned short menu_set_min_max_12bit_value = 0; 166 | 167 | // Used during ALL states which use the set 16 bit function 168 | short menu_set_16bit_value = 0; 169 | 170 | // This handle is used for task which run only a defined period of time and need to be deleted 171 | TaskHandle_t rtos_task_handle = NULL; 172 | 173 | // Actual lcd initialization can be found in Nokia5110-Display.ino 174 | extern Nokia_LCD lcd; 175 | // Can be found in Nokia5110-Display.ino 176 | extern void initialize_display(); 177 | 178 | // Can be found in Encoder.ino 179 | void encoder_button_isr(); 180 | 181 | // Can be found in Stepper-Rotor.ino 182 | extern A4988 stepper_rotor; 183 | extern void initialize_stepper_rotor(); 184 | 185 | // Can be found in Stepper-Rotor.ino 186 | extern float STEPPER_ROTOR_MIN_RPM; 187 | extern float STEPPER_ROTOR_RPM_STEP_SIZE; 188 | extern unsigned short STEPPER_ROTOR_MIN_ACCEL; 189 | extern unsigned short STEPPER_ROTOR_ACCEL_STEP_SIZE; 190 | extern unsigned short STEPPER_ROTOR_MIN_DECEL; 191 | extern unsigned short STEPPER_ROTOR_DECEL_STEP_SIZE; 192 | 193 | // Can be found in EEPROM.ino 194 | extern const uint8_t EEPROM_STEPPER_ROTOR_RPM_POS; 195 | extern const uint8_t EEPROM_STEPPER_ROTOR_RPM_MS_POS; 196 | extern const uint8_t EEPROM_STEPPER_ROTOR_ACCEL_POS; 197 | extern const uint8_t EEPROM_STEPPER_ROTOR_DECEL_POS; 198 | extern const uint8_t EEPROM_STEPPER_ROTOR_ACCEL_DECEL_POS; 199 | 200 | 201 | // Can be found in Stepper-Turntable.ino 202 | extern A4988 stepper_turntable; 203 | extern void initialize_stepper_turntable(); 204 | 205 | // Can be found in Stepper-Turntable.ino 206 | extern float STEPPER_TURNTABLE_MIN_RPM; 207 | extern float STEPPER_TURNTABLE_RPM_STEP_SIZE; 208 | extern unsigned short STEPPER_TURNTABLE_MIN_ACCEL; 209 | extern unsigned short STEPPER_TURNTABLE_ACCEL_STEP_SIZE; 210 | extern unsigned short STEPPER_TURNTABLE_MIN_DECEL; 211 | extern unsigned short STEPPER_TURNTABLE_DECEL_STEP_SIZE; 212 | 213 | // Can be found in EEPROM.ino 214 | extern const uint8_t EEPROM_STEPPER_TURNTABLE_RPM_POS; 215 | extern const uint8_t EEPROM_STEPPER_TURNTABLE_RPM_MS_POS; 216 | extern const uint8_t EEPROM_STEPPER_TURNTABLE_ACCEL_POS; 217 | extern const uint8_t EEPROM_STEPPER_TURNTABLE_DECEL_POS; 218 | extern const uint8_t EEPROM_STEPPER_TURNTABLE_ACCEL_DECEL_POS; 219 | extern const uint8_t EEPROM_TIME_BETWEEN_PHOTO_LOW_POS; 220 | extern const uint8_t EEPROM_TIME_BETWEEN_PHOTO_HIGH_POS; 221 | extern const uint8_t EEPROM_TIME_AFTER_MOVE_LOW_POS; 222 | extern const uint8_t EEPROM_TIME_AFTER_MOVE_HIGH_POS; 223 | 224 | // Can be found in Menu.ino 225 | extern void initialize_menu_structure(); 226 | 227 | // Can be found in State_Menu.ino 228 | extern void menu_state_logic(); 229 | 230 | // Can be found in State-Menu-Change-Contrast.ino 231 | extern void menu_change_contrast_state_logic(); 232 | 233 | // Can be found in State-Menu-Set-Min-Max-12Bit.ino 234 | extern void menu_state_set_min_max_12bit_logic( 235 | const String affected_element, 236 | const String affected_setting, 237 | const bool use_float_values, 238 | const short min_short, 239 | const short step_short, 240 | const float min_float, 241 | const float step_float, 242 | const uint8_t store_address_a, 243 | const uint8_t store_address_b, 244 | const bool use_upper_bits); 245 | 246 | /** 247 | * Begin of scroll multiplier values which are used in multiple locations. 248 | */ 249 | 250 | 251 | /** 252 | * Since there are 4096 different values some kind of scroll speed multiplier will help to make big adjustments. 253 | */ 254 | float scroll_speed_multiplier = 1.0; 255 | 256 | /** 257 | * Counter how long no input was done. Required to reset the speed multiplier. 258 | */ 259 | uint8_t no_input_loops = 0; 260 | 261 | /** 262 | * After how many frames without input the multiplier should be reset 263 | */ 264 | uint8_t multiplier_resetter = 6; 265 | 266 | /** 267 | * Minimum scroll multiplier speed. 268 | */ 269 | float min_multiplier = 1.0; 270 | 271 | /** 272 | * Maximum scroll multiplier speed. 273 | */ 274 | float max_multiplier = 10.0; 275 | 276 | /** 277 | * This is a multiplier for the multiplier, and is used to increase the multiplier. 278 | */ 279 | float multplier_modifier = 1.16; 280 | 281 | /** 282 | * End of multiplier flags. 283 | */ 284 | 285 | /** 286 | * Default arduino function. Will be called once on startup and is used to init 287 | * all subsystems. 288 | */ 289 | void setup() { 290 | // initialize serial connection for output printing 291 | Serial.begin(115200); 292 | 293 | // initialize all (hardware & software) subsystems 294 | initialize_light(); 295 | initialize_status_led(); 296 | initialize_EEPROM(); 297 | initialize_BLE(); 298 | initialize_display(); 299 | initialize_stepper_rotor(); 300 | initialize_stepper_turntable(); 301 | initialize_encoder(); 302 | initialize_scan(); 303 | initialize_custom_scan(); 304 | initialize_menu_structure(); 305 | 306 | // application starts in menu state 307 | current_state = MENU; 308 | 309 | // start the main logic loop as freeRTOS task 310 | xTaskCreate(main_loop, "MainLoop", 20000, NULL, 5, NULL); 311 | } 312 | 313 | /** 314 | * The main logic loop will different logic functions depending on the current applications state. 315 | */ 316 | void main_loop(void*) { 317 | while (true) { 318 | // the BLE functionality seems to mess up interrupt handling. 319 | // therefore it is necessary to call this function here for proper user input handling. 320 | encoder_button_isr(); 321 | // execute logic based on current application state 322 | if (current_state == SCAN_CONFIGURE) { 323 | scan_configure_state_logic(); 324 | } else if (current_state == SCAN) { 325 | perform_scan(); 326 | } else if (current_state == SCAN_CONFIRM) { 327 | scan_confirm_state_logic(); 328 | } else if (current_state == MENU) { 329 | menu_state_logic(); 330 | } else if(current_state == MENU_CHANGE_CONTRAST) { 331 | menu_change_contrast_state_logic(); 332 | } else if(current_state == MENU_CHANGE_RPM_ROTOR) { 333 | menu_state_set_min_max_12bit_logic( 334 | "Rotor", 335 | "RPM", 336 | true, 337 | 0, 338 | 0, 339 | STEPPER_ROTOR_MIN_RPM, 340 | STEPPER_ROTOR_RPM_STEP_SIZE, 341 | EEPROM_STEPPER_ROTOR_RPM_POS, 342 | EEPROM_STEPPER_ROTOR_RPM_MS_POS, 343 | false); 344 | } else if(current_state == MENU_CHANGE_ACCELERATION_ROTOR) { 345 | menu_state_set_min_max_12bit_logic( 346 | "Rotor", 347 | "Acceleration", 348 | false, 349 | STEPPER_ROTOR_MIN_ACCEL, 350 | STEPPER_ROTOR_ACCEL_STEP_SIZE, 351 | 0.0, 352 | 0.0, 353 | EEPROM_STEPPER_ROTOR_ACCEL_POS, 354 | EEPROM_STEPPER_ROTOR_ACCEL_DECEL_POS, 355 | false); 356 | } else if(current_state == MENU_CHANGE_DECELERATION_ROTOR) { 357 | menu_state_set_min_max_12bit_logic( 358 | "Rotor", 359 | "Deceleration", 360 | false, 361 | STEPPER_ROTOR_MIN_DECEL, 362 | STEPPER_ROTOR_DECEL_STEP_SIZE, 363 | 0.0, 364 | 0.0, 365 | EEPROM_STEPPER_ROTOR_DECEL_POS, 366 | EEPROM_STEPPER_ROTOR_ACCEL_DECEL_POS, 367 | true); 368 | } else if(current_state == MENU_CHANGE_RPM_TURNTABLE) { 369 | menu_state_set_min_max_12bit_logic( 370 | "Turntable", 371 | "RPM", 372 | true, 373 | 0, 374 | 0, 375 | STEPPER_TURNTABLE_MIN_RPM, 376 | STEPPER_TURNTABLE_RPM_STEP_SIZE, 377 | EEPROM_STEPPER_TURNTABLE_RPM_POS, 378 | EEPROM_STEPPER_TURNTABLE_RPM_MS_POS, 379 | false); 380 | } else if(current_state == MENU_CHANGE_ACCELERATION_TURNTABLE) { 381 | menu_state_set_min_max_12bit_logic( 382 | "Turntable", 383 | "Acceleration", 384 | false, 385 | STEPPER_TURNTABLE_MIN_ACCEL, 386 | STEPPER_TURNTABLE_ACCEL_STEP_SIZE, 387 | 0.0, 388 | 0.0, 389 | EEPROM_STEPPER_TURNTABLE_ACCEL_POS, 390 | EEPROM_STEPPER_TURNTABLE_ACCEL_DECEL_POS, 391 | false); 392 | } else if(current_state == MENU_CHANGE_DECELERATION_TURNTABLE) { 393 | menu_state_set_min_max_12bit_logic( 394 | "Turntable", 395 | "Deceleration", 396 | false, 397 | STEPPER_TURNTABLE_MIN_DECEL, 398 | STEPPER_TURNTABLE_DECEL_STEP_SIZE, 399 | 0.0, 400 | 0.0, 401 | EEPROM_STEPPER_TURNTABLE_DECEL_POS, 402 | EEPROM_STEPPER_TURNTABLE_ACCEL_DECEL_POS, 403 | true); 404 | } else if(current_state == MENU_CHANGE_PHOTO_DELAY) { 405 | menu_state_set_16bit_logic( 406 | String("Photo Delay"), 407 | 100, 408 | 30000, 409 | EEPROM_TIME_BETWEEN_PHOTO_LOW_POS, 410 | EEPROM_TIME_BETWEEN_PHOTO_HIGH_POS); 411 | } else if(current_state == MENU_CHANGE_MOVE_DELAY) { 412 | menu_state_set_16bit_logic( 413 | String("Move Delay"), 414 | 100, 415 | 30000, 416 | EEPROM_TIME_AFTER_MOVE_LOW_POS, 417 | EEPROM_TIME_AFTER_MOVE_HIGH_POS); 418 | } 419 | } 420 | } 421 | 422 | /** 423 | * The default arduino loop is empty except of a delay since all functionality is handled with freeRTOS tasks. 424 | */ 425 | void loop() { 426 | delay(100); 427 | } 428 | -------------------------------------------------------------------------------- /Firmware/Lights.ino: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * This code manages the outputpin for the transistor which is driving the spotlights. 4 | */ 5 | 6 | boolean is_light_on = false; 7 | 8 | void turn_light_on() { 9 | if (is_light_on) return; 10 | 11 | is_light_on = true; 12 | digitalWrite(LIGHT_SWITCH, HIGH); 13 | } 14 | 15 | void turn_light_off() { 16 | if (!is_light_on) return; 17 | 18 | is_light_on = false; 19 | digitalWrite(LIGHT_SWITCH, LOW); 20 | } 21 | 22 | void switch_light() { 23 | if (is_light_on) 24 | turn_light_off(); 25 | else 26 | turn_light_on(); 27 | } 28 | 29 | /** 30 | * Configure output pin for the correct mode. 31 | */ 32 | void initialize_light() { 33 | pinMode(LIGHT_SWITCH, OUTPUT); 34 | digitalWrite(LIGHT_SWITCH, LOW); 35 | } 36 | -------------------------------------------------------------------------------- /Firmware/Nokia5110-Display.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /** 4 | * The used Nokia5110 Display is a monochrome 84*48 display which is used to display various information and contextual data to the user. 5 | */ 6 | 7 | // delay in ms between 2 frames/logic executions 8 | #define TIME_BETWEEN_FRAMES 50 9 | 10 | /** 11 | * Each character drawn takes 5*8 pixels of the 84*48 pixel display. 12 | */ 13 | Nokia_LCD lcd(DISPLAY_CLK, DISPLAY_DIN, DISPLAY_DC, DISPLAY_CE, DISPLAY_RST); 14 | 15 | /** 16 | * Initialization of the lcd. 17 | * This includes clearing its content and loading relevant data from EEPROM for configuration. 18 | * 19 | * The settings for contrast and backgroundlight are stored within EEPROM at address EEPROM_LCD_BL_CONTRAST_POS. 20 | * Bit seven (most significant one) is used as flag if the backgroundlight shall be turned on (1) or off (0), 21 | * while bits 0 to 6 contain a value between 0 and 127 which is used for the contrast of the display. 22 | * 23 | * Bitorder within a byte: 24 | * Value | 2^7 | 2^6 | 2^5 | 2^4 | 2^3 | 2^2 | 2^1 | 2^0 25 | * Index | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 26 | * Most significant <-----------------> Least significant 27 | */ 28 | void initialize_display() { 29 | lcd.begin(); 30 | // the parameter indicates if the display should be filled with black pixels 31 | lcd.clear(false); 32 | // read relevant data from EEPROM 33 | uint8_t bl_constrast_setting = EEPROM.read(EEPROM_LCD_BL_CONTRAST_POS); 34 | // extract and set contrast value 35 | lcd.setContrast(bl_constrast_setting & 0x7F); 36 | // ensure the pin used for the background light is an output pin 37 | pinMode(DISPLAY_BL, OUTPUT); 38 | // extract and set state of display's background light 39 | if ((bl_constrast_setting & 0x80) > 0) { 40 | digitalWrite(DISPLAY_BL, HIGH); 41 | } else { 42 | digitalWrite(DISPLAY_BL, LOW); 43 | } 44 | } 45 | 46 | /** 47 | * Utility function which allows to print a string centered at a given line. 48 | */ 49 | void print_centered(String str, char line) { 50 | lcd.setCursor((84 - (str.length() * 5)) / 2, line); 51 | lcd.print(str.c_str()); 52 | } 53 | -------------------------------------------------------------------------------- /Firmware/Remote-Shutter.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "BLE2902.h" 5 | #include "BLEHIDDevice.h" 6 | #include "HIDTypes.h" 7 | #include "HIDKeyboardTypes.h" 8 | #include 9 | 10 | /** 11 | * The remote shutter for this application is a BLE service which operates as keyboard/user device (depending on the connected device [iOS/Android]). 12 | * BLE logic as well as the actual shutter code can be found here. 13 | */ 14 | 15 | /** 16 | * Definitions can be found in EEPROM.ino 17 | */ 18 | extern const uint8_t EEPROM_CAMERA_TYPE_POS; 19 | extern const uint8_t EEPROM_CAMERA_TYPE_ANDROID_DEVICE; 20 | extern const uint8_t EEPROM_CAMERA_TYPE_IOS_DEVICE; 21 | 22 | /** 23 | * Relevant data for BLE functionality. 24 | * 25 | * The BLE HID code is based on https://github.com/nkolban/esp32-snippets/issues/230#issuecomment-474594017 26 | */ 27 | 28 | // HID device containing different charactersitics which form the services 29 | BLEHIDDevice* hid; 30 | // keyboard input characteristic 31 | BLECharacteristic* input; 32 | // keyboard output characteristic 33 | BLECharacteristic* output; 34 | // characteristics for media keys (e.g. volume up) 35 | BLECharacteristic* volume; 36 | 37 | // indicator if currently a BLE connection is established 38 | bool hid_connected = false; 39 | 40 | /** 41 | * The server callbacks handle starting and ending BLE connections 42 | */ 43 | class BLECallbacks : public BLEServerCallbacks { 44 | void onConnect(BLEServer* pServer){ 45 | hid_connected = true; 46 | BLE2902* desc = (BLE2902*)input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); 47 | desc->setNotifications(true); 48 | } 49 | 50 | void onDisconnect(BLEServer* pServer){ 51 | hid_connected = false; 52 | BLE2902* desc = (BLE2902*)input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902)); 53 | desc->setNotifications(false); 54 | } 55 | }; 56 | 57 | /* 58 | * This callback is connect with output report. In keyboard output report report special keys changes, like CAPSLOCK, NUMLOCK 59 | * We can add digital pins with LED to show status 60 | * bit 0 - NUM LOCK 61 | * bit 1 - CAPS LOCK 62 | * bit 2 - SCROLL LOCK 63 | */ 64 | class BLEOutputCallbacks : public BLECharacteristicCallbacks { 65 | void onWrite(BLECharacteristic* me){ 66 | uint8_t* value = (uint8_t*)(me->getValue().c_str()); 67 | ESP_LOGI(LOG_TAG, "special keys: %d", *value); 68 | } 69 | }; 70 | 71 | /** 72 | * This function will be executed as freeRTOS task. 73 | * It configures and starts the BLE device 74 | */ 75 | void ble_task_server(void*) { 76 | BLEDevice::init("Nazrim's 3D Scanner"); 77 | BLEServer *pServer = BLEDevice::createServer(); 78 | pServer->setCallbacks(new BLECallbacks()); 79 | 80 | hid = new BLEHIDDevice(pServer); 81 | input = hid->inputReport(1); // <-- input REPORT_ID from report map 82 | output = hid->outputReport(1); // <-- output REPORT_ID from report map 83 | volume = hid->inputReport(2); 84 | output->setCallbacks(new BLEOutputCallbacks()); 85 | // Set manufacturer name (OPTIONAL) 86 | std::string name = "Nazrim"; 87 | hid->manufacturer()->setValue(name); 88 | // Set pnp parameters (MANDATORY) 89 | hid->pnp(0x02, 0xe502, 0xa111, 0x0210); 90 | // Set hid informations (MANDATORY) 91 | hid->hidInfo(0x00,0x02); 92 | /* 93 | * The report contains two different services: 94 | * - keyboard (relevant for android cameras) 95 | * - consumer control (media keys) for iOS 96 | */ 97 | const uint8_t report[] = { 98 | USAGE_PAGE(1), 0x01, // Generic Desktop Ctrls 99 | USAGE(1), 0x06, // Keyboard 100 | COLLECTION(1), 0x01, // Application 101 | REPORT_ID(1), 0x01, // Report ID (1) 102 | USAGE_PAGE(1), 0x07, // Kbrd/Keypad 103 | USAGE_MINIMUM(1), 0xE0, 104 | USAGE_MAXIMUM(1), 0xE7, 105 | LOGICAL_MINIMUM(1), 0x00, 106 | LOGICAL_MAXIMUM(1), 0x01, 107 | REPORT_SIZE(1), 0x01, // 1 byte (Modifier) 108 | REPORT_COUNT(1), 0x08, 109 | HIDINPUT(1), 0x02, // Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position 110 | REPORT_COUNT(1), 0x01, // 1 byte (Reserved) 111 | REPORT_SIZE(1), 0x08, 112 | HIDINPUT(1), 0x01, // Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position 113 | REPORT_COUNT(1), 0x01, // 6 bytes (Keys) 114 | REPORT_SIZE(1), 0x08, 115 | LOGICAL_MINIMUM(1), 0x00, 116 | LOGICAL_MAXIMUM(1), 0x65, // 101 keys 117 | USAGE_MINIMUM(1), 0x00, 118 | USAGE_MAXIMUM(1), 0x65, 119 | HIDINPUT(1), 0x00, // Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position 120 | REPORT_COUNT(1), 0x05, // 5 bits (Num lock, Caps lock, Scroll lock, Compose, Kana) 121 | REPORT_SIZE(1), 0x01, 122 | USAGE_PAGE(1), 0x08, // LEDs 123 | USAGE_MINIMUM(1), 0x01, // Num Lock 124 | USAGE_MAXIMUM(1), 0x05, // Kana 125 | HIDOUTPUT(1), 0x02, // Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile 126 | REPORT_COUNT(1), 0x01, // 3 bits (Padding) 127 | REPORT_SIZE(1), 0x03, 128 | HIDOUTPUT(1), 0x01, // Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile 129 | END_COLLECTION(0) 130 | , 131 | 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) 132 | 0x09, 0x01, // USAGE (Consumer Control) 133 | 0x85, 0x02, 134 | 0xa1, 0x01, // COLLECTION (Application) 135 | // -------------------- common global items 136 | 0x15, 0x00, // LOGICAL_MINIMUM (0) 137 | 0x25, 0x01, // LOGICAL_MAXIMUM (1) 138 | 0x75, 0x01, // REPORT_SIZE (1) - each field occupies 1 bit 139 | // -------------------- misc bits 140 | 0x95, 0x05, // REPORT_COUNT (5) 141 | 0x09, 0xb5, // USAGE (Scan Next Track) 142 | 0x09, 0xb6, // USAGE (Scan Previous Track) 143 | 0x09, 0xb7, // USAGE (Stop) 144 | 0x09, 0xcd, // USAGE (Play/Pause) 145 | 0x09, 0xe2, // USAGE (Mute) 146 | 0x81, 0x06, // INPUT (Data,Var,Rel) - relative inputs 147 | // -------------------- volume up/down bits 148 | 0x95, 0x02, // REPORT_COUNT (2) 149 | 0x09, 0xe9, // USAGE (Volume Up) 150 | 0x09, 0xea, // USAGE (Volume Down) 151 | 0x81, 0x02, // INPUT (Data,Var,Abs) - absolute inputs 152 | // -------------------- padding bit 153 | 0x95, 0x01, // REPORT_COUNT (1) 154 | 0x81, 0x01, // INPUT (Cnst,Ary,Abs) 155 | 0xc0 // END_COLLECTION 156 | }; 157 | 158 | /* 159 | * Set report map (here is initialized device driver on client side) (MANDATORY) 160 | * https://www.bluetooth.com/specifications/gatt/viewer?attributeXmlFile=org.bluetooth.characteristic.report_map.xml 161 | */ 162 | hid->reportMap((uint8_t*)report, sizeof(report)); 163 | 164 | /* 165 | * We are prepared to start hid device services. Before this point we can change all values and/or set parameters we need. 166 | * Also before we start, if we want to provide battery info, we need to prepare battery service. 167 | * We can setup characteristics authorization 168 | */ 169 | hid->startServices(); 170 | 171 | /* 172 | * Its good to setup advertising by providing appearance and advertised service. This will let clients find our device by type 173 | */ 174 | BLEAdvertising *pAdvertising = pServer->getAdvertising(); 175 | pAdvertising->setAppearance(HID_KEYBOARD); 176 | pAdvertising->addServiceUUID(hid->hidService()->getUUID()); 177 | pAdvertising->start(); 178 | hid->setBatteryLevel(100); 179 | 180 | ESP_LOGD(LOG_TAG, "Advertising started!"); 181 | 182 | BLESecurity *pSecurity = new BLESecurity(); 183 | pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND); 184 | 185 | 186 | while(true) { 187 | vTaskDelay(portMAX_DELAY); 188 | } 189 | }; 190 | 191 | /** 192 | * Send the required keyboard inputs to a connected device which triggers to take a 193 | * photo as long as the camera app is opened. 194 | * 195 | * Right now only android smartphones are supported. 196 | */ 197 | void ble_take_photo() { 198 | if (hid_connected) { 199 | uint8_t camera_type = EEPROM.read(EEPROM_CAMERA_TYPE_POS); 200 | 201 | if (camera_type == EEPROM_CAMERA_TYPE_ANDROID_DEVICE) { 202 | // for android the enter key (0x0A) triggers to take a photo 203 | const char triggerCameraAndroid = 0x0A; 204 | KEYMAP map = keymap[(uint8_t)triggerCameraAndroid]; 205 | 206 | uint8_t triggerCameraAndroidDown[] = {map.modifier, 0x0, map.usage}; 207 | input->setValue(triggerCameraAndroidDown, sizeof(triggerCameraAndroidDown)); 208 | input->notify(); 209 | 210 | uint8_t triggerCameraAndroidUp[] = {0x0, 0x0, 0x0}; 211 | input->setValue(triggerCameraAndroidUp, sizeof(triggerCameraAndroidUp)); 212 | input->notify(); 213 | } else if (camera_type == EEPROM_CAMERA_TYPE_IOS_DEVICE) { 214 | // on iOS devices the volume up key must be triggered 215 | uint8_t vol_up_msg[] = {0x20}; 216 | volume->setValue(vol_up_msg, sizeof(vol_up_msg)); 217 | volume->notify(); 218 | 219 | uint8_t vol_up_msg1[] = {0x00}; 220 | volume->setValue(vol_up_msg1, sizeof(vol_up_msg1)); 221 | volume->notify(); 222 | } 223 | } 224 | } 225 | 226 | /** 227 | * Start a RTOS thread which takes care of the ble functionality. 228 | */ 229 | void initialize_BLE() { 230 | xTaskCreate(ble_task_server, "BleServer", 20000, NULL, 5, NULL); 231 | } 232 | -------------------------------------------------------------------------------- /Firmware/State_Change_Contrast.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * State logic for changing the LCD's contrast. Includes a "gradient" bitmap for better visibility. 3 | */ 4 | 5 | // Actual lcd initialization can be found in Nokia5110-Display.ino 6 | extern Nokia_LCD lcd; 7 | 8 | // Encoder initialization can be found in Encoder.ino 9 | extern ESP32Encoder encoder; 10 | 11 | // Encoder button initialization can be found in Encoder.ino 12 | extern volatile boolean encoder_button_pressed; 13 | 14 | // Bitmap to display on the lcd. It covers the half Nokia5110 Display and shows a "gradient" 15 | // from black to white 16 | const unsigned char CONTRAST_ADJUSTMENT_GRADIENT[252] PROGMEM = { 17 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 18 | 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xBD, 0xFA, 0xFF, 0xFB, 19 | 0xE3, 0xFF, 0x3F, 0xFF, 0xF7, 0xFF, 0xFF, 0x37, 0x7F, 0xFF, 0xFF, 0xE4, 0xFE, 0xDC, 0xDF, 0xF7, 20 | 0xF5, 0xFE, 0xA7, 0xDF, 0xF7, 0xE5, 0xFE, 0x27, 0x39, 0xBF, 0x5D, 0xC4, 0xFE, 0x5C, 0x86, 0x5F, 21 | 0x36, 0xA7, 0x08, 0x9D, 0x13, 0x81, 0xE8, 0x08, 0x02, 0x44, 0x00, 0x20, 0x04, 0x04, 0x00, 0x00, 22 | 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 23 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 24 | 0x77, 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xFF, 0x5F, 0xFF, 0xBE, 0x7F, 0xFF, 0x7E, 0xFF, 0xBF, 25 | 0xBE, 0xFF, 0xFF, 0xFF, 0x7F, 0xBA, 0x5F, 0xFF, 0xFF, 0x7F, 0xBA, 0x5F, 0xBF, 0x5E, 0xDF, 0x36, 26 | 0x08, 0x3F, 0x6C, 0x08, 0x13, 0x54, 0x86, 0x1B, 0xA0, 0x30, 0x10, 0x28, 0x20, 0x01, 0x40, 0x00, 27 | 0x40, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 28 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 29 | 0xFF, 0xFB, 0xFF, 0xF9, 0xDF, 0xFF, 0xFF, 0xFF, 0xFA, 0xFF, 0xBD, 0xFF, 0xFE, 0xEF, 0xF6, 0xBD, 30 | 0xAD, 0xDF, 0xFF, 0xFD, 0xDF, 0x93, 0xFF, 0xFF, 0x8B, 0xB3, 0x3F, 0xFF, 0xFF, 0x8A, 0xB2, 0x3D, 31 | 0xAD, 0xDF, 0xDF, 0xFD, 0xDD, 0x93, 0x24, 0x2F, 0x47, 0x0E, 0x4E, 0x28, 0x20, 0x23, 0x0E, 0x01, 32 | 0x36, 0x10, 0x02, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 33 | }; 34 | 35 | /** 36 | * Process user input to adjust contrast value and finaly store the new value on state exit. 37 | */ 38 | void menu_change_contrast_state_logic() { 39 | // process inputs 40 | if (encoder_button_pressed) { 41 | uint8_t new_contrast_value = menu_change_contrast_backlight_state | menu_change_contrast_current_value; 42 | EEPROM.write(EEPROM_LCD_BL_CONTRAST_POS, new_contrast_value); 43 | EEPROM.commit(); 44 | 45 | current_state = MENU; 46 | consume_encoder_button(); 47 | } else if ((int32_t)encoder.getCount() != 0) { 48 | menu_change_contrast_current_value += encoder.getCount(); 49 | if (menu_change_contrast_current_value > 127) { 50 | if ((int32_t)encoder.getCount() > 0) { 51 | menu_change_contrast_current_value = 127; 52 | } else { 53 | menu_change_contrast_current_value = 0; 54 | } 55 | } 56 | encoder.setCount(0); 57 | lcd.setContrast(menu_change_contrast_current_value); 58 | } 59 | 60 | // draw the config screen 61 | lcd.clear(); 62 | lcd.draw(CONTRAST_ADJUSTMENT_GRADIENT, 63 | sizeof(CONTRAST_ADJUSTMENT_GRADIENT) / sizeof(CONTRAST_ADJUSTMENT_GRADIENT[0]), 64 | true); 65 | // draw the current value at the x-middle of the screen and take numbers >100 and >10 into account 66 | uint8_t x_pos = 35; 67 | if (menu_change_contrast_current_value < 100) { 68 | x_pos += 5; 69 | } 70 | if (menu_change_contrast_current_value < 10) { 71 | x_pos += 5; 72 | } 73 | lcd.setCursor(7, 4); 74 | lcd.print("Current Value:"); 75 | lcd.setCursor(x_pos, 5); 76 | lcd.print(menu_change_contrast_current_value); 77 | delay(TIME_BETWEEN_FRAMES); 78 | } 79 | -------------------------------------------------------------------------------- /Firmware/State_Menu.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Simple state logic which allows the navigation of the menu structure. 3 | */ 4 | 5 | // The actual definition can be found in Menu.ino 6 | extern MenuSystem menu_system; 7 | 8 | // Encoder initialization can be found in Encoder.ino 9 | extern ESP32Encoder encoder; 10 | 11 | // Encoder button initialization can be found in Encoder.ino 12 | extern volatile boolean encoder_button_pressed; 13 | 14 | // Can be found in Menu.ino 15 | extern void push_current_menu_navigation_data(); 16 | 17 | // Can be found in Menu.ino 18 | extern void navigate_forward(); 19 | 20 | // Can be found in Menu.ino 21 | extern void navigate_backward(); 22 | 23 | /** 24 | * Logic function for this state handles user input to navigate the menu which is displayed on the lcd. 25 | */ 26 | void menu_state_logic() { 27 | // process inputs 28 | // the encoder button has higher precedence than the encoder rotation 29 | if (encoder_button_pressed) { 30 | menu_system.select(); 31 | consume_encoder_button(); 32 | push_current_menu_navigation_data(); 33 | } else if ((int32_t)encoder.getCount() != 0) { 34 | if ((int32_t)encoder.getCount() > 0) { 35 | menu_system.next(); 36 | navigate_forward(); 37 | } else { 38 | menu_system.prev(); 39 | navigate_backward(); 40 | } 41 | encoder.setCount(0); 42 | } 43 | // draw the menu 44 | menu_system.display(); 45 | // sleep some time for (better) visibility on screen 46 | delay(TIME_BETWEEN_FRAMES); 47 | } 48 | -------------------------------------------------------------------------------- /Firmware/State_Scan_Configure.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * If the user wants to start a custom print, it is necessary to get his input for the various settings. 3 | */ 4 | 5 | /** 6 | * This object contains the custom scan the user wants to perform. 7 | */ 8 | Scan custom_scan; 9 | 10 | /** 11 | * Loads the last known custom scan from EEPROM 12 | */ 13 | void initialize_custom_scan() { 14 | custom_scan.photos_per_revolution = (EEPROM.read(EEPROM_CUSTOM_SCAN_PHOTOS_PER_REVOLUTION_HIGH_POS) << 8) | EEPROM.read(EEPROM_CUSTOM_SCAN_PHOTOS_PER_REVOLUTION_LOW_POS); 15 | custom_scan.rotation = (EEPROM.read(EEPROM_CUSTOM_SCAN_ROTATION_HIGH_POS) << 8) | EEPROM.read(EEPROM_CUSTOM_SCAN_ROTATION_LOW_POS); 16 | custom_scan.rotation_divisions = (EEPROM.read(EEPROM_CUSTOM_SCAN_ROTATION_DIVISIONS_HIGH_POS) << 8) | EEPROM.read(EEPROM_CUSTOM_SCAN_ROTATION_DIVISIONS_LOW_POS); 17 | } 18 | 19 | /** 20 | * Logic for getting user input for all required scan settings and proceed to scanning. 21 | */ 22 | void scan_configure_state_logic() { 23 | query_photos_per_rev(); 24 | query_rotation(); 25 | query_rotation_steps(); 26 | 27 | selected_scan = &custom_scan; 28 | current_state = SCAN_CONFIRM; 29 | 30 | // store the new custom print to eeprom 31 | EEPROM.write(EEPROM_CUSTOM_SCAN_PHOTOS_PER_REVOLUTION_LOW_POS, custom_scan.photos_per_revolution & 0xFF); 32 | EEPROM.write(EEPROM_CUSTOM_SCAN_PHOTOS_PER_REVOLUTION_HIGH_POS, (custom_scan.photos_per_revolution >> 8) & 0xFF); 33 | EEPROM.write(EEPROM_CUSTOM_SCAN_ROTATION_LOW_POS, custom_scan.rotation & 0xFF); 34 | EEPROM.write(EEPROM_CUSTOM_SCAN_ROTATION_HIGH_POS, (custom_scan.rotation >> 8) & 0xFF); 35 | EEPROM.write(EEPROM_CUSTOM_SCAN_ROTATION_DIVISIONS_LOW_POS, custom_scan.rotation_divisions & 0xFF); 36 | EEPROM.write(EEPROM_CUSTOM_SCAN_ROTATION_DIVISIONS_HIGH_POS, (custom_scan.rotation_divisions >> 8) & 0xFF); 37 | 38 | EEPROM.commit(); 39 | } 40 | 41 | void query_photos_per_rev() { 42 | const char* lines[4]; 43 | lines[0] = "How many photos"; 44 | lines[1] = "should be taken"; 45 | lines[2] = "during each tu-"; 46 | lines[3] = "rntable rev?"; 47 | custom_scan.photos_per_revolution = query_user(lines, 4, 1, custom_scan.photos_per_revolution, 3200); 48 | } 49 | 50 | void query_rotation() { 51 | const char* lines[4]; 52 | lines[0] = "How many degrees"; 53 | lines[1] = "should the rotor"; 54 | lines[2] = "be turned in"; 55 | lines[3] = "total?"; 56 | custom_scan.rotation = query_user(lines, 4, 1, custom_scan.rotation, 359); 57 | } 58 | 59 | void query_rotation_steps() { 60 | short max_val = (short) (3200 * (custom_scan.rotation / 360.0)); 61 | const char* lines[4]; 62 | lines[0] = "Into how many"; 63 | lines[1] = "steps should the"; 64 | lines[2] = "turntable rota-"; 65 | lines[3] = "tion divided?"; 66 | custom_scan.rotation_divisions = query_user(lines, 4, 1, custom_scan.rotation_divisions, max_val); 67 | } 68 | 69 | short query_user(const char** lines, uint8_t num_lines, short min_val, short def_val, short max_val) { 70 | short result = def_val; 71 | while (true) { 72 | // handle user input 73 | if (encoder_button_pressed) { 74 | consume_encoder_button(); 75 | // a value was selected so return it 76 | break; 77 | } else if ((int32_t)encoder.getCount() != 0) { 78 | result += (short) (encoder.getCount() * scroll_speed_multiplier); 79 | if (result < min_val || result > max_val) { 80 | if ((int32_t)encoder.getCount() > 0) { 81 | result = max_val; 82 | } else { 83 | result = min_val; 84 | } 85 | } 86 | encoder.setCount(0); 87 | // adjust the multiplier for the next loop 88 | no_input_loops = 0; 89 | scroll_speed_multiplier = min(scroll_speed_multiplier * multplier_modifier, max_multiplier); 90 | } else { 91 | if (no_input_loops++ >= multiplier_resetter) { 92 | scroll_speed_multiplier = min_multiplier; 93 | } 94 | } 95 | // draw to lcd 96 | lcd.clear(); 97 | for (uint8_t i = 0; i < num_lines; i++) { 98 | lcd.println(lines[i]); 99 | } 100 | String min_str = "Min:" + String(min_val); 101 | String max_str = "Max:" + String(max_val); 102 | lcd.setCursor((42 - (min_str.length() * 5)) / 2, 4); 103 | lcd.print(min_str.c_str()); 104 | lcd.setCursor(42 + ((42 - (max_str.length() * 5)) / 2), 4); 105 | lcd.print(max_str.c_str()); 106 | lcd.setCursor((84 - (String(result).length() * 5)) / 2, 5); 107 | lcd.print(result); 108 | 109 | delay(TIME_BETWEEN_FRAMES); 110 | } 111 | return result; 112 | } 113 | -------------------------------------------------------------------------------- /Firmware/State_Scan_Confirm.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Prior starting a scan an overview of all settings and values are presented to the user which can 3 | * either confirm or abort the scanning job. 4 | */ 5 | 6 | /** 7 | * Indicator if ok or cancel was selected 8 | */ 9 | bool ok_selected = true; 10 | 11 | // Bitmap to display on the lcd. It one line on the screen and shows OK and CANCEL 12 | // OK is selected 13 | const unsigned char OK_SELECTED[84] PROGMEM = { 14 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 15 | 0xBD, 0xBD, 0xBD, 0xC3, 0xFF, 0x81, 0xE7, 0xDB, 0xBD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 16 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x42, 17 | 0x42, 0x42, 0x24, 0x00, 0x7C, 0x0A, 0x0A, 0x0A, 0x7C, 0x00, 0x7E, 0x04, 0x08, 0x10, 0x7E, 0x00, 18 | 0x3C, 0x42, 0x42, 0x42, 0x24, 0x00, 0x7E, 0x4A, 0x4A, 0x42, 0x42, 0x00, 0x7E, 0x40, 0x40, 0x40, 19 | 0x00, 0x00, 0x00, 0x00, 20 | }; 21 | 22 | // Bitmap to display on the lcd. It one line on the screen and shows OK and CANCEL 23 | // CANCEL is selected 24 | const unsigned char CANCEL_SELECTED[84] PROGMEM = { 25 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 26 | 0x42, 0x42, 0x42, 0x3C, 0x00, 0x7E, 0x18, 0x24, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 27 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xBD, 28 | 0xBD, 0xBD, 0xDB, 0xFF, 0x83, 0xF5, 0xF5, 0xF5, 0x83, 0xFF, 0x81, 0xFB, 0xF7, 0xEF, 0x81, 0xFF, 29 | 0xC3, 0xBD, 0xBD, 0xBD, 0xDB, 0xFF, 0x81, 0xB5, 0xB5, 0xBD, 0xBD, 0xFF, 0x81, 0xBF, 0xBF, 0xBF, 30 | 0xFF, 0xFF, 0xFF, 0xFF, 31 | }; 32 | 33 | void scan_confirm_state_logic() { 34 | // process inputs 35 | if (encoder_button_pressed) { 36 | consume_encoder_button(); 37 | // depending on the seleted item change to another state 38 | if (ok_selected) { 39 | current_state = SCAN; 40 | } else { 41 | current_state = MENU; 42 | } 43 | // reset the ok_selected status for next time the menu is opened 44 | ok_selected = true; 45 | } else if ((int32_t)encoder.getCount() != 0) { 46 | if ((int32_t)encoder.getCount() > 0) { 47 | ok_selected = false; 48 | } else { 49 | ok_selected = true; 50 | } 51 | encoder.setCount(0); 52 | } 53 | 54 | // retrieve/calculate data to display 55 | uint64_t etr = time_for_scan(*selected_scan); 56 | 57 | // show content on lcd 58 | String photos_per_revolution = "Photos/Rev: " + String(selected_scan->photos_per_revolution); 59 | String rotation = "Rotation: " + String(selected_scan->rotation); 60 | String rotation_steps = "#Rot Steps: " + String(selected_scan->rotation_divisions); 61 | String number_of_photos = "#Pics: " + String(selected_scan->photos_per_revolution * selected_scan->rotation_divisions); 62 | String etr_str = retrieve_time_string_for_ms(etr); 63 | 64 | lcd.clear(false); 65 | print_centered(photos_per_revolution, 0); 66 | print_centered(rotation, 1); 67 | print_centered(rotation_steps, 2); 68 | print_centered(number_of_photos, 3); 69 | print_centered(etr_str, 4); 70 | lcd.setCursor(0, 5); 71 | if (ok_selected) { 72 | lcd.draw(OK_SELECTED, 84, true); 73 | } else { 74 | lcd.draw(CANCEL_SELECTED, 84, true); 75 | } 76 | 77 | // sleep some time for (better) visibility on screen 78 | delay(TIME_BETWEEN_FRAMES); 79 | } 80 | -------------------------------------------------------------------------------- /Firmware/State_Set_12Bit.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * This is the logic for a menu state that is used for different situation. 3 | * It allows to set a 12 bit value for short and float values. 4 | * Minimum, maximum and current value are displayed. 5 | * Since 12 bit are 1.5 bytes the user can define if the upper or lower half of the second byte will be used. 6 | */ 7 | 8 | // The actual definition can be found in Menu.ino 9 | extern MenuSystem menu_system; 10 | 11 | // Encoder initialization can be found in Encoder.ino 12 | extern ESP32Encoder encoder; 13 | 14 | // Encoder button initialization can be found in Encoder.ino 15 | extern volatile boolean encoder_button_pressed; 16 | 17 | /** 18 | * Logic function for this state handles user input to navigate the menu which is displayed on the lcd. 19 | * In theory all 12 bit values with type float or short are supported. If a new value should be made 20 | * changeable by this function some code changes are required since the application of the new value 21 | * after a change is hard coded right now. 22 | * 23 | * @param affected_element Name of the element which uses the affected setting 24 | * @param affacted_setting Name of the actual setting which is adjusted now 25 | * @param use_float_values True if the altered setting is a float value, false if it is a short value 26 | * @param min_short Minimal value if short values are used 27 | * @param step_short Minimal difference between to values if short values are used 28 | * @param min_float Minimal value if float values are used 29 | * @param step_float Minimal difference between to values if short values are used 30 | * @param store_address_a EEPROM address where bits 0 to 7 are stored 31 | * @param store_address_b EEPROM address where bits 8 to 11 are stored 32 | * @param use_upper bits True if bits 8 to 11 should be stored in bits 4 to 7 of store_address_b, false for target bits 0 to 3 33 | */ 34 | void menu_state_set_min_max_12bit_logic( 35 | const String affected_element, 36 | const String affected_setting, 37 | const bool use_float_values, 38 | const short min_short, 39 | const short step_short, 40 | const float min_float, 41 | const float step_float, 42 | const uint8_t store_address_a, 43 | const uint8_t store_address_b, 44 | const bool use_upper_bits) { 45 | // process inputs 46 | // the encoder button has higher precedence than the encoder rotation 47 | if (encoder_button_pressed) { 48 | uint8_t lower_byte = menu_set_min_max_12bit_value & 0xFF; 49 | uint8_t upper_bits = (menu_set_min_max_12bit_value >> 8) & 0x0F; 50 | if (use_upper_bits) { 51 | upper_bits = (upper_bits << 4) | (EEPROM.read(store_address_b) & 0x0F); 52 | } else { 53 | upper_bits = (upper_bits) | (EEPROM.read(store_address_b) & 0xF0); 54 | } 55 | EEPROM.write(store_address_a, lower_byte); 56 | EEPROM.write(store_address_b, upper_bits); 57 | EEPROM.commit(); 58 | consume_encoder_button(); 59 | current_state = MENU; 60 | } else if ((int32_t)encoder.getCount() != 0) { 61 | menu_set_min_max_12bit_value += (short) (encoder.getCount() * scroll_speed_multiplier); 62 | // prevent over- and underflows 63 | if (menu_set_min_max_12bit_value > 4095) { 64 | if ((int32_t)encoder.getCount() > 0) { 65 | menu_set_min_max_12bit_value = 4095; 66 | } else { 67 | menu_set_min_max_12bit_value = 0; 68 | } 69 | } 70 | // reset encoder 71 | encoder.setCount(0); 72 | // adjust the multiplier for the next loop 73 | no_input_loops = 0; 74 | scroll_speed_multiplier = min(scroll_speed_multiplier * multplier_modifier, max_multiplier); 75 | // set the new value depending on the current applications state 76 | if(current_state == MENU_CHANGE_RPM_ROTOR) { 77 | stepper_rotor.setRPM(STEPPER_ROTOR_GEAR_RATIO * min_float + (menu_set_min_max_12bit_value * step_float)); 78 | } else if(current_state == MENU_CHANGE_ACCELERATION_ROTOR) { 79 | stepper_rotor.setSpeedProfile(stepper_rotor.getSpeedProfile().mode, min_short + (menu_set_min_max_12bit_value * step_short), stepper_rotor.getDeceleration()); 80 | } else if(current_state == MENU_CHANGE_DECELERATION_ROTOR) { 81 | stepper_rotor.setSpeedProfile(stepper_rotor.getSpeedProfile().mode, stepper_rotor.getAcceleration(), min_short + (menu_set_min_max_12bit_value * step_short)); 82 | } else if(current_state == MENU_CHANGE_RPM_TURNTABLE) { 83 | stepper_turntable.setRPM(min_float + (menu_set_min_max_12bit_value * step_float)); 84 | } else if(current_state == MENU_CHANGE_ACCELERATION_TURNTABLE) { 85 | stepper_turntable.setSpeedProfile(stepper_turntable.getSpeedProfile().mode, min_short + (menu_set_min_max_12bit_value * step_short), stepper_turntable.getDeceleration()); 86 | } else if(current_state == MENU_CHANGE_DECELERATION_TURNTABLE) { 87 | stepper_turntable.setSpeedProfile(stepper_turntable.getSpeedProfile().mode, stepper_turntable.getAcceleration(), min_short + (menu_set_min_max_12bit_value * step_short)); 88 | } 89 | } else { 90 | if (no_input_loops++ >= multiplier_resetter) { 91 | scroll_speed_multiplier = min_multiplier; 92 | } 93 | } 94 | // draw screen 95 | lcd.clear(false); 96 | // construct and draw title line 97 | String title = "Change " + affected_element; 98 | if (title.length() <= 16) { 99 | lcd.setCursor((84 - (title.length() * 5)) / 2, 0); 100 | } 101 | lcd.println(title.c_str()); 102 | // constuct and draw second title line 103 | if (affected_setting.length() <= 16) { 104 | lcd.setCursor((84 - (affected_setting.length() * 5)) / 2, 1); 105 | } 106 | lcd.println(affected_setting.c_str()); 107 | // draw min/max "title" - x-offset= (halfscreen (4px mid separation) - 4 characters) / 2 --> (40 - 20) / 2 108 | // for second entry 44 needs to be added 109 | lcd.setCursor(10, 2); 110 | lcd.print("Min:"); 111 | lcd.setCursor(54, 2); 112 | lcd.print("Max:"); 113 | // draw min and max values 114 | String min_str; 115 | String max_str; 116 | String current_value; 117 | if (use_float_values) { 118 | min_str = String(min_float, 2); 119 | max_str = String(min_float + (4095 * step_float), 2); 120 | current_value = String(min_float + (menu_set_min_max_12bit_value * step_float), 2); 121 | } else { 122 | min_str = String(min_short); 123 | max_str = String(min_short + (4095 * step_short)); 124 | current_value = String(min_short + (menu_set_min_max_12bit_value * step_short)); 125 | } 126 | lcd.setCursor((40 - (min_str.length() * 5)) / 2, 3); 127 | lcd.print(min_str.c_str()); 128 | lcd.setCursor(44 + (40 - (max_str.length() * 5)) / 2, 3); 129 | lcd.print(max_str.c_str()); 130 | // draw current value title and value itself 131 | lcd.setCursor(22, 4); 132 | lcd.print("Current:"); 133 | lcd.setCursor((84 - (current_value.length() * 5)) / 2, 5); 134 | lcd.print(current_value.c_str()); 135 | 136 | // sleep some time for (better) visibility on screen 137 | delay(TIME_BETWEEN_FRAMES); 138 | } 139 | -------------------------------------------------------------------------------- /Firmware/State_Set_16Bit.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * Since all values for a scan are 16 bit values a single generic 3 | * state can be used for adjusting all values. 4 | */ 5 | 6 | void menu_state_set_16bit_logic( 7 | const String affected_setting, 8 | const short min_value, 9 | const short max_value, 10 | const uint8_t store_address_a, 11 | const uint8_t store_address_b) { 12 | // process inputs 13 | // the encoder button has higher precedence than the encoder rotation 14 | if (encoder_button_pressed) { 15 | uint8_t lower_byte = menu_set_16bit_value & 0xFF; 16 | uint8_t upper_bits = (menu_set_16bit_value >> 8) & 0xFF; 17 | EEPROM.write(store_address_a, lower_byte); 18 | EEPROM.write(store_address_b, upper_bits); 19 | EEPROM.commit(); 20 | consume_encoder_button(); 21 | current_state = MENU; 22 | } else if ((int32_t)encoder.getCount() != 0) { 23 | menu_set_16bit_value += (short) (encoder.getCount() * scroll_speed_multiplier); 24 | // prevent over- and underflows 25 | if (menu_set_16bit_value > max_value || menu_set_16bit_value < min_value) { 26 | if ((int32_t)encoder.getCount() > 0) { 27 | menu_set_16bit_value = max_value; 28 | } else { 29 | menu_set_16bit_value = min_value; 30 | } 31 | } 32 | // reset encoder 33 | encoder.setCount(0); 34 | // adjust the multiplier for the next loop 35 | no_input_loops = 0; 36 | scroll_speed_multiplier = min(scroll_speed_multiplier * multplier_modifier, max_multiplier); 37 | // set the new value depending on the current applications state 38 | if(current_state == MENU_CHANGE_PHOTO_DELAY) { 39 | TIME_AFTER_PHOTO = menu_set_16bit_value; 40 | } else if(current_state == MENU_CHANGE_MOVE_DELAY) { 41 | TIME_AFTER_MOVE = menu_set_16bit_value; 42 | } 43 | } else { 44 | if (no_input_loops++ >= multiplier_resetter) { 45 | scroll_speed_multiplier = min_multiplier; 46 | } 47 | } 48 | // draw screen 49 | lcd.clear(false); 50 | // construct and draw title line 51 | String title = "Scan Settings"; 52 | if (title.length() <= 16) { 53 | lcd.setCursor((84 - (title.length() * 5)) / 2, 0); 54 | } 55 | lcd.println(title.c_str()); 56 | // constuct and draw second title line 57 | if (affected_setting.length() <= 16) { 58 | lcd.setCursor((84 - (affected_setting.length() * 5)) / 2, 1); 59 | } 60 | lcd.println(affected_setting.c_str()); 61 | // draw min/max "title" - x-offset= (halfscreen (4px mid separation) - 4 characters) / 2 --> (40 - 20) / 2 62 | // for second entry 44 needs to be added 63 | lcd.setCursor(10, 2); 64 | lcd.print("Min:"); 65 | lcd.setCursor(54, 2); 66 | lcd.print("Max:"); 67 | // draw min and max values 68 | String min_str = String(min_value); 69 | String max_str = String(max_value); 70 | String current_value = String(menu_set_16bit_value); 71 | lcd.setCursor((40 - (min_str.length() * 5)) / 2, 3); 72 | lcd.print(min_str.c_str()); 73 | lcd.setCursor(44 + (40 - (max_str.length() * 5)) / 2, 3); 74 | lcd.print(max_str.c_str()); 75 | // draw current value title and value itself 76 | lcd.setCursor(22, 4); 77 | lcd.print("Current:"); 78 | lcd.setCursor((84 - (current_value.length() * 5)) / 2, 5); 79 | lcd.print(current_value.c_str()); 80 | 81 | // sleep some time for (better) visibility on screen 82 | delay(TIME_BETWEEN_FRAMES); 83 | } 84 | -------------------------------------------------------------------------------- /Firmware/Status-LED.ino: -------------------------------------------------------------------------------- 1 | /** 2 | * The status LED is used to present the current state of the application to the user. 3 | * Green --> Turned on 4 | * Yellow --> Operating (Scanning) 5 | * Red --> Error 6 | * 7 | * Various blinking frequencies are used to create "sub-status" 8 | */ 9 | 10 | // Time how long the led is turned on/off for fast blinking 11 | short FAST_BLINK_TIME = 250; 12 | 13 | // Time how long the led is turned on/off for slow blinking 14 | short SLOW_BLINK_TIME = 500; 15 | 16 | // Time how long the led is turned on/off for extra slow blinking 17 | short EXTRA_SLOW_BLINK_TIME = 750; 18 | 19 | // This handle is used for task which run only a defined period of time and need to be deleted 20 | TaskHandle_t blinking_task_handle = NULL; 21 | 22 | /** 23 | * Initialization of the red/green duo LED which is used for indicating the 24 | * current status (read/operating). 25 | */ 26 | void initialize_status_led() { 27 | pinMode(STATUS_LED_GREEN, OUTPUT); 28 | digitalWrite(STATUS_LED_GREEN, LOW); 29 | 30 | pinMode(STATUS_LED_RED, OUTPUT); 31 | digitalWrite(STATUS_LED_RED, LOW); 32 | 33 | status_led_green(); 34 | } 35 | 36 | // Enable LED in green mode 37 | void status_led_green() { 38 | digitalWrite(STATUS_LED_RED, LOW); 39 | digitalWrite(STATUS_LED_GREEN, HIGH); 40 | } 41 | 42 | // Enable LED in yellow (red+green) mode 43 | void status_led_yellow() { 44 | digitalWrite(STATUS_LED_RED, HIGH); 45 | digitalWrite(STATUS_LED_GREEN, HIGH); 46 | } 47 | 48 | // Enable LED in red mode 49 | void status_led_red() { 50 | digitalWrite(STATUS_LED_GREEN, LOW); 51 | digitalWrite(STATUS_LED_RED, HIGH); 52 | } 53 | 54 | // Turn LED off 55 | void status_led_off() { 56 | digitalWrite(STATUS_LED_GREEN, LOW); 57 | digitalWrite(STATUS_LED_RED, LOW); 58 | } 59 | 60 | /** 61 | * Start freeRTOS task which blinks the led. 62 | * speed_mode: 63 | * - 0 --> slow blinking 64 | * - 1 --> fast blinking 65 | * - 2 --> extra slow blinking 66 | * 67 | * color: 68 | * - 0 --> red 69 | * - 1 --> yellow 70 | * - 2 --> green 71 | */ 72 | void start_blinking(uint8_t speed_mode, uint8_t color) { 73 | xTaskCreate(blinking_task, "StatusLedBlinking", 1000, (void*)(color | (speed_mode << 4)), 5, &blinking_task_handle); 74 | } 75 | 76 | /** 77 | * If the status LED is currently blinking, stop blinking and turn LED off. 78 | */ 79 | void stop_blinking() { 80 | if (blinking_task_handle != NULL) { 81 | vTaskSuspend(blinking_task_handle); 82 | vTaskDelete(blinking_task_handle); 83 | blinking_task_handle = NULL; 84 | status_led_off(); 85 | } 86 | } 87 | 88 | /** 89 | * Starts blinking of the status LED with given color and speed. 90 | * The data is coded within a single uint32_t 91 | * See start_blinking documentation for further details on the provided parameter 92 | */ 93 | void blinking_task(void* parameter) { 94 | // extract values from parameters 95 | uint32_t param = (uint32_t) parameter; 96 | uint8_t color = param & 0x0F; 97 | uint8_t speed_mode = (param >> 4) & 0x0F; 98 | // obtain used values/functions 99 | short delay_time = 0; 100 | switch (speed_mode) { 101 | case 0: 102 | delay_time = SLOW_BLINK_TIME; 103 | break; 104 | case 1: 105 | delay_time = FAST_BLINK_TIME; 106 | break; 107 | case 2: 108 | delay_time = EXTRA_SLOW_BLINK_TIME; 109 | break; 110 | } 111 | void (*led_on)() = NULL; 112 | switch (color) { 113 | case 0: 114 | led_on = &status_led_red; 115 | break; 116 | case 1: 117 | led_on = &status_led_yellow; 118 | break; 119 | case 2: 120 | led_on = &status_led_green; 121 | break; 122 | } 123 | // at first turn of the led to ensure no colors overlap 124 | status_led_off(); 125 | // actual blinking of the status led 126 | while (true) { 127 | led_on(); 128 | vTaskDelay(delay_time); 129 | status_led_off(); 130 | vTaskDelay(delay_time); 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /Firmware/Stepper-Rotor.ino: -------------------------------------------------------------------------------- 1 | #include "soc/timer_group_struct.h" 2 | #include "soc/timer_group_reg.h" 3 | #include 4 | 5 | /** 6 | * The rotor stepper is used for rotating the scanned object around the x-axis. 7 | */ 8 | 9 | // gear ratio which is used to drive the rotor 10 | float STEPPER_ROTOR_GEAR_RATIO = 40/8.0; 11 | 12 | // rotor stepper's minimal RPM value 13 | float STEPPER_ROTOR_MIN_RPM = 0.01; 14 | // minimal difference between to RPM values for rotor stepper 15 | float STEPPER_ROTOR_RPM_STEP_SIZE = 0.01; 16 | 17 | // rotor stepper's minimal acceleration value 18 | unsigned short STEPPER_ROTOR_MIN_ACCEL = 100; 19 | // minimal difference between to acceleration values for rotor stepper 20 | unsigned short STEPPER_ROTOR_ACCEL_STEP_SIZE = 1; 21 | 22 | // rotor stepper's minimal deceleration value 23 | unsigned short STEPPER_ROTOR_MIN_DECEL = 100; 24 | // minimal difference between to deceleration values for rotor stepper 25 | unsigned short STEPPER_ROTOR_DECEL_STEP_SIZE = 1; 26 | 27 | // this is the number of steps the stepper needs for a full revolution 28 | // typical values are 200 (1.8° stepper) and 400 (0.9° stepper) 29 | short ROTOR_STEPS_PER_REVOLUTION = 200; 30 | 31 | // The actual A4988 instance; microstepping disabled because the ESP32 offers not enough gpio pins for all functionality 32 | A4988 stepper_rotor(ROTOR_STEPS_PER_REVOLUTION, ROTOR_DIR, ROTOR_STEP, ROTOR_ENABLE);//, ROTOR_MS1, ROTOR_MS2, ROTOR_MS3); 33 | 34 | /** 35 | * Initialization of the rotor stepper loads all needed values from EEPROM 36 | * (RPM, microstepping, speedmode, acceleration, deceleration) and enables 37 | * the motor. 38 | */ 39 | void initialize_stepper_rotor() { 40 | stepper_rotor.begin(load_stepper_rotor_rpm(), load_stepper_rotor_ms()); 41 | stepper_rotor.setEnableActiveState(LOW); 42 | stepper_rotor.disable(); 43 | update_stepper_rotor_speed_profile(); 44 | } 45 | 46 | /** 47 | * Get the current RPM value for the rotor stepper. 48 | * The value is stored and EEPROM and is a combination of two bytes (one and a half to be more precise). 49 | */ 50 | float load_stepper_rotor_rpm() { 51 | // get rpm and ms settings from eeprom 52 | uint8_t rpm_byte = EEPROM.read(EEPROM_STEPPER_ROTOR_RPM_POS); 53 | uint8_t rpm_ms_byte = EEPROM.read(EEPROM_STEPPER_ROTOR_RPM_MS_POS); 54 | 55 | return STEPPER_ROTOR_GEAR_RATIO * STEPPER_ROTOR_MIN_RPM + (STEPPER_ROTOR_RPM_STEP_SIZE * (((rpm_ms_byte & 0x0F) << 8) | rpm_byte)); 56 | } 57 | 58 | /** 59 | * Get the microstepping settings for the rotor stepper. 60 | * The value is stored in the upper half of a byte in EEPROM which is used for RPM settings. 61 | */ 62 | uint8_t load_stepper_rotor_ms() { 63 | // get ms settings from eeprom 64 | /*uint8_t rpm_ms_byte = EEPROM.read(EEPROM_STEPPER_ROTOR_RPM_MS_POS); 65 | 66 | if (bitRead(rpm_ms_byte, 4) == 1) { 67 | return HALF_STEP; 68 | } else if (bitRead(rpm_ms_byte, 5) == 1) { 69 | return QUARTER_STEP; 70 | } else if (bitRead(rpm_ms_byte, 6) == 1) { 71 | return EIGHTH_STEP; 72 | } else if (bitRead(rpm_ms_byte, 7) == 1) { 73 | return SIXTEENTH_STEP; 74 | } 75 | 76 | return FULL_STEP;*/ 77 | return SIXTEENTH_STEP; 78 | } 79 | 80 | /** 81 | * Load the speed profile for the rotor motor from EEPROM. 82 | * The profile contains data about the speed type, acceleration and deceleration. 83 | */ 84 | void update_stepper_rotor_speed_profile() { 85 | // load EEPROM data 86 | uint8_t accel_byte = EEPROM.read(EEPROM_STEPPER_ROTOR_ACCEL_POS); 87 | uint8_t decel_byte = EEPROM.read(EEPROM_STEPPER_ROTOR_DECEL_POS); 88 | uint8_t accel_decel_byte = EEPROM.read(EEPROM_STEPPER_ROTOR_ACCEL_DECEL_POS); 89 | uint8_t bitmask = EEPROM.read(EEPROM_STEPPER_BITMASK_POS) & 0x0F; 90 | // create data for speed profile 91 | BasicStepperDriver::Mode speed_mode = (bitRead(bitmask, 0) == 1) ? stepper_rotor.LINEAR_SPEED : stepper_rotor.CONSTANT_SPEED; 92 | unsigned short accel = STEPPER_ROTOR_MIN_ACCEL + (STEPPER_ROTOR_ACCEL_STEP_SIZE * ((accel_decel_byte & 0x0F) << 8) | accel_byte); 93 | unsigned short decel = STEPPER_ROTOR_MIN_DECEL + (STEPPER_ROTOR_DECEL_STEP_SIZE * ((accel_decel_byte & 0xF0) << 4) | decel_byte); 94 | 95 | stepper_rotor.setSpeedProfile(speed_mode, accel, decel); 96 | } 97 | 98 | /** 99 | * This function will be executed as RTOS task if changes to the stepper configuration are applied. 100 | * It will periodically turn the stepper by 180 degrees into alternating direction. 101 | */ 102 | void stepper_rotor_debug_task(void*) { 103 | long rotate_degrees = 15; 104 | stepper_rotor.enable(); 105 | while(true) { 106 | // start an asynchronous movement (triggering steps programatically is required) 107 | int8_t multiplier = (bitRead(EEPROM.read(EEPROM_STEPPER_BITMASK_POS), 1) == 0) ? 1 : -1; 108 | stepper_rotor.startRotate(multiplier*rotate_degrees * STEPPER_ROTOR_GEAR_RATIO); 109 | rotate_degrees *= -1; 110 | unsigned int wait_time = stepper_rotor.nextAction(); 111 | while (stepper_rotor.getStepsRemaining() > 0) { 112 | // reset the watchdog manually since delayMicroseconds does not do it 113 | TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; 114 | TIMERG0.wdt_feed=1; 115 | TIMERG0.wdt_wprotect=0; 116 | // wait till next action needs to be executed 117 | delayMicroseconds(wait_time); 118 | // execute next action 119 | wait_time = stepper_rotor.nextAction(); 120 | } 121 | vTaskDelay(250); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /Firmware/Stepper-Turntable.ino: -------------------------------------------------------------------------------- 1 | #include "soc/timer_group_struct.h" 2 | #include "soc/timer_group_reg.h" 3 | #include 4 | 5 | /** 6 | * The turntable stepper is used for rotating the scanned object around the z-axis. 7 | */ 8 | 9 | // turntable stepper's minimal RPM value 10 | float STEPPER_TURNTABLE_MIN_RPM = 0.01; 11 | // minimal difference between to RPM values for turntable stepper 12 | float STEPPER_TURNTABLE_RPM_STEP_SIZE = 0.01; 13 | 14 | // turntable stepper's minimal acceleration value 15 | unsigned short STEPPER_TURNTABLE_MIN_ACCEL = 100; 16 | // minimal difference between to acceleration values for turntable stepper 17 | unsigned short STEPPER_TURNTABLE_ACCEL_STEP_SIZE = 1; 18 | 19 | // turntable stepper's minimal deceleration value 20 | unsigned short STEPPER_TURNTABLE_MIN_DECEL = 100; 21 | // minimal difference between to deceleration values for turntable stepper 22 | unsigned short STEPPER_TURNTABLE_DECEL_STEP_SIZE = 1; 23 | 24 | // this is the number of steps the stepper needs for a full revolution 25 | // typical values are 200 (1.8° stepper) and 400 (0.9° stepper) 26 | short TURNTABLE_STEPS_PER_REVOLUTION = 200; 27 | 28 | // The actual A4988 instance; microstepping disabled because the ESP32 offers not enough gpio pins for all functionality 29 | A4988 stepper_turntable(TURNTABLE_STEPS_PER_REVOLUTION, TURNTABLE_DIR, TURNTABLE_STEP, TURNTABLE_ENABLE);//, TURNTABLE_MS1, TURNTABLE_MS2, TURNTABLE_MS3); 30 | 31 | /** 32 | * Initialization of the turntable stepper loads all needed values from EEPROM 33 | * (RPM, microstepping, speedmode, acceleration, deceleration) and enables 34 | * the motor. 35 | */ 36 | void initialize_stepper_turntable() { 37 | stepper_turntable.begin(load_stepper_turntable_rpm(), load_stepper_turntable_ms()); 38 | stepper_turntable.setEnableActiveState(LOW); 39 | stepper_turntable.disable(); 40 | update_stepper_turntable_speed_profile(); 41 | } 42 | 43 | /** 44 | * Get the current RPM value for the turntable stepper. 45 | * The value is stored and EEPROM and is a combination of two bytes (one and a half to be more precise). 46 | */ 47 | float load_stepper_turntable_rpm() { 48 | // get rpm and ms settings from eeprom 49 | uint8_t rpm_byte = EEPROM.read(EEPROM_STEPPER_TURNTABLE_RPM_POS); 50 | uint8_t rpm_ms_byte = EEPROM.read(EEPROM_STEPPER_TURNTABLE_RPM_MS_POS); 51 | 52 | return STEPPER_TURNTABLE_MIN_RPM + (STEPPER_TURNTABLE_RPM_STEP_SIZE * (((rpm_ms_byte & 0x0F) << 8) | rpm_byte)); 53 | } 54 | 55 | /** 56 | * Get the microstepping settings for the turntable stepper. 57 | * The value is stored in the upper half of a byte in EEPROM which is used for RPM settings. 58 | */ 59 | uint8_t load_stepper_turntable_ms() { 60 | // get ms settings from eeprom 61 | /*uint8_t rpm_ms_byte = EEPROM.read(EEPROM_STEPPER_TURNTABLE_RPM_MS_POS); 62 | 63 | if (bitRead(rpm_ms_byte, 4) == 1) { 64 | return HALF_STEP; 65 | } else if (bitRead(rpm_ms_byte, 5) == 1) { 66 | return QUARTER_STEP; 67 | } else if (bitRead(rpm_ms_byte, 6) == 1) { 68 | return EIGHTH_STEP; 69 | } else if (bitRead(rpm_ms_byte, 7) == 1) { 70 | return SIXTEENTH_STEP; 71 | } 72 | 73 | return FULL_STEP;*/ 74 | return SIXTEENTH_STEP; 75 | } 76 | 77 | /** 78 | * Load the speed profile for the turntable motor from EEPROM. 79 | * The profile contains data about the speed type, acceleration and deceleration. 80 | */ 81 | void update_stepper_turntable_speed_profile() { 82 | // load EEPROM data 83 | uint8_t accel_byte = EEPROM.read(EEPROM_STEPPER_TURNTABLE_ACCEL_POS); 84 | uint8_t decel_byte = EEPROM.read(EEPROM_STEPPER_TURNTABLE_DECEL_POS); 85 | uint8_t accel_decel_byte = EEPROM.read(EEPROM_STEPPER_TURNTABLE_ACCEL_DECEL_POS); 86 | uint8_t bitmask = EEPROM.read(EEPROM_STEPPER_BITMASK_POS) & 0x0F; 87 | // create data for speed profile 88 | BasicStepperDriver::Mode speed_mode = (bitRead(bitmask, 4) == 1) ? stepper_turntable.LINEAR_SPEED : stepper_turntable.CONSTANT_SPEED; 89 | unsigned short accel = STEPPER_TURNTABLE_MIN_ACCEL + (STEPPER_TURNTABLE_ACCEL_STEP_SIZE * ((accel_decel_byte & 0x0F) << 8) | accel_byte); 90 | unsigned short decel = STEPPER_TURNTABLE_MIN_DECEL + (STEPPER_TURNTABLE_DECEL_STEP_SIZE * ((accel_decel_byte & 0xF0) << 4) | decel_byte); 91 | 92 | stepper_turntable.setSpeedProfile(speed_mode, accel, decel); 93 | } 94 | 95 | /** 96 | * This function will be executed as RTOS task if changes to the stepper configuration are applied. 97 | * It will periodically turn the stepper by 180 degrees into alternating direction. 98 | */ 99 | void stepper_turntable_debug_task(void*) { 100 | stepper_turntable.enable(); 101 | long rotate_degrees = 30; 102 | while(true) { 103 | // start an asynchronous movement (triggering steps programatically is required) 104 | int8_t multiplier = (bitRead(EEPROM.read(EEPROM_STEPPER_BITMASK_POS), 5) == 0) ? 1 : -1; 105 | stepper_turntable.startRotate(multiplier*rotate_degrees); 106 | rotate_degrees *= -1; 107 | unsigned int wait_time = stepper_turntable.nextAction(); 108 | while (stepper_turntable.getStepsRemaining() > 0) { 109 | // reset the watchdog manually since delayMicroseconds does not do it 110 | TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE; 111 | TIMERG0.wdt_feed=1; 112 | TIMERG0.wdt_wprotect=0; 113 | // wait till next action needs to be executed 114 | delayMicroseconds(wait_time); 115 | // execute next action 116 | wait_time = stepper_turntable.nextAction(); 117 | } 118 | vTaskDelay(250); 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /Gear_Settings/Spur_gear_3d_scanner_gear.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Gear_Settings/Spur_gear_3d_scanner_gear.PNG -------------------------------------------------------------------------------- /Gear_Settings/Spur_gear_3d_scanner_pinion.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Gear_Settings/Spur_gear_3d_scanner_pinion.PNG -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | Since this repository contains mixed artifacts (code, documents, images, ...) each subfolder of the root directory contains its own LICENSE.md file which is applicable to the resources in the corresponding folder. 4 | 5 | Because this is an open source project, source code artifacts and 3D models are licensed with the GPLv3 license while other artifacts (e.g. documents) are licensed with the CC-BY-SA 4.0 license. 6 | 7 | But to be sure please check the respective folder for the used license. -------------------------------------------------------------------------------- /Manual/AppendixPCB.tex: -------------------------------------------------------------------------------- 1 | \chapter{Picture Series PCB Assembly}% 2 | \label{cha:picSerPCB}% 3 | 4 | This chapter contains a series of pictures that show step by step how the individual components are soldered onto the PCB.% 5 | 6 | The images are completely uncommented, as they are not intended as instructions, but only as a reference.% 7 | 8 | More detailed information on assembling the circuit board can be found in section~\ref{sec:assPCB}.% 9 | 10 | It is quite possible that individual components may look different in your case, this applies especially to resistors and heat sinks. This is not a problem as long as the components are purchased to match the BOM.% 11 | 12 | It is possible to use the pictures to determine the order in which the individual parts are assembled. However, this is not an instruction or obligation. Assemble the parts in the order that suits you best.% 13 | 14 | \begin{figure}[ht!]% 15 | \begin{centered}% 16 | \includegraphics[width=\linewidth]{images/PcbSeries1.jpg}% 17 | \caption{Steps \numrange[text-rm=\lightBoldFont]{1}{6} of PCB assembly}% 18 | \end{centered}% 19 | \end{figure}% 20 | 21 | \begin{figure}[ht!]% 22 | \begin{centered}% 23 | \includegraphics[width=\linewidth]{images/PcbSeries2.jpg}% 24 | \caption{Steps \numrange[text-rm=\lightBoldFont]{7}{12} of PCB assembly}% 25 | \end{centered}% 26 | \end{figure}% 27 | 28 | \begin{figure}[ht!]% 29 | \begin{centered}% 30 | \includegraphics[width=\linewidth]{images/PcbSeries3.jpg}% 31 | \caption{Steps \numrange[text-rm=\lightBoldFont]{13}{18} of PCB assembly}% 32 | \end{centered}% 33 | \end{figure}% 34 | 35 | \begin{figure}[ht!]% 36 | \begin{centered}% 37 | \includegraphics[width=\linewidth]{images/PcbSeries4.jpg}% 38 | \caption{Steps \numrange[text-rm=\lightBoldFont]{19}{24} of PCB assembly}% 39 | \end{centered}% 40 | \end{figure}% 41 | 42 | \begin{figure}[ht!]% 43 | \begin{centered}% 44 | \includegraphics[width=\linewidth]{images/PcbSeries5.jpg}% 45 | \caption{Steps \numrange[text-rm=\lightBoldFont]{25}{30} of PCB assembly}% 46 | \end{centered}% 47 | \end{figure}% 48 | 49 | \begin{figure}[ht!]% 50 | \begin{centered}% 51 | \includegraphics[width=\linewidth]{images/PcbSeries6.jpg}% 52 | \caption{Steps \numrange[text-rm=\lightBoldFont]{31}{36} of PCB assembly}% 53 | \end{centered}% 54 | \end{figure}% 55 | 56 | \begin{figure}[ht!]% 57 | \begin{centered}% 58 | \includegraphics[width=\linewidth]{images/PcbSeries7.jpg}% 59 | \caption{Steps \numrange[text-rm=\lightBoldFont]{37}{38} of PCB assembly}% 60 | \end{centered}% 61 | \end{figure}% -------------------------------------------------------------------------------- /Manual/Commands.tex: -------------------------------------------------------------------------------- 1 | % This is a derivation of the \printMarginPartialToc command of yReport.cls which does not work (the way I want it) with reports 2 | \DeclareDocumentCommand{\printMarginToc}{O{1} O{\partialTocTitle} o o}{% 3 | \mdfapptodefinestyle{partialToc}{% 4 | backgroundcolor=light-gray% 5 | }% 6 | \colorlet{partialTocColor}{mainColor}% 7 | \marginElement{% 8 | \IfValueT{#3}{\vspace*{#3}}% 9 | \begin{mdframed}[style=partialToc]% 10 | \alignLeftOrRightStandaloneInversed{\fontspec{Fira Sans Book}\Large #2}% 11 | {\color{partialTocColor}\hfill\rule{\linewidth}{.5mm}}% 12 | \vspace*{-2mm}% 13 | \printcontents[content]{partial}{0}{\setcounter{tocdepth}{#1}\hypersetup{linkcolor=black}}% 14 | \end{mdframed}% 15 | \IfValueT{#4}{\vspace*{#4}}% 16 | }% 17 | }% 18 | 19 | % use the toc style which is used by yReport for sections, for chapters too 20 | \titlecontents{chapter}[0mm]% chapter style 21 | {\contentsmargin[4mm]{0mm}\fontspec{Fira Sans Book}\alignLeftOrRightStandaloneInversed}% 22 | {\isOddPage% 23 | {\makebox[3.5mm]{\color{partialTocColor}$\blacktriangleright$\hfill}}% 24 | {(p. \thecontentspage)}% 25 | \yTocSection}% 26 | {}{}[\vspace*{-1mm}]% 27 | 28 | \newcommand\setrow[1]{\gdef\rowmac{#1}#1\ignorespaces}% specify style of a tabularx row 29 | \newcommand\clearrow{\global\let\rowmac\relax}% clear tabularx row style to default 30 | \clearrow% 31 | \newcommand{\tabularxHeader}{% table header style for tabularx tables 32 | \rowcolor{mainColor}% 33 | \setrow{\bfseries\sffamily\leavevmode\color{white}}% 34 | }% 35 | \rowcolors{2}{tableLineTwo}{tableLineOne}% specify rowcolors in tabularx style 36 | \setlength{\extrarowheight}{1.5mm}% line separation between tabluarx rows 37 | 38 | \makeatletter% 39 | \DeclareDocumentCommand{\sideTabularx}{o m}{% 40 | \marginElement{% 41 | \strictpagechecktrue% 42 | \checkoddpage% 43 | \ifoddpage% 44 | \justifying\footnotesize% 45 | \else% 46 | \RaggedLeft\footnotesize% 47 | \fi% 48 | \@afterindentfalse\@afterheading% 49 | \vspace*{6mm} % compensate the table space added above the first line by the gape command 50 | #2% 51 | \captionsetup*[table]{font={footnotesize}}% 52 | \IfValueT{#1}{\captionof{table}{#1}}% 53 | }% 54 | }% 55 | \makeatother% 56 | 57 | % small modifications to yReports titleTwo command 58 | \makeatletter% 59 | \DeclareDocumentCommand{\titleThree}{o o}{% 60 | \updateDarkMainColor% 61 | \thispagestyle{empty}% 62 | \symmetricalPage% 63 | \null% 64 | \tikzset{% 65 | fitting node/.style={% 66 | inner sep=0pt,% 67 | fill=none,% 68 | draw=none,% 69 | reset transform,% 70 | fit={(\pgf@pathminx,\pgf@pathminy) (\pgf@pathmaxx,\pgf@pathmaxy)}% 71 | },% 72 | reset transform/.code={\pgftransformreset}% 73 | }% 74 | \begin{tikzpicture}[remember picture, overlay]% 75 | % some coordinates 76 | \coordinate[yshift=-\titlepageHeaderHeight](rectangleEnd) at (current page.north east);% 77 | \coordinate[xshift=-4cm](dateCenter) at (rectangleEnd);% 78 | 79 | % draw an image if one was provided 80 | \IfValueT{#1}{\draw (current page.center)[yshift=-\titlepageHeaderHeight/2] node[align=center, inner sep=0mm, anchor=center] {\IfValueTF{#2}{\includegraphics[#2]{#1}}{\includegraphics[height=\paperheight-\titlepageHeaderHeight]{#1}}};}% 81 | 82 | % red rectangle 83 | \fill[mainColor] (current page.north west) rectangle (rectangleEnd) node[fitting node] (headerRectangle) {};% 84 | 85 | % title page text (title rule and subtitle) 86 | % title 87 | \draw (\leftmargin-9mm, -3cm) node[align=left, inner sep=0mm, anchor=south west, font=\fontsize{1.4cm}{1.2cm}\selectfont\chapterFont] (title) {% 88 | \hspace*{-.8mm}\begin{varwidth}{\textwidth}% 89 | \FlushLeft% 90 | \noHyphen\runtitle% 91 | \end{varwidth}% 92 | };% 93 | % rule 94 | \getwidthofnode{\titlepageTitleLength}{title}% 95 | \node[inner xsep=0mm, text width=\titlepageTitleLength+2mm, anchor=north west, yshift=-2mm, xshift=-1mm] (rule) at (title.south west) {{\color{White}\rule{\linewidth}{.6mm}}};% 96 | % author 97 | \node[inner xsep=0mm, text width=\linewidth, anchor=north west, yshift=-2mm] (subtitle) at (rule.south west) { 98 | {\fontsize{.6cm}{.72cm}\selectfont\color{White}% 99 | \@subtitle}% \runauthor 100 | }; 101 | 102 | % Date 103 | \hexagon[mainColor]{dateCenter}{\dateRadius}% 104 | \hexagon[darkMainColor]{dateCenter}{\dateRadius}% 105 | \draw(dateCenter) node[text width=1.3cm, align=center] (day) {% 106 | \fontsize{1cm}{1.2cm}\selectfont\textbf{\twodigits{\the\day}}% 107 | };% 108 | \draw(dateCenter) node [node distance = .75cm, above of=day, text width=1.3cm, align=center](month) {\fontsize{.5cm}{1.2cm}\selectfont\textsc{\addfontfeatures{LetterSpace=10.0}\monthThreeLetterName}};% 109 | \draw(dateCenter) node[node distance = .65cm, below of=day, text width=1.3cm, align=center] (year) {\fontsize{.4cm}{1.2cm}\selectfont{\addfontfeatures{LetterSpace=20.0}\the\year} };% 110 | % author 111 | \node[anchor=south east] at ($(current page.south east)+(-6mm, 6mm)$) {\fontspec{Canter Light}\fontsize{10mm}{6mm}\color{White}\selectfont\@author};% 112 | \end{tikzpicture}% 113 | \null% 114 | \vfill% 115 | \newpage% 116 | \asymmetricalPage% 117 | } 118 | \makeatother% 119 | 120 | \titleformat{\chapter}[block]% 121 | {}% format 122 | {% label 123 | {\darkMainColor}% 124 | \backgroundThisPageColor% 125 | \begin{tikzpicture}[remember picture, overlay]% 126 | \tikzfading[name=monfading,left color=transparent!100,right color=transparent!0]% 127 | \isOddPage{% 128 | \coordinate[xshift=-\bigVerticalLineWidth/2, yshift=-5.8cm] (numberCenter) at (current page.north east);% 129 | }{% 130 | \coordinate[xshift=\bigVerticalLineWidth/2, yshift=-5.8cm] (numberCenter) at (current page.north west);% 131 | }% 132 | \hexagon[darkMainColor]{numberCenter}{\chapterNumberRadius}% 133 | \node[yshift=2mm] at (numberCenter) (chapterNumber) {% 134 | \chapterNumberFont% 135 | \fontsize{\chapterNumberRadius}{\chapterNumberRadius}% 136 | \selectfont% 137 | \thechapter% 138 | };% 139 | \node [below=1mm of chapterNumber, text=Black!80] {% 140 | \addfontfeatures{LetterSpace=20.0}% 141 | \fontsize{1.2em}{1.4em}\selectfont% 142 | \chaptertitlename% 143 | };% 144 | \end{tikzpicture}% 145 | }% 146 | {0pt}% sep 147 | {% code before 148 | \isOddPage{% 149 | \begin{FlushRight}% 150 | \vspace*{-1.5mm}% 151 | }{% 152 | \begin{FlushLeft}% 153 | \vspace*{-10mm}% 154 | }% 155 | \fontsize{1.8cm}{2.16cm}\chapterFont\selectfont% 156 | }[% code after 157 | \alignLeftOrRightEnd% 158 | ]% 159 | 160 | \hypersetup{% 161 | urlcolor=secondColor,% 162 | citecolor=secondColor,% 163 | linkcolor=secondColor% 164 | }% Set link color to secondary color 165 | \sisetup{mode = text}% Numbers and units from siunitx shall be displayed in normal text font 166 | 167 | % Configure imakeidx package and href command to automatically build a href list 168 | \makeindex[name=hrefs, title={References}, columns=1]% 169 | \indexsetup{level=\chapter}% 170 | \DeclareDocumentCommand{\hrefIdx}{m m}{% 171 | \href{#1}{#2} 172 | \index[hrefs]{ 173 | \protect{% 174 | #2:\newline\href{#1}{% 175 | \texttt{% 176 | \replace{\markletters{#1}}{_}{\_}% iterate over all characters and add an empty hskip to allow line breaks at every character and then replace _ (subscript) with \_ (_ character) 177 | }% 178 | }% 179 | }% 180 | }% 181 | }% 182 | 183 | % Little helper function to ensure number x with 0 <= x< 100 is always displayed with two digits (add a leading 0 if required) 184 | \newcommand\twodigits[1]{% 185 | \ifnum#1<10 0#1\else #1\fi% 186 | }% 187 | 188 | % makro to iterate a string char by char 189 | \def\xloop<#1#2>{% 190 | \ifx\relax#1% 191 | \else% 192 | #1\hskip0mm\xloop<#2>% 193 | \fi}% 194 | \def\markletters#1{\xloop<#1\relax>}% 195 | 196 | % Helper command for string replacements 197 | \ExplSyntaxOn% 198 | \NewDocumentCommand{\replace}{mmm}{% 199 | \marian_replace:nnn {#1} {#2} {#3}% 200 | }% 201 | \tl_new:N \l_marian_input_text_tl% 202 | \cs_new_protected:Npn \marian_replace:nnn #1 #2 #3 {% 203 | \tl_set:Nn \l_marian_input_text_tl { #1 }% 204 | \tl_replace_all:Nnn \l_marian_input_text_tl { #2 } { #3 }% 205 | \tl_use:N \l_marian_input_text_tl% 206 | }% 207 | \ExplSyntaxOff% 208 | 209 | % Format caption lables to use grey background on caption label and sideTitle format for caption itself 210 | \DeclareCaptionLabelFormat{yLabel}{% 211 | {\raisebox{-1mm}{\normalsize\tikz{\node[anchor=west, inner sep=1mm, fill=lightGrey, font=\bfseries, text=mainColor] {#1 #2};}}\vspace{1mm}}{~}% 212 | }% 213 | \DeclareCaptionLabelFormat{yLabelFigure}{% 214 | {\raisebox{-1.5mm}{\normalsize\tikz{\node[anchor=west, inner sep=1mm, fill=lightGrey, font=\bfseries, text=mainColor] {#1 #2};}}\vspace{1mm}}{~}% 215 | }% 216 | \DeclareCaptionStyle{yReportCaptionStyleFigure}{labelsep=none, labelformat=yLabelFigure, singlelinecheck=false}% 217 | \DeclareCaptionFormat{caption}{#1#2\lightBoldFont{#3}}% 218 | \captionsetup*[figure]{style=yReportCaptionStyleFigure, justification=RaggedRight, position=bottom, format=caption}% 219 | \captionsetup*[table]{style=yReportCaptionStyle, justification=RaggedRight, position=bottom, format=caption}% 220 | 221 | % Allow to set side captions with label 222 | \DeclareDocumentCommand{\sideCaptionOfL}{m m m}{\marginnote{\captionof{#1}{#2}\label{#3}}} -------------------------------------------------------------------------------- /Manual/Introduction.tex: -------------------------------------------------------------------------------- 1 | \chapter{Preface}% 2 | \label{c:preface}% 3 | A 3D scanner is a good addition to a 3D printer.% 4 | 5 | Before a detailed examination of the subject is performed, it is necessary to clarify what is the meaning of the term 3D scanning.% 6 | 7 | \blockQuote[\hrefIdx{https://en.wikipedia.org/wiki/3D\_scanning}{3D scanning --- Wikipedia}]{3D scanning is the process of analyzing a real-world object or environment to collect data on its shape and possibly its appearance (e.g. colour). The collected data can then be used to construct digital 3D models.}% 8 | 9 | 3D scanning can greatly simplify the process of making a printed copy of an object. For example, when a component is broken and a 3D printer should be used to make a replacement. Or if a physical object for which no 3D files are available should be modified.% 10 | 11 | While there are great 3D printers available for various budgets, the market for 3D scanners is not that big. At least the devices are not as common as 3D printers.% 12 | 13 | Similar to 3D printing there are several technological approaches for the realization of 3D scanners, which are connected with different efforts and costs and show differences in the quality of the results.% 14 | 15 | A particularly interesting approach for the average maker is photogrammetry. In photogrammetry a large number of photos from different viewing angles are taken from an object. Then a special software is used to create a 3D object from the images in a multi-stage process.\sideNote[white]{A great introduction to the photogrammetry pipeline, including references to scientific papers is provided by \hrefIdx{https://alicevision.org/\#photogrammetry}{AliceVision}.}% 16 | 17 | Depending on the number and quality (illumination, sharpness, resolution, camera distance to object, \dots) of the images, an accurate 3D model of the physical model can be created.\sideNote[white]{Further information on the factors which affect the quality of the final model are explained by \hrefIdx{https://www.photomodeler.com/kb/factors\_affecting\_accuracy\_in\_photogramm/}{Pho\-to\-Mod\-el\-er Technologies}.} Theoretically, results with an accuracy of \SI{0.1}{\milli\meter} can be achieved.% 18 | 19 | Since the cameras in smartphones (especially in high-end devices) are continuously being improved and nowadays deliver considerable quality, most people already have the most important tool for creating their own photogrammetry images.% 20 | 21 | The other important tool in the photogrammetry pipeline is the software that processes the captured images and calculates the 3D model. There are many different software solutions which have been developed for photogrammetry.\sideNote{An extensive list of software for photogrammetry, which highlights some features for each software, is provided by \hrefIdx{https://all3dp.com/1/best-photogrammetry-software/}{ALL3DP}.} Fortunately, there are also several open source projects in this list.% 22 | 23 | All that is missing is a computer (as powerful as possible) that runs the software. This shouldn't be a problem because most makers already have a home computer.% 24 | 25 | Thus for many makers all necessary tools are available to create 3D scans with photogrammetry. So the question arises why 3D scanning has such a low popularity compared to 3D printing. One possible answer to this question is that there is simply no need for it. Another possible answer is that the manual creation of the many photos that are needed will discourage most people because it is very time-consuming. Perhaps it is also because a 3D scanner is used much less often than a 3D printer, which is why one does not want to buy a 3D scanner, even if it is similarly inexpensive as a 3D printer.\sideNote{An overview of a large number of available 3D scanners and some of their features can be viewed at \hrefIdx{https://www.aniwaa.com/comparison/3d-scanners/}{ANIWAA}. The list contains photogrammetry devices as well as various other technologies, but it is possible to filter the displayed devices.}% 26 | 27 | For this reason the Open3DScanner project was started. The goal of the project is to provide the maker community with a 3D scanner that delivers 3D scans in good quality while keeping costs as low as possible by relying on existing tools such as smartphones and computers. It should be possible to implement the entire project for less than \SI[round-precision=2,round-mode=places,round-integer-to-decimal]{150}[\$], provided the necessary tools are available and the required parts can be procured without extreme (e.g. shipping) costs.% 28 | 29 | In its standard configuration, the Open3DScanner offers a scanning area that includes a cylinder with a diameter of approximately \SI{26}{\centi\meter} and a height of approximately \SI{16}{\centi\meter}. This restriction can easily be circumvented to a certain extent by configuring the scans accordingly. Detailed information can be found in chapter~\ref{c:performingScans}. All parts are designed to fit on the print bed of an original Prusa i3 to allow the use of a variety of 3D printers.% 30 | 31 | This document serves as a complete reference for the Open3DScanner project. It contains all the necessary information that makers need to build their own Open3DScanner, modify the 3D scanner, or simply get detailed information about the project.% 32 | 33 | Before a detailed examination of the Open3DScanner, chapter~\ref{c:rel_projects} introduces other open source 3D scanners and compares them with the Open3DScanner. Chapter~\ref{c:usedSoftware} describes the toolchain used to create and design the Open3DScanner and shows dependencies to other projects (e.g. software libraries). Chapter~\ref{c:bom} contains a BOM, which contains all parts needed to build the Open3DScanner. In addition, the required tools for building the scanner are listed and hardware required for operation is described. Chapter~\ref{c:build} then describes in detail all the steps necessary to build your own Open3DScanner from the individual components. Chapter~\ref{c:userGuide} contains a user manual which describes the use of the fully assembled Open3DScanner. Finally, chapter~\ref{c:performingScans} presents various tips and tricks that make it easier to create successful 3D scans using photogrammetry.% 34 | 35 | Thus, depending on the interests of the reader, not all chapters are equally interesting. However, the structure of the document should allow the chapters to be read individually and independently of each other. The necessary cross-references can be found in the necessary places.% 36 | 37 | There is no schedule for future development of this project. They are based on my needs and the needs of the Open3DScanner users.% 38 | 39 | The Open3DScanner has been published in various communities to reach a wider audience. The center of development and secure reference point for the latest version of the project is the {\faGithub} \hrefIdx{https://github.com/nazzrim/Open3DScanner}{Open3DScanner repository}.% -------------------------------------------------------------------------------- /Manual/Manual.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/Manual.pdf -------------------------------------------------------------------------------- /Manual/Manual.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper]{yReport}% 2 | 3 | \usepackage{fontawesome5}% Required by yAuthorBlock 4 | \usepackage{yAuthorBlock}% Used to create the author block on page 2 5 | \usepackage{tabularx}% Since tabu (used by yReport) is not behaving the expected way, use tabularx 6 | \usepackage[binary-units=true]{siunitx}% Used to display numbers and units in a proper way 7 | \usepackage{indextools}% Used to build a href list for printed documents 8 | \usepackage{xparse}% Required for string magic to display urls in index a proper way 9 | \usepackage{infoBulle}% Necessary to display the info/warn/... blocks in the main area 10 | \usepackage{marginInfoBulle}% Necessary to display the info/warn/... blocks in the margin area 11 | \usepackage[cleanlook, english, TeX]{isodate}% Used for uniform displaying dates. Required because of strange behaviour of datetime package (included in yReport) 12 | \usepackage{xurl}% Override url command do allow linebreaks everywhere 13 | \usepackage{hologo}% Used to disaplay logos from the latex family 14 | 15 | \definecolor{mainColor}{RGB}{39, 174, 96}% Main color used for decorations --> nephretis 16 | \definecolor{secondColor}{RGB}{142, 68, 173}% Secondary color used for e.g. links --> wisteria 17 | 18 | \newcommand{\urlCheckedOne}{\origdate\printdateTeX{2019/10/20}\TeXdate}% Date variables 19 | \newcommand{\releaseOne}{\printdateTeX{2019/10/20}}% 20 | \newcommand{\releaseTwo}{\printdateTeX{2019/10/26}}% 21 | 22 | \input{Commands}% This file contains 'messy' configuration which would make this file less readable 23 | 24 | \author{Nazrim}% 25 | \subtitle{Manual --- Rev. 1.1}% 26 | \title{Open3DScanner}% 27 | 28 | \hypersetup{% 29 | pdftitle={Open3DScanner},% 30 | pdfsubject={Manual --- Rev. 1.1},% 31 | pdfauthor={Nazrim},% 32 | pdfkeywords={{3D Scanner}{Open Source}{Open Hardware}{Photogrammetry}{Arduino}{ESP32}},% 33 | }% 34 | 35 | \makeatletter% 36 | \let\runauthor\@author% 37 | \let\runtitle\@title% 38 | \makeatother% 39 | 40 | \begin{document}% 41 | \startcontents[content]% Ensure function of Toc 42 | \titleThree[images/cover]% Build title page 43 | \chaptermark{License}% Create valid header on toc/license/author side 44 | \printMarginToc[1][Table of contents]% Print toc in margin 45 | 46 | \sideTabularx[History of this document]{% 47 | \begin{tabularx} {\marginparwidth} {>{\rowmac \hsize=.6\hsize}X>{\rowmac}X>{\rowmac \hsize=1.4\hsize}X<{\clearrow}}% 48 | \tabularxHeader% 49 | Version & Date & Note\\% 50 | 1.0 & \releaseOne & Initial release\\% 51 | 1.1 & \releaseTwo & Minior bugfixes\\% 52 | \end{tabularx}% 53 | }% 54 | 55 | \section*{License}% 56 | This document is licensed under the Creative Commons At\-tri\-bu\-tion-Share\-Alike 4.0 International License. To view a copy of this license, visit \url{https://creativecommons.org/licenses/by-sa/4.0/}.% 57 | 58 | \vfill% 59 | \authorBlock{% 60 | \authorName{Nazrim}% 61 | \authorWebsite{https://www.myminifactory.com/users/Nazrim}[\faCubes]% 62 | \authorWebsite{https://www.thingiverse.com/Nazrim}[\faCubes]% 63 | \authorWebsite{https://www.hackster.io/Nazrim}[\faCubes]% 64 | \authorWebsite{https://github.com/nazzrim}[\faGithub]% 65 | }% 66 | \include{Introduction}% 67 | \include{RelatedProjects} 68 | \include{References}% 69 | \include{Requirements}% 70 | \include{BuildInstructions}% 71 | \include{UserGuide}% 72 | \include{PerformingScans}% 73 | \appendix% start appendices 74 | \include{AppendixPCB} 75 | \indexprologue{% 76 | \label{ca:refs}% 77 | In case the document is available in printed form, this chapter contains all used links, which are provided with alternative display texts. This also allows these references to be followed.% 78 | 79 | The references are sorted alphabetically and not according to their appearance in the document.A few of the link texts are interpreted as special characters (e.g. \hologo{XeLaTeX}), so they do not appear at the expected position of the index, but at the beginning.% 80 | 81 | All links listed in this appendix were checked for validity on \urlCheckedOne.% 82 | }% 83 | \printindex[hrefs]% 84 | \end{document}% -------------------------------------------------------------------------------- /Manual/PerformingScans.tex: -------------------------------------------------------------------------------- 1 | \chapter{Perform Scans} 2 | \label{c:performingScans} 3 | Even though I am not an expert in the field of photogrammetry, I have gathered some experiences which I would like to share here. The recommendations given in this chapter do not claim to be universally valid and are based on my individual experiences.% 4 | 5 | \section{Lighting \& Surface}% 6 | A uniform illumination of the object to be scanned improves the quality of the scans significantly. In addition, glossy and transparent objects are much harder to scan compared to matte objects. For this reason, such objects should be treated (if possible) so that they have a better surface for the scanner. This can be done, for example, by spraying the objects with chalk spray.% 7 | 8 | \section{Camera Settings}% 9 | Most smartphone cameras have several features that automatically improve image quality. These range from autofocus and automatic white balance to AI functions that adjust color schemes based on recognized image content. Even if these functions provide better snapshots in everyday life, they are detrimental to the goals of photogrammetry. These functions make it more difficult to combine the images, which results in poorer scans.% 10 | 11 | For this reason, the functions should be deactivated as far as possible and photos should be taken with fixed settings. This is especially true for color temperature, auto white balance, and autofocus.% 12 | 13 | \section{Augmented Reconstruction}% 14 | Since the object to be scanned must be attached to the turntable, an area of the object is always not visible on the captured images. This means that a single scan is not sufficient to scan an object completely. This may not be a problem for objects that have a flat base on which they stand and when no texture is required for that area.% 15 | 16 | For many other objects this is a problem and multiple scans must be performed with different orientations of the object to capture the object from all sides.% 17 | 18 | At least the software Meshroom has the function augmented reconstruction for this case. It allows to add another data set (an additional scan) to an existing data set (the first scan) and to calculate a new overall result. This can repeated as often as needed and results in a tree like structure of the Meshroom processing graph.% 19 | 20 | That way it is often possible to create complete scans of objects. It may be necessary to filter some remaining artifacts of e.g. the Turntable of the reconstructed 3D model, but except from that you get a full scan and 3D model of the scanned object.% 21 | 22 | This feature can also be used if the reconstructed model lacks details in some areas. Just perform an additional (detailed) scan of the respective area and start an augmented reconstruction.% -------------------------------------------------------------------------------- /Manual/RelatedProjects.tex: -------------------------------------------------------------------------------- 1 | \chapter[Related OSS Projects]{Related OSS\\Projects}% 2 | \label{c:rel_projects}% 3 | This chapter looks at other projects from the open source software and open source hardware community which have the goal to develop their own 3D scanners\marginWarning[Important Notice]{It should be noted that the list of projects considered in this chapter does not claim to be exhaustive. In particular, there are various variations for the presented projects and the projects itself may already be a variation of an existing project.}. In some places comparisons to the Open3DScanner are given and influences that the projects have on the Open3DScanner are pointed out.% 4 | 5 | In the sections~\ref{s:open_scan} and~\ref{s:3dTurn} other photogrammetry scanners are introduced while in the remaining sections 3D scanners based on other technologies are introduced.% 6 | 7 | \section{OpenScan}% 8 | \label{s:open_scan}% 9 | First of all lets take a look at the project that had the biggest influence on the Open3DScanner, because it served as inspiration for it. The Open3DScanner is only an alternative realization of Thomas Megel's project:% 10 | 11 | \hrefIdx{https://www.openscan.eu/}{OpenScan}% 12 | \marginElement{\includegraphics[width=\linewidth]{images/OpenScan.png}\captionof{figure}{The OpenScan 3D Scanner}}% 13 | 14 | OpenScan is based on automatically rotating the object to be scanned on two axes (X and Z) while automatically shooting the photos.% 15 | 16 | The OpenScan project, like the Open3DScanner, relies on existing cameras that are connected to the scanner. One possibility that OpenScan offers, but was omitted from the Open3DScanner, is the usage of various SLR cameras for 3D scanning. The SLR camera is connected to the scanner via an infrared remote shutter which is connected to the scanner via an optocoupler. This option was removed for the Open3DScanner, because I don't own a SLR camera, nor do I plan to buy one. Furthermore, I am convinced that the quality of modern smartphone cameras is sufficient for the production of good quality 3D scans.% 17 | 18 | A feature of the Open3DScanner that OpenScan does not provide is the possibility to connect LED lights directly to the 3D scanner and let the hardware control them during the scanning process.% 19 | 20 | While there is no information about the applicable license on the project's homepage, the \hrefIdx{https://www.thingiverse.com/thing:3050437}{OpenScan Thingiverse project} indicates that the project is published under the CC-BY-NC 3.0 license.% 21 | 22 | Scans with the OpenScan 3D Scanner are performed fully automatically after the settings for the respective scan have been selected. It is possible to configure how many images are taken per rotation of the z-axis and by which angle the scanner should rotate on the x-axis. In addition, it is possible to determine at how many positions on the x-axis a stop should be made, which in turn results in a complete rotation of the z-axis.% 23 | 24 | In addition, there is a setting to adjust the time the scanner stops for each photo. This is important to ensure that the camera can refocus if necessary and avoid blurry shots.% 25 | 26 | \infoInfo{Note}{Although the Open3DScanner was developed on the basis of the OpenScan project, it is not a simple copy. After OpenScan motivated the development of the Open3DScanner, requirements were defined independently from the original project. All artifacts (3D models, firmware, BOM) were developed especially for the Open3DScanner.}% 27 | 28 | \section{3D Scanner Turntable}% 29 | \label{s:3dTurn}% 30 | Another open source photogrammetry 3D scanner is the project 3D Scanner Turntable by Dave Clarke.% 31 | 32 | \hrefIdx{https://www.hackster.io/daveclarke/3d-scanner-turntable-for-cell-phones-updated-64fdb8}{3D Scanner Turntable}% 33 | \marginElement{\includegraphics[width=\linewidth]{images/3DTurntable.png}\captionof{figure}{The 3D Scanner Turntable}} 34 | 35 | It relies on the use of a smartphone camera and promises that only the filament costs (\SI[round-precision=2,round-mode=places,round-integer-to-decimal]{30}[\$]) will be incurred for the construction of the 3D scanner. In addition to the smartphone, matching headphones with buttons that allow the camera to be released are required.% 36 | 37 | In order to achieve the goal of a 3D scanner that is as inexpensive as possible, the project does not use additional electronics that automate scanning. Instead, it is necessary for the user to turn a crank that rotates the object to be scanned and ensures that the smartphone takes 55 photos every full turn.% 38 | 39 | Unlike the Open3DScanner or the OpenScan, the object is only rotated on one axis during the scan, so it may be necessary to perform several scans and reposition the object each time. It is therefore necessary for the user to interact more strongly with the 3D scanner during use, but this is the only way to keep costs so low compared to other projects.% 40 | 41 | As with the OpenScan project, the captured images must then be processed with appropriate software in order to obtain a 3D model.% 42 | 43 | \section{Ciclop}% 44 | The Ciclop 3D Scanner is an ambitious project of Jesús Arroyo, published by bq and based on laser triangulation. In addition to the 3D scanner itself, the project also provides its own software (Windows, Linux, and Mac OS X) for performing the 3D scans.% 45 | 46 | \hrefIdx{http://diwo.bq.com/en/einfuhrung-ciclop-und-horus/}{Ciclop}% 47 | \marginElement{\includegraphics[width=\linewidth]{images/Ciclop.jpg}\captionof{figure}{The Ciclop 3D Scanner}}% 48 | 49 | Even though this project has no influence on the development of the Open3DScanner, it shall be introduced briefly here, as it is a wonderful open source hardware project for the creation of a 3D scanner, which provides detailed source information and documentation.% 50 | 51 | The result of a scan is a point cloud, which has to be converted into a 3D model with other software (e.g. \hrefIdx{https://www.blender.org/}{Blender}) before the model can be used further, e.g. for 3D printing.% 52 | 53 | The whole project is published under the CC-BY-SA 3.0 license as well as the GPL v2.% 54 | 55 | Unlike the previous projects, the Ciclop is not based on external hardware (like the camera of a smartphone), but is a complete project in itself, requiring only a PC for operation.% 56 | 57 | The core of the project is formed by a \hrefIdx{https://www.logitech.com/en-us/product/hd-webcam-c270}{Logitech C270 HD webcam} for creating the photos and two class 1 lasers, which are used to sample the object. The object to be scanned is positioned on a plate which is automatically rotated.% -------------------------------------------------------------------------------- /Manual/UserGuide.tex: -------------------------------------------------------------------------------- 1 | \chapter{User Guide} 2 | \label{c:userGuide} 3 | This chapter describes how to use the fully assembled Open3D scanner to create 3D scans. First, the menu navigation of the Open3DScanner is explained and then the handling of the hardware.% 4 | 5 | \section{Menu Navigation}% 6 | If the Open3DScanner is switched on, the user sees the main menu on the display. It contains three sub-items which lead to the menus described in the following sections. The navigation within the menu is done by the knob to the right of the display. If it is rotated, the cursor position changes or the currently selected value is changed. To confirm a selection, press the knob.% 7 | 8 | \subsection{Scan}% 9 | The user has two options for starting a scan: Using a preset or creating a custom scan.% 10 | 11 | The presets are predefined scan settings that allow a quick and easy start of the scan.% 12 | 13 | If a custom scan is selected, the user must successively specify a series of settings that define the characteristics of the subsequent scan. The selected values are persisted and selected as default values for the next custom scan. This is done under the assumption that similar scans are frequently performed.% 14 | 15 | First, the user must determine how many images are to be taken each time the turntable on which the object to be scanned is mounted is rotated. Any value between 1 and 3200 (inclusive) can be used. 3200 corresponds to the maximum resolution of the stepper motors at 200 steps per revolution and 1/16 microstepping.% 16 | 17 | The next step is to select how far the turntable and the object are to be rotated on the x-axis during the scan. Any value between 1 and 359 (incluseive) degrees can be selected\marginInfo[Reasonable Values]{Even if there is a large range of values for the user to choose from, it often makes little sense to rotate the object further than 180 degrees around the x-axis. I usually use values in the range of 45 and 135.}.% 18 | 19 | Finally, the number of steps in which the rotation on the x-axis is divided must be selected. Each step corresponds to a complete rotation of the turntable with the initially selected number of steps. The value range always starts at 1 and has a maximum value that corresponds to the maximum resolution of the stepper motor for the previously selected rotation around the x-axis.% 20 | 21 | After all these parameters have been selected, the user is presented with a summary containing all selected values, the resulting number of images and the duration of the scan. At this point the scan can either be confirmed or aborted. When a preset is selected, the summary is presented directly to the user.% 22 | 23 | Before the actual scan is started, it must be selected whether the lights of the Open3DScanner are to be switched on or off during the scan. The user is now prompted via the display to position the used smartphone appropriately and (if not already done) to establish a Bluetooth connection with the scanner. The scan cannot be started until the necessary Bluetooth connection has been established. As soon as this has been done, the Turntable can be moved to the desired start position and the scan can be started via the knob.% 24 | 25 | During scanning, the current progress is shown on the display. It shows the number of recorded images, their total number and the remaining time. If the Bluetooth connection to the smartphone is lost during the scan, the scan is interrupted and the user is prompted to re-establish the connection. If the knob is pressed during the scan, the scan can be aborted or resumed after confirmation.% 26 | 27 | \subsection{Settings}% 28 | The settings menu is divided into categories that group the individual settings.% 29 | 30 | \subsubsection{Scan}% 31 | In this setting menu, you can set how many milliseconds the scanner stops after a motor movement or after taking a photo. This is necessary to allow the camera to focus images, but also to prevent possible vibrations of the scanner from blurring the images.% 32 | 33 | \subsubsection{Display}% 34 | In addition to the option of switching the backlight for the display on or off, the contrast of the display can be adjusted here.% 35 | 36 | \subsubsection{Camera}% 37 | Here you can select which camera type will be used during the scan. This is important because the control of various devices is different. Currently iOs and Android devices are supported.% 38 | 39 | \subsubsection{Steppers}% 40 | This menu allows you to adjust the behavior of the stepper motors. The selected stepper motor moves 15° back and forth while the settings are adjusted. This makes changes directly visible.% 41 | 42 | The direction of movement of the motors can be changed if necessary. In addition, it can be determined with how many RPM the motor should move, what the acceleration and deceleration curve should look like, and which maximum values should be used for acceleration and deceleration.% 43 | 44 | \subsection{Debug}% 45 | The debug menu contains options to test some features of the Open3DScanner. Currently it is possible to switch the connected lights on and off and to trigger the camera. The system does not check whether a Bluetooth connection is actually present, so this must be checked in advance on the connected device.% 46 | 47 | \section{Hardware Handling}% 48 | This section contains some information about the built scanner and the interaction with the device.% 49 | 50 | \subsection{Object Mounting}% 51 | For the scan it is necessary to attach the object to be scanned to the Turntable. The holes in the Turntable allow to fix the object with cable ties. But this can lead to artefacts in the scan, so I prefer to use adhesive putty which can be reused many times.% 52 | 53 | \subsection{Scanner Adjustment}% 54 | Depending on the size of the object to be scanned, it may be useful to adjust the height of the lights or the turntable. The parts have been designed to allow this. This makes it possible to move the rotation center of the x-axis near the center of the object to be scanned.% 55 | 56 | Thus, depending on the object, it can be ensured that it is always in the field of view of the camera, which is important for the automatic creation of images.% 57 | 58 | \subsection{Status LED}% 59 | The Open3DScanner has a bi-color LED, which is used to indicate the state of the scanner. The different state are explained below.% 60 | 61 | \begin{table}[ht!]% 62 | \begin{centered}% 63 | \rowcolors{2}{tableLineTwo}{tableLineOne}% specify rowcolors in tabularx style 64 | \begin{tabularx} {\linewidth} {>{\rowmac \hsize=1\hsize}X>{\rowmac \hsize=1\hsize}X>{\rowmac \hsize=1\hsize}X<{\clearrow}}% 65 | \tabularxHeader% 66 | LED & State & Note\\% 67 | The LED lights green & Running & The scanner is turned on and ready for user interaction.\\% 68 | The LED lights yellow & Scanning & The scanner is performing a scan.\\% 69 | The LED flashes green very slowly & Scan finished & A scan has been finished successfully.\\% 70 | The LED flashes yellow slowly & Scan will continue & An interrupted scan will be continued soon.\\% 71 | The LED flashes red fast & No connection & The Bluetooth connection has been lost during scanning.\\% 72 | \end{tabularx}% 73 | \caption{Different states of the status LED}% 74 | \end{centered}% 75 | \end{table}% -------------------------------------------------------------------------------- /Manual/images/3DTurntable.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/3DTurntable.png -------------------------------------------------------------------------------- /Manual/images/Assembly1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly1.png -------------------------------------------------------------------------------- /Manual/images/Assembly10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly10.png -------------------------------------------------------------------------------- /Manual/images/Assembly11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly11.png -------------------------------------------------------------------------------- /Manual/images/Assembly12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly12.png -------------------------------------------------------------------------------- /Manual/images/Assembly13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly13.png -------------------------------------------------------------------------------- /Manual/images/Assembly14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly14.png -------------------------------------------------------------------------------- /Manual/images/Assembly15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly15.png -------------------------------------------------------------------------------- /Manual/images/Assembly16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly16.png -------------------------------------------------------------------------------- /Manual/images/Assembly17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly17.png -------------------------------------------------------------------------------- /Manual/images/Assembly18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly18.png -------------------------------------------------------------------------------- /Manual/images/Assembly2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly2.png -------------------------------------------------------------------------------- /Manual/images/Assembly3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly3.png -------------------------------------------------------------------------------- /Manual/images/Assembly4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly4.png -------------------------------------------------------------------------------- /Manual/images/Assembly5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly5.png -------------------------------------------------------------------------------- /Manual/images/Assembly6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly6.png -------------------------------------------------------------------------------- /Manual/images/Assembly7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly7.png -------------------------------------------------------------------------------- /Manual/images/Assembly8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly8.png -------------------------------------------------------------------------------- /Manual/images/Assembly9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Assembly9.png -------------------------------------------------------------------------------- /Manual/images/Breadboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Breadboard.jpg -------------------------------------------------------------------------------- /Manual/images/Ciclop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Ciclop.jpg -------------------------------------------------------------------------------- /Manual/images/DisplayCable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/DisplayCable.jpg -------------------------------------------------------------------------------- /Manual/images/DualColorLedCable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/DualColorLedCable.jpg -------------------------------------------------------------------------------- /Manual/images/EncoderCable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/EncoderCable.jpg -------------------------------------------------------------------------------- /Manual/images/HeatSink.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/HeatSink.jpg -------------------------------------------------------------------------------- /Manual/images/LCDAssistant.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/LCDAssistant.png -------------------------------------------------------------------------------- /Manual/images/LedStrip.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/LedStrip.jpg -------------------------------------------------------------------------------- /Manual/images/LedStripAssembly.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/LedStripAssembly.jpg -------------------------------------------------------------------------------- /Manual/images/LedStripCable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/LedStripCable.jpg -------------------------------------------------------------------------------- /Manual/images/LedStripGlue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/LedStripGlue.jpg -------------------------------------------------------------------------------- /Manual/images/OpenScan.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/OpenScan.png -------------------------------------------------------------------------------- /Manual/images/PCB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/PCB.png -------------------------------------------------------------------------------- /Manual/images/PcbSeries1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/PcbSeries1.jpg -------------------------------------------------------------------------------- /Manual/images/PcbSeries2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/PcbSeries2.jpg -------------------------------------------------------------------------------- /Manual/images/PcbSeries3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/PcbSeries3.jpg -------------------------------------------------------------------------------- /Manual/images/PcbSeries4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/PcbSeries4.jpg -------------------------------------------------------------------------------- /Manual/images/PcbSeries5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/PcbSeries5.jpg -------------------------------------------------------------------------------- /Manual/images/PcbSeries6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/PcbSeries6.jpg -------------------------------------------------------------------------------- /Manual/images/PcbSeries7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/PcbSeries7.jpg -------------------------------------------------------------------------------- /Manual/images/PinHeader.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/PinHeader.jpg -------------------------------------------------------------------------------- /Manual/images/PinSocket.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/PinSocket.jpg -------------------------------------------------------------------------------- /Manual/images/PowerCable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/PowerCable.jpg -------------------------------------------------------------------------------- /Manual/images/Render.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Render.png -------------------------------------------------------------------------------- /Manual/images/Schematic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Schematic.png -------------------------------------------------------------------------------- /Manual/images/Spur_gear_3d_scanner_gear.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/Spur_gear_3d_scanner_gear.png -------------------------------------------------------------------------------- /Manual/images/ThermalPaste.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/ThermalPaste.jpg -------------------------------------------------------------------------------- /Manual/images/UsbCable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/UsbCable.jpg -------------------------------------------------------------------------------- /Manual/images/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/cover.png -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly1.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly1.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly10.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly10.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly11.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly11.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly12.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly12.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly13.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly13.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly14.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly14.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly15.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly15.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly16.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly16.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly17.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly17.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly18.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly18.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly2.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly2.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly3.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly3.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly4.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly4.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly5.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly5.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly6.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly6.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly7.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly7.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly8.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly8.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/Assembly9.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/Assembly9.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/DisplayCable.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/DisplayCable.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/DualColorLedCable.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/DualColorLedCable.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/EncoderCable.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/EncoderCable.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/LedStripAssembly.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/LedStripAssembly.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/LedStripCable.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/LedStripCable.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/PowerCable.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/PowerCable.xcf -------------------------------------------------------------------------------- /Manual/images/gimp/UsbCable.xcf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/Manual/images/gimp/UsbCable.xcf -------------------------------------------------------------------------------- /PCB/3D Scanner.pro: -------------------------------------------------------------------------------- 1 | update=10/08/2019 00:38:29 2 | version=1 3 | last_client=kicad 4 | [general] 5 | version=1 6 | RootSch= 7 | BoardNm= 8 | [cvpcb] 9 | version=1 10 | NetIExt=net 11 | [eeschema] 12 | version=1 13 | LibDir= 14 | [eeschema/libraries] 15 | [pcbnew] 16 | version=1 17 | PageLayoutDescrFile= 18 | LastNetListRead= 19 | CopperLayerCount=2 20 | BoardThickness=1.6 21 | AllowMicroVias=0 22 | AllowBlindVias=0 23 | RequireCourtyardDefinitions=0 24 | ProhibitOverlappingCourtyards=1 25 | MinTrackWidth=0.25 26 | MinViaDiameter=0.4 27 | MinViaDrill=0.3 28 | MinMicroViaDiameter=0.2 29 | MinMicroViaDrill=0.09999999999999999 30 | MinHoleToHole=0.25 31 | TrackWidth1=0.25 32 | ViaDiameter1=0.8 33 | ViaDrill1=0.4 34 | dPairWidth1=0.25 35 | dPairGap1=0.25 36 | dPairViaGap1=0.25 37 | SilkLineWidth=0.12 38 | SilkTextSizeV=1 39 | SilkTextSizeH=1 40 | SilkTextSizeThickness=0.15 41 | SilkTextItalic=0 42 | SilkTextUpright=1 43 | CopperLineWidth=0.2 44 | CopperTextSizeV=1.5 45 | CopperTextSizeH=1.5 46 | CopperTextThickness=0.3 47 | CopperTextItalic=0 48 | CopperTextUpright=1 49 | EdgeCutLineWidth=0.05 50 | CourtyardLineWidth=0.05 51 | OthersLineWidth=0.15 52 | OthersTextSizeV=1 53 | OthersTextSizeH=1 54 | OthersTextSizeThickness=0.15 55 | OthersTextItalic=0 56 | OthersTextUpright=1 57 | SolderMaskClearance=0.051 58 | SolderMaskMinWidth=0.25 59 | SolderPasteClearance=0 60 | SolderPasteRatio=-0 61 | [pcbnew/Layer.F.Cu] 62 | Name=F.Cu 63 | Type=2 64 | Enabled=1 65 | [pcbnew/Layer.In1.Cu] 66 | Name=In1.Cu 67 | Type=0 68 | Enabled=0 69 | [pcbnew/Layer.In2.Cu] 70 | Name=In2.Cu 71 | Type=0 72 | Enabled=0 73 | [pcbnew/Layer.In3.Cu] 74 | Name=In3.Cu 75 | Type=0 76 | Enabled=0 77 | [pcbnew/Layer.In4.Cu] 78 | Name=In4.Cu 79 | Type=0 80 | Enabled=0 81 | [pcbnew/Layer.In5.Cu] 82 | Name=In5.Cu 83 | Type=0 84 | Enabled=0 85 | [pcbnew/Layer.In6.Cu] 86 | Name=In6.Cu 87 | Type=0 88 | Enabled=0 89 | [pcbnew/Layer.In7.Cu] 90 | Name=In7.Cu 91 | Type=0 92 | Enabled=0 93 | [pcbnew/Layer.In8.Cu] 94 | Name=In8.Cu 95 | Type=0 96 | Enabled=0 97 | [pcbnew/Layer.In9.Cu] 98 | Name=In9.Cu 99 | Type=0 100 | Enabled=0 101 | [pcbnew/Layer.In10.Cu] 102 | Name=In10.Cu 103 | Type=0 104 | Enabled=0 105 | [pcbnew/Layer.In11.Cu] 106 | Name=In11.Cu 107 | Type=0 108 | Enabled=0 109 | [pcbnew/Layer.In12.Cu] 110 | Name=In12.Cu 111 | Type=0 112 | Enabled=0 113 | [pcbnew/Layer.In13.Cu] 114 | Name=In13.Cu 115 | Type=0 116 | Enabled=0 117 | [pcbnew/Layer.In14.Cu] 118 | Name=In14.Cu 119 | Type=0 120 | Enabled=0 121 | [pcbnew/Layer.In15.Cu] 122 | Name=In15.Cu 123 | Type=0 124 | Enabled=0 125 | [pcbnew/Layer.In16.Cu] 126 | Name=In16.Cu 127 | Type=0 128 | Enabled=0 129 | [pcbnew/Layer.In17.Cu] 130 | Name=In17.Cu 131 | Type=0 132 | Enabled=0 133 | [pcbnew/Layer.In18.Cu] 134 | Name=In18.Cu 135 | Type=0 136 | Enabled=0 137 | [pcbnew/Layer.In19.Cu] 138 | Name=In19.Cu 139 | Type=0 140 | Enabled=0 141 | [pcbnew/Layer.In20.Cu] 142 | Name=In20.Cu 143 | Type=0 144 | Enabled=0 145 | [pcbnew/Layer.In21.Cu] 146 | Name=In21.Cu 147 | Type=0 148 | Enabled=0 149 | [pcbnew/Layer.In22.Cu] 150 | Name=In22.Cu 151 | Type=0 152 | Enabled=0 153 | [pcbnew/Layer.In23.Cu] 154 | Name=In23.Cu 155 | Type=0 156 | Enabled=0 157 | [pcbnew/Layer.In24.Cu] 158 | Name=In24.Cu 159 | Type=0 160 | Enabled=0 161 | [pcbnew/Layer.In25.Cu] 162 | Name=In25.Cu 163 | Type=0 164 | Enabled=0 165 | [pcbnew/Layer.In26.Cu] 166 | Name=In26.Cu 167 | Type=0 168 | Enabled=0 169 | [pcbnew/Layer.In27.Cu] 170 | Name=In27.Cu 171 | Type=0 172 | Enabled=0 173 | [pcbnew/Layer.In28.Cu] 174 | Name=In28.Cu 175 | Type=0 176 | Enabled=0 177 | [pcbnew/Layer.In29.Cu] 178 | Name=In29.Cu 179 | Type=0 180 | Enabled=0 181 | [pcbnew/Layer.In30.Cu] 182 | Name=In30.Cu 183 | Type=0 184 | Enabled=0 185 | [pcbnew/Layer.B.Cu] 186 | Name=B.Cu 187 | Type=2 188 | Enabled=1 189 | [pcbnew/Layer.B.Adhes] 190 | Enabled=1 191 | [pcbnew/Layer.F.Adhes] 192 | Enabled=1 193 | [pcbnew/Layer.B.Paste] 194 | Enabled=1 195 | [pcbnew/Layer.F.Paste] 196 | Enabled=1 197 | [pcbnew/Layer.B.SilkS] 198 | Enabled=1 199 | [pcbnew/Layer.F.SilkS] 200 | Enabled=1 201 | [pcbnew/Layer.B.Mask] 202 | Enabled=1 203 | [pcbnew/Layer.F.Mask] 204 | Enabled=1 205 | [pcbnew/Layer.Dwgs.User] 206 | Enabled=1 207 | [pcbnew/Layer.Cmts.User] 208 | Enabled=1 209 | [pcbnew/Layer.Eco1.User] 210 | Enabled=1 211 | [pcbnew/Layer.Eco2.User] 212 | Enabled=1 213 | [pcbnew/Layer.Edge.Cuts] 214 | Enabled=1 215 | [pcbnew/Layer.Margin] 216 | Enabled=1 217 | [pcbnew/Layer.B.CrtYd] 218 | Enabled=1 219 | [pcbnew/Layer.F.CrtYd] 220 | Enabled=1 221 | [pcbnew/Layer.B.Fab] 222 | Enabled=1 223 | [pcbnew/Layer.F.Fab] 224 | Enabled=1 225 | [pcbnew/Layer.Rescue] 226 | Enabled=0 227 | [pcbnew/Netclasses] 228 | [pcbnew/Netclasses/Default] 229 | Name=Default 230 | Clearance=0.25 231 | TrackWidth=0.25 232 | ViaDiameter=0.8 233 | ViaDrill=0.4 234 | uViaDiameter=0.3 235 | uViaDrill=0.1 236 | dPairWidth=0.25 237 | dPairGap=0.25 238 | dPairViaGap=0.25 239 | [pcbnew/Netclasses/1] 240 | Name=Power_12V 241 | Clearance=0.25 242 | TrackWidth=1.25 243 | ViaDiameter=0.8 244 | ViaDrill=0.4 245 | uViaDiameter=0.3 246 | uViaDrill=0.1 247 | dPairWidth=0.25 248 | dPairGap=0.25 249 | dPairViaGap=0.25 250 | [pcbnew/Netclasses/2] 251 | Name=Power_5V 252 | Clearance=0.25 253 | TrackWidth=0.75 254 | ViaDiameter=0.8 255 | ViaDrill=0.4 256 | uViaDiameter=0.3 257 | uViaDrill=0.1 258 | dPairWidth=0.25 259 | dPairGap=0.25 260 | dPairViaGap=0.25 261 | [schematic_editor] 262 | version=1 263 | PageLayoutDescrFile= 264 | PlotDirectoryName= 265 | SubpartIdSeparator=0 266 | SubpartFirstId=65 267 | NetFmtName= 268 | SpiceAjustPassiveValues=0 269 | LabSize=50 270 | ERC_TestSimilarLabels=1 271 | -------------------------------------------------------------------------------- /PCB/Footprints/Nazrim.bck: -------------------------------------------------------------------------------- 1 | EESchema-DOCLIB Version 2.0 2 | # 3 | $CMP AZDelivery-ESP32_NodeMCU 4 | K ESP32 5 | F https://cdn.shopify.com/s/files/1/1509/1638/files/ESP_-_32_NodeMCU_Developmentboard_Datenblatt_a3bf98d8-6a53-4d26-8f1c-c61b1c82af39.pdf?76837 6 | $ENDCMP 7 | # 8 | $CMP LM1084-5.0 9 | D 5A 27V Linear Regulator, Fixed Output 5.0V, TO-220/TO-263 10 | K Voltage Regulator 5A Positive 11 | F http://www.ti.com/lit/ds/symlink/lm1084.pdf 12 | $ENDCMP 13 | # 14 | $CMP LM1085-12 15 | D 3A 18V Linear Regulator, Fixed Output 12.0V, TO-220/TO-263 16 | K Voltage Regulator 5A Positive 17 | F http://www.ti.com/lit/ds/symlink/lm1085.pdf 18 | $ENDCMP 19 | # 20 | $CMP LM1085-3.3 21 | D 3A 27V Linear Regulator, Fixed Output 3.3V, TO-220/TO-263 22 | K Voltage Regulator Fixed 5A Positive 23 | F http://www.ti.com/lit/ds/symlink/lm1085.pdf 24 | $ENDCMP 25 | # 26 | $CMP LM1085-5.0 27 | D 3A 25V Linear Regulator, Fixed Output 5.0V, TO-220/TO-263 28 | K Voltage Regulator 5A Positive 29 | F http://www.ti.com/lit/ds/symlink/lm1085.pdf 30 | $ENDCMP 31 | # 32 | $CMP LT1083-12 33 | D 7.5A 25V LDO Linear Regulator, Fixed Output 12V, TO-220/TO-263 34 | K Voltage Regulator Fixed 7.5A Positive LDO 35 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1083ffe.pdf 36 | $ENDCMP 37 | # 38 | $CMP LT1083-3.3 39 | D 7.5A 20V LDO Linear Regulator, Fixed Output 3.3V, TO-220/TO-263 40 | K Voltage Regulator Fixed 7.5A Positive LDO 41 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1083ffe.pdf 42 | $ENDCMP 43 | # 44 | $CMP LT1083-3.6 45 | D 7.5A 20V LDO Linear Regulator, Fixed Output 3.6V, TO-220/TO-263 46 | K Voltage Regulator Fixed 7.5A Positive LDO 47 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1083ffe.pdf 48 | $ENDCMP 49 | # 50 | $CMP LT1083-5.0 51 | D 7.5A 20V LDO Linear Regulator, Fixed Output 5.V, TO-220/TO-263 52 | K Voltage Regulator Fixed 7.5A Positive LDO 53 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1083ffe.pdf 54 | $ENDCMP 55 | # 56 | $CMP LT1084-12 57 | D 5.0A 25V LDO Linear Regulator, Fixed Output 12V, TO-220/TO-263 58 | K Voltage Regulator Fixed 5.0A Positive LDO 59 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1083ffe.pdf 60 | $ENDCMP 61 | # 62 | $CMP LT1084-3.3 63 | D 5.0A 20V LDO Linear Regulator, Fixed Output 3.3V, TO-220/TO-263 64 | K Voltage Regulator Fixed 5.0A Positive LDO 65 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1083ffe.pdf 66 | $ENDCMP 67 | # 68 | $CMP LT1084-3.6 69 | D 5.0A 20V LDO Linear Regulator, Fixed Output 3.6V, TO-220/TO-263 70 | K Voltage Regulator Fixed 5.0A Positive LDO 71 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1083ffe.pdf 72 | $ENDCMP 73 | # 74 | $CMP LT1084-5.0 75 | D 5.0A 20V LDO Linear Regulator, Fixed Output 5.V, TO-220/TO-263 76 | K Voltage Regulator Fixed 5.0A Positive LDO 77 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1083ffe.pdf 78 | $ENDCMP 79 | # 80 | $CMP LT1085-12 81 | D 3.0A 25V LDO Linear Regulator, Fixed Output 12V, TO-220/TO-263 82 | K Voltage Regulator Fixed 3.0A Positive LDO 83 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1083ffe.pdf 84 | $ENDCMP 85 | # 86 | $CMP LT1085-3.3 87 | D 3.0A 20V LDO Linear Regulator, Fixed Output 3.3V, TO-220/TO-263 88 | K Voltage Regulator Fixed 3.0A Positive LDO 89 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1083ffe.pdf 90 | $ENDCMP 91 | # 92 | $CMP LT1085-3.6 93 | D 3.0A 20V LDO Linear Regulator, Fixed Output 3.6V, TO-220/TO-263 94 | K Voltage Regulator Fixed 3.0A Positive LDO 95 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1083ffe.pdf 96 | $ENDCMP 97 | # 98 | $CMP LT1085-5.0 99 | D 3.0A 20V LDO Linear Regulator, Fixed Output 5.V, TO-220/TO-263 100 | K Voltage Regulator Fixed 3.0A Positive LDO 101 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1083ffe.pdf 102 | $ENDCMP 103 | # 104 | $CMP LT1086-12 105 | D 1.5A 25V LDO Linear Regulator, Fixed Output 12V, TO-220/TO-263 106 | K Voltage Regulator Fixed 1.5A Positive LDO 107 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1086ffs.pdf 108 | $ENDCMP 109 | # 110 | $CMP LT1086-2.85 111 | D 1.5A 18V LDO Linear Regulator, Fixed Output 2.85V, TO-220/TO-263 112 | K Voltage Regulator Fixed 1.5A Positive LDO 113 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1086ffs.pdf 114 | $ENDCMP 115 | # 116 | $CMP LT1086-3.3 117 | D 1.5A 20V LDO Linear Regulator, Fixed Output 3.3V, TO-220/TO-263 118 | K Voltage Regulator Fixed 1.5A Positive LDO 119 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1086ffs.pdf 120 | $ENDCMP 121 | # 122 | $CMP LT1086-3.6 123 | D 1.5A 20V LDO Linear Regulator, Fixed Output 3.6V, TO-220/TO-263 124 | K Voltage Regulator Fixed 1.5A Positive LDO 125 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1086ffs.pdf 126 | $ENDCMP 127 | # 128 | $CMP LT1086-5.0 129 | D 1.5A 20V LDO Linear Regulator, Fixed Output 5.V, TO-220/TO-263 130 | K Voltage Regulator Fixed 1.5A Positive LDO 131 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1086ffs.pdf 132 | $ENDCMP 133 | # 134 | $CMP LT1086CT-5.0 135 | D 5A 27V Linear Regulator, Fixed Output 3.3V, TO-220/TO-263 136 | K Voltage Regulator Fixed 5A Positive 137 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1086ffs.pdf 138 | $ENDCMP 139 | # 140 | #End Doc Library 141 | -------------------------------------------------------------------------------- /PCB/Footprints/Nazrim.dcm: -------------------------------------------------------------------------------- 1 | EESchema-DOCLIB Version 2.0 2 | # 3 | $CMP A4988 4 | D Pololu Breakout Board, Stepper Driver A4988 5 | K Pololu Breakout Board Stepper Driver A4988 6 | F https://www.pololu.com/product/2980/pictures 7 | $ENDCMP 8 | # 9 | $CMP AZDelivery-ESP32_NodeMCU 10 | K ESP32 11 | F https://cdn.shopify.com/s/files/1/1509/1638/files/ESP_-_32_NodeMCU_Developmentboard_Datenblatt_a3bf98d8-6a53-4d26-8f1c-c61b1c82af39.pdf?76837 12 | $ENDCMP 13 | # 14 | $CMP LT1086CT-5 15 | F https://www.analog.com/media/en/technical-documentation/data-sheets/1086ffs.pdf 16 | $ENDCMP 17 | # 18 | $CMP Nokia5110-Display 19 | F http://www.sparkfun.com/datasheets/LCD/Monochrome/Nokia5110.pdf 20 | $ENDCMP 21 | # 22 | #End Doc Library 23 | -------------------------------------------------------------------------------- /PCB/Footprints/Nazrim.lib: -------------------------------------------------------------------------------- 1 | EESchema-LIBRARY Version 2.4 2 | #encoding utf-8 3 | # 4 | # A4988 5 | # 6 | DEF A4988 A 0 20 Y Y 1 F N 7 | F0 "A" -100 750 50 H V R CNN 8 | F1 "A4988" -100 650 50 H V R CNN 9 | F2 "Module:Pololu_Breakout-16_15.2x20.3mm" 275 -750 50 H I L CNN 10 | F3 "" 100 -300 50 H I C CNN 11 | $FPLIST 12 | Pololu*Breakout*15.2x20.3mm* 13 | $ENDFPLIST 14 | DRAW 15 | S 400 -700 -300 600 0 1 10 f 16 | X GND 1 0 -800 100 U 50 50 1 1 W 17 | X MS1 10 -400 -300 100 R 50 50 1 1 I 18 | X MS2 11 -400 -400 100 R 50 50 1 1 I 19 | X MS3 12 -400 -500 100 R 50 50 1 1 I 20 | X ~RESET 13 -400 400 100 R 50 50 1 1 B 21 | X ~SLEEP 14 -400 300 100 R 50 50 1 1 B 22 | X STEP 15 -400 0 100 R 50 50 1 1 I 23 | X DIR 16 -400 -100 100 R 50 50 1 1 I 24 | X VDD 2 0 700 100 D 50 50 1 1 W 25 | X 1B 3 500 100 100 L 50 50 1 1 O 26 | X 1A 4 500 0 100 L 50 50 1 1 O 27 | X 2A 5 500 -100 100 L 50 50 1 1 O 28 | X 2B 6 500 -200 100 L 50 50 1 1 O 29 | X GND 7 200 -800 100 U 50 50 1 1 W 30 | X VMOT 8 200 700 100 D 50 50 1 1 W 31 | X ~ENABLE 9 -400 100 100 R 50 50 1 1 I 32 | ENDDRAW 33 | ENDDEF 34 | # 35 | # AZDelivery-ESP32_NodeMCU 36 | # 37 | DEF AZDelivery-ESP32_NodeMCU A 0 40 Y Y 1 F N 38 | F0 "A" 0 0 50 H V C CNN 39 | F1 "AZDelivery-ESP32_NodeMCU" 0 -100 50 H V C CNN 40 | F2 "" 0 0 50 H I C CNN 41 | F3 "" 0 0 50 H I C CNN 42 | DRAW 43 | S -600 50 600 1950 0 1 0 f 44 | X CLK 1 -700 1900 100 R 50 50 1 1 O 45 | X G5 10 -700 1000 100 R 50 50 1 1 B 46 | X G18 11 -700 900 100 R 50 50 1 1 B 47 | X G19 12 -700 800 100 R 50 50 1 1 B 48 | X GND 13 -700 700 100 R 50 50 1 1 O 49 | X G21 14 -700 600 100 R 50 50 1 1 B 50 | X RXD 15 -700 500 100 R 50 50 1 1 O 51 | X TXD 16 -700 400 100 R 50 50 1 1 O 52 | X G22 17 -700 300 100 R 50 50 1 1 B 53 | X G23 18 -700 200 100 R 50 50 1 1 B 54 | X GND 19 -700 100 100 R 50 50 1 1 w 55 | X SD0 2 -700 1800 100 R 50 50 1 1 O 56 | X 5V 20 700 1900 100 L 50 50 1 1 w 57 | X GND 21 700 1800 100 L 50 50 1 1 w 58 | X SD3 22 700 1700 100 L 50 50 1 1 O 59 | X SD2 23 700 1600 100 L 50 50 1 1 O 60 | X G13 24 700 1500 100 L 50 50 1 1 B 61 | X GND 25 700 1400 100 L 50 50 1 1 O 62 | X G12 26 700 1300 100 L 50 50 1 1 B 63 | X G14 27 700 1200 100 L 50 50 1 1 B 64 | X G27 28 700 1100 100 L 50 50 1 1 B 65 | X G26 29 700 1000 100 L 50 50 1 1 B 66 | X SD1 3 -700 1700 100 R 50 50 1 1 O 67 | X G25 30 700 900 100 L 50 50 1 1 B 68 | X G33 31 700 800 100 L 50 50 1 1 B 69 | X G32 32 700 700 100 L 50 50 1 1 B 70 | X G35 33 700 600 100 L 50 50 1 1 I 71 | X G34 34 700 500 100 L 50 50 1 1 I 72 | X SN 35 700 400 100 L 50 50 1 1 O 73 | X SP 36 700 300 100 L 50 50 1 1 O 74 | X EN 37 700 200 100 L 50 50 1 1 I 75 | X 3V3 38 700 100 100 L 50 50 1 1 w 76 | X G15 4 -700 1600 100 R 50 50 1 1 B 77 | X G2 5 -700 1500 100 R 50 50 1 1 B 78 | X G0 6 -700 1400 100 R 50 50 1 1 B 79 | X G4 7 -700 1300 100 R 50 50 1 1 B 80 | X G16 8 -700 1200 100 R 50 50 1 1 B 81 | X G17 9 -700 1100 100 R 50 50 1 1 B 82 | ENDDRAW 83 | ENDDEF 84 | # 85 | # LT1086CT-5 86 | # 87 | DEF LT1086CT-5 U 0 40 Y Y 1 F N 88 | F0 "U" -150 150 50 H V C CNN 89 | F1 "LT1086CT-5" 250 150 50 H V C CNN 90 | F2 "" -150 150 50 H I C CNN 91 | F3 "" -150 150 50 H I C CNN 92 | DRAW 93 | S -200 100 200 -200 0 1 0 f 94 | X GND 1 0 -300 100 U 50 50 1 1 W 95 | X VO 2 300 0 100 L 50 50 1 1 w 96 | X VI 3 -300 0 100 R 50 50 1 1 W 97 | ENDDRAW 98 | ENDDEF 99 | # 100 | # Nokia5110-Display 101 | # 102 | DEF Nokia5110-Display DS 0 40 Y Y 1 F N 103 | F0 "DS" 0 0 50 H V C CNN 104 | F1 "Nokia5110-Display" 0 -100 50 H V C CNN 105 | F2 "" 0 0 50 H I C CNN 106 | F3 "" 0 0 50 H I C CNN 107 | DRAW 108 | S -400 -150 400 -550 0 1 0 f 109 | X RST 1 -500 -200 100 R 50 50 1 1 I 110 | X CLK 2 -500 -300 100 R 50 50 1 1 I 111 | X DC 3 -500 -400 100 R 50 50 1 1 I 112 | X Din 4 -500 -500 100 R 50 50 1 1 I 113 | X Clk 5 500 -200 100 L 50 50 1 1 I 114 | X Vcc 6 500 -300 100 L 50 50 1 1 W 115 | X BL 7 500 -400 100 L 50 50 1 1 I 116 | X Gnd 8 500 -500 100 L 50 50 1 1 W 117 | ENDDRAW 118 | ENDDEF 119 | # 120 | #End Library 121 | -------------------------------------------------------------------------------- /PCB/Footprints/Nazrim.pretty/A4988.kicad_mod: -------------------------------------------------------------------------------- 1 | (module A4988 (layer F.Cu) (tedit 5D4E1C2C) 2 | (descr "Pololu Breakout 16-pin 15.2x20.3mm 0.6x0.8\\") 3 | (tags "Pololu Breakout") 4 | (fp_text reference REF** (at 6.35 -2.54) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value A4988 (at 6.35 20.17) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_text user %R (at 6.35 0) (layer F.Fab) 11 | (effects (font (size 1 1) (thickness 0.15))) 12 | ) 13 | (fp_line (start 11.43 -1.4) (end 11.43 19.18) (layer F.SilkS) (width 0.12)) 14 | (fp_line (start 1.27 1.27) (end 1.27 19.18) (layer F.SilkS) (width 0.12)) 15 | (fp_line (start 0 -1.4) (end -1.4 -1.4) (layer F.SilkS) (width 0.12)) 16 | (fp_line (start -1.4 -1.4) (end -1.4 0) (layer F.SilkS) (width 0.12)) 17 | (fp_line (start 1.27 -1.4) (end 1.27 1.27) (layer F.SilkS) (width 0.12)) 18 | (fp_line (start 1.27 1.27) (end -1.4 1.27) (layer F.SilkS) (width 0.12)) 19 | (fp_line (start -1.4 1.27) (end -1.4 19.18) (layer F.SilkS) (width 0.12)) 20 | (fp_line (start -1.4 19.18) (end 14.1 19.18) (layer F.SilkS) (width 0.12)) 21 | (fp_line (start 14.1 19.18) (end 14.1 -1.4) (layer F.SilkS) (width 0.12)) 22 | (fp_line (start 14.1 -1.4) (end 1.27 -1.4) (layer F.SilkS) (width 0.12)) 23 | (fp_line (start -1.27 0) (end 0 -1.27) (layer F.Fab) (width 0.1)) 24 | (fp_line (start 0 -1.27) (end 13.97 -1.27) (layer F.Fab) (width 0.1)) 25 | (fp_line (start 13.97 -1.27) (end 13.97 19.05) (layer F.Fab) (width 0.1)) 26 | (fp_line (start 13.97 19.05) (end -1.27 19.05) (layer F.Fab) (width 0.1)) 27 | (fp_line (start -1.27 19.05) (end -1.27 0) (layer F.Fab) (width 0.1)) 28 | (fp_line (start -1.53 -1.52) (end 14.21 -1.52) (layer F.CrtYd) (width 0.05)) 29 | (fp_line (start -1.53 -1.52) (end -1.53 19.3) (layer F.CrtYd) (width 0.05)) 30 | (fp_line (start 14.21 19.3) (end 14.21 -1.52) (layer F.CrtYd) (width 0.05)) 31 | (fp_line (start 14.21 19.3) (end -1.53 19.3) (layer F.CrtYd) (width 0.05)) 32 | (pad 1 thru_hole rect (at 0 0) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 33 | (pad 9 thru_hole oval (at 12.7 17.78) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 34 | (pad 2 thru_hole oval (at 0 2.54) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 35 | (pad 10 thru_hole oval (at 12.7 15.24) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 36 | (pad 3 thru_hole oval (at 0 5.08) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 37 | (pad 11 thru_hole oval (at 12.7 12.7) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 38 | (pad 4 thru_hole oval (at 0 7.62) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 39 | (pad 12 thru_hole oval (at 12.7 10.16) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 40 | (pad 5 thru_hole oval (at 0 10.16) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 41 | (pad 13 thru_hole oval (at 12.7 7.62) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 42 | (pad 6 thru_hole oval (at 0 12.7) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 43 | (pad 14 thru_hole oval (at 12.7 5.08) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 44 | (pad 7 thru_hole oval (at 0 15.24) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 45 | (pad 15 thru_hole oval (at 12.7 2.54) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 46 | (pad 8 thru_hole oval (at 0 17.78) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 47 | (pad 16 thru_hole oval (at 12.7 0) (size 1.6 1.6) (drill 0.8) (layers *.Cu *.Mask)) 48 | (model ${KISYS3DMOD}/Connector_PinSocket_2.54mm.3dshapes/PinSocket_1x08_P2.54mm_Vertical.wrl 49 | (at (xyz 0 0 0)) 50 | (scale (xyz 1 1 1)) 51 | (rotate (xyz 0 0 0)) 52 | ) 53 | (model ${KISYS3DMOD}/Connector_PinSocket_2.54mm.3dshapes/PinSocket_1x08_P2.54mm_Vertical.wrl 54 | (offset (xyz 12.7 0 0)) 55 | (scale (xyz 1 1 1)) 56 | (rotate (xyz 0 0 0)) 57 | ) 58 | (model ${KISYS3DMOD}/Connector_PinHeader_2.54mm.3dshapes/PinHeader_1x08_P2.54mm_Vertical.wrl 59 | (offset (xyz 0 0 9.699999999999999)) 60 | (scale (xyz 1 1 1)) 61 | (rotate (xyz 0 180 0)) 62 | ) 63 | (model ${KISYS3DMOD}/Connector_PinHeader_2.54mm.3dshapes/PinHeader_1x08_P2.54mm_Vertical.wrl 64 | (offset (xyz 12.7 0 9.699999999999999)) 65 | (scale (xyz 1 1 1)) 66 | (rotate (xyz 0 180 0)) 67 | ) 68 | (model "${KIPRJMOD}/3D Models/a4988-stepper-motor-driver-carrier.step" 69 | (offset (xyz 13.9 1.3 10)) 70 | (scale (xyz 1 1 1)) 71 | (rotate (xyz 0 0 180)) 72 | ) 73 | ) 74 | -------------------------------------------------------------------------------- /PCB/Footprints/Nazrim.pretty/AZDelivery-ESP32_NodeMCU.kicad_mod: -------------------------------------------------------------------------------- 1 | (module AZDelivery-ESP32_NodeMCU (layer F.Cu) (tedit 5D4E7F5D) 2 | (descr "Through hole straight pin header, 1x19, 2.54mm pitch, single row") 3 | (tags "Through hole pin header THT 1x19 2.54mm single row") 4 | (fp_text reference REF** (at 12.7 5.08) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value AZDelivery-ESP32_NodeMCU (at 12.7 49.53) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start -1.27 50.8) (end 26.67 50.8) (layer F.SilkS) (width 0.12)) 11 | (fp_line (start 26.67 50.8) (end 26.67 -5.08) (layer F.SilkS) (width 0.12)) 12 | (fp_line (start 26.67 -5.08) (end -1.27 -5.08) (layer F.SilkS) (width 0.12)) 13 | (fp_text user USB_PWR_IN (at 12.7 -3.81) (layer F.SilkS) 14 | (effects (font (size 1 1) (thickness 0.15))) 15 | ) 16 | (fp_line (start 1.27 -0.635) (end 1.27 46.99) (layer F.Fab) (width 0.1)) 17 | (fp_line (start -1.8 -1.8) (end 1.75 -1.8) (layer F.CrtYd) (width 0.05)) 18 | (fp_line (start 0 -1.33) (end 1.33 -1.33) (layer F.SilkS) (width 0.12)) 19 | (fp_line (start 0.635 -1.27) (end 1.27 -0.635) (layer F.Fab) (width 0.1)) 20 | (fp_line (start 1.75 -1.8) (end 1.75 47.5) (layer F.CrtYd) (width 0.05)) 21 | (fp_line (start 1.33 -1.33) (end 1.33 0) (layer F.SilkS) (width 0.12)) 22 | (fp_line (start -1.33 1.27) (end -1.33 47.05) (layer F.SilkS) (width 0.12)) 23 | (fp_line (start 1.27 46.99) (end -1.27 46.99) (layer F.Fab) (width 0.1)) 24 | (fp_line (start -1.33 47.05) (end 1.33 47.05) (layer F.SilkS) (width 0.12)) 25 | (fp_line (start -1.33 1.27) (end 1.33 1.27) (layer F.SilkS) (width 0.12)) 26 | (fp_line (start -1.27 46.99) (end -1.27 -1.27) (layer F.Fab) (width 0.1)) 27 | (fp_line (start -1.27 -1.27) (end 0.635 -1.27) (layer F.Fab) (width 0.1)) 28 | (fp_line (start -1.8 47.5) (end -1.8 -1.8) (layer F.CrtYd) (width 0.05)) 29 | (fp_line (start 1.75 47.5) (end -1.8 47.5) (layer F.CrtYd) (width 0.05)) 30 | (fp_line (start 1.33 1.27) (end 1.33 47.05) (layer F.SilkS) (width 0.12)) 31 | (fp_text user %R (at 0 22.86 90) (layer F.Fab) 32 | (effects (font (size 1 1) (thickness 0.15))) 33 | ) 34 | (fp_line (start -1.27 -5.08) (end -1.27 50.8) (layer F.SilkS) (width 0.12)) 35 | (fp_line (start 26.67 -0.635) (end 26.67 46.99) (layer F.Fab) (width 0.1)) 36 | (fp_line (start 23.6 -1.8) (end 27.15 -1.8) (layer F.CrtYd) (width 0.05)) 37 | (fp_line (start 25.4 -1.33) (end 26.73 -1.33) (layer F.SilkS) (width 0.12)) 38 | (fp_line (start 26.035 -1.27) (end 26.67 -0.635) (layer F.Fab) (width 0.1)) 39 | (fp_line (start 27.15 -1.8) (end 27.15 47.5) (layer F.CrtYd) (width 0.05)) 40 | (fp_line (start 26.73 -1.33) (end 26.73 0) (layer F.SilkS) (width 0.12)) 41 | (fp_line (start 24.07 1.27) (end 24.07 47.05) (layer F.SilkS) (width 0.12)) 42 | (fp_line (start 26.67 46.99) (end 24.13 46.99) (layer F.Fab) (width 0.1)) 43 | (fp_line (start 24.07 47.05) (end 26.73 47.05) (layer F.SilkS) (width 0.12)) 44 | (fp_line (start 24.07 1.27) (end 26.73 1.27) (layer F.SilkS) (width 0.12)) 45 | (fp_line (start 24.13 46.99) (end 24.13 -1.27) (layer F.Fab) (width 0.1)) 46 | (fp_line (start 24.13 -1.27) (end 26.035 -1.27) (layer F.Fab) (width 0.1)) 47 | (fp_line (start 23.6 47.5) (end 23.6 -1.8) (layer F.CrtYd) (width 0.05)) 48 | (fp_line (start 27.15 47.5) (end 23.6 47.5) (layer F.CrtYd) (width 0.05)) 49 | (fp_line (start 26.73 1.27) (end 26.73 47.05) (layer F.SilkS) (width 0.12)) 50 | (fp_text user %R (at 25.4 22.86 90) (layer F.Fab) 51 | (effects (font (size 1 1) (thickness 0.15))) 52 | ) 53 | (pad 9 thru_hole oval (at 0 20.32) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 54 | (pad 14 thru_hole oval (at 0 33.02) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 55 | (pad 4 thru_hole oval (at 0 7.62) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 56 | (pad 11 thru_hole oval (at 0 25.4) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 57 | (pad 2 thru_hole oval (at 0 2.54) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 58 | (pad 7 thru_hole oval (at 0 15.24) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 59 | (pad 19 thru_hole oval (at 0 45.72) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 60 | (pad 18 thru_hole oval (at 0 43.18) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 61 | (pad 17 thru_hole oval (at 0 40.64) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 62 | (pad 5 thru_hole oval (at 0 10.16) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 63 | (pad 3 thru_hole oval (at 0 5.08) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 64 | (pad 1 thru_hole rect (at 0 0) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 65 | (pad 16 thru_hole oval (at 0 38.1) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 66 | (pad 6 thru_hole oval (at 0 12.7) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 67 | (pad 13 thru_hole oval (at 0 30.48) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 68 | (pad 8 thru_hole oval (at 0 17.78) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 69 | (pad 10 thru_hole oval (at 0 22.86) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 70 | (pad 15 thru_hole oval (at 0 35.56) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 71 | (pad 12 thru_hole oval (at 0 27.94) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 72 | (pad 28 thru_hole oval (at 25.4 20.32) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 73 | (pad 33 thru_hole oval (at 25.4 33.02) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 74 | (pad 23 thru_hole oval (at 25.4 7.62) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 75 | (pad 30 thru_hole oval (at 25.4 25.4) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 76 | (pad 21 thru_hole oval (at 25.4 2.54) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 77 | (pad 26 thru_hole oval (at 25.4 15.24) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 78 | (pad 38 thru_hole oval (at 25.4 45.72) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 79 | (pad 37 thru_hole oval (at 25.4 43.18) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 80 | (pad 36 thru_hole oval (at 25.4 40.64) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 81 | (pad 24 thru_hole oval (at 25.4 10.16) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 82 | (pad 22 thru_hole oval (at 25.4 5.08) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 83 | (pad 20 thru_hole rect (at 25.4 0) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 84 | (pad 35 thru_hole oval (at 25.4 38.1) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 85 | (pad 25 thru_hole oval (at 25.4 12.7) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 86 | (pad 32 thru_hole oval (at 25.4 30.48) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 87 | (pad 27 thru_hole oval (at 25.4 17.78) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 88 | (pad 29 thru_hole oval (at 25.4 22.86) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 89 | (pad 34 thru_hole oval (at 25.4 35.56) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 90 | (pad 31 thru_hole oval (at 25.4 27.94) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 91 | (model ${KISYS3DMOD}/Connector_PinSocket_2.54mm.3dshapes/PinSocket_1x19_P2.54mm_Vertical.wrl 92 | (at (xyz 0 0 0)) 93 | (scale (xyz 1 1 1)) 94 | (rotate (xyz 0 0 0)) 95 | ) 96 | (model ${KISYS3DMOD}/Connector_PinSocket_2.54mm.3dshapes/PinSocket_1x19_P2.54mm_Vertical.wrl 97 | (offset (xyz 25.4 0 0)) 98 | (scale (xyz 1 1 1)) 99 | (rotate (xyz 0 0 0)) 100 | ) 101 | (model "${KIPRJMOD}/3D Models/ESP32-DEVKITC-32D--3DModel-STEP-56544.STEP" 102 | (offset (xyz 12.7 -22.75 10.5)) 103 | (scale (xyz 1 1 1)) 104 | (rotate (xyz -90 0 180)) 105 | ) 106 | ) 107 | -------------------------------------------------------------------------------- /PCB/Footprints/Nazrim.pretty/Rotary_Encoder_Switch.kicad_mod: -------------------------------------------------------------------------------- 1 | (module Rotary_Encoder_Switch (layer F.Cu) (tedit 5D3B73EA) 2 | (descr "Through hole straight pin header, 1x05, 2.54mm pitch, single row") 3 | (tags "Through hole pin header THT 1x05 2.54mm single row") 4 | (fp_text reference REF** (at 0 -2.54) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value Rotary_Encoder_Switch (at 0 12.7) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start 1.27 -1.27) (end 1.27 11.43) (layer F.Fab) (width 0.1)) 11 | (fp_line (start -1.33 -1.33) (end 0 -1.33) (layer F.SilkS) (width 0.12)) 12 | (fp_line (start 1.8 11.95) (end 1.8 -1.8) (layer F.CrtYd) (width 0.05)) 13 | (fp_line (start -1.27 -0.635) (end -0.635 -1.27) (layer F.Fab) (width 0.1)) 14 | (fp_line (start -1.33 0) (end -1.33 -1.33) (layer F.SilkS) (width 0.12)) 15 | (fp_line (start -0.635 -1.27) (end 1.27 -1.27) (layer F.Fab) (width 0.1)) 16 | (fp_line (start 1.8 -1.8) (end -1.8 -1.8) (layer F.CrtYd) (width 0.05)) 17 | (fp_line (start -1.33 1.27) (end 1.33 1.27) (layer F.SilkS) (width 0.12)) 18 | (fp_line (start -1.33 11.49) (end 1.33 11.49) (layer F.SilkS) (width 0.12)) 19 | (fp_line (start 1.33 1.27) (end 1.33 11.49) (layer F.SilkS) (width 0.12)) 20 | (fp_line (start 1.27 11.43) (end -1.27 11.43) (layer F.Fab) (width 0.1)) 21 | (fp_line (start -1.8 -1.8) (end -1.8 11.95) (layer F.CrtYd) (width 0.05)) 22 | (fp_line (start -1.27 11.43) (end -1.27 -0.635) (layer F.Fab) (width 0.1)) 23 | (fp_line (start -1.8 11.95) (end 1.8 11.95) (layer F.CrtYd) (width 0.05)) 24 | (fp_line (start -1.33 1.27) (end -1.33 11.49) (layer F.SilkS) (width 0.12)) 25 | (fp_text user %R (at 0 5.08 90) (layer F.Fab) 26 | (effects (font (size 1 1) (thickness 0.15))) 27 | ) 28 | (pad A thru_hole rect (at 0 0) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 29 | (pad C thru_hole oval (at 0 5.08) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 30 | (pad S2 thru_hole oval (at 0 10.16) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 31 | (pad S1 thru_hole oval (at 0 7.62) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 32 | (pad B thru_hole oval (at 0 2.54) (size 1.7 1.7) (drill 1) (layers *.Cu *.Mask)) 33 | (model ${KISYS3DMOD}/Connector_PinHeader_2.54mm.3dshapes/PinHeader_1x05_P2.54mm_Vertical.wrl 34 | (at (xyz 0 0 0)) 35 | (scale (xyz 1 1 1)) 36 | (rotate (xyz 0 0 0)) 37 | ) 38 | ) 39 | -------------------------------------------------------------------------------- /PCB/Footprints/Nazrim.pretty/TO-220-3_Vertical_Cooler.kicad_mod: -------------------------------------------------------------------------------- 1 | (module TO-220-3_Vertical_Cooler (layer F.Cu) (tedit 5D4E806B) 2 | (descr "TO-220-3, Vertical, RM 2.54mm, see https://www.vishay.com/docs/66542/to-220-1.pdf") 3 | (tags "TO-220-3 Vertical RM 2.54mm") 4 | (fp_text reference REF** (at 2.54 -4.27) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value TO-220-3_Vertical_Cooler (at 2.54 2.5) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_line (start -2.46 -3.15) (end -2.46 1.25) (layer F.Fab) (width 0.1)) 11 | (fp_line (start -2.46 1.25) (end 7.54 1.25) (layer F.Fab) (width 0.1)) 12 | (fp_line (start 7.54 1.25) (end 7.54 -3.15) (layer F.Fab) (width 0.1)) 13 | (fp_line (start 7.54 -3.15) (end -2.46 -3.15) (layer F.Fab) (width 0.1)) 14 | (fp_line (start -2.46 -1.88) (end 7.54 -1.88) (layer F.Fab) (width 0.1)) 15 | (fp_line (start 0.69 -3.15) (end 0.69 -1.88) (layer F.Fab) (width 0.1)) 16 | (fp_line (start 4.39 -3.15) (end 4.39 -1.88) (layer F.Fab) (width 0.1)) 17 | (fp_line (start -2.58 -3.27) (end 7.66 -3.27) (layer F.SilkS) (width 0.12)) 18 | (fp_line (start -2.58 1.371) (end 7.66 1.371) (layer F.SilkS) (width 0.12)) 19 | (fp_line (start -2.58 -3.27) (end -2.58 1.371) (layer F.SilkS) (width 0.12)) 20 | (fp_line (start 7.66 -3.27) (end 7.66 1.371) (layer F.SilkS) (width 0.12)) 21 | (fp_line (start -2.58 -1.76) (end 7.66 -1.76) (layer F.SilkS) (width 0.12)) 22 | (fp_line (start 0.69 -3.27) (end 0.69 -1.76) (layer F.SilkS) (width 0.12)) 23 | (fp_line (start 4.391 -3.27) (end 4.391 -1.76) (layer F.SilkS) (width 0.12)) 24 | (fp_line (start -2.71 -3.4) (end -2.71 1.51) (layer F.CrtYd) (width 0.05)) 25 | (fp_line (start -2.71 1.51) (end 7.79 1.51) (layer F.CrtYd) (width 0.05)) 26 | (fp_line (start 7.79 1.51) (end 7.79 -3.4) (layer F.CrtYd) (width 0.05)) 27 | (fp_line (start 7.79 -3.4) (end -2.71 -3.4) (layer F.CrtYd) (width 0.05)) 28 | (fp_text user %R (at 2.54 -4.27) (layer F.Fab) 29 | (effects (font (size 1 1) (thickness 0.15))) 30 | ) 31 | (fp_line (start -2.54 -3.81) (end 13.97 -3.81) (layer F.SilkS) (width 0.12)) 32 | (fp_line (start 13.97 -3.81) (end 13.97 6.35) (layer F.SilkS) (width 0.12)) 33 | (fp_line (start 13.97 6.35) (end -8.89 6.35) (layer F.SilkS) (width 0.12)) 34 | (fp_line (start -8.89 6.35) (end -8.89 -3.81) (layer F.SilkS) (width 0.12)) 35 | (fp_line (start -8.89 -3.81) (end -2.54 -3.81) (layer F.SilkS) (width 0.12)) 36 | (pad 1 thru_hole rect (at 0 0) (size 1.905 2) (drill 1.1) (layers *.Cu *.Mask)) 37 | (pad 2 thru_hole oval (at 2.54 0) (size 1.905 2) (drill 1.1) (layers *.Cu *.Mask)) 38 | (pad 3 thru_hole oval (at 5.08 0) (size 1.905 2) (drill 1.1) (layers *.Cu *.Mask)) 39 | (model ${KISYS3DMOD}/Package_TO_SOT_THT.3dshapes/TO-220-3_Vertical.wrl 40 | (at (xyz 0 0 0)) 41 | (scale (xyz 1 1 1)) 42 | (rotate (xyz 0 0 0)) 43 | ) 44 | (model "${KIPRJMOD}/3D Models/fk_245_mi_247_o.stp" 45 | (offset (xyz 30.5 3.5 -19)) 46 | (scale (xyz 1 1 1)) 47 | (rotate (xyz -90 90 0)) 48 | ) 49 | ) 50 | -------------------------------------------------------------------------------- /PCB/Footprints/Nazrim.pretty/TerminalBlock_2_P5.08mm.kicad_mod: -------------------------------------------------------------------------------- 1 | (module TerminalBlock_2_P5.08mm (layer F.Cu) (tedit 5D4E7FB7) 2 | (descr "simple 2-pin terminal block, pitch 5.08mm, revamped version of bornier2") 3 | (tags "terminal block bornier2") 4 | (fp_text reference REF** (at 2.54 -5.08) (layer F.SilkS) 5 | (effects (font (size 1 1) (thickness 0.15))) 6 | ) 7 | (fp_text value TerminalBlock_2_P5.08mm (at 2.54 5.08) (layer F.Fab) 8 | (effects (font (size 1 1) (thickness 0.15))) 9 | ) 10 | (fp_text user %R (at 2.54 0) (layer F.Fab) 11 | (effects (font (size 1 1) (thickness 0.15))) 12 | ) 13 | (fp_line (start -2.41 2.55) (end 7.49 2.55) (layer F.Fab) (width 0.1)) 14 | (fp_line (start -2.46 -3.75) (end -2.46 3.75) (layer F.Fab) (width 0.1)) 15 | (fp_line (start -2.46 3.75) (end 7.54 3.75) (layer F.Fab) (width 0.1)) 16 | (fp_line (start 7.54 3.75) (end 7.54 -3.75) (layer F.Fab) (width 0.1)) 17 | (fp_line (start 7.54 -3.75) (end -2.46 -3.75) (layer F.Fab) (width 0.1)) 18 | (fp_line (start 7.62 2.54) (end -2.54 2.54) (layer F.SilkS) (width 0.12)) 19 | (fp_line (start 7.62 3.81) (end 7.62 -3.81) (layer F.SilkS) (width 0.12)) 20 | (fp_line (start 7.62 -3.81) (end -2.54 -3.81) (layer F.SilkS) (width 0.12)) 21 | (fp_line (start -2.54 -3.81) (end -2.54 3.81) (layer F.SilkS) (width 0.12)) 22 | (fp_line (start -2.54 3.81) (end 7.62 3.81) (layer F.SilkS) (width 0.12)) 23 | (fp_line (start -2.71 -4) (end 7.79 -4) (layer F.CrtYd) (width 0.05)) 24 | (fp_line (start -2.71 -4) (end -2.71 4) (layer F.CrtYd) (width 0.05)) 25 | (fp_line (start 7.79 4) (end 7.79 -4) (layer F.CrtYd) (width 0.05)) 26 | (fp_line (start 7.79 4) (end -2.71 4) (layer F.CrtYd) (width 0.05)) 27 | (pad 1 thru_hole rect (at 0 0) (size 3 3) (drill 1.52) (layers *.Cu *.Mask)) 28 | (pad 2 thru_hole circle (at 5.08 0) (size 3 3) (drill 1.52) (layers *.Cu *.Mask)) 29 | (model "${KIPRJMOD}/3D Models/CUI_TB002-500-02BE.step" 30 | (offset (xyz 7.5 4.2 0)) 31 | (scale (xyz 1 1 1)) 32 | (rotate (xyz 0 0 180)) 33 | ) 34 | ) 35 | -------------------------------------------------------------------------------- /PCB/Gerber Files/3D Scanner-B_Cu.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(5.1.2)-2* 2 | G04 #@! TF.CreationDate,2019-07-27T17:10:03+02:00* 3 | G04 #@! TF.ProjectId,3D Scanner,33442053-6361-46e6-9e65-722e6b696361,1.0* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Copper,L2,Bot* 6 | G04 #@! TF.FilePolarity,Positive* 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW (5.1.2)-2) date 2019-07-27 17:10:03* 10 | %MOMM*% 11 | %LPD*% 12 | G04 APERTURE LIST* 13 | %ADD10C,0.050000*% 14 | %ADD11O,1.600000X1.600000*% 15 | %ADD12R,1.600000X1.600000*% 16 | %ADD13C,3.000000*% 17 | %ADD14R,3.000000X3.000000*% 18 | %ADD15O,1.905000X2.000000*% 19 | %ADD16R,1.905000X2.000000*% 20 | %ADD17O,2.000000X1.905000*% 21 | %ADD18R,2.000000X1.905000*% 22 | %ADD19O,1.700000X1.700000*% 23 | %ADD20R,1.700000X1.700000*% 24 | %ADD21C,1.600000*% 25 | %ADD22C,1.200000*% 26 | %ADD23R,1.200000X1.200000*% 27 | %ADD24C,0.800000*% 28 | %ADD25C,0.250000*% 29 | %ADD26C,1.250000*% 30 | %ADD27C,0.750000*% 31 | G04 APERTURE END LIST* 32 | D10* 33 | X58420000Y-163830000D02* 34 | X58420000Y-68580000D01* 35 | X157480000Y-68580000D02* 36 | X157480000Y-163830000D01* 37 | X58420000Y-68580000D02* 38 | X157480000Y-68580000D01* 39 | X58420000Y-167640000D02* 40 | X58420000Y-163830000D01* 41 | X157480000Y-167640000D02* 42 | X58420000Y-167640000D01* 43 | X157480000Y-163830000D02* 44 | X157480000Y-167640000D01* 45 | D11* 46 | X90170000Y-77470000D03* 47 | X77470000Y-95250000D03* 48 | X90170000Y-80010000D03* 49 | X77470000Y-92710000D03* 50 | X90170000Y-82550000D03* 51 | X77470000Y-90170000D03* 52 | X90170000Y-85090000D03* 53 | X77470000Y-87630000D03* 54 | X90170000Y-87630000D03* 55 | X77470000Y-85090000D03* 56 | X90170000Y-90170000D03* 57 | X77470000Y-82550000D03* 58 | X90170000Y-92710000D03* 59 | X77470000Y-80010000D03* 60 | X90170000Y-95250000D03* 61 | D12* 62 | X77470000Y-77470000D03* 63 | D11* 64 | X90170000Y-110490000D03* 65 | X77470000Y-128270000D03* 66 | X90170000Y-113030000D03* 67 | X77470000Y-125730000D03* 68 | X90170000Y-115570000D03* 69 | X77470000Y-123190000D03* 70 | X90170000Y-118110000D03* 71 | X77470000Y-120650000D03* 72 | X90170000Y-120650000D03* 73 | X77470000Y-118110000D03* 74 | X90170000Y-123190000D03* 75 | X77470000Y-115570000D03* 76 | X90170000Y-125730000D03* 77 | X77470000Y-113030000D03* 78 | X90170000Y-128270000D03* 79 | D12* 80 | X77470000Y-110490000D03* 81 | D13* 82 | X66040000Y-140970000D03* 83 | D14* 84 | X66040000Y-135890000D03* 85 | D13* 86 | X66040000Y-109220000D03* 87 | D14* 88 | X66040000Y-104140000D03* 89 | D13* 90 | X66040000Y-153670000D03* 91 | D14* 92 | X66040000Y-148590000D03* 93 | D13* 94 | X138430000Y-157480000D03* 95 | D14* 96 | X133350000Y-157480000D03* 97 | D13* 98 | X124460000Y-157480000D03* 99 | D14* 100 | X119380000Y-157480000D03* 101 | D13* 102 | X110490000Y-157480000D03* 103 | D14* 104 | X105410000Y-157480000D03* 105 | D13* 106 | X96520000Y-157480000D03* 107 | D14* 108 | X91440000Y-157480000D03* 109 | D15* 110 | X139700000Y-143510000D03* 111 | X142240000Y-143510000D03* 112 | D16* 113 | X144780000Y-143510000D03* 114 | D17* 115 | X82550000Y-152400000D03* 116 | X82550000Y-149860000D03* 117 | D18* 118 | X82550000Y-147320000D03* 119 | D19* 120 | X127000000Y-116840000D03* 121 | X127000000Y-124460000D03* 122 | X127000000Y-111760000D03* 123 | X127000000Y-106680000D03* 124 | X127000000Y-119380000D03* 125 | X127000000Y-101600000D03* 126 | X127000000Y-127000000D03* 127 | D20* 128 | X127000000Y-88900000D03* 129 | D19* 130 | X127000000Y-93980000D03* 131 | X127000000Y-99060000D03* 132 | X127000000Y-129540000D03* 133 | X127000000Y-132080000D03* 134 | X127000000Y-134620000D03* 135 | X127000000Y-104140000D03* 136 | X127000000Y-91440000D03* 137 | X127000000Y-114300000D03* 138 | X127000000Y-96520000D03* 139 | X127000000Y-121920000D03* 140 | X127000000Y-109220000D03* 141 | X101600000Y-116840000D03* 142 | X101600000Y-124460000D03* 143 | X101600000Y-111760000D03* 144 | X101600000Y-106680000D03* 145 | X101600000Y-119380000D03* 146 | X101600000Y-101600000D03* 147 | X101600000Y-127000000D03* 148 | D20* 149 | X101600000Y-88900000D03* 150 | D19* 151 | X101600000Y-93980000D03* 152 | X101600000Y-99060000D03* 153 | X101600000Y-129540000D03* 154 | X101600000Y-132080000D03* 155 | X101600000Y-134620000D03* 156 | X101600000Y-104140000D03* 157 | X101600000Y-91440000D03* 158 | X101600000Y-114300000D03* 159 | X101600000Y-96520000D03* 160 | X101600000Y-121920000D03* 161 | X101600000Y-109220000D03* 162 | X151130000Y-130810000D03* 163 | X151130000Y-125730000D03* 164 | X151130000Y-123190000D03* 165 | X151130000Y-128270000D03* 166 | D20* 167 | X151130000Y-133350000D03* 168 | D19* 169 | X71120000Y-123190000D03* 170 | X71120000Y-120650000D03* 171 | X71120000Y-118110000D03* 172 | D20* 173 | X71120000Y-115570000D03* 174 | D19* 175 | X71120000Y-90170000D03* 176 | X71120000Y-87630000D03* 177 | X71120000Y-85090000D03* 178 | D20* 179 | X71120000Y-82550000D03* 180 | D19* 181 | X151130000Y-116840000D03* 182 | X151130000Y-114300000D03* 183 | X151130000Y-111760000D03* 184 | X151130000Y-109220000D03* 185 | X151130000Y-106680000D03* 186 | X151130000Y-104140000D03* 187 | X151130000Y-101600000D03* 188 | D20* 189 | X151130000Y-99060000D03* 190 | D19* 191 | X151130000Y-85090000D03* 192 | X151130000Y-87630000D03* 193 | D20* 194 | X151130000Y-90170000D03* 195 | D11* 196 | X144780000Y-129540000D03* 197 | D21* 198 | X134620000Y-129540000D03* 199 | D11* 200 | X115570000Y-147320000D03* 201 | D21* 202 | X125730000Y-147320000D03* 203 | D11* 204 | X144780000Y-104140000D03* 205 | D21* 206 | X134620000Y-104140000D03* 207 | D11* 208 | X144780000Y-118110000D03* 209 | D21* 210 | X134620000Y-118110000D03* 211 | D11* 212 | X134620000Y-88900000D03* 213 | D21* 214 | X144780000Y-88900000D03* 215 | D11* 216 | X134620000Y-83820000D03* 217 | D21* 218 | X144780000Y-83820000D03* 219 | X64770000Y-125770000D03* 220 | D12* 221 | X64770000Y-128270000D03* 222 | D21* 223 | X64770000Y-92750000D03* 224 | D12* 225 | X64770000Y-95250000D03* 226 | D21* 227 | X96520000Y-147360000D03* 228 | X96520000Y-149860000D03* 229 | X91440000Y-147360000D03* 230 | D12* 231 | X91440000Y-149860000D03* 232 | D22* 233 | X78740000Y-147860000D03* 234 | D23* 235 | X78740000Y-149860000D03* 236 | D24* 237 | X148590000Y-113030000D03* 238 | X142240000Y-110490000D03* 239 | X144780000Y-109220000D03* 240 | X143510000Y-106680000D03* 241 | X139700000Y-109220000D03* 242 | X104140000Y-118110000D03* 243 | X144780000Y-113030000D03* 244 | X147320000Y-111760000D03* 245 | X114300000Y-121920000D03* 246 | D25* 247 | X144780000Y-116840000D02* 248 | X144780000Y-118110000D01* 249 | X148590000Y-113030000D02* 250 | X144780000Y-116840000D01* 251 | X128270000Y-124460000D02* 252 | X134620000Y-118110000D01* 253 | X127000000Y-124460000D02* 254 | X128270000Y-124460000D01* 255 | X139700000Y-123190000D02* 256 | X151130000Y-123190000D01* 257 | X134620000Y-118110000D02* 258 | X139700000Y-123190000D01* 259 | X142240000Y-101600000D02* 260 | X151130000Y-101600000D01* 261 | X127000000Y-116840000D02* 262 | X142240000Y-101600000D01* 263 | X142240000Y-110490000D02* 264 | X143510000Y-109220000D01* 265 | X143510000Y-109220000D02* 266 | X144780000Y-109220000D01* 267 | X143510000Y-106680000D02* 268 | X142240000Y-106680000D01* 269 | X142240000Y-106680000D02* 270 | X139700000Y-109220000D01* 271 | X119380000Y-118110000D02* 272 | X121920000Y-115570000D01* 273 | X121920000Y-111760000D02* 274 | X127000000Y-106680000D01* 275 | X121920000Y-115570000D02* 276 | X121920000Y-111760000D01* 277 | X104140000Y-118110000D02* 278 | X119380000Y-118110000D01* 279 | X144780000Y-113030000D02* 280 | X146050000Y-111760000D01* 281 | X146050000Y-111760000D02* 282 | X147320000Y-111760000D01* 283 | X127000000Y-104140000D02* 284 | X134620000Y-104140000D01* 285 | X151130000Y-99060000D02* 286 | X127000000Y-99060000D01* 287 | X114300000Y-121920000D02* 288 | X118110000Y-125730000D01* 289 | X151130000Y-128270000D02* 290 | X148590000Y-125730000D01* 291 | X118110000Y-125730000D02* 292 | X148590000Y-125730000D01* 293 | X148590000Y-125730000D02* 294 | X151130000Y-125730000D01* 295 | X105410000Y-132080000D02* 296 | X101600000Y-132080000D01* 297 | X113030000Y-139700000D02* 298 | X105410000Y-132080000D01* 299 | X147155002Y-139700000D02* 300 | X150965002Y-135890000D01* 301 | X142240000Y-139700000D02* 302 | X147155002Y-139700000D01* 303 | X142240000Y-139700000D02* 304 | X113030000Y-139700000D01* 305 | X142645002Y-139700000D02* 306 | X142240000Y-139700000D01* 307 | X150965002Y-135890000D02* 308 | X152400000Y-135890000D01* 309 | X152400000Y-135890000D02* 310 | X153670000Y-134620000D01* 311 | X153670000Y-134620000D02* 312 | X153670000Y-132080000D01* 313 | X153670000Y-132080000D02* 314 | X152400000Y-130810000D01* 315 | X152400000Y-130810000D02* 316 | X151130000Y-130810000D01* 317 | X101600000Y-129540000D02* 318 | X114300000Y-129540000D01* 319 | X114300000Y-129540000D02* 320 | X123190000Y-138430000D01* 321 | X123190000Y-138430000D02* 322 | X141490000Y-138430000D01* 323 | X146570000Y-133350000D02* 324 | X151130000Y-133350000D01* 325 | X141490000Y-138430000D02* 326 | X146570000Y-133350000D01* 327 | X128270000Y-82550000D02* 328 | X134620000Y-88900000D01* 329 | X120650000Y-82550000D02* 330 | X128270000Y-82550000D01* 331 | X105410000Y-97790000D02* 332 | X120650000Y-82550000D01* 333 | X101600000Y-104140000D02* 334 | X105410000Y-100330000D01* 335 | X105410000Y-100330000D02* 336 | X105410000Y-97790000D01* 337 | X150030000Y-90170000D02* 338 | X151130000Y-90170000D01* 339 | X147320000Y-87460000D02* 340 | X150030000Y-90170000D01* 341 | X147320000Y-83820000D02* 342 | X147320000Y-87460000D01* 343 | X144780000Y-81280000D02* 344 | X147320000Y-83820000D01* 345 | X119380000Y-81280000D02* 346 | X144780000Y-81280000D01* 347 | X101600000Y-99060000D02* 348 | X119380000Y-81280000D01* 349 | D26* 350 | X62230000Y-97790000D02* 351 | X64770000Y-95250000D01* 352 | X62230000Y-129330000D02* 353 | X62230000Y-97790000D01* 354 | X66040000Y-135890000D02* 355 | X66040000Y-133140000D01* 356 | X64770000Y-128270000D02* 357 | X62970000Y-130070000D01* 358 | X66040000Y-133140000D02* 359 | X62970000Y-130070000D01* 360 | X62970000Y-130070000D02* 361 | X62230000Y-129330000D01* 362 | D27* 363 | X96520000Y-149860000D02* 364 | X97945001Y-148434999D01* 365 | X90170000Y-87630000D02* 366 | X92710000Y-87630000D01* 367 | X92710000Y-87630000D02* 368 | X97790000Y-92710000D01* 369 | X90170000Y-90170000D02* 370 | X92710000Y-90170000D01* 371 | X92710000Y-90170000D02* 372 | X97945001Y-95405001D01* 373 | X97945001Y-97634999D02* 374 | X97945001Y-95405001D01* 375 | X97945001Y-95405001D02* 376 | X97945001Y-94135001D01* 377 | X90170000Y-92710000D02* 378 | X92710000Y-92710000D01* 379 | X92710000Y-92710000D02* 380 | X97945001Y-97945001D01* 381 | X97945001Y-124615001D02* 382 | X97945001Y-97945001D01* 383 | X97945001Y-97945001D02* 384 | X97945001Y-97634999D01* 385 | X90170000Y-120650000D02* 386 | X92710000Y-120650000D01* 387 | X92710000Y-120650000D02* 388 | X97945001Y-125885001D01* 389 | X97945001Y-125885001D02* 390 | X97945001Y-124615001D01* 391 | X90170000Y-123190000D02* 392 | X92710000Y-123190000D01* 393 | X92710000Y-123190000D02* 394 | X97945001Y-128425001D01* 395 | X97945001Y-128425001D02* 396 | X97945001Y-125885001D01* 397 | X90170000Y-125730000D02* 398 | X92710000Y-125730000D01* 399 | X92710000Y-125730000D02* 400 | X97945001Y-130965001D01* 401 | X97945001Y-148434999D02* 402 | X97945001Y-130965001D01* 403 | X97945001Y-130965001D02* 404 | X97945001Y-128425001D01* 405 | X97945001Y-94135001D02* 406 | X97945001Y-92865001D01* 407 | X82550000Y-80010000D02* 408 | X90170000Y-87630000D01* 409 | X77470000Y-80010000D02* 410 | X82550000Y-80010000D01* 411 | X82550000Y-113030000D02* 412 | X90170000Y-120650000D01* 413 | X77470000Y-113030000D02* 414 | X82550000Y-113030000D01* 415 | D25* 416 | X144780000Y-107950000D02* 417 | X151130000Y-114300000D01* 418 | X144780000Y-104140000D02* 419 | X144780000Y-107950000D01* 420 | X144780000Y-143557500D02* 421 | X144780000Y-143510000D01* 422 | X141017500Y-147320000D02* 423 | X144780000Y-143557500D01* 424 | X125730000Y-147320000D02* 425 | X141017500Y-147320000D01* 426 | D26* 427 | X71850000Y-147860000D02* 428 | X78740000Y-147860000D01* 429 | X66040000Y-153670000D02* 430 | X71850000Y-147860000D01* 431 | X67171370Y-92750000D02* 432 | X64770000Y-92750000D01* 433 | X71850000Y-97428630D02* 434 | X67171370Y-92750000D01* 435 | X71850000Y-147860000D02* 436 | X71850000Y-131350000D01* 437 | X66270000Y-125770000D02* 438 | X64770000Y-125770000D01* 439 | X71850000Y-131350000D02* 440 | X66270000Y-125770000D01* 441 | X66270000Y-125770000D02* 442 | X66270000Y-114070000D01* 443 | X71850000Y-108490000D02* 444 | X71850000Y-97428630D01* 445 | X66270000Y-114070000D02* 446 | X71850000Y-108490000D01* 447 | M02* 448 | -------------------------------------------------------------------------------- /PCB/Gerber Files/3D Scanner-B_SilkS.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(5.1.2)-2* 2 | G04 #@! TF.CreationDate,2019-07-27T17:10:04+02:00* 3 | G04 #@! TF.ProjectId,3D Scanner,33442053-6361-46e6-9e65-722e6b696361,1.0* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Legend,Bot* 6 | G04 #@! TF.FilePolarity,Positive* 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW (5.1.2)-2) date 2019-07-27 17:10:04* 10 | %MOMM*% 11 | %LPD*% 12 | G04 APERTURE LIST* 13 | %ADD10C,0.050000*% 14 | G04 APERTURE END LIST* 15 | D10* 16 | X58420000Y-163830000D02* 17 | X58420000Y-68580000D01* 18 | X157480000Y-68580000D02* 19 | X157480000Y-163830000D01* 20 | X58420000Y-68580000D02* 21 | X157480000Y-68580000D01* 22 | X58420000Y-167640000D02* 23 | X58420000Y-163830000D01* 24 | X157480000Y-167640000D02* 25 | X58420000Y-167640000D01* 26 | X157480000Y-163830000D02* 27 | X157480000Y-167640000D01* 28 | M02* 29 | -------------------------------------------------------------------------------- /PCB/Gerber Files/3D Scanner-Edge_Cuts.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(5.1.2)-2* 2 | G04 #@! TF.CreationDate,2019-07-27T17:10:04+02:00* 3 | G04 #@! TF.ProjectId,3D Scanner,33442053-6361-46e6-9e65-722e6b696361,1.0* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Profile,NP* 6 | %FSLAX46Y46*% 7 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 8 | G04 Created by KiCad (PCBNEW (5.1.2)-2) date 2019-07-27 17:10:04* 9 | %MOMM*% 10 | %LPD*% 11 | G04 APERTURE LIST* 12 | %ADD10C,0.050000*% 13 | G04 APERTURE END LIST* 14 | D10* 15 | X58420000Y-163830000D02* 16 | X58420000Y-68580000D01* 17 | X157480000Y-68580000D02* 18 | X157480000Y-163830000D01* 19 | X58420000Y-68580000D02* 20 | X157480000Y-68580000D01* 21 | X58420000Y-167640000D02* 22 | X58420000Y-163830000D01* 23 | X157480000Y-167640000D02* 24 | X58420000Y-167640000D01* 25 | X157480000Y-163830000D02* 26 | X157480000Y-167640000D01* 27 | M02* 28 | -------------------------------------------------------------------------------- /PCB/Gerber Files/3D Scanner-F_Cu.gbr: -------------------------------------------------------------------------------- 1 | G04 #@! TF.GenerationSoftware,KiCad,Pcbnew,(5.1.2)-2* 2 | G04 #@! TF.CreationDate,2019-07-27T17:10:03+02:00* 3 | G04 #@! TF.ProjectId,3D Scanner,33442053-6361-46e6-9e65-722e6b696361,1.0* 4 | G04 #@! TF.SameCoordinates,Original* 5 | G04 #@! TF.FileFunction,Copper,L1,Top* 6 | G04 #@! TF.FilePolarity,Positive* 7 | %FSLAX46Y46*% 8 | G04 Gerber Fmt 4.6, Leading zero omitted, Abs format (unit mm)* 9 | G04 Created by KiCad (PCBNEW (5.1.2)-2) date 2019-07-27 17:10:03* 10 | %MOMM*% 11 | %LPD*% 12 | G04 APERTURE LIST* 13 | %ADD10C,0.050000*% 14 | %ADD11O,1.600000X1.600000*% 15 | %ADD12R,1.600000X1.600000*% 16 | %ADD13C,3.000000*% 17 | %ADD14R,3.000000X3.000000*% 18 | %ADD15O,1.905000X2.000000*% 19 | %ADD16R,1.905000X2.000000*% 20 | %ADD17O,2.000000X1.905000*% 21 | %ADD18R,2.000000X1.905000*% 22 | %ADD19O,1.700000X1.700000*% 23 | %ADD20R,1.700000X1.700000*% 24 | %ADD21C,1.600000*% 25 | %ADD22C,1.200000*% 26 | %ADD23R,1.200000X1.200000*% 27 | %ADD24C,0.800000*% 28 | %ADD25C,0.250000*% 29 | %ADD26C,1.250000*% 30 | %ADD27C,0.750000*% 31 | G04 APERTURE END LIST* 32 | D10* 33 | X58420000Y-163830000D02* 34 | X58420000Y-68580000D01* 35 | X157480000Y-68580000D02* 36 | X157480000Y-163830000D01* 37 | X58420000Y-68580000D02* 38 | X157480000Y-68580000D01* 39 | X58420000Y-167640000D02* 40 | X58420000Y-163830000D01* 41 | X157480000Y-167640000D02* 42 | X58420000Y-167640000D01* 43 | X157480000Y-163830000D02* 44 | X157480000Y-167640000D01* 45 | D11* 46 | X90170000Y-77470000D03* 47 | X77470000Y-95250000D03* 48 | X90170000Y-80010000D03* 49 | X77470000Y-92710000D03* 50 | X90170000Y-82550000D03* 51 | X77470000Y-90170000D03* 52 | X90170000Y-85090000D03* 53 | X77470000Y-87630000D03* 54 | X90170000Y-87630000D03* 55 | X77470000Y-85090000D03* 56 | X90170000Y-90170000D03* 57 | X77470000Y-82550000D03* 58 | X90170000Y-92710000D03* 59 | X77470000Y-80010000D03* 60 | X90170000Y-95250000D03* 61 | D12* 62 | X77470000Y-77470000D03* 63 | D11* 64 | X90170000Y-110490000D03* 65 | X77470000Y-128270000D03* 66 | X90170000Y-113030000D03* 67 | X77470000Y-125730000D03* 68 | X90170000Y-115570000D03* 69 | X77470000Y-123190000D03* 70 | X90170000Y-118110000D03* 71 | X77470000Y-120650000D03* 72 | X90170000Y-120650000D03* 73 | X77470000Y-118110000D03* 74 | X90170000Y-123190000D03* 75 | X77470000Y-115570000D03* 76 | X90170000Y-125730000D03* 77 | X77470000Y-113030000D03* 78 | X90170000Y-128270000D03* 79 | D12* 80 | X77470000Y-110490000D03* 81 | D13* 82 | X66040000Y-140970000D03* 83 | D14* 84 | X66040000Y-135890000D03* 85 | D13* 86 | X66040000Y-109220000D03* 87 | D14* 88 | X66040000Y-104140000D03* 89 | D13* 90 | X66040000Y-153670000D03* 91 | D14* 92 | X66040000Y-148590000D03* 93 | D13* 94 | X138430000Y-157480000D03* 95 | D14* 96 | X133350000Y-157480000D03* 97 | D13* 98 | X124460000Y-157480000D03* 99 | D14* 100 | X119380000Y-157480000D03* 101 | D13* 102 | X110490000Y-157480000D03* 103 | D14* 104 | X105410000Y-157480000D03* 105 | D13* 106 | X96520000Y-157480000D03* 107 | D14* 108 | X91440000Y-157480000D03* 109 | D15* 110 | X139700000Y-143510000D03* 111 | X142240000Y-143510000D03* 112 | D16* 113 | X144780000Y-143510000D03* 114 | D17* 115 | X82550000Y-152400000D03* 116 | X82550000Y-149860000D03* 117 | D18* 118 | X82550000Y-147320000D03* 119 | D19* 120 | X127000000Y-116840000D03* 121 | X127000000Y-124460000D03* 122 | X127000000Y-111760000D03* 123 | X127000000Y-106680000D03* 124 | X127000000Y-119380000D03* 125 | X127000000Y-101600000D03* 126 | X127000000Y-127000000D03* 127 | D20* 128 | X127000000Y-88900000D03* 129 | D19* 130 | X127000000Y-93980000D03* 131 | X127000000Y-99060000D03* 132 | X127000000Y-129540000D03* 133 | X127000000Y-132080000D03* 134 | X127000000Y-134620000D03* 135 | X127000000Y-104140000D03* 136 | X127000000Y-91440000D03* 137 | X127000000Y-114300000D03* 138 | X127000000Y-96520000D03* 139 | X127000000Y-121920000D03* 140 | X127000000Y-109220000D03* 141 | X101600000Y-116840000D03* 142 | X101600000Y-124460000D03* 143 | X101600000Y-111760000D03* 144 | X101600000Y-106680000D03* 145 | X101600000Y-119380000D03* 146 | X101600000Y-101600000D03* 147 | X101600000Y-127000000D03* 148 | D20* 149 | X101600000Y-88900000D03* 150 | D19* 151 | X101600000Y-93980000D03* 152 | X101600000Y-99060000D03* 153 | X101600000Y-129540000D03* 154 | X101600000Y-132080000D03* 155 | X101600000Y-134620000D03* 156 | X101600000Y-104140000D03* 157 | X101600000Y-91440000D03* 158 | X101600000Y-114300000D03* 159 | X101600000Y-96520000D03* 160 | X101600000Y-121920000D03* 161 | X101600000Y-109220000D03* 162 | X151130000Y-130810000D03* 163 | X151130000Y-125730000D03* 164 | X151130000Y-123190000D03* 165 | X151130000Y-128270000D03* 166 | D20* 167 | X151130000Y-133350000D03* 168 | D19* 169 | X71120000Y-123190000D03* 170 | X71120000Y-120650000D03* 171 | X71120000Y-118110000D03* 172 | D20* 173 | X71120000Y-115570000D03* 174 | D19* 175 | X71120000Y-90170000D03* 176 | X71120000Y-87630000D03* 177 | X71120000Y-85090000D03* 178 | D20* 179 | X71120000Y-82550000D03* 180 | D19* 181 | X151130000Y-116840000D03* 182 | X151130000Y-114300000D03* 183 | X151130000Y-111760000D03* 184 | X151130000Y-109220000D03* 185 | X151130000Y-106680000D03* 186 | X151130000Y-104140000D03* 187 | X151130000Y-101600000D03* 188 | D20* 189 | X151130000Y-99060000D03* 190 | D19* 191 | X151130000Y-85090000D03* 192 | X151130000Y-87630000D03* 193 | D20* 194 | X151130000Y-90170000D03* 195 | D11* 196 | X144780000Y-129540000D03* 197 | D21* 198 | X134620000Y-129540000D03* 199 | D11* 200 | X115570000Y-147320000D03* 201 | D21* 202 | X125730000Y-147320000D03* 203 | D11* 204 | X144780000Y-104140000D03* 205 | D21* 206 | X134620000Y-104140000D03* 207 | D11* 208 | X144780000Y-118110000D03* 209 | D21* 210 | X134620000Y-118110000D03* 211 | D11* 212 | X134620000Y-88900000D03* 213 | D21* 214 | X144780000Y-88900000D03* 215 | D11* 216 | X134620000Y-83820000D03* 217 | D21* 218 | X144780000Y-83820000D03* 219 | X64770000Y-125770000D03* 220 | D12* 221 | X64770000Y-128270000D03* 222 | D21* 223 | X64770000Y-92750000D03* 224 | D12* 225 | X64770000Y-95250000D03* 226 | D21* 227 | X96520000Y-147360000D03* 228 | X96520000Y-149860000D03* 229 | X91440000Y-147360000D03* 230 | D12* 231 | X91440000Y-149860000D03* 232 | D22* 233 | X78740000Y-147860000D03* 234 | D23* 235 | X78740000Y-149860000D03* 236 | D24* 237 | X148590000Y-113030000D03* 238 | X142240000Y-110490000D03* 239 | X144780000Y-109220000D03* 240 | X143510000Y-106680000D03* 241 | X139700000Y-109220000D03* 242 | X104140000Y-118110000D03* 243 | X144780000Y-113030000D03* 244 | X147320000Y-111760000D03* 245 | X114300000Y-121920000D03* 246 | D25* 247 | X127000000Y-134620000D02* 248 | X135890000Y-134620000D01* 249 | X135890000Y-134620000D02* 250 | X138430000Y-132080000D01* 251 | X138430000Y-124460000D02* 252 | X144780000Y-118110000D01* 253 | X138430000Y-132080000D02* 254 | X138430000Y-124460000D01* 255 | X151130000Y-111760000D02* 256 | X149860000Y-111760000D01* 257 | X149860000Y-111760000D02* 258 | X148590000Y-113030000D01* 259 | X134620000Y-127000000D02* 260 | X127000000Y-119380000D01* 261 | X134620000Y-129540000D02* 262 | X134620000Y-127000000D01* 263 | X127000000Y-111760000D02* 264 | X140970000Y-111760000D01* 265 | X140970000Y-111760000D02* 266 | X142240000Y-110490000D01* 267 | X148590000Y-109220000D02* 268 | X151130000Y-106680000D01* 269 | X144780000Y-109220000D02* 270 | X148590000Y-109220000D01* 271 | X151130000Y-104140000D02* 272 | X148590000Y-106680000D01* 273 | X148590000Y-106680000D02* 274 | X143510000Y-106680000D01* 275 | X139700000Y-109220000D02* 276 | X127000000Y-109220000D01* 277 | X135890000Y-101600000D02* 278 | X151130000Y-116840000D01* 279 | X127000000Y-101600000D02* 280 | X135890000Y-101600000D01* 281 | X90170000Y-113030000D02* 282 | X95250000Y-118110000D01* 283 | X95250000Y-118110000D02* 284 | X104140000Y-118110000D01* 285 | X127000000Y-114300000D02* 286 | X143510000Y-114300000D01* 287 | X143510000Y-114300000D02* 288 | X144780000Y-113030000D01* 289 | X148590000Y-111760000D02* 290 | X151130000Y-109220000D01* 291 | X147320000Y-111760000D02* 292 | X148590000Y-111760000D01* 293 | X101600000Y-134620000D02* 294 | X114300000Y-121920000D01* 295 | X133350000Y-82550000D02* 296 | X134620000Y-83820000D01* 297 | X120650000Y-82550000D02* 298 | X133350000Y-82550000D01* 299 | X114300000Y-121920000D02* 300 | X114300000Y-88900000D01* 301 | X114300000Y-88900000D02* 302 | X120650000Y-82550000D01* 303 | X95250000Y-110490000D02* 304 | X101600000Y-116840000D01* 305 | X90170000Y-110490000D02* 306 | X95250000Y-110490000D01* 307 | X90170000Y-95250000D02* 308 | X93980000Y-99060000D01* 309 | X93980000Y-106680000D02* 310 | X101600000Y-114300000D01* 311 | X93980000Y-99060000D02* 312 | X93980000Y-106680000D01* 313 | X102802081Y-111760000D02* 314 | X101600000Y-111760000D01* 315 | X104017002Y-111760000D02* 316 | X102802081Y-111760000D01* 317 | X90170000Y-128270000D02* 318 | X102143002Y-128270000D01* 319 | X104017002Y-111760000D02* 320 | X104140000Y-111760000D01* 321 | X104140000Y-111760000D02* 322 | X105410000Y-113030000D01* 323 | X105410000Y-113030000D02* 324 | X105410000Y-118110000D01* 325 | X105410000Y-125003002D02* 326 | X102143002Y-128270000D01* 327 | X105410000Y-118110000D02* 328 | X105410000Y-125003002D01* 329 | X102143002Y-128270000D02* 330 | X101600000Y-128270000D01* 331 | X90969999Y-80809999D02* 332 | X90170000Y-80010000D01* 333 | X94480010Y-84320010D02* 334 | X90969999Y-80809999D01* 335 | X94480010Y-102100010D02* 336 | X94480010Y-84320010D01* 337 | X101600000Y-109220000D02* 338 | X94480010Y-102100010D01* 339 | X95250000Y-82550000D02* 340 | X90170000Y-77470000D01* 341 | X101600000Y-106680000D02* 342 | X95250000Y-100330000D01* 343 | X95250000Y-100330000D02* 344 | X95250000Y-82550000D01* 345 | D26* 346 | X81280000Y-152400000D02* 347 | X82550000Y-152400000D01* 348 | X78740000Y-149860000D02* 349 | X81280000Y-152400000D01* 350 | X71120000Y-149860000D02* 351 | X73660000Y-152400000D01* 352 | X66040000Y-135890000D02* 353 | X71120000Y-140970000D01* 354 | X77430000Y-95210000D02* 355 | X77470000Y-95250000D01* 356 | X71120000Y-147320000D02* 357 | X73660000Y-149860000D01* 358 | X71120000Y-146050000D02* 359 | X71120000Y-147320000D01* 360 | X73660000Y-149860000D02* 361 | X78740000Y-149860000D01* 362 | X71120000Y-146050000D02* 363 | X71120000Y-149860000D01* 364 | X71120000Y-140970000D02* 365 | X71120000Y-146050000D01* 366 | X78105000Y-160655000D02* 367 | X73660000Y-156210000D01* 368 | X73660000Y-152400000D02* 369 | X73660000Y-156210000D01* 370 | X135255000Y-160655000D02* 371 | X138430000Y-157480000D01* 372 | X122960001Y-158979999D02* 373 | X121285000Y-160655000D01* 374 | X124460000Y-157480000D02* 375 | X122960001Y-158979999D01* 376 | X135255000Y-160655000D02* 377 | X121285000Y-160655000D01* 378 | X108990001Y-158979999D02* 379 | X107315000Y-160655000D01* 380 | X110490000Y-157480000D02* 381 | X108990001Y-158979999D01* 382 | X121285000Y-160655000D02* 383 | X107315000Y-160655000D01* 384 | X95020001Y-158979999D02* 385 | X93345000Y-160655000D01* 386 | X96520000Y-157480000D02* 387 | X95020001Y-158979999D01* 388 | X107315000Y-160655000D02* 389 | X93345000Y-160655000D01* 390 | X107315000Y-160655000D02* 391 | X78105000Y-160655000D01* 392 | X77430000Y-128230000D02* 393 | X77470000Y-128270000D01* 394 | X64770000Y-95250000D02* 395 | X77470000Y-95250000D01* 396 | X64770000Y-128270000D02* 397 | X77470000Y-128270000D01* 398 | D27* 399 | X82550000Y-149860000D02* 400 | X90170000Y-149860000D01* 401 | X96480000Y-149860000D02* 402 | X96520000Y-149820000D01* 403 | X90170000Y-149860000D02* 404 | X96480000Y-149860000D01* 405 | X74930000Y-113030000D02* 406 | X66040000Y-104140000D01* 407 | X77470000Y-113030000D02* 408 | X74930000Y-113030000D01* 409 | D25* 410 | X90170000Y-118110000D02* 411 | X90170000Y-115570000D01* 412 | D26* 413 | X77470000Y-123190000D02* 414 | X71120000Y-123190000D01* 415 | X71120000Y-120650000D02* 416 | X77470000Y-120650000D01* 417 | X77470000Y-118110000D02* 418 | X71120000Y-118110000D01* 419 | X71120000Y-115570000D02* 420 | X77470000Y-115570000D01* 421 | D25* 422 | X90170000Y-85090000D02* 423 | X90170000Y-82550000D01* 424 | D26* 425 | X71120000Y-90170000D02* 426 | X77470000Y-90170000D01* 427 | X77470000Y-87630000D02* 428 | X71120000Y-87630000D01* 429 | X71120000Y-85090000D02* 430 | X77470000Y-85090000D01* 431 | X77470000Y-82550000D02* 432 | X71120000Y-82550000D01* 433 | D25* 434 | X149860000Y-83820000D02* 435 | X151130000Y-85090000D01* 436 | X144780000Y-83820000D02* 437 | X149860000Y-83820000D01* 438 | X149860000Y-88900000D02* 439 | X151130000Y-87630000D01* 440 | X144780000Y-88900000D02* 441 | X149860000Y-88900000D01* 442 | D26* 443 | X91440000Y-155730000D02* 444 | X91440000Y-157480000D01* 445 | X108740000Y-152400000D02* 446 | X105410000Y-155730000D01* 447 | D25* 448 | X122710000Y-152400000D02* 449 | X123190000Y-152400000D01* 450 | D26* 451 | X105410000Y-157480000D02* 452 | X105410000Y-155730000D01* 453 | X108740000Y-152400000D02* 454 | X123190000Y-152400000D01* 455 | X139700000Y-152400000D02* 456 | X135680000Y-152400000D01* 457 | X123190000Y-152400000D02* 458 | X124460000Y-152400000D01* 459 | X122400000Y-152400000D02* 460 | X124460000Y-152400000D01* 461 | X124460000Y-152400000D02* 462 | X119380000Y-157480000D01* 463 | X138430000Y-152400000D02* 464 | X133350000Y-157480000D01* 465 | X138430000Y-152400000D02* 466 | X139700000Y-152400000D01* 467 | X124460000Y-152400000D02* 468 | X138430000Y-152400000D01* 469 | X92230000Y-154940000D02* 470 | X100330000Y-154940000D01* 471 | X91440000Y-155730000D02* 472 | X92230000Y-154940000D01* 473 | X102870000Y-152400000D02* 474 | X108740000Y-152400000D01* 475 | X100330000Y-154940000D02* 476 | X102870000Y-152400000D01* 477 | X142240000Y-149860000D02* 478 | X139700000Y-152400000D01* 479 | X142240000Y-143510000D02* 480 | X142240000Y-149860000D01* 481 | X66040000Y-148590000D02* 482 | X66040000Y-140970000D01* 483 | D25* 484 | X144780000Y-143510000D02* 485 | X144780000Y-139700000D01* 486 | X144780000Y-139700000D02* 487 | X144780000Y-129540000D01* 488 | D27* 489 | X82010000Y-147860000D02* 490 | X82550000Y-147320000D01* 491 | D26* 492 | X78740000Y-147860000D02* 493 | X82010000Y-147860000D01* 494 | D27* 495 | X90130000Y-147320000D02* 496 | X90170000Y-147360000D01* 497 | X82550000Y-147320000D02* 498 | X90130000Y-147320000D01* 499 | X90170000Y-147360000D02* 500 | X94020000Y-147360000D01* 501 | X94060000Y-147320000D02* 502 | X96520000Y-147320000D01* 503 | X94020000Y-147360000D02* 504 | X94060000Y-147320000D01* 505 | X115530000Y-147360000D02* 506 | X115570000Y-147320000D01* 507 | X110450000Y-147360000D02* 508 | X114300000Y-143510000D01* 509 | X110450000Y-147360000D02* 510 | X115530000Y-147360000D01* 511 | X96520000Y-144780000D02* 512 | X85090000Y-133350000D01* 513 | X83820000Y-77470000D02* 514 | X77470000Y-77470000D01* 515 | X85090000Y-78740000D02* 516 | X83820000Y-77470000D01* 517 | X82550000Y-110490000D02* 518 | X85090000Y-113030000D01* 519 | X77470000Y-110490000D02* 520 | X82550000Y-110490000D01* 521 | X85090000Y-133350000D02* 522 | X85090000Y-113030000D01* 523 | X85090000Y-113030000D02* 524 | X85090000Y-78740000D01* 525 | X79020000Y-110490000D02* 526 | X82550000Y-110490000D01* 527 | X63500000Y-109220000D02* 528 | X62230000Y-107950000D01* 529 | X62230000Y-107950000D02* 530 | X62230000Y-101600000D01* 531 | X66040000Y-109220000D02* 532 | X63500000Y-109220000D01* 533 | X62230000Y-101600000D02* 534 | X63500000Y-100330000D01* 535 | X63500000Y-100330000D02* 536 | X68860000Y-100330000D01* 537 | X68860000Y-100330000D02* 538 | X79020000Y-110490000D01* 539 | X114300000Y-143510000D02* 540 | X139700000Y-143510000D01* 541 | X77430000Y-92750000D02* 542 | X77470000Y-92710000D01* 543 | D26* 544 | X64770000Y-92750000D02* 545 | X77430000Y-92750000D01* 546 | D27* 547 | X77430000Y-125770000D02* 548 | X77470000Y-125730000D01* 549 | D26* 550 | X64770000Y-125770000D02* 551 | X77430000Y-125770000D01* 552 | D27* 553 | X96520000Y-144780000D02* 554 | X99100000Y-147360000D01* 555 | X96520000Y-147360000D02* 556 | X99100000Y-147360000D01* 557 | X99100000Y-147360000D02* 558 | X110450000Y-147360000D01* 559 | M02* 560 | -------------------------------------------------------------------------------- /PCB/Gerber Files/3D Scanner.drl: -------------------------------------------------------------------------------- 1 | M48 2 | ; DRILL file {KiCad (5.1.2)-2} date 27/07/2019 17:10:27 3 | ; FORMAT={-:-/ absolute / inch / decimal} 4 | ; #@! TF.CreationDate,2019-07-27T17:10:27+02:00 5 | ; #@! TF.GenerationSoftware,Kicad,Pcbnew,(5.1.2)-2 6 | FMAT,2 7 | INCH 8 | T1C0.0157 9 | T2C0.0236 10 | T3C0.0315 11 | T4C0.0394 12 | T5C0.0433 13 | T6C0.0598 14 | T7C0.1260 15 | % 16 | G90 17 | G05 18 | T1 19 | X4.1Y-4.65 20 | X4.5Y-4.8 21 | X5.5Y-4.3 22 | X5.6Y-4.35 23 | X5.65Y-4.2 24 | X5.7Y-4.3 25 | X5.7Y-4.45 26 | X5.8Y-4.4 27 | X5.85Y-4.45 28 | T2 29 | X3.1Y-5.8213 30 | X3.1Y-5.9 31 | T3 32 | X5.3Y-5.1 33 | X5.7Y-5.1 34 | X4.55Y-5.8 35 | X4.95Y-5.8 36 | X5.3Y-3.5 37 | X5.7Y-3.5 38 | X5.3Y-3.3 39 | X5.7Y-3.3 40 | X2.55Y-4.9516 41 | X2.55Y-5.05 42 | X3.05Y-3.05 43 | X3.05Y-3.15 44 | X3.05Y-3.25 45 | X3.05Y-3.35 46 | X3.05Y-3.45 47 | X3.05Y-3.55 48 | X3.05Y-3.65 49 | X3.05Y-3.75 50 | X3.55Y-3.05 51 | X3.55Y-3.15 52 | X3.55Y-3.25 53 | X3.55Y-3.35 54 | X3.55Y-3.45 55 | X3.55Y-3.55 56 | X3.55Y-3.65 57 | X3.55Y-3.75 58 | X5.3Y-4.65 59 | X5.7Y-4.65 60 | X5.3Y-4.1 61 | X5.7Y-4.1 62 | X2.55Y-3.6516 63 | X2.55Y-3.75 64 | X3.05Y-4.35 65 | X3.05Y-4.45 66 | X3.05Y-4.55 67 | X3.05Y-4.65 68 | X3.05Y-4.75 69 | X3.05Y-4.85 70 | X3.05Y-4.95 71 | X3.05Y-5.05 72 | X3.55Y-4.35 73 | X3.55Y-4.45 74 | X3.55Y-4.55 75 | X3.55Y-4.65 76 | X3.55Y-4.75 77 | X3.55Y-4.85 78 | X3.55Y-4.95 79 | X3.55Y-5.05 80 | X3.8Y-5.8016 81 | X3.8Y-5.9 82 | X3.6Y-5.8016 83 | X3.6Y-5.9 84 | T4 85 | X2.8Y-3.25 86 | X2.8Y-3.35 87 | X2.8Y-3.45 88 | X2.8Y-3.55 89 | X5.95Y-3.9 90 | X5.95Y-4.0 91 | X5.95Y-4.1 92 | X5.95Y-4.2 93 | X5.95Y-4.3 94 | X5.95Y-4.4 95 | X5.95Y-4.5 96 | X5.95Y-4.6 97 | X5.95Y-4.85 98 | X5.95Y-4.95 99 | X5.95Y-5.05 100 | X5.95Y-5.15 101 | X5.95Y-5.25 102 | X2.8Y-4.55 103 | X2.8Y-4.65 104 | X2.8Y-4.75 105 | X2.8Y-4.85 106 | X5.95Y-3.35 107 | X5.95Y-3.45 108 | X5.95Y-3.55 109 | X4.0Y-3.5 110 | X4.0Y-3.6 111 | X4.0Y-3.7 112 | X4.0Y-3.8 113 | X4.0Y-3.9 114 | X4.0Y-4.0 115 | X4.0Y-4.1 116 | X4.0Y-4.2 117 | X4.0Y-4.3 118 | X4.0Y-4.4 119 | X4.0Y-4.5 120 | X4.0Y-4.6 121 | X4.0Y-4.7 122 | X4.0Y-4.8 123 | X4.0Y-4.9 124 | X4.0Y-5.0 125 | X4.0Y-5.1 126 | X4.0Y-5.2 127 | X4.0Y-5.3 128 | X5.0Y-3.5 129 | X5.0Y-3.6 130 | X5.0Y-3.7 131 | X5.0Y-3.8 132 | X5.0Y-3.9 133 | X5.0Y-4.0 134 | X5.0Y-4.1 135 | X5.0Y-4.2 136 | X5.0Y-4.3 137 | X5.0Y-4.4 138 | X5.0Y-4.5 139 | X5.0Y-4.6 140 | X5.0Y-4.7 141 | X5.0Y-4.8 142 | X5.0Y-4.9 143 | X5.0Y-5.0 144 | X5.0Y-5.1 145 | X5.0Y-5.2 146 | X5.0Y-5.3 147 | T5 148 | X3.25Y-5.8 149 | X3.25Y-5.9 150 | X3.25Y-6.0 151 | X5.5Y-5.65 152 | X5.6Y-5.65 153 | X5.7Y-5.65 154 | T6 155 | X5.25Y-6.2 156 | X5.45Y-6.2 157 | X2.6Y-4.1 158 | X2.6Y-4.3 159 | X4.15Y-6.2 160 | X4.35Y-6.2 161 | X4.7Y-6.2 162 | X4.9Y-6.2 163 | X2.6Y-5.35 164 | X2.6Y-5.55 165 | X2.6Y-5.85 166 | X2.6Y-6.05 167 | X3.6Y-6.2 168 | X3.8Y-6.2 169 | T7 170 | X2.6Y-3.0 171 | X2.6Y-6.3 172 | X5.9Y-6.3 173 | X5.9Y-3.0 174 | T0 175 | M30 176 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open3DScanner 2 | ![The Open3DScanner](/images/logo.png?raw=true) 3 | 4 | The Open3DScanner is an open source photogrammetry 3D Scanner. Despite its name it does not provide you with the full photogrammetry pipeline. 5 | 6 | Instead it enables you to automaticall create sets of photos by using your smartphone camera. These photos need to be processed by your normal photogrammetry pipeline later on. 7 | 8 | But by automating the process of capturing the required photos the time you need to spend on creating a 3D scan can significantly decreased. 9 | 10 | ## Features 11 | - Automatic generation of photosets for photogrammetry 12 | - Support for android and iOS devices 13 | - Adjustable scanning parameters for different granularities of detail 14 | - Integrated LED lights to increase illumination of photos 15 | - Removable backplate and storage area below the baseplate for reduces space requirements 16 | - Adjustable scanner frame for differently sized objects 17 | - Extensive documentation, providing you with build instructions and many additional informations about photogrammetry, the design process, and other open source 3D scanners 18 | 19 | ## License 20 | Since this repository contains mixed resources (code, documents, images, ...) thera are different licenses which apply to different portions of the repository. 21 | 22 | For that reason each subfolder of the root folder contains its own LICENSE.md file which defines the license which applies to the corresponding resources. 23 | 24 | But in general code and 3D model resources are licensed under the GPLv3 while media resources (like documents and images) are licensed with the CC-BY-SA 4.0 license. -------------------------------------------------------------------------------- /STLs/Backplate-Holder_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Backplate-Holder_v1.stl -------------------------------------------------------------------------------- /STLs/Cable-Holder_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Cable-Holder_v1.stl -------------------------------------------------------------------------------- /STLs/Foot-Holder-Clamp_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Foot-Holder-Clamp_v1.stl -------------------------------------------------------------------------------- /STLs/Housing/Encoder-Holder_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Housing/Encoder-Holder_v1.stl -------------------------------------------------------------------------------- /STLs/Housing/Housing-Main_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Housing/Housing-Main_v1.stl -------------------------------------------------------------------------------- /STLs/Housing/Housing-Plate_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Housing/Housing-Plate_v1.stl -------------------------------------------------------------------------------- /STLs/Housing/Housing-Top_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Housing/Housing-Top_v1.stl -------------------------------------------------------------------------------- /STLs/Housing/Knob_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Housing/Knob_v1.stl -------------------------------------------------------------------------------- /STLs/Housing/LCD-Holder_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Housing/LCD-Holder_v1.stl -------------------------------------------------------------------------------- /STLs/Housing/LED-Holder_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Housing/LED-Holder_v1.stl -------------------------------------------------------------------------------- /STLs/Housing/MicroFit-Holder-P1_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Housing/MicroFit-Holder-P1_v1.stl -------------------------------------------------------------------------------- /STLs/Housing/MicroFit-Holder-P2_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Housing/MicroFit-Holder-P2_v1.stl -------------------------------------------------------------------------------- /STLs/Passive-Stand_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Passive-Stand_v1.stl -------------------------------------------------------------------------------- /STLs/Rotor-Arm_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Rotor-Arm_v1.stl -------------------------------------------------------------------------------- /STLs/Rotor-Gear_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Rotor-Gear_v1.stl -------------------------------------------------------------------------------- /STLs/Rotor-Pinion_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Rotor-Pinion_v1.stl -------------------------------------------------------------------------------- /STLs/Rotor-Stand_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Rotor-Stand_v1.stl -------------------------------------------------------------------------------- /STLs/Spotligt-Frame_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Spotligt-Frame_v1.stl -------------------------------------------------------------------------------- /STLs/Spotligt-Stand_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Spotligt-Stand_v1.stl -------------------------------------------------------------------------------- /STLs/Turntable-Arm_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Turntable-Arm_v1.stl -------------------------------------------------------------------------------- /STLs/Turntable-Medium_v1.stl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/STLs/Turntable-Medium_v1.stl -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nazzrim/Open3DScanner/70efe16f8fbf27a087b61e25a5c89d0acc1ae91b/images/logo.png --------------------------------------------------------------------------------