Dear DAVID Community,

As you are probably aware, the entire DAVID company, team and product range has been integrated into HP Inc.
This forum is now read-only. Relevant content has been migrated to HP and merged into HP's Support Forums on November 1, 2016.

To start new discussions for 3D Scanning, please register and post your new topic at the HP Support Forums

Laser Scanner for Planeless Scanning

Which camera works? Where can you buy an adequate laser? And more...

Laser Scanner for Planeless Scanning

Postby WalterMo » Mon Nov 15, 2010 6:25 pm

This new controller, suitable for the planeless scanning, is a teamwork of Sven and me.
Sven has programmed the Arduino code and I have made the hardware. For a better understanding of the code he has added a lot of comments to the single statements.

The device is very similar to the 'Simple Laserscanner with Arduino':
viewtopic.php?f=6&t=1999

.....and the 'Simple Turntable with Arduino':
viewtopic.php?f=6&t=2383

But in contrast to the 'Simple Laserscanner' this controller is suitable also for planeless scanning. It is possible to do it manually or remote controlled by DAVID. Latter will work if the device is connected via an USB cable to your pc and both toggle switches, 'Laser' and 'Motor' are in its middle position. Additionally some parameters in the Advanced Settings must be set or changed:

1) Communication, COM, Portname = COMx (the number of x you will find on the device manager, USB Serial Port).
A hint: Use each time the same USB port of your pc. So the number x will be constant.

2) Communication, Messages, AnalyzeImage = set one or up to four M.
One M (the ratio motor step rate to frame rate is 1, that means high resolution with very low speed).
Four M (4 motor steps from one frame to the next. Result: higher speed). Best is to test it yourself.

3) Laserscanner, LaserPlaneCalculation, LaserMotionEstimation, Enabled = True
4) ........................................................................, MotionBase = 2
5) ........................................................................, ScanStartDetectionMode = 0
6)........................................................................., UseRememberedPlanePoses = True

Hardware

Sometimes it's difficult to get exactly the same components for a remake as what was noted on the circuit diagram. So I will give some hints:

1) LCD display:
You can use displays with 2 x 16 or 2 x 20 characters. If you have the latter please download the program 'Katie' to the Arduino. Otherwise 'KatieB'. The content on both displays is basically the same, but due to less characters the text is compressed and the unit 'Hz' for the real clock rate (downright) is saved.
It is not a requirement that you have such a display for planeless scanning if you set the controller to 'AUTO'. See below my second post of Nov 17th.

2) Voltage stabilizer for the 3V laser:
Instead of LD1117V30 you can use LD111V33 or the LM1086CT-3.3. Their TO-220 packages are pin-compatible.

3) Diodes 1N4001:
Instead of the 1N4001 you can use 1N4002, 1N4003, 1N4004, 1N4005, 1N4006 or 1N4007.

4) Transistor to switch the laser on and off:
I have chosen two BS170 in parallel because this type is rather common. There are some other MOSFETs suitable. E.g. the IRLIZ34N or the IRL530NS will also work fine. Power transistors like the latter must be used 'alone'. Important is to select a N-Channel MOSFET with a low gate_source voltage, so called Logic-Level ones.

5) Resistor R3:
This resistor is necessary to limit the backlight illumination current of the built-in LEDs. Some displays don't need it, they can directly connected to 5V. Take a look on the data sheet of your display. For the beginning and if you feel uneasy, use 180 Ohm. But some displays even need a higher voltage than 5V. If so, choose the 8.2V of the controller. Important: In this case R3 is imperative!

6) The 10k potentiometer at the display is necessary for adjusting a fine visibility of the characters.

7) The 10k potentiometer for 'Speed' must have a linear characteristic of its resistor. It can also be a 1k one. It is a linear working component, but here it acts digital, means the full range is subdived by the outreading software to 6 discrete levels. But instead of this potentiometer you can also use a 6-ary step switch. See my post below of Nov 17th.

8.) I have used two push buttons in series for the Reset of the step counter. So it's a bit safer not to reset inadvertently.

9) The toggle switches for 'Laser' and 'Motor' must be 3-position ones. Type: On-Off-On. They are connected to analog inputs and will be readout by 3 levels: 0V, 5V and just the half of 5V = 2.5V. Therefore the two resistors „around“ them must have exactly the same value.
But if you have problems to find this special toggle switches, here I have posted an alternative with SPDTs = “Single Pole Double Throw”:
viewtopic.php?f=6&p=16440#p16440

10) Here are some useful infos regarding the EasyDriver board: http://schmalzhaus.com/EasyDriver/

11) Instead of the EasyDriver V4 (max. 750mA per phase) you can also use the Big EasyDriver.....:
http://www.schmalzhaus.com/BigEasyDriver/
.....or the Pololu driver board:
http://www.watterott.com/index.php?page ... &info=1787
The last two can drive up to 2 Amp per phase and are also suitable for different microstepping modes. On this site is an example how to connect a Pololu:
viewtopic.php?f=6&t=4154

12) Instead of the Arduino Duemilanove we can use its successor, the Arduino Uno. The Uno is completely hard- and software compatible.

13) All resistors should have a wattage of 0.25W and a tolerance of 5%.

Walter

Edit: If you intend to use this controller and Sven's Katie software not with DAVID V2 but with V3 please read my post from Oct 11th 2011:
viewtopic.php?f=6&t=2421&start=210
Attachments
PlanelessControllerArdu3.jpg
PlanelessArdu4.jpg
User avatar
WalterMo
Moderator
 
Posts: 2363
Joined: Mon Apr 02, 2007 6:52 pm
Location: Braunschweig, Germany

Re: Laser Scanner for Planeless Scanning

Postby Sven » Mon Nov 15, 2010 6:36 pm

Hi,

... and here is my Arduino program for Walter's controller.

I have tried to give the program a clear structure and a few comments, to make it easy to understand and adopt. I suggest you look at it inside the Arduino editor because it looks clearer with syntax highlighting.

1) GLOBAL PARAMETER DEFINITIONS
Here you can adjust some settings like pin numbers and speeds etc. Even if you don't understand the rest of the program, you can change parameters here.

2) GLOBAL VARIABLE DECLARATIONS
There are a few global variables that store the current state, step counter etc.

3) HELPERS
Some helper functions and declarations that help make the rest of the program more simple.

4) SETUP
The setup() function that is called once at the beginning and initializes everything.

5) DISPLAY
Functions that write on the LCD. Most important: showState() which is called regularly and writes the current state (step counter etc.) to the display.

6) MOTOR
A few functions that move the stepper motor. These are the only functions that actually send steps to the stepper motor and change the global step counter. "...Rel" functions move a given number of steps relative to the current position, while "...Abs" functions move to an absolute step counter position.

7) LASER
A function that switches the laser on and off.

8 ) MAIN LOOP
Here is the loop() function which runs repeatedly. It does not communicate directly with the display or the stepper motor; instead it uses the above functions.
The loop() function first reads inputs (mechanical switches and COM), then acts according to them, then calls showState() to update the LCD.


While I was writing the core functions and looked for a name, Katie Melua was singing for me, thus the name... :D

If you have any comments or questions, don't hesitate.

(In case you are planning improvements, we could create a Wiki page for the program and collaborate on it there.)

Sven

EDIT 2011-10-15: For DAVID 3: New Katie version 1.1 is here.

Code: Select all
/*
 * "Katie"
 * Arduino program controlling a stepper motor and a laser
 * as an interface between the DAVID-Laserscanner software and
 * a motor-driven laser for automated 3D laser scanning.
 * It supports additional switches and a LC display for manual control.
 * Some functions will be supported by future DAVID versions (probably 3.0).
 *
 * Copyright (C) 2010 Sven Molkenstruck
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 *
 * You can find the GNU General Public License here: http://www.gnu.org/licenses/
 *
 */


// Requires Arduino version 0020 or later!

#include <LiquidCrystal.h>


const char PROGRAM_VERSION[20] = "Katie Version 1.0";


//////////////////////////////////
// GLOBAL PARAMETER DEFINITIONS //
//////////////////////////////////
// do not use laser and motor switches, instead force "remote control" by DAVID:
const bool FORCE_REMOTE_CONTROL = false;  // set "true" if you don't have any laser and motor switches

// analog input pins:
const int PIN_IN_SPEED   = A0;
const int PIN_IN_LASER   = A1;
const int PIN_IN_MOTOR   = A2;
const int PIN_IN_DIR     = A3;
const int PIN_IN_GO_ZERO = A4;

// digital output pins:
const int PIN_OUT_CLOCK  = 2;
const int PIN_OUT_DIR    = 3;
const int PIN_OUT_LASER  = 4;
const int PIN_OUT_LCD    = 8;  // and 5 more directly following (8-13)

// digital input pins:
const int PIN_IN_SET_ZERO = 5;

// speed steps and their delays [µs]:
const int NUM_SPEED_STEPS=6;
const unsigned long DELAYS[NUM_SPEED_STEPS] = {50000,20000,10000,5000,2000,1000};  // in µs
const unsigned long HOMING_MOTOR_DELAY = 1000;  // defines the speed for the "return" = "go home" = "go to zero" command [µs]

// Gearbox backlash compensation:
const long BACKLASH_STEPS = 500;  // number of steps

const long MIDDLE_POS = -2000;  // counter position where the laser is "in the middle" of the object / camera image
const long NUM_STEPS_FAST = 100;  // number of steps to go when receiving command "<" or ">"

// Time interval [ms] for display updates:
const unsigned long DISPLAY_INTERVAL = 200;  // 200ms --> 5 Hz


//////////////////////////////////
// GLOBAL VARIABLE DECLARATIONS //
//////////////////////////////////
long g_motorPos = 0;               ///< global motor step counter
int g_speed = 0;                   ///< global speed setting in [0,NUM_SPEED_STEPS-1]
bool g_isLaserOn = false;          ///< global state of laser (on or off)
int g_lastCOM = ' ';               ///< latest COM message
long g_dir = -1;                   ///< scan direction (1 or -1)

LiquidCrystal g_lcd(PIN_OUT_LCD, PIN_OUT_LCD+1, PIN_OUT_LCD+2, PIN_OUT_LCD+3, PIN_OUT_LCD+4, PIN_OUT_LCD+5);  // initialize the library with the numbers of the interface pins


///////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////// HELPERS /////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////


/// modes for laser and motor
enum eMode
{
  MODE_ON   = 0,
  MODE_AUTO = 1,  // "auto" means remote controlled, e.g. via serial COM port
  MODE_OFF  = 2,
};


/// Maps an "analog" input value to a descrete step value.
/// @param value The input value.
/// @param num The number of steps to convert to.
/// @param mod the maximum possible input value+1; assuming 0<=value<mod.
/// @return Discrete step value in [0,num-1]
long analogToDiscrete(long value, long num, long mod=1024)
{
  return (value*num)/mod;
  // Should also work, but not so nicely: return map(value,0,mod-1,0,num);
}

/// Maps an "analog" input value into one of the eModes MODE_OFF, MODE_AUTO, or MODE_ON. See #analogToDescrete and #eMode.
eMode analogToMode(long value, long mod=1024)
{
  return (eMode)analogToDiscrete(value,3,mod);
}


/// Delays until a given time span has passed SINCE THE LAST CALL.
/// So when e.g. you want a delay of 1000µs between two actions, but some other code has consumed 200µs already, call this function with delay_us=1000 and it will delay only 800µs.
/// Uses lastTime to store the time stamp of the call. So you must call this function repeatedly with reference to the same lastTime variable.
/// @param delay_us How many µs to delay (since the last call).
/// @param lastTime Reference to a (static) variable that is used to remember the time stamp of the previous call.
void delaySinceLastCall(unsigned long delay_us, unsigned long &lastTime)
{
  unsigned long m;
 
  do
  {
    m=micros();  // get current time stamp
    if (m<lastTime) lastTime=m;  // reset when micros() has flown over (happens every 2^32 µs = 71.6 minutes)
  }
  while (m-lastTime <= delay_us);  // loop until delay_us µs have passed
 
  lastTime = m;  // remember this time stamp for next time
}


///////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////// SETUP //////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////

/// The setup() method runs once, when the sketch starts.
void setup()
{
  // Init LC Display:
  g_lcd.begin(20, 2);

  // Init serial port:
  Serial.begin(9600);
 
  // Init input pins:
  pinMode(PIN_IN_SPEED,    INPUT);
  pinMode(PIN_IN_LASER,    INPUT);
  pinMode(PIN_IN_MOTOR,    INPUT);
  pinMode(PIN_IN_DIR,      INPUT);
  pinMode(PIN_IN_GO_ZERO,  INPUT);
  pinMode(PIN_IN_SET_ZERO, INPUT);

  // Pull inputs to HIGH by a pull-up resistor, in case they are left "open":
  digitalWrite(PIN_IN_SPEED, HIGH);
  digitalWrite(PIN_IN_LASER, HIGH);
  digitalWrite(PIN_IN_MOTOR, HIGH);
  digitalWrite(PIN_IN_DIR, HIGH);
  digitalWrite(PIN_IN_GO_ZERO, HIGH);
  digitalWrite(PIN_IN_SET_ZERO, HIGH);
 
  // Init output pins:
  pinMode(PIN_OUT_CLOCK, OUTPUT);
  pinMode(PIN_OUT_DIR,   OUTPUT);
  pinMode(PIN_OUT_LASER, OUTPUT);
 
  // Show welcome message:
  g_lcd.clear();
  g_lcd.setCursor(0,0);
  g_lcd.print(PROGRAM_VERSION);
  g_lcd.setCursor(0,1);
  g_lcd.print("DAVID-Laserscanner");
  delay(3000);
  g_lcd.clear();
}


///////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////// DISPLAY ////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////

/// Prints a given floating point value on LCD, with given number of digits and precision.
/// @param lcd Reference to the LyquidCrystal object.
/// @param value The float value to be printed.
/// @param width The total number of digits to print (max. 20).
/// @param precision The number of positions after decimal point.
/// Example: value=12.345678, width=7, precision=3 will print " 12.346".
void printFormattedFloat(LiquidCrystal &lcd, float value, int width, int precision)
{
  char string[20];  // temporary string buffer
  dtostrf(value, width, precision, string);  // convert to string using dtostrf
  lcd.print(string);  // print
}


/// Shows the current state (step counter, laser on/off, motor speed, COM message) on LCD.
/// Prints only those values to the LCD which have changed.
void showState()
{
  // static variables remembering the last state (which is shown on display),
  // so that this function can know what has changed since last time,
  // and does not need to write values to display more than necessary:
  static int  last_isLaserOn = -42;
  static long last_motorPos = -42;  // for step display
  static long last_motorPos2 = -42;  // for speed measurement
  static int  last_speed = -42;
  static int  last_ch = 0;
 
  static unsigned long lastTime = 0;  // remember last call time stamp

  //-----------------
  // FIRST LCD LINE:
  //-----------------
  // Laser on/off:
  if (g_isLaserOn!=last_isLaserOn)  // if the laser has changed since last time
  {
    g_lcd.setCursor(0,0);
    g_lcd.print("Laser:");
    if (g_isLaserOn) g_lcd.print("1");
    else             g_lcd.print("0");
    last_isLaserOn = g_isLaserOn;  // remember new laser state
  }
 
  // motor step counter:
  if(last_motorPos!=g_motorPos)  // if the motor position has changed since last time
  {
    g_lcd.setCursor(8,0);
    g_lcd.print("Step        ");
    g_lcd.setCursor(12,0);
    g_lcd.print(":");
    g_lcd.setCursor(13,0);
    g_lcd.print(g_motorPos);
    last_motorPos = g_motorPos;  // remember new motor position
  }
 
  //------------------
  // SECOND LCD LINE:
  //------------------
  // COM:
  if (last_ch!=g_lastCOM)
  {
    g_lcd.setCursor(0,1);
    g_lcd.print("COM: ");
    g_lcd.setCursor(4,1);
    g_lcd.print((char)g_lastCOM);
    last_ch = g_lastCOM;
  }
  g_lastCOM = ' ';  // show nothing next time

  // Speed setting:
  if (last_speed!=g_speed)  // if speed has changed
  {
    g_lcd.setCursor(6,1);
    g_lcd.print("Spd:");
    if (g_speed<0) g_lcd.print("R");        // Show "R" for "Returning"
    else           g_lcd.print(g_speed+1);  // speed is [0-5], but show as [1-6]
    last_speed = g_speed;  // remember for next time
  }
 
  // Measured speed:
  {
    g_lcd.setCursor(13,1);
    long stepsPassed = g_motorPos-last_motorPos2;
    unsigned long now = micros();  // current time stamp
    if (0!=stepsPassed)
    {
      float dt = (float)(now-lastTime)/1E6;  // delta t in s
      float spd = (float)stepsPassed / dt;  // steps per second
      printFormattedFloat(g_lcd, fabs(spd), 5, 1);  // remove sign and convert speed to Hz in ###.# format
      g_lcd.print("Hz");
      lastTime=now;  // remember time stamp for next time
      last_motorPos2=g_motorPos;  // remember new motor position
    }
    else
    {
      g_lcd.print("       ");  // show no speed
    }
  }
}


///////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////// MOTOR //////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////

