Hi again, Here is the sensor schematic: (Apologies for the quality - I am also still learning how to use the fantastic Fritzing software too! The sensor itself is fairly robust and includes mounting holes so I reckon makes a good solution with a plastic post or similar attached to the turntable/moving part to trigger it. As I mentioned I got mine from Jaycar (Aus and NZ co) but I would expect Maplin or someone similar would have an equivalent. Here is the package image and datasheet: The resistor values used give an output voltage of around 0.12v when not blocked and just under 4v when obstructed which appears to be enough difference for the Arduino to detect the change of state. I am powering it directly from the 5v and gnd pins on the Arduino along with Ray's Isolator DC circuit and the seven segment LED. For reference here is the hardware list I have used:
Arduino Duemilianove w/ ATmega328
Adafruit Motor Shield V2
DCC circuit as per Ray's posting
Sensor circuit:
ZD1901 x 1
220 ohm resistor x 1
4K7 ohm resistor x 1
Motors:
Mercury Motor SM-42BYG011-25 (200 steps per revolution)
"Transmission"
Acetal MOD 1 gear racks 4 x 250mm and 12 tooth Spur gears by HUCO via Farnell (element 14)
LED display RS987-894 (I think these are now obsolete (80's vintage from my components box) but I am sure there is a modern equivalent.
And the code: (Hopefully it posts OK)
Please note: I am a novice programmer so it isn't that elegant and although this works on my hardware, it is still a work in progress, so please use with caution (and at your own risk). Apart from that, please feel free to use it as you wish - any suggestions for improvements are welcome.
Many Thanks also to Ray for the initial code posting which was a great help in getting me started.
////////////////////////////////////////////////////////////////////////////////
//
// DCC Turntable Control Test Routines (Accessory Address 200)
#include <DCC_Decoder.h>
#include <AccelStepper.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Defines and structures
//
#define kDCC_INTERRUPT 0
typedef struct
{
int address; // Address to respond to
}
DCCAccessoryAddress;
DCCAccessoryAddress gAddresses[1];
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
// Adafruit Setup
Adafruit_MotorShield AFMStop(0x60); // Default address, no jumpers
// Connect stepper with 200 steps per revolution (1.8 degree)
// to the M3, M4 terminals (blue,yellow,green,red)
Adafruit_StepperMotor *myStepper2 = AFMStop.getStepper(200, 2);
// you can change these to SINGLE, DOUBLE, INTERLEAVE or MICROSTEP!
// wrapper for the motor! (3200 Microsteps/revolution)
void forwardstep2() {
myStepper2->onestep(FORWARD, MICROSTEP);
}
void backwardstep2() {
myStepper2->onestep(BACKWARD, MICROSTEP);
}
//Variables
long lngMotorPos;
long lngTargetPosition;
const long lngOneRev = 5690.021;
int intPos = 0;//set initial LED value
//set up for LED Display
// bits representing segments A through G (and decimal point) for numerals 0-9
const byte numeral[10] = {
//ABCDEFG /dp
B11111100, // 0
B01100000, // 1
B11011010, // 2
B11110010, // 3
B01100110, // 4
B10110110, // 5
B00111110, // 6
B11100000, // 7
B11111110, // 8
B11100110, // 9
};
// pins for decimal point and each segment
// dp,G,F,E,D,C,B,A
const int segmentPins[8] = {7,11,10,9,8,6,5,4};//defines Arduino pins for each segment
const int segmentSpin[6] = {4,5,6,8,9,10};// used to "rotate" the segments while motor is moving to sensor position
// Now we'll wrap the stepper in an AccelStepper object
AccelStepper stepper2(forwardstep2, backwardstep2);
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Decoder Init
//
void ConfigureDecoder()
{
gAddresses[0].address = 200;
gAddresses[1].address = 201;
gAddresses[2].address = 202;
gAddresses[3].address = 203;
gAddresses[4].address = 204;
gAddresses[5].address = 205;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Basic accessory packet handler
//
void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)
{
// Convert NMRA packet address format to human address
address -= 1;
address *= 4;
address += 1;
address += (data & 0x06) >> 1;
boolean enable = (data & 0x01) ? 1 : 0;
// Check for DCC imput & determine entered address
switch (address) { //Set target position based on address selected
case 200:
lngTargetPosition = lngOneRev*1;
intPos=1;
break;
case 201:
lngTargetPosition = lngOneRev*2;
intPos=2;
break;
case 202:
lngTargetPosition = lngOneRev*3;
intPos=3;
break;
case 203:
lngTargetPosition = lngOneRev*4;
intPos=4;
break;
case 204:
lngTargetPosition = lngOneRev*5;
intPos=5;
break;
case 205:
lngTargetPosition = lngOneRev*6;
intPos=6;
default:
//nothing selected
lngMotorPos=stepper2.currentPosition();
Serial.println(lngMotorPos,DEC);
}
// Serial.print("Basic addr: ");
// Serial.print(address,DEC);
// Serial.print(" activate: ");
// Serial.println(enable,DEC);
if ( enable )
{
Serial.print("Motor at: ");
lngMotorPos=stepper2.currentPosition();
Serial.println(lngMotorPos,DEC);
Serial.print("Moving to: ");
Serial.println(lngTargetPosition);
showDigit(intPos);
stepper2.moveTo(lngTargetPosition);
while (stepper2.currentPosition() != lngTargetPosition) // move to target position
stepper2.run();
digitalWrite(segmentPins[0],0);
}
else
{
// stepper2.moveTo(2000);
lngMotorPos=stepper2.currentPosition();
Serial.println(lngMotorPos,DEC);
delay(1000);
// showDigit(intPos);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Setup
//
void setup() //runs once to determine start position when sensor reached.
{
Serial.begin(9600);
AFMStop.begin(); // Start the shield
//configure pin3 as an input and enable the internal pull-up resistor
pinMode(3, INPUT_PULLUP);
//read the sensor (open collector type) value into a variable
int sensorVal = digitalRead(3);
//set stepper motor speed and acceleration
stepper2.setMaxSpeed(10000.0);
stepper2.setAcceleration(100.0);
// stepper2.setSpeed(100);
// stepper2.moveTo(800);
for(int i=0; i < 8; i++)//assign pins for led display
{
pinMode(segmentPins[i], OUTPUT); // set segment and DP pins to output
}
showDigit(10);
Serial.println("At switch off segments");
delay(1000);
// if near reference point move away
Serial.println("Check for reference point");
// delay(2000);
sensorVal = digitalRead(3);
while (sensorVal == HIGH) {
Serial.println("At Sensor");
Serial.print("Motor at: ");
lngMotorPos=stepper2.currentPosition();
Serial.println(lngMotorPos,DEC);
intPos=0;
showDigit(intPos);
sensorVal = digitalRead(3);
// forwardstep2();
delay(50);
}
// step forward to sensor index point
while (sensorVal == LOW) {
sensorVal = digitalRead(3);
Serial.println("Moving to sensor");
backwardstep2();
//stepper2.run();
digitalWrite(segmentPins[0],0);//DP off
//digitalWrite(segmentPins[1],1);
for(int i=0; i < 7; i++)//Switch onsegments
{
digitalWrite(segmentSpin[i],1);
delay(50);
digitalWrite(segmentSpin[i],0);
digitalWrite(segmentPins[0],1);//DP on
//digitalWrite(segmentPins[1],1);
}
// delay(50);
}
DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, true);
ConfigureDecoder();
DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT );
}
void showDigit( int number) //display number on seven segment display
{
boolean isBitSet;
for(int segment = 0; segment < 8; segment++) //was 1
{
if( number < 0 || number > 9){
isBitSet = 0; // turn off all segments
digitalWrite( segmentPins[segment], isBitSet);
}
else{
// isBitSet will be true if given bit is 1
isBitSet = bitRead(numeral[number], segment);
}
isBitSet = ! isBitSet; // remove this line if common cathode display
digitalWrite( segmentPins[segment], isBitSet);
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Main loop
//
void loop()
{
static int addr = 0;
////////////////////////////////////////////////////////////////
// Loop DCC library
DCC.loop();
////////////////////////////////////////////////////////////////
// Loop Stepper
stepper2.run();
}