I managed to code an interface in Python that tells the Arduino to move the steppers:
Attachment:
VirtuRange_Gui_V00.JPG [ 19.66 KiB | Viewed 20931 times ]
The upper part defines the COM boards. Enter the COM of the Arduino and hit "init" to set up the connection.
The lower part defines, how many steps the LIDAR should move (5 in this example) to the next measurement point. "MaxSteps" are the total amount of steps in Y- and Z-Axis. 1.600 steps would be a full rotation, 800 half, 400 a quarter aso.
This is the Python code:
Code:
#Source: http://www.tkdocs.com/tutorial/install.html#helloworld
# // String "mx10100"
# // m ... "move"
# // s ... "start"
# // x ... "stop"
# // x ... x-Axis
# // y ... y-Axis
# // 1 ... turn cw
# // 0 ... turn ccw
# // 0100 ... make 100 Microsteps
from tkinter import *
from tkinter import ttk
import serial
import time
import sys
class MyGui:
def __init__(self, master):
mainframe = ttk.Frame(master, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S))
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
ySteps = StringVar()
zSteps = StringVar()
yStepsMax = StringVar()
zStepsMax = StringVar()
yPosition = StringVar()
zPosition = StringVar()
arduinoCom = StringVar()
flukeCom = StringVar()
ttk.Label(mainframe, text="Arduino COM").grid(column=1, row=1, sticky=N)
ttk.Label(mainframe, text="Fluke COM").grid(column=1, row=2, sticky=N)
ttk.Label(mainframe, text="Y-Axis").grid(column=1, row=4, sticky=N)
ttk.Label(mainframe, text="Z-Axis").grid(column=1, row=5, sticky=N)
ttk.Label(mainframe, text="Steps").grid(column=2, row=3, sticky=E)
ttk.Label(mainframe, text="Max Steps").grid(column=3, row=3, sticky=E)
ttk.Label(mainframe, text="Position").grid(column=4, row=3, sticky=E)
self.arduinoCom = ttk.Entry(mainframe, width=2, textvariable=arduinoCom)
self.arduinoCom.grid(column=2, row=1, sticky=(W, E))
self.arduinoCom.insert(0, "COM4")
self.flukeCom = ttk.Entry(mainframe, width=2, textvariable=flukeCom)
self.flukeCom.grid(column=2, row=2, sticky=(W, E))
self.ySteps = ttk.Entry(mainframe, width=7, textvariable=ySteps)
self.ySteps.grid(column=2, row=4, sticky=(W, E))
self.ySteps.insert(0,"1")
self.zSteps = ttk.Entry(mainframe, width=7, textvariable=zSteps)
self.zSteps.grid(column=2, row=5, sticky=(W, E))
self.yStepsMax = ttk.Entry(mainframe, width=7, textvariable=yStepsMax)
self.yStepsMax.grid(column=3, row=4, sticky=(W, E))
self.zStepsMax = ttk.Entry(mainframe, width=7, textvariable=zStepsMax)
self.zStepsMax.grid(column=3, row=5, sticky=(W, E))
self.yPosition = ttk.Label(mainframe, width=7, textvariable=yPosition)
self.yPosition.grid(column=4, row=4, sticky=(W, E))
self.zPosition = ttk.Label(mainframe, width=7, textvariable=zPosition)
self.zPosition.grid(column=4, row=5, sticky=(W, E))
ttk.Button(mainframe, text="init", command=self.scanInit).grid(column=3, row=2, sticky=W)
ttk.Button(mainframe, text="Start", command=self.scanStart).grid(column=2, row=6, sticky=W)
ttk.Button(mainframe, text="Stop", command=self.scanStop).grid(column=3, row=6, sticky=W)
ttk.Button(mainframe, text="Exit", command=self.scanExit).grid(column=4, row=6, sticky=W)
for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)
def callback(self):
self.root.quit()
def scanStart(self):
self.scanStop()
global scanState
scanState = 1
if (ser.isOpen()):
ser.write(bytes("s", encoding='ascii'))
scanSeq = MyScanLoop(self.ySteps.get(),self.yStepsMax.get(),self.zSteps.get(),self.zStepsMax.get())
scanSeq.run()
def scanStop(self):
global scanState
scanState = 0
if (ser.isOpen()):
ser.write(bytes("x", encoding='ascii'))
def scanExit(self):
ser.close()
sys.exit()
def scanInit(self):
ser.setPort(self.arduinoCom.get())
ser.baudrate = 9600
ser.open()
class MyScanLoop:
def __init__(self, ySteps, yStepsMax, zSteps, zStepsMax):
self.ySteps = int(ySteps)
self.yStepsMax = int(yStepsMax)
self.zSteps = int(zSteps)
self.zStepsMax = int(zStepsMax)
def run(self):
z = 1
dirY = "0"
while z <= self.zStepsMax:
y = 1
while y <= self.yStepsMax:
if (ser.isOpen()):
stpY = str(self.ySteps)
command = "my" + dirY + stpY.zfill(4)
ser.write(bytes(command, encoding='ascii'))
y = y + self.ySteps
root.update()
time.sleep(0.5)
if scanState == 0:
return
if dirY == "1":
dirY = "0"
else:
dirY = "1"
if (ser.isOpen()):
stpZ = str(self.zSteps)
command = "mz0" + stpZ.zfill(4)
ser.write(bytes(command, encoding='ascii'))
z = z + self.zSteps
root.update()
time.sleep(0.5)
if (ser.isOpen()):
ser.write(bytes("x", encoding='ascii'))
ser = serial.Serial()
global scanState
root = Tk()
app = MyGui(root)
root.mainloop()
and this is the Firmware of the Arduino:
Code:
/* VirtuRange Firmware V11 by VirtuMake
** Follow it at www.diy3dscan.com
** Homebase www.virtumake.com
** This is Open Source. Do whatever you want with the code :)
** low/low Full Step (2 phase)
** high/low Half Step
** low/high Quarter Step
** high/high Eight Step
** Step Full = 1,8° = 200 steps * 8 = 1600 steps
*********************************************************/
int dirPinY = 4;
int stepperPinY = 5;
int dirPinZ = 2;
int stepperPinZ = 3;
int sleepPin = 7;
int MS1 = 10;
int MS2 = 11;
char command;
char doit[2];
char dost[4];
int stepperPin;
int dirPin;
char dir;
int steps;
void setup() {
pinMode(dirPinY, OUTPUT);
pinMode(stepperPinY, OUTPUT);
pinMode(dirPinZ, OUTPUT);
pinMode(stepperPinZ, OUTPUT);
pinMode(sleepPin, OUTPUT);
pinMode(MS1, OUTPUT); // set pin 13 to output
pinMode(MS2, OUTPUT); // set pin 9 to output
Serial.begin(9600);
digitalWrite(sleepPin, LOW);
digitalWrite(MS1, 1); // step mode 1/2 // Set state of MS1 based on the returned value from the MS1_MODE() switch statement.
digitalWrite(MS2, 1);
}
void step(int dirPin,int stepperPin,boolean dir,int steps){
digitalWrite(dirPin,dir);
delay(50);
for(int i=0;i<steps;i++){
digitalWrite(stepperPin, HIGH);
delayMicroseconds(1500);
digitalWrite(stepperPin, LOW);
delayMicroseconds(1500);
}
}
void loop(){
// String "mx10100"
// m ... "move"
// s ... "start"
// x ... "stop"
// x ... x-Axis
// y ... y-Axis
// 1 ... turn cw
// 0 ... turn ccw
// 0100 ... make 100 Microsteps
if(Serial.available() > 0){
command = char(Serial.read());
if( command == 's') {
digitalWrite(sleepPin, HIGH);
}
if( command == 'x') {
digitalWrite(sleepPin, LOW);
}
if(command == 'm'){
for (int i = 0; i < 2; i++) {
command = char(Serial.read());
doit[i] = command;
}
for (int i = 0; i < 4; i++) {
command = char(Serial.read());
dost[i] = command;
}
if (doit[0] == 'y') {
stepperPin = stepperPinY;
dirPin = dirPinY;
}
else {
stepperPin = stepperPinZ;
dirPin = dirPinZ;
}
if (doit[1] == '1') {
dir = true;
}
else {
dir = false;
}
steps = atoi(dost);
step(dirPin,stepperPin,dir,steps);
}
}
}
Unfortunately if have no idea how to talk to the Range Finder. Any ideas?