/// Lets the motor move a given number of steps.
/// This is the only function that really sends signals to the motor and changes g_motorPos!
/// @param steps The number of steps. Use a negative value for backward direction.
/// @param motorDelay Delay between rising and falling edges [µs]. Default HOMING_MOTOR_DELAY.
void moveMotorRel(long steps, unsigned long motorDelay=HOMING_MOTOR_DELAY)
{
  if (steps>0) digitalWrite(PIN_OUT_DIR, HIGH);  // move forward
  else         digitalWrite(PIN_OUT_DIR, LOW);   // move backward
  delayMicroseconds(50);  // Time for the motor driver to set direction

  static unsigned long lastTime=0;
  for (long i=0; i<abs(steps); ++i)
  {
    delaySinceLastCall(motorDelay,lastTime);
    digitalWrite(PIN_OUT_CLOCK, HIGH);
    delaySinceLastCall(motorDelay,lastTime);
    digitalWrite(PIN_OUT_CLOCK, LOW);
  }

  g_motorPos += steps;  // update the global step counter
}

/// Moves the motor to a given absolute step position.
void moveMotorAbs(long pos, unsigned long motorDelay=HOMING_MOTOR_DELAY)
{
  moveMotorRel(pos-g_motorPos, motorDelay);
}

/// Moves the motor to a given absolute step position, and updates display regularly.
void moveMotorAbs_withDisplay(long pos, unsigned long motorDelay=HOMING_MOTOR_DELAY)
{
  // Go step by step:
  long stepsToGo = abs(pos-g_motorPos);  // how many steps
  long dir = (pos>g_motorPos) ? 1 : -1;  // direction of each step (1 or -1)

  unsigned long lastTime=0;  // time stamp for display update
  for (long i=0; i<stepsToGo; ++i)  // each step separately
  {
    moveMotorRel(dir,motorDelay);  // make one step

    unsigned long time=millis();      // in ms
    if (time-lastTime>DISPLAY_INTERVAL)  // if at least DISPLAY_INTERVAL ms have passed
    {
      showState();  // update display
      lastTime=time;  // reset time stamp
    }
  }
}

/// Moves the motor to the zero position. Always goes BACKLASH_STEPS over 0 to compensate gearbox backlash.
void moveMotorHome(unsigned long motorDelay=HOMING_MOTOR_DELAY)
{
  // move a little over 0 to compensate backlash:
  moveMotorAbs_withDisplay(-g_dir*BACKLASH_STEPS,  motorDelay);

  // move to 0:
  moveMotorAbs(0, motorDelay);
}

/// Moves the motor to the zero position. Always goes BACKLASH_STEPS over 0 to compensate gearbox backlash.
/// Uses moveMotorAbs_withDisplay which regularly updates the display.
void moveMotorHome_withDisplay(unsigned long motorDelay=HOMING_MOTOR_DELAY)
{
  int rememberedSpeed = g_speed;
  g_speed = -1;  // for display
 
  // move a little over 0 to compensate backlash:
  moveMotorAbs_withDisplay(-g_dir*BACKLASH_STEPS,  motorDelay);

  // update display:
  showState();
  delay(200);

  // move to 0:
  moveMotorAbs_withDisplay(0, motorDelay);
  delay(200);
 
  g_speed = rememberedSpeed;  // re-set speed
}



///////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////// LASER //////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////

/// setLaser(true) switches the laser on. setLaser(false) switches the laser off.
void setLaser(bool on)
{
  if (on==g_isLaserOn) return;  // nothing to do
 
  if (on==true)
  {
    // switch the laser on
    digitalWrite(PIN_OUT_LASER, HIGH);
  }
  else
  {
    // switch the laser off
    digitalWrite(PIN_OUT_LASER, LOW);
  }

  g_isLaserOn = on;  // remember the new laser state
}


///////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////// MAIN LOOP //////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////

