Hi all, I have built one of the DIY Desktop 3d Scanner from indestructible and am having a problem that is driving me crazy.
It is supposed to use the select button to start scanning, the left button to manually move 1 unit clock wise, up to cycle through options, down to move one step ccw, right to move 1step CW. The only button I can get to work is the right button. I have tried several different shields.
Here is a copy of the sketch:
/* Shapespeare Scanner by Whitney Potter
This work is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
Controls
SELECT: Start/Stop automatic scan.
LEFT: Trigger exposure and advance one unit clockwise.
RIGHT: Step one unit clockwise without triggering camera.
DOWN: Step one unit counter clockwise without triggering camera.
UP: Cycle through options for number of exposures per revolution.
*/
#include <LiquidCrystal.h>
#include "DFR_Key.h"
#include <Stepper.h>
#include "multiCameraIrControl.h"
const int stepsPerRevolution = 200*64; // change this to fit the number of steps per revolution for your motor
Stepper myStepper(stepsPerRevolution, 20,21); // initialize stepper
// Enable pin is 19. Step pin is 20. Direction pin is 21
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); //pin assignments for SainSmart LCD Keypad Shield
DFR_Key keypad; // initialize keypad
int localKey = 0;
int lastKey = 0;
int keyChange = 1; //set true when key is released. Prevents double triggers.
int stepChoices [] = {25,50,75,100,200}; //different numbers of exposures per revolution which may be selected. Higher number = smaller angle change
int stepIndex = 0; // count exposures starting at 1
int numChoices = 5; //number of step choices
int runFlag = 0; //is scanner running
int stepCount =1; // count exposures starting at 1
unsigned long startWait; //time we start the wait timer
unsigned long currentTime; // current time
const long preWait = 2000; // pre exposure pause in milis. Allows the specimen to settle before exposure.
const long postWait = 2000; // post exposure pause in milis. Allows time for the exposure to finish before moving.
int waitFlag = 0; // 0=ready to move 1=pre-exposure wait 2=post-exposure wait
Nikon Camera(53); //change Nikon to any other supported brand
void setup()
{
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Shapespeare Scanner");
delay(2500);
lcd.clear();
// set the speed at 60 rpm:
myStepper.setSpeed(2);
pinMode(19, OUTPUT); //enable pin
digitalWrite(19, HIGH);
}
void loop(){
//
lcd.setCursor(0,0);
lcd.print("Steps:");
lcd.setCursor(6,0);
lcd.print(" ");
lcd.setCursor(6,0);
lcd.print(stepChoices[stepIndex]);
lcd.setCursor(0,1);
if (runFlag == 1)
{
lcd.print("run ");
}
else
{
lcd.print("stop ");
}
localKey = keypad.getKey(); // read keypad
if (localKey != SAMPLE_WAIT)
{
if (localKey == 0) // key has been released
{
keyChange = 1; // the next key data represents a new key press
}
if (localKey ==4 && keyChange == 1) //select=start sequence
{
if (runFlag == 0 && keyChange ==1)
{
runFlag = 1;
waitFlag = 0;
keyChange = 0;
}
if (runFlag == 1 && keyChange ==1)
{
runFlag = 0;
stepCount = 1; //uncomment to reset stepCount every time the auto scan is stopped.
keyChange = 0;
}
}
if (localKey ==2 ) //left=manual mode
{
keyChange =0;
lcd.setCursor(0,1);
lcd.print("manual");
Camera.shutterNow(); //trigger exposure
delay (postWait); //wait for exposure to complete
digitalWrite(19, LOW); // activate stepper driver
myStepper.step(stepsPerRevolution/stepChoices[stepIndex]); // advance stepper
digitalWrite(19, HIGH); // deactivate stepper driver to save power, heat and noise
stepCount ++;
}
if (localKey ==3 && runFlag ==0) //up cycle through angle choices
{
keyChange =0;
if (stepIndex < numChoices -1)
{
stepIndex ++;
}
else
{
stepIndex = 0;
}
}
if (localKey == 5 ) //down
{
keyChange =0;
lcd.setCursor(0,1);
lcd.print("CCW step");
digitalWrite(19, LOW);
myStepper.step(-stepsPerRevolution/stepChoices[stepIndex]);
digitalWrite(19, HIGH);
}
if (localKey == 1 && keyChange == 1) //right
{
keyChange =0;
lcd.setCursor(0,1);
lcd.print("CW step");
digitalWrite(19, LOW);
myStepper.step(stepsPerRevolution/stepChoices[stepIndex]);
digitalWrite(19, HIGH);
}
}
if (runFlag == 1) //sequence is running
{
if (stepCount > stepChoices[stepIndex]) //the revolution is complete.
{
runFlag = 0; // stop sequence
lcd.setCursor(9,1);
lcd.print("Done ");
}
//This interrupt based time delay allows us to still receive keypad input during the delay
currentTime = millis();
if (waitFlag == 0) // advance stepper and start wait timer
{
startWait = millis();
waitFlag = 1; // start preshutter wait
lcd.setCursor(9,1);
lcd.print("Exp#: ");
lcd.setCursor(13,1);
lcd.print(stepCount);
digitalWrite(19, LOW); //activate stepper driver
myStepper.step(stepsPerRevolution/stepChoices[stepIndex]); //advance stepper
digitalWrite(19, HIGH); //deactivate stepper driver
}
if (waitFlag == 1) // when preshutter wait expires trigger shutter
{
if (currentTime - startWait >= preWait) //wait time has expired
{
Camera.shutterNow(); // trigger shutter
startWait = millis(); // restart wait timer
waitFlag = 2; // initiate post shutter wait
stepCount ++;
}
if (waitFlag == 2) // wait after triggering shutter before moving motor
{
if (currentTime - startWait >= postWait) //wait time has expired
{
waitFlag = 0; //done waiting
}
}
}
}
}
And here is the shield sketch:
#ifndef DFR_Key_h
#define DFR_Key_h
#include "Arduino.h"
#define SAMPLE_WAIT -1
#define NO_KEY 0
#define UP_KEY 3
#define DOWN_KEY 4
#define LEFT_KEY 2
#define RIGHT_KEY 5
#define SELECT_KEY 1
class DFR_Key
{
public:
DFR_Key();
int getKey();
void setRate(int);
private:
int _refreshRate;
int _keyPin;
int _threshold;
int _keyIn;
int _curInput;
int _curKey;
int _prevInput;
int _prevKey;
boolean _change;
unsigned long _oldTime;
};
#endif
Thanks for any help!!!!!