/// the loop() method runs over and over again, as long as the Arduino has power
void loop()
{
  //------------------
  // Read input pins:
  //------------------
  // Laser: OFF, AUTO, or ON. See #eMode declaration.
  eMode laserMode = analogToMode(analogRead(PIN_IN_LASER));

  // Motor: OFF, AUTO, or ON. See #eMode declaration.
  eMode motorMode = analogToMode(analogRead(PIN_IN_MOTOR));

  if (FORCE_REMOTE_CONTROL)
  {
   // Overwrite to AUTO:
   laserMode = MODE_AUTO;
   motorMode = MODE_AUTO;
  }
 
  // Direction: -1=down, 1=up
  g_dir = analogToDiscrete(analogRead(PIN_IN_DIR),2) * 2 - 1;
 
  // Speed: 0 to NUM_SPEED_STEPS-1
  g_speed = analogToDiscrete(analogRead(PIN_IN_SPEED),NUM_SPEED_STEPS);

  // Move to zero
  bool moveHome = 1-analogToDiscrete(analogRead(PIN_IN_GO_ZERO),2);

  // Set counter to zero:
  bool setZero = !digitalRead(PIN_IN_SET_ZERO);

  //--------------------------
  // Act according to inputs:
  //--------------------------
  // Set laser:
  if      (MODE_OFF  ==laserMode) setLaser(false);
  else if (MODE_ON   ==laserMode) setLaser(true);
  else if (MODE_AUTO ==laserMode && MODE_AUTO!=motorMode) setLaser(MODE_ON==motorMode);
 
  // Motor:
  if (moveHome) moveMotorHome_withDisplay(HOMING_MOTOR_DELAY);
  if (MODE_ON==motorMode) moveMotorRel(g_dir,DELAYS[g_speed]);  // move one step in the desired direction

  // Counter:
  if (setZero) g_motorPos = 0;
 
  //----------------------------
  // Read serial input into ch:
  //----------------------------
  int ch = 0;
  if (Serial.available() > 0)
  {
    // read the incoming byte:
    ch = Serial.read();
    g_lastCOM = ch;  // remember in g_lastCOM (for display)
  }
 
  //--------------------------------------------------------
  // Act according to ch, if motorMode and laserMode allow:
  //--------------------------------------------------------
  if (MODE_AUTO==motorMode)  // allow remote control of motor
  {
    if ('+' == ch)      moveMotorRel(1);                                      // one step forward
    else if ('-' == ch) moveMotorRel(-1);                                     // one step backward
    else if ('>' == ch) moveMotorRel(NUM_STEPS_FAST);                         // several steps forward
    else if ('<' == ch) moveMotorRel(-NUM_STEPS_FAST);                        // several steps backward
    else if ('M' == ch) moveMotorRel(g_dir);                                  // one step forward
    else if ('Q' == ch) moveMotorHome_withDisplay(HOMING_MOTOR_DELAY);        // move to zero [deprecated?]
    else if ('#' == ch)  // move laser into camera image:
    {
      if (MODE_AUTO==laserMode) setLaser(true);                               // switch laser on
      moveMotorAbs_withDisplay(MIDDLE_POS, HOMING_MOTOR_DELAY);               // move to MIDDLE_POS
    }
    else if ('P' == ch)  // Prepare for next scan:
    {
      if (MODE_AUTO==laserMode) setLaser(true);                               // switch laser on
      moveMotorHome_withDisplay(HOMING_MOTOR_DELAY);                          // move to zero
      if (MODE_AUTO==laserMode) setLaser(false);                              // switch laser off
    }
  }
  if (MODE_AUTO==laserMode)  // allow remote control of laser
  {
    if ('S' == ch) setLaser(true);                                            // scan start --> switch laser on
    else if ('L' == ch) setLaser(true);                                       // switch laser on
    else if ('l' == ch) setLaser(false);                                      // switch laser off
    else if ('1' == ch) setLaser(false);                                      // cam.calib --> switch laser off
    else if ('3' == ch) setLaser(false);                                      // texturing --> switch laser off
  }
 
  if ('T' == ch)  // received "Stop"
  {
    if (MODE_AUTO==motorMode) moveMotorHome_withDisplay(HOMING_MOTOR_DELAY);  // move to zero
    if (MODE_AUTO==laserMode) setLaser(false);                                // switch laser off
  }

  if ('0' == ch) g_motorPos = 0;                                              // Reset step counter

  //------------------------------------
  // Show the current state on display:
  //------------------------------------
  static unsigned long lastTime=0;  // in ms
  unsigned long time=millis();      // in ms
  if (time-lastTime>DISPLAY_INTERVAL)  // if at least DISPLAY_INTERVAL ms have passed
  {
    showState();  // update display
    lastTime=time;  // reset timer
  }
}
Attachments
Katie.zip
Ardiuno source code "Katie"
(5.29 KiB) Downloaded 1082 times
User avatar
Sven
DAVID Developer
 
Posts: 1541
Joined: Mon Jan 22, 2007 8:59 am
Location: Braunschweig, Germany

Re: Laser Scanner for Planeless Scanning

Postby Khalid Khattak » Mon Nov 15, 2010 7:01 pm

Hi Walter and Sven... What a generous peoples you are.. I love you both... Thanks for sharing.. I have to read it in details..
Regards
PC: Dell Inspiron i3, 2.27GHz,4GB RAM,64 bit windows 7
CAMERA:
David CCD Mono USB
LASER:
David 5mW Green line laser
PROJECTOR:
3D LED Mini Projector 250lumens, Native 1024x600
[b]http://free3dscans.blogspot.com/
Khalid Khattak
 
Posts: 942
Joined: Thu Apr 23, 2009 1:30 pm
Location: Pakistan

Re: Laser Scanner for Planeless Scanning

Postby pottersfriend » Mon Nov 15, 2010 7:32 pm

Yes, thanks! Very helpful.
pottersfriend
 
Posts: 153
Joined: Wed Jun 03, 2009 1:49 am
Location: Washington State, USA

Postby hal » Mon Nov 15, 2010 10:11 pm

Good works guys! :D

Sharing is a good way to grow up this scan-community.
Thanks for your efforts, Walter and Sven.

Mattia
User avatar
hal
Moderator
 
Posts: 1527
Joined: Thu Mar 01, 2007 4:08 pm
Location: Cavaria con Premezzo (VA), Italy.

Re: Laser Scanner for Planeless Scanning

Postby pottersfriend » Mon Nov 15, 2010 10:51 pm

Just found out that the latest EasyStepper boards are fixed to 1/8th microstepping but I was still curious if anyone thinks it would be a good idea to add some sort of microstepping control for earlier EasyStepper or Pololu boards? I have a Pololu board, which is very similar to the EasyStepper, and I've been playing around with the microstepping but have always found it a pain to have to change the microstepping in the software and upload it to the Arduino. It would be nice to be able to set it with another knob on the controller if possible.

Not sure if other users would find the option useful, but thought I'd mention it. Something to think about I guess.

Thanks again for all of your hard work. I'm looking forward to playing with this when I get some time.
pottersfriend
 
Posts: 153
Joined: Wed Jun 03, 2009 1:49 am
Location: Washington State, USA

Re: Laser Scanner for Planeless Scanning

Postby WalterMo » Tue Nov 16, 2010 10:04 am

Here we have an overview of all EasyDriver boards:
http://schmalzhaus.com/EasyDriver/

The latest versions V4.2 and V4.3 have the possibility to change the step mode by external „hardware programming“. There are the two logic inputs MS1 and MS2. If they are left open the board runs in 1/8 step microstepping. By connecting one or both to 0V (Gnd), fullstep, halfstep or quarterstep can be achieved. See the datasheet of the IC A3967.
User avatar
WalterMo
Moderator
 
Posts: 2363
Joined: Mon Apr 02, 2007 6:52 pm
Location: Braunschweig, Germany

Re: Laser Scanner for Planeless Scanning

Postby WalterMo » Wed Nov 17, 2010 8:44 am

I have modified Sven's Katie software a bit for a smaller display with 2 x 16 characters.
The new name is now KatieB.

Edit (May 2012): Also please find KatieB V1.1 for DAVID V3.
Attachments
KatieB.zip
Arduino source code "KatieB"
(5.53 KiB) Downloaded 454 times
KatieB_1_1.zip
Arduino source code "KatieB v1.1"
(5.79 KiB) Downloaded 393 times
User avatar
WalterMo
Moderator
 
Posts: 2363
Joined: Mon Apr 02, 2007 6:52 pm
Location: Braunschweig, Germany

Re: Laser Scanner for Planeless Scanning

Postby Ordibble Plop » Wed Nov 17, 2010 9:33 am

Many thanks Walter and Sven for devising this controller and publishing it. I know what I want for Christmas so I had better put my beard on and go to the shops :)
Ordibble Plop
 
Posts: 103
Joined: Mon Mar 12, 2007 7:18 am
Location: New Zealand

Re: Laser Scanner for Planeless Scanning

Postby WalterMo » Wed Nov 17, 2010 6:52 pm

The controller Ardu3 can also be used without a LCD display. But then it's better to use a step switch instead of the 10k potentiometer. This ensures that each time the correct same speed is adjusted. Otherwise, because there isn't a control by the display, it might happen that it differs for the reference and the repetition scan. :(

Walter
Attachments
Potentiometerersatz.jpg
Instead of the potentiometer
User avatar
WalterMo
Moderator
 
Posts: 2363
Joined: Mon Apr 02, 2007 6:52 pm
Location: Braunschweig, Germany

Re: Laser Scanner for Planeless Scanning

Postby pottersfriend » Wed Nov 17, 2010 7:46 pm

@Walter - I re-read the EasyStepper http://www.schmalzhaus.com/EasyDriver/ description so I guess I was a bit confused on the microstepping. I think the "Quick Specs:" text is referring to the older boards where he said, "It is permanently set to use 8 step microstepping mode." Anyway, just wanted to put this here so others know, as you stated, the newer boards DO support microstepping.

Thanks for the clarification.

Darin
pottersfriend
 
Posts: 153
Joined: Wed Jun 03, 2009 1:49 am
Location: Washington State, USA

Re: Laser Scanner for Planeless Scanning

Postby pledgy2000 » Thu Nov 25, 2010 9:58 pm

Hi all

I have ordered an Arduino and lcd so I can have a go at building a controller.
At the moment I am using a second PC running Mach3 to control the stepper motor so it will be a big improvement.
I have been looking at the circuit diagram and can understand all but the ground connection to the easy driver step/direction.
You have the ground connected via 10k resistors to both the step and direction lines so with my limited knowledge I am unsure as to where the ground is coming from.

Dave
pledgy2000
 
Posts: 13
Joined: Tue Nov 02, 2010 12:03 pm

Re: Laser Scanner for Planeless Scanning

Postby WalterMo » Thu Nov 25, 2010 11:27 pm

Hi Dave,

The Gnd of both 10k resistors is coming out of the EasyDriver board. Means it is the very same as the Power In Gnd. Both Gnd are connected on (by) the board. I have simply drawn it in this way to save Gnd lines around the board.
Regarding Gnd lines in general: Best is to distribute Gnd lines radially from the 9V input jack to each load (board). The same is true for the 8.2V wires.

Walter
User avatar
WalterMo
Moderator
 
Posts: 2363
Joined: Mon Apr 02, 2007 6:52 pm
Location: Braunschweig, Germany

Re: Laser Scanner for Planeless Scanning

Postby pledgy2000 » Fri Nov 26, 2010 8:39 pm

Hi Walter

Thank you for explaining that it all makes sense now, I am used to drives that isolate the motor supply from the step and direction.
My Arduino came today so I will be busy experimenting this week end.

Dave
pledgy2000
 
Posts: 13
Joined: Tue Nov 02, 2010 12:03 pm

Re: Laser Scanner for Planeless Scanning

Postby milz » Sun Nov 28, 2010 8:40 am

heho

related to this cross posting (sorry)
viewtopic.php?f=9&t=2261&start=30

WalterMo wrote:Hi milz,
We could develop nearly everything. But how many users would like to use it? And where should it be manufactured? If the number of items is low, the price would be horrendous.

What I was thinking about, was to „produce“ a printed circuit board for our new planeless controller. It should have on board the 3V stabilizer and the MOSFet switch for the laser.
I have an exposure box and an etching equippment available. Not a professional one, only for hobbyists. And I prefer single-sided copper laminated.

Walter



at first i would say my controller are very inspirational from some ideas here
thanks for sharing all the knowledge -)

I love the idea with a professional made ciruit board.
last night i searched for cheap membrane keyboard and found this
http://www.shop.display3000.com/wichtig ... bs600.html
combined with a A/D converter its need only one pin and i believe no pull down resistors etc ...

back to the main idea circuit board. i love do think automaticly cause i hate work -)
my controller setup can do for example 8 scans with textures (lights) and save it.
do calibration >> starts scan >> go away drink coffee >> came back 10 min later an all is done -)
so here a small list from my side what the controller must have
- 2 Stepmotor controller (laserdrive / turntable)
- 3V Regulator for Laser with relais
- Camera Trigger Port
- A/D converter for the buttons
- LCD Panel hooked up via I2C to save pins
- Connection for a auto zoom/focus lens (not sure how to do this)
- Relais for 220/110V to trigger lights for texture shots (not sure about laws and safety regulations)

perhaps we can start develop a solutions with a eagle file. I think with some cheap ICs its possible to drop the price.
my controller setup works fine but when im look inside it looks ugly -)
im not sure how many user need it. i have around 20000 hits on my David youtube videos and often
the question how to build a scanner setup.

Perhaps we can ask the chinese spammer who try to sell wedding dresses here to build a cheap one :lol:

mfg milz
Xeon x5650@4ghz
Cam : USB2 CCD 1024x768 / USB3 1280x900
Laser : LC532-5-3-F(16x65) Focusable Green
Projector Acer X110P / Acer K132
dControl one David control box + Turntable + automatic texture lights
mooooom bathroom!!!!!!
User avatar
milz
 
Posts: 520
Joined: Wed Jul 15, 2009 12:24 pm
Location: Germany Cologne

Next

Return to Laser and Camera Hardware

Who is online

Users browsing this forum: No registered users and 2 guests

cron