commit 06453416ed99bc0ce4be42467ede486eeaa48e09 Author: Alex Date: Sun Jun 9 13:19:56 2013 +0200 first commit diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..412eeda --- /dev/null +++ b/.gitattributes @@ -0,0 +1,22 @@ +# Auto detect text files and perform LF normalization +* text=auto + +# Custom for Visual Studio +*.cs diff=csharp +*.sln merge=union +*.csproj merge=union +*.vbproj merge=union +*.fsproj merge=union +*.dbproj merge=union + +# Standard to msysgit +*.doc diff=astextplain +*.DOC diff=astextplain +*.docx diff=astextplain +*.DOCX diff=astextplain +*.dot diff=astextplain +*.DOT diff=astextplain +*.pdf diff=astextplain +*.PDF diff=astextplain +*.rtf diff=astextplain +*.RTF diff=astextplain diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b9d6bd9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,215 @@ +################# +## Eclipse +################# + +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath + + +################# +## Visual Studio +################# + +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.sln.docstates + +# Build results + +[Dd]ebug/ +[Rr]elease/ +x64/ +build/ +[Bb]in/ +[Oo]bj/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +*_i.c +*_p.c +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.log +*.scc + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.cachefile + +# Visual Studio profiler +*.psess +*.vsp +*.vspx + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +*.ncrunch* +.*crunch*.local.xml + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.Publish.xml +*.pubxml + +# NuGet Packages Directory +## TODO: If you have NuGet Package Restore enabled, uncomment the next line +#packages/ + +# Windows Azure Build Output +csx +*.build.csdef + +# Windows Store app package directory +AppPackages/ + +# Others +sql/ +*.Cache +ClientBin/ +[Ss]tyle[Cc]op.* +~$* +*~ +*.dbmdl +*.[Pp]ublish.xml +*.pfx +*.publishsettings + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file to a newer +# Visual Studio version. Backup files are not needed, because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +App_Data/*.mdf +App_Data/*.ldf + +############# +## Windows detritus +############# + +# Windows image file caches +Thumbs.db +ehthumbs.db + +# Folder config file +Desktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Mac crap +.DS_Store + + +############# +## Python +############# + +*.py[co] + +# Packages +*.egg +*.egg-info +dist/ +build/ +eggs/ +parts/ +var/ +sdist/ +develop-eggs/ +.installed.cfg + +# Installer logs +pip-log.txt + +# Unit test / coverage reports +.coverage +.tox + +#Translations +*.mo + +#Mr Developer +.mr.developer.cfg diff --git a/Readme.txt b/Readme.txt new file mode 100644 index 0000000..4ecedf1 --- /dev/null +++ b/Readme.txt @@ -0,0 +1,36 @@ + +Copyright 2011 by Alexander Balasch http://coolrobotprojects.blogspot.co.at/ + +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 should have received a copy of the GNU General Public License +along with this program. If not, see + +this project has been inspired by: + +http://pleasantsoftware.com/developer/3d/spherebot/ + +/////////////////////////////////////////////////////////////////////////////////// + +HOW TO: + +1.) Upload the Arduino sketch. + + (I have added an additional multiplicator to the y-Step calculation to + match my spherebot to the unicorn-script coordinates. You will maybe have to + do the same adjustment for your Spherebot) + + (You will also have to redefine your pins accordingly to your electronics design) + +2.) Start the Spherebot-UI.exe and connect to your Arduino + +Warning for custom Firmwares: The send file function will only work if the arduino answers each sent command with a message + that contains "ok:" so that the next command is sent. \ No newline at end of file diff --git a/SphereBot Arduino/SphereBot.ino b/SphereBot Arduino/SphereBot.ino new file mode 100644 index 0000000..9dd813c --- /dev/null +++ b/SphereBot Arduino/SphereBot.ino @@ -0,0 +1,552 @@ +/* + * Copyright 2011 by Eberhard Rensch + * + * 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 should have received a copy of the GNU General Public License + * along with this program. If not, see + * + * Part of this code is based on/inspired by the Helium Frog Delta Robot Firmware + * by Martin Price + * + * !!!!!!!! + * This sketch needs the following non-standard libraries (install them in the Arduino library directory): + * SoftwareServo: http://www.arduino.cc/playground/ComponentLib/Servo + * TimerOne: http://www.arduino.cc/playground/Code/Timer1 + * !!!!!!!! + */ + +#include +#include +#include "StepperModel.h" + + +#define TIMER_DELAY 64 + +/* + * PINS + */ + + /* ms1 | ms2 + ---------------- + L | L -> Full Step + H | L -> Half Step + L | H -> Quarter Step + H | H -> Sixteenth Step + */ + +#define XAXIS_VMS1 HIGH +#define XAXIS_VMS2 HIGH +#define YAXIS_VMS1 HIGH +#define YAXIS_VMS2 HIGH + +#define YAXIS_DIR_PIN 14 +#define YAXIS_STEP_PIN 15 +#define YAXIS_ENABLE_PIN 21 +#define YAXIS_MS1_PIN 19 //don“t make this connection!! ADC6 and ADC7 can not be used as a digital pin ( I made the pull up connection manually) +#define YAXIS_MS2_PIN 28 +//#define YAXIS_MS3_PIN 18 +#define YAXIS_ENDSTOP_PIN -1 //13 + +#define XAXIS_DIR_PIN 10 +#define XAXIS_STEP_PIN 8 +#define XAXIS_ENABLE_PIN 2 +#define XAXIS_MS1_PIN 3 +#define XAXIS_MS2_PIN 4 +#define XAXIS_ENDSTOP_PIN -1 // <0 0> No Endstop! + +#define SERVO_PIN 13 + +/* + * Other Configuration + */ + +#define DEFAULT_PEN_UP_POSITION 35 +#define XAXIS_MIN_STEPCOUNT -5.6*230000 +#define XAXIS_MAX_STEPCOUNT 5*230000 +#define DEFAULT_ZOOM_FACTOR 0.1808 // With a Zoom-Faktor of .65, I can print gcode for Makerbot Unicorn without changes. + // The zoom factor can be also manipulated by the propretiary code M402 + + +/* --------- */ + +StepperModel xAxisStepper(XAXIS_DIR_PIN, XAXIS_STEP_PIN, XAXIS_ENABLE_PIN, XAXIS_ENDSTOP_PIN, XAXIS_MS1_PIN, XAXIS_MS2_PIN, XAXIS_VMS1, XAXIS_VMS2, + XAXIS_MIN_STEPCOUNT, XAXIS_MAX_STEPCOUNT, 200.0, 16); +StepperModel rotationStepper(YAXIS_DIR_PIN, YAXIS_STEP_PIN, YAXIS_ENABLE_PIN, YAXIS_ENDSTOP_PIN, YAXIS_MS1_PIN, YAXIS_MS2_PIN, YAXIS_VMS1, YAXIS_VMS2, + 0, 0, 200.0, 16); + +SoftwareServo servo; +boolean servoEnabled=true; + +long intervals=0; +volatile long intervals_remaining=0; +volatile boolean isRunning=false; + +// comm variables +const int MAX_CMD_SIZE = 256; +char buffer[MAX_CMD_SIZE]; // buffer for serial commands +char serial_char; // value for each byte read in from serial comms +int serial_count = 0; // current length of command +char *strchr_pointer; // just a pointer to find chars in the cmd string like X, Y, Z, E, etc +boolean comment_mode = false; +// end comm variables + +// GCode States +double currentOffsetX = 0.; +double currentOffsetY = 0.; +boolean absoluteMode = true; +double feedrate = 300.; // mm/minute +double zoom = DEFAULT_ZOOM_FACTOR; + +const double maxFeedrate = 2000.; +// ------ + +void setup() +{ + Serial.begin(115200); + Serial.print("EBB 1.0\n"); + + clear_buffer(); + + servo.attach(SERVO_PIN); + servo.write(DEFAULT_PEN_UP_POSITION); + + if(servoEnabled) + { + for(int i=0;i<100;i++) + { + SoftwareServo::refresh(); + delay(4); + } + } + + //--- Activate the PWM timer + Timer1.initialize(TIMER_DELAY); // Timer for updating pwm pins + Timer1.attachInterrupt(doInterrupt); + +#ifdef AUTO_HOMING + xAxisStepper.autoHoming(); + xAxisStepper.setTargetPosition(0.); + commitSteppers(maxFeedrate); + delay(2000); + xAxisStepper.enableStepper(false); +#endif +} + +void loop() // input loop, looks for manual input and then checks to see if and serial commands are coming in +{ + get_command(); // check for Gcodes + if(servoEnabled) + SoftwareServo::refresh(); +} + +//--- Interrupt-Routine: Move the steppers +void doInterrupt() +{ + if(isRunning) + { + if (intervals_remaining-- == 0) + isRunning = false; + else + { + rotationStepper.doStep(intervals); + xAxisStepper.doStep(intervals); + } + } +} + +void commitSteppers(double speedrate) +{ + long deltaStepsX = xAxisStepper.delta; + if(deltaStepsX != 0L) + { + xAxisStepper.enableStepper(true); + } + + long deltaStepsY = rotationStepper.delta; + if(deltaStepsY != 0L) + { + rotationStepper.enableStepper(true); + } + long masterSteps = (deltaStepsX>deltaStepsY)?deltaStepsX:deltaStepsY; + + double deltaDistanceX = xAxisStepper.targetPosition-xAxisStepper.getCurrentPosition(); + double deltaDistanceY = rotationStepper.targetPosition-rotationStepper.getCurrentPosition(); + + // how long is our line length? + double distance = sqrt(deltaDistanceX*deltaDistanceX+deltaDistanceY*deltaDistanceY); + + // compute number of intervals for this move + double sub1 = (60000.* distance / speedrate); + double sub2 = sub1 * 1000.; + intervals = (long)sub2/TIMER_DELAY; + + intervals_remaining = intervals; + const long negative_half_interval = -intervals / 2; + + rotationStepper.counter = negative_half_interval; + xAxisStepper.counter = negative_half_interval; + +// Serial.print("Speedrate:"); +// Serial.print(speedrate, 6); +// Serial.print(" dX:"); +// Serial.print(deltaStepsX); +// Serial.print(" dY:"); +// Serial.print(deltaStepsY); +// Serial.print(" masterSteps:"); +// Serial.print(masterSteps); +// Serial.print(" dDistX:"); +// Serial.print(deltaDistanceX); +// Serial.print(" dDistY:"); +// Serial.print(deltaDistanceY); +// Serial.print(" distance:"); +// Serial.print(distance); +// Serial.print(" sub1:"); +// Serial.print(sub1, 6); +// Serial.print(" sub2:"); +// Serial.print(sub2, 6); +// Serial.print(" intervals:"); +// Serial.print(intervals); +// Serial.print(" negative_half_interval:"); +// Serial.println(negative_half_interval); +// Serial.print("Y currentStepCount:"); +// Serial.print(rotationStepper.currentStepcount); +// Serial.print(" targetStepCount:"); +// Serial.println(rotationStepper.targetStepcount); + + isRunning=true; +} + +void get_command() // gets commands from serial connection and then calls up subsequent functions to deal with them +{ + if (!isRunning && Serial.available() > 0) // each time we see something + { + serial_char = Serial.read(); // read individual byte from serial connection + + if (serial_char == '\n' || serial_char == '\r') // end of a command character + { + buffer[serial_count]=0; + process_commands(buffer, serial_count); + clear_buffer(); + comment_mode = false; // reset comment mode before each new command is processed + //Serial.write("process: command"); + } + else // not end of command + { + if (serial_char == ';' || serial_char == '(') // semicolon signifies start of comment + { + comment_mode = true; + } + + if (comment_mode != true) // ignore if a comment has started + { + buffer[serial_count] = serial_char; // add byte to buffer string + serial_count++; + if (serial_count > MAX_CMD_SIZE) // overflow, dump and restart + { + clear_buffer(); + Serial.flush(); + } + } + else + { + } + } + } +} + +void clear_buffer() // empties command buffer from serial connection +{ + serial_count = 0; // reset buffer placement +} + +boolean getValue(char key, char command[], double* value) +{ + // find key parameter + strchr_pointer = strchr(buffer, key); + if (strchr_pointer != NULL) // We found a key value + { + *value = (double)strtod(&command[strchr_pointer - command + 1], NULL); + return true; + } + return false; +} + +void check_for_version_controll(char command) +{ + if(command == 'v') + { + Serial.print("EBB 1.0\n"); + } +} + + +void process_commands(char command[], int command_length) // deals with standardized input from serial connection +{ + if(command_length == 1) + { + check_for_version_controll(command[0]); + } + if (command_length>0 && command[0] == 'G') // G code + { + //Serial.print("proces G: \n"); + int codenum = (int)strtod(&command[1], NULL); + + double tempX = xAxisStepper.getCurrentPosition(); + double tempY = rotationStepper.getCurrentPosition(); + + double xVal; + boolean hasXVal = getValue('X', command, &xVal); + if(hasXVal) xVal*=zoom*1.71/2; //this factor is for correction to meet the unicorn coordinates + double yVal; + boolean hasYVal = getValue('Y', command, &yVal); + if(hasYVal) yVal*=zoom; + double iVal; + boolean hasIVal = getValue('I', command, &iVal); + if(hasIVal) iVal*=zoom; + double jVal; + boolean hasJVal = getValue('J', command, &jVal); + if(hasJVal) jVal*=zoom; + double rVal; + boolean hasRVal = getValue('R', command, &rVal); + if(hasRVal) rVal*=zoom; + double pVal; + boolean hasPVal = getValue('P', command, &pVal); + + getValue('F', command, &feedrate); + + xVal+=currentOffsetX; + yVal+=currentOffsetY; + + if(absoluteMode) + { + if(hasXVal) + tempX=xVal; + if(hasYVal) + tempY=yVal; + } + else + { + if(hasXVal) + tempX+=xVal; + if(hasYVal) + tempY+=yVal; + } + + switch(codenum) + { + case 0: // G0, Rapid positioning + xAxisStepper.setTargetPosition(tempX); + rotationStepper.setTargetPosition(tempY); + commitSteppers(maxFeedrate); + break; + case 1: // G1, linear interpolation at specified speed + xAxisStepper.setTargetPosition(tempX); + rotationStepper.setTargetPosition(tempY); + commitSteppers(feedrate); + break; + case 2: // G2, Clockwise arc + case 3: // G3, Counterclockwise arc + if(hasIVal && hasJVal) + { + double centerX=xAxisStepper.getCurrentPosition()+iVal; + double centerY=rotationStepper.getCurrentPosition()+jVal; + drawArc(centerX, centerY, tempX, tempY, (codenum==2)); + } + else if(hasRVal) + { + //drawRadius(tempX, tempY, rVal, (codenum==2)); + } + break; + case 4: // G4, Delay P ms + if(hasPVal) + { + unsigned long endDelay = millis()+ (unsigned long)pVal; + while(millis()0 && command[0] == 'M') // M code + { + //Serial.print("proces M:\n"); + double value; + int codenum = (int)strtod(&command[1], NULL); + switch(codenum) + { + case 18: // Disable Drives + xAxisStepper.resetStepper(); + rotationStepper.resetStepper(); + break; + + case 300: // Servo Position + if(getValue('S', command, &value)) + { + servoEnabled=true; + if(value<0.) + value=0.; + else if(value>180.) + { + value=DEFAULT_PEN_UP_POSITION; + servo.write((int)value); + for(int i=0;i<100;i++) + { + SoftwareServo::refresh(); + delay(4); + } + servoEnabled=false; + } + servo.write((int)value); + } + break; + + case 400: // Propretary: Reset X-Axis-Stepper settings to new object diameter + if(getValue('S', command, &value)) + { + xAxisStepper.resetSteppersForObjectDiameter(value); + xAxisStepper.setTargetPosition(0.); + commitSteppers(maxFeedrate); + delay(2000); + xAxisStepper.enableStepper(false); + } + break; + + case 401: // Propretary: Reset Y-Axis-Stepper settings to new object diameter + if(getValue('S', command, &value)) + { + rotationStepper.resetSteppersForObjectDiameter(value); + rotationStepper.setTargetPosition(0.); + commitSteppers(maxFeedrate); + delay(2000); + rotationStepper.enableStepper(false); + } + break; + + case 402: // Propretary: Reset Y-Axis-Stepper settings to new object diameter + if(getValue('S', command, &value)) + { + zoom = value/100; + } + break; + + } + } + +//done processing commands +if (Serial.available() <= 0) { +Serial.print("ok:"); +Serial.println(command); +Serial.print("\n"); + } +} + +/* This code was ported from the Makerbot/ReplicatorG java sources */ +void drawArc(double centerX, double centerY, double endpointX, double endpointY, boolean clockwise) +{ + // angle variables. + double angleA; + double angleB; + double angle; + double radius; + double length; + + // delta variables. + double aX; + double aY; + double bX; + double bY; + + // figure out our deltas + double currentX = xAxisStepper.getCurrentPosition(); + double currentY = rotationStepper.getCurrentPosition(); + aX = currentX - centerX; + aY = currentY - centerY; + bX = endpointX - centerX; + bY = endpointY - centerY; + + // Clockwise + if (clockwise) { + angleA = atan2(bY, bX); + angleB = atan2(aY, aX); + } + // Counterclockwise + else { + angleA = atan2(aY, aX); + angleB = atan2(bY, bX); + } + + // Make sure angleB is always greater than angleA + // and if not add 2PI so that it is (this also takes + // care of the special case of angleA == angleB, + // ie we want a complete circle) + if (angleB <= angleA) + angleB += 2. * M_PI; + angle = angleB - angleA; + + // calculate a couple useful things. + radius = sqrt(aX * aX + aY * aY); + length = radius * angle; + + // for doing the actual move. + int steps; + int s; + int step; + + // Maximum of either 2.4 times the angle in radians + // or the length of the curve divided by the curve section constant + steps = (int)ceil(max(angle * 2.4, length)); + + // this is the real draw action. + double newPointX = 0.; + double newPointY = 0.; + + for (s = 1; s <= steps; s++) { + // Forwards for CCW, backwards for CW + if (!clockwise) + step = s; + else + step = steps - s; + + // calculate our waypoint. + newPointX = centerX + radius * cos(angleA + angle * ((double) step / steps)); + newPointY= centerY + radius * sin(angleA + angle * ((double) step / steps)); + + // start the move + xAxisStepper.setTargetPosition(newPointX); + rotationStepper.setTargetPosition(newPointY); + commitSteppers(feedrate); + + while(isRunning) + { + delay(1); + if(servoEnabled) + SoftwareServo::refresh(); + }; + } +} + +/* Make life easier for vim users */ +/* vim:set filetype=cpp: */ diff --git a/SphereBot Arduino/StepperModel.cpp b/SphereBot Arduino/StepperModel.cpp new file mode 100644 index 0000000..69ff40e --- /dev/null +++ b/SphereBot Arduino/StepperModel.cpp @@ -0,0 +1,179 @@ +/* + * Copyright 2011 by Eberhard Rensch + * + * 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 should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +#include "StepperModel.h" +#include "Arduino.h" + + +/* + * inEnablePin < 0 => No Endstop + */ +StepperModel::StepperModel(int inDirPin, int inStepPin, int inEnablePin, int inEndStopPin,int inMs1Pin, int inMs2Pin, bool vms1,bool vms2, + long minSC, long maxSC, + double in_kStepsPerRevolution, int in_kMicroStepping) +{ + kStepsPerRevolution=in_kStepsPerRevolution; + kMicroStepping=in_kMicroStepping; + + dirPin = inDirPin; + stepPin = inStepPin; + enablePin = inEnablePin; + endStopPin = inEndStopPin; + ms1Pin = inMs1Pin; + ms2Pin = inMs2Pin; + + minStepCount=minSC; + maxStepCount=maxSC; + + pinMode(dirPin, OUTPUT); + pinMode(stepPin, OUTPUT); + pinMode(enablePin, OUTPUT); + pinMode(ms1Pin, OUTPUT); + pinMode(ms2Pin, OUTPUT); + if(endStopPin>=0) + pinMode(endStopPin, INPUT); + + digitalWrite(dirPin, LOW); + digitalWrite(stepPin, LOW); + + digitalWrite(ms1Pin, vms1); + digitalWrite(ms2Pin, vms2); + + currentStepcount=0; + targetStepcount=0; + + steps_per_mm = (int)((kStepsPerRevolution/(45.*M_PI))*kMicroStepping+0.5); // default value for a "normal" egg (45 mm diameter) + enableStepper(false); +} + +void StepperModel::resetSteppersForObjectDiameter(double diameter) +{ + // Calculate the motor steps required to move per mm. + steps_per_mm = (int)((kStepsPerRevolution/(diameter*M_PI))*kMicroStepping+0.5); + if(endStopPin>=0) + { +#ifdef AUTO_HOMING + autoHoming(); +#endif + enableStepper(false); + } + else + resetStepper(); +} + +long StepperModel::getStepsForMM(double mm) +{ + long steps = (long)(steps_per_mm*mm); + +// Serial.print("steps for "); +// Serial.print(mm); +// Serial.print(" mm: "); +// Serial.println(steps); + + return steps; +} + +/* Currently unused */ +/* +void StepperModel::setTargetStepcount(long tsc) +{ + targetPosition = (double)tsc/steps_per_mm; + targetStepcount = tsc; + delta = targetStepcount-currentStepcount; + direction = true; + if (delta != 0) { + enableStepper(true); + } + if (delta < 0) { + delta = -delta; + direction = false; + } +}*/ + +void StepperModel::setTargetPosition(double pos) +{ + targetPosition = pos; + targetStepcount = getStepsForMM(targetPosition); + //Serial.println(targetStepcount); + delta = targetStepcount-currentStepcount; + direction = true; + if (delta != 0) { + enableStepper(true); + } + if (delta < 0) { + delta = -delta; + direction = false; + } +} + +double StepperModel::getCurrentPosition() +{ + return (double)currentStepcount/steps_per_mm; +} + +void StepperModel::enableStepper(bool enabled) +{ + digitalWrite(enablePin, !enabled); +} + +void StepperModel::resetStepper() +{ + enableStepper(false); + currentStepcount=0; + targetStepcount=0; + delta=0; +} + +void StepperModel::doStep(long intervals) +{ + counter += delta; + if (counter >= 0) { + digitalWrite(dirPin, direction?HIGH:LOW); + counter -= intervals; + if (direction) { + if(maxStepCount==0 || currentStepcount<=maxStepCount) + { + digitalWrite(stepPin, HIGH); + currentStepcount++; + } + } else { + if(minStepCount==0 || currentStepcount>=minStepCount) + { + digitalWrite(stepPin, HIGH); + currentStepcount--; + } + } + digitalWrite(stepPin, LOW); + } +} + +#ifdef AUTO_HOMING +void StepperModel::autoHoming() +{ + enableStepper(true); + digitalWrite(dirPin, LOW); + + while(digitalRead(endStopPin)) + { + digitalWrite(stepPin, HIGH); + digitalWrite(stepPin, LOW); + delay(1); + } + + currentStepcount= minStepCount-16; +} +#endif diff --git a/SphereBot Arduino/StepperModel.h b/SphereBot Arduino/StepperModel.h new file mode 100644 index 0000000..b317dec --- /dev/null +++ b/SphereBot Arduino/StepperModel.h @@ -0,0 +1,75 @@ +/* + * Copyright 2011 by Eberhard Rensch + * + * 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 should have received a copy of the GNU General Public License + * along with this program. If not, see + */ + +#ifndef STEPPERMODEL +#define STEPPERMODEL + +// Uncomment if You have Autohoming: +//#define AUTO_HOMING + +class StepperModel +{ +private: + + int dirPin; + int stepPin; + int enablePin; + int ms1Pin; + int ms2Pin; + int endStopPin; + + long minStepCount; + long maxStepCount; + double steps_per_mm; + + double kStepsPerRevolution; + int kMicroStepping; + + volatile long currentStepcount; + volatile long targetStepcount; + + volatile bool direction; + + long getStepsForMM(double mm); + +public: + volatile long delta; + volatile long counter; + double targetPosition; + + StepperModel(int inDirPin, int inStepPin, int inEnablePin, int inEndStopPin,int inMs1Pin, int inMs2Pin,bool vms1,bool vms2, + long minSC, long maxSC, + double in_kStepsPerRevolution, int in_kMicroStepping); + + void resetSteppersForObjectDiameter(double diameter); + +#ifdef AUTO_HOMING + void autoHoming(); +#endif + + + void setTargetPosition(double pos); + double getCurrentPosition(); + + void enableStepper(bool enabled); + + void resetStepper(); + + void doStep(long intervals); +}; + +#endif diff --git a/SphereBot Arduino/Utils/egg-displace.dat b/SphereBot Arduino/Utils/egg-displace.dat new file mode 100644 index 0000000..3a4cd66 --- /dev/null +++ b/SphereBot Arduino/Utils/egg-displace.dat @@ -0,0 +1,25 @@ +# Gnuplot Session +# +# Erste Spalte=x, Zweite=y +# Ei Spitze zeigt nach rechts (positive x) +# +# plot "egg-displace.dat" using 1:2 title "Ei" +# ==> graph looks like a parabola +# f(x)=a*x*x + b*x + c +# fit f(x) "egg-displace.dat" using 1:2 via a,b,c +# a=0.00795338 +# b=0.0734545 +# c=0.15711 +# plot "egg-displace.dat" using 1:2 title "Ei" with lines, f(x) +# ==> fits reasonable well +-25 3 +-20 2 +-15 1 +-10 0.5 +-5 0.1 +0 0 +5 0.5 +10 1.5 +15 3 +20 5 +25 7 diff --git a/SphereBot Arduino/readme.txt b/SphereBot Arduino/readme.txt new file mode 100644 index 0000000..e646a1b --- /dev/null +++ b/SphereBot Arduino/readme.txt @@ -0,0 +1,51 @@ +v0.1 + +This is the firmware for an EggBot-style SphereBot. +The firmware directly interprets GCode send over the serial port. + +There will be more information on the SphereBot at http://pleasantsoftware.com/developer/3d (in the near future...) + +!!!!!!!! +This sketch needs the following non-standard libraries (install them in the Arduino library directory): +SoftwareServo: http://www.arduino.cc/playground/ComponentLib/Servo +TimerOne: http://www.arduino.cc/playground/Code/Timer1 +!!!!!!!! + +Copyright 2011 by Eberhard Rensch + +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 should have received a copy of the GNU General Public License +along with this program. If not, see + +Part of this code is based on/inspired by the Helium Frog Delta Robot Firmware +by Martin Price + +To create tags File: ctags --langmap="C++:+.pde" S* + + +GCode commands: + +G90 Absolut modus +G91 Icremental modus: + +M300S0 Servo 0 degree +M300S90 Servo 90 degree + + +M18 Stepper off + +G0X0Y40 Rapid movement (pen 0mm, rotation 40mm) +G1X40Y0 Slower movement (pen 40mm, rotation 0mm) +G1Y10F660 Movement with feed 660mm/s (rotation 10mm) + +; Comment +( .. ) Comment diff --git a/Spherebot_UI.exe b/Spherebot_UI.exe new file mode 100644 index 0000000..b7649f9 Binary files /dev/null and b/Spherebot_UI.exe differ diff --git a/Spherebot_UI/3rdparty/qextserialport b/Spherebot_UI/3rdparty/qextserialport new file mode 160000 index 0000000..0394a5d --- /dev/null +++ b/Spherebot_UI/3rdparty/qextserialport @@ -0,0 +1 @@ +Subproject commit 0394a5d33beb7f585b5c9dfac7967e6f67389006 diff --git a/Spherebot_UI/Spherebot_UI.pro b/Spherebot_UI/Spherebot_UI.pro new file mode 100644 index 0000000..4e9b99f --- /dev/null +++ b/Spherebot_UI/Spherebot_UI.pro @@ -0,0 +1,28 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2013-05-30T07:01:31 +# +#------------------------------------------------- + +QT += core gui + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = Spherebot_UI +TEMPLATE = app + + +SOURCES += main.cpp\ + mainwindow.cpp \ + spherebot.cpp \ + txthread.cpp + +include(3rdparty/qextserialport/src/qextserialport.pri) + +HEADERS += mainwindow.h \ + spherebot.h \ + txthread.h + +FORMS += mainwindow.ui + +CONFIG += static diff --git a/Spherebot_UI/main.cpp b/Spherebot_UI/main.cpp new file mode 100644 index 0000000..bd2ef31 --- /dev/null +++ b/Spherebot_UI/main.cpp @@ -0,0 +1,13 @@ +#include "mainwindow.h" +#include + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + app.setOrganizationName("thunderbug1"); + MainWindow w; + w.setWindowTitle("Spherebot control"); + w.show(); + + return app.exec(); +} diff --git a/Spherebot_UI/mainwindow.cpp b/Spherebot_UI/mainwindow.cpp new file mode 100644 index 0000000..d26a88d --- /dev/null +++ b/Spherebot_UI/mainwindow.cpp @@ -0,0 +1,350 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + resetPortList(); + + sendState = false; + rxTimer = new QTimer(this); + + //connect( bot.port, SIGNAL(readyRead()), this, SLOT(receiveData()) ); + connect( rxTimer,SIGNAL(timeout()),this,SLOT(receiveData())); + connect( &bot, SIGNAL(dataSent(QString)),this, SLOT(sendData(QString))); + connect(this,SIGNAL(receivedLine(QString)),&Transceiver,SLOT(checkResponse(QString))); + connect(&Transceiver,SIGNAL(progressChanged(int)),this,SLOT(refreshSendProgress(int))); + connect(&Transceiver,SIGNAL(fileTransmitted()),this,SLOT(finishedTransmission())); +} + +MainWindow::~MainWindow() +{ + qDebug()<<"delete main window"; + QSettings settings(nameSettingsFile, QSettings::NativeFormat); + QString tmp = (ui->portBox->currentText()); + settings.setValue("portName", tmp); + delete ui; +} + +/////////////////////////////////////////////////////////////////////////////// + +void MainWindow::loadFile(const QString &fileName) +{ + QFile file(fileName); + if (!file.open(QFile::ReadOnly | QFile::Text)) { + QMessageBox::warning(this, tr("Application"), + tr("Cannot read file %1:\n%2.") + .arg(fileName) + .arg(file.errorString())); + return; + } + + statusBar()->showMessage(tr("File loaded"), 2000); + ui->fileTextEdit->setText(file.readAll()); +} + +bool MainWindow::saveFile(const QString &fileName) +//! [44] //! [45] +{ + QFile file(fileName); + if (!file.open(QFile::WriteOnly | QFile::Text)) { + QMessageBox::warning(this, tr("Application"), + tr("Cannot write file %1:\n%2.") + .arg(fileName) + .arg(file.errorString())); + return false; + } + + QTextStream out(&file); + + out<fileTextEdit->toPlainText(); + statusBar()->showMessage(tr("File saved"), 2000); + return true; +} + +void MainWindow::receiveData() +{ + if(bot.port->bytesAvailable()) + { + //qDebug()<< "Read line"; + QString line =bot.port->readLine(1024); + line.chop(1); + emit receivedLine(line); + ui->rxList->insertItem(0,line); + } +} + +void MainWindow::refreshSendProgress(int value) +{ + ui->fileSendProgressBar->setValue(value); +} + +void MainWindow::finishedTransmission() +{ + ui->sendFileButton->setText("Send File"); + ui->controllBox->setEnabled(true); + ui->fileSendProgressBar->setEnabled(false); + statusBar()->showMessage(tr("File successfully sent")); + sendState = false; +} + +/////////////////////////////////////////////////////////////////// + +void MainWindow::on_connectButton_clicked() +{ + if(bot.isConnected()) + { + //disconnect + rxTimer->stop(); + bot.disconnectWithBot(); + ui->connectButton->setChecked(false); + ui->connectButton->setText("Connect"); + ui->controllBox->setEnabled(false); + ui->resetButton->setEnabled(true); + ui->portBox->setEnabled(true); + ui->sendFileButton->setEnabled(false); + ui->eggSlider->setValue(0); + ui->diameterSlider->setValue(DEFAULTDIAMETER); + ui->penSlider->setValue(0); + ui->servoSlider->setValue(DEFAULTPENUP); + ui->FeedratespinBox->setValue(DEFAULTFEEDRATE); + ui->fileSendProgressBar->setValue(0); + sendState = 0; + ui->sendFileButton->setText("Send File"); + } + else if(bot.connectWithBot(ui->portBox->currentText())) + { + //successfully connected + rxTimer->start(2); + qDebug()<<"Start Timer"; + ui->connectButton->setChecked(true); + ui->controllBox->setEnabled(true); + ui->portBox->setEnabled(false); + ui->resetButton->setEnabled(false); + ui->connectButton->setText("Disconnect"); + if(!ui->fileTextEdit->toPlainText().isEmpty()) ui->sendFileButton->setEnabled(true); + } + else + { + + } +} + + +void MainWindow::resetPortList() +{ + portList =serialEnumerator.getPorts(); + ui->portBox->clear(); + for(int i=0;iportBox->addItem(portList[i].portName); + } +} + +void MainWindow::on_resetButton_clicked() +{ + resetPortList(); +} + +void MainWindow::sendData(QString data) +{ + ui->txList->insertItem(0,data); +} + +void MainWindow::on_sendString_editingFinished() +{ + if(!bot.send(ui->sendString->text())) + { + //sendData(ui->sendString->text()); + } + else + { + qDebug()<errorString(); + sendData("Error while sending Data!"); + } +} + +void MainWindow::on_sendButton_clicked() +{ + if(!bot.send(ui->sendString->text())) + { + //sendData(ui->sendString->text()); + } + else + { + qDebug()<errorString(); + //sendData("Error while sending Data!"); + } +} + +void MainWindow::on_servoSlider_sliderMoved(int position) +{ + //ui->servospinBox->setValue(position); + QString tmp = ("M300 S" + QString::number(position)+"\n"); + bot.send(tmp); + //sendData(tmp); +} + +void MainWindow::on_servospinBox_valueChanged(int arg1) +{ + ui->servoSlider->setValue(arg1); + QString tmp = ("M300 S" + QString::number(arg1)+"\n"); + bot.send(tmp); +} + +void MainWindow::on_penRotationBox_valueChanged(int arg1) +{ + QString tmp = ("G1 Y" + QString::number((double)arg1)); + bot.send(tmp); + ui->penSlider->setValue(arg1); +} + +void MainWindow::on_penSlider_valueChanged(int value) +{ + ui->penRotationBox->setValue(value); +} + +void MainWindow::on_eggSlider_valueChanged(int value) +{ + ui->eggRotationBox->setValue(value); +} + +void MainWindow::on_eggRotationBox_valueChanged(int arg1) +{ + QString tmp = ("G1 X" + QString::number((double)arg1)+"\n"); + bot.send(tmp); + ui->eggSlider->setValue(arg1); +} + +void MainWindow::on_loadFileButton_clicked() +{ + QString fileName = QFileDialog::getOpenFileName(this); + if (!fileName.isEmpty()) + loadFile(fileName); + if(!ui->fileTextEdit->toPlainText().isEmpty()) + { + setWindowTitle("Spherebot Controll File: " + fileName); + ui->fileName->setText(QFileInfo(fileName).fileName()); + } + else ui->sendButton->setEnabled(false); +} + + +void MainWindow::on_saveFileButton_clicked() +{ + saveFile(curFile); + ui->saveFileButton->setEnabled(false); +} + +QString removeComments(QString input); + +void MainWindow::on_fileTextEdit_textChanged() +{ + ui->saveFileButton->setEnabled(true); + ui->outputText->setText(removeComments((ui->fileTextEdit->toPlainText()))); + if(!ui->fileTextEdit->toPlainText().isEmpty()) + { + setWindowTitle("Spherebot Controll"); + ui->fileName->setText(""); + if(bot.isConnected()) ui->sendFileButton->setEnabled(true); + else ui->sendButton->setEnabled(false); + } +} + + +void MainWindow::on_sendFileButton_clicked() +{ + QScrollBar *vScrollBar = ui->fileTextEdit->verticalScrollBar(); + qDebug()<<"enter button code"; + switch(sendState) + { + case 0: //start to send + qDebug()<<"start sending"; + sendState = 1; + ui->controllBox->setEnabled(false); + ui->fileSendProgressBar->setEnabled(true); + ui->sendFileButton->setText("Stop"); + ui->controllBox->setEnabled(false); + ui->sendButton->setEnabled(false); + Transceiver.set(ui->fileTextEdit->toPlainText(),this->bot); + qDebug()<<"tx is set"; + Transceiver.run(); + statusBar()->showMessage(tr("Sending File")); + break; + case 1: //stop the print + qDebug()<< "You have stoped sending"; + sendState = 2; + ui->restartButton->setEnabled(true); + ui->sendFileButton->setText("Continue"); + ui->controllBox->setEnabled(true); + ui->sendButton->setEnabled(true); + vScrollBar->setValue(Transceiver.getLineCounter()); + Transceiver.checkSendBufferTimer->stop(); + break; + case 2: //continue + sendState = 1; + Transceiver.checkSendBufferTimer->start(SENDBUFFERINTERVAL); + ui->restartButton->setEnabled(false); + ui->sendFileButton->setText("Stop"); + ui->controllBox->setEnabled(false); + ui->sendButton->setEnabled(false); + break; + } + + qDebug()<<"leave button code"; +} + +void MainWindow::on_restartButton_clicked() +{ + sendState = 1; + ui->controllBox->setEnabled(false); + ui->fileSendProgressBar->setEnabled(true); + ui->sendFileButton->setText("Stop"); + ui->controllBox->setEnabled(false); + ui->sendButton->setEnabled(false); + Transceiver.set(ui->fileTextEdit->toPlainText(),this->bot); + qDebug()<<"tx is set"; + Transceiver.run(); + statusBar()->showMessage(tr("Sending File")); +} + +void MainWindow::on_servoFeedrateSlider_valueChanged(int value) +{ + QString tmp = ("G1 F" + QString::number(value)+"\n"); + bot.send(tmp); +} + +void MainWindow::on_setDiameterButton_clicked() +{ + QString tmp = ("M400 S" + QString::number(ui->diameterSlider->value())+"\n"); + bot.send(tmp); + tmp.clear(); + tmp = ("M401 S" + QString::number(ui->diameterSlider->value())+"\n"); + bot.send(tmp); +} + +void MainWindow::on_undoButton_clicked() +{ + ui->fileTextEdit->undo(); +} + +void MainWindow::on_redoButton_clicked() +{ + ui->fileTextEdit->redo(); +} + +void MainWindow::on_fileTextEdit_undoAvailable(bool b) +{ + if(b) ui->undoButton->setEnabled(true); + else ui->undoButton->setEnabled(false); +} + +void MainWindow::on_fileTextEdit_redoAvailable(bool b) +{ + if(b) ui->redoButton->setEnabled(true); + else ui->redoButton->setEnabled(false); +} + + diff --git a/Spherebot_UI/mainwindow.h b/Spherebot_UI/mainwindow.h new file mode 100644 index 0000000..a0ff6de --- /dev/null +++ b/Spherebot_UI/mainwindow.h @@ -0,0 +1,88 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include "spherebot.h" +#include "qextserialenumerator.h" +#include +#include +#include +#include +#include +#include "txthread.h" +#include +#include +#include + + +#define DEFAULTDIAMETER 20 +#define DEFAULTPENUP 35 +#define DEFAULTFEEDRATE 2000 + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + void send_data(); + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); +signals: + void receivedLine(QString); +public slots: + void receiveData(); + void sendData(QString data); + void finishedTransmission(); + void refreshSendProgress(int value); + +private slots: + void on_connectButton_clicked(); + void resetPortList(); + void on_sendButton_clicked(); + void on_resetButton_clicked(); + void on_sendString_editingFinished(); + void on_servoSlider_sliderMoved(int position); + void on_servospinBox_valueChanged(int arg1); + void on_penSlider_valueChanged(int value); + void on_eggSlider_valueChanged(int value); + void on_penRotationBox_valueChanged(int arg1); + void on_eggRotationBox_valueChanged(int arg1); + void on_loadFileButton_clicked(); + void on_saveFileButton_clicked(); + void on_fileTextEdit_textChanged(); + void on_sendFileButton_clicked(); + void on_servoFeedrateSlider_valueChanged(int value); + void on_setDiameterButton_clicked(); + + void on_undoButton_clicked(); + + void on_redoButton_clicked(); + + void on_fileTextEdit_undoAvailable(bool b); + + void on_fileTextEdit_redoAvailable(bool b); + + void on_restartButton_clicked(); + +private: + + void loadFile(const QString &fileName); + bool saveFile(const QString &fileName); + void setCurrentFile(const QString &fileName); + QString curFile; + int sendState; + + QString nameSettingsFile; + Ui::MainWindow *ui; + QextSerialEnumerator serialEnumerator; + QList portList; + spherebot bot; + QTimer *rxTimer; + txThread Transceiver; +}; + +#endif // MAINWINDOW_H diff --git a/Spherebot_UI/mainwindow.ui b/Spherebot_UI/mainwindow.ui new file mode 100644 index 0000000..db1c785 --- /dev/null +++ b/Spherebot_UI/mainwindow.ui @@ -0,0 +1,826 @@ + + + MainWindow + + + + 0 + 0 + 1427 + 497 + + + + MainWindow + + + + + false + + + + 10 + 60 + 551 + 231 + + + + + + + false + + + false + + + + + 8 + 0 + 541 + 221 + + + + + + + + + set Diameter + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::LeftToRight + + + 5 + + + 120 + + + 20 + + + Qt::Vertical + + + false + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + 5 + + + 120 + + + 1 + + + 20 + + + + + + + Obj. Diameter + + + + + + + + + + + Qt::Vertical + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::LeftToRight + + + 10 + + + 6000 + + + 2000 + + + Qt::Vertical + + + false + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 10 + + + 6000 + + + 2000 + + + + + + + Feedrate + + + + + + + + + Qt::Vertical + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::LeftToRight + + + 23 + + + 120 + + + 35 + + + Qt::Vertical + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + 23 + + + 35 + + + + + + + Servo + + + + + + + + + + + + + + + -112 + + + 112 + + + 1 + + + 0 + + + 0 + + + Qt::Horizontal + + + true + + + + + + + + + Pen Rotation + + + + + + + -112 + + + 112 + + + 1 + + + + + + + + + + + -450 + + + 450 + + + 0 + + + 0 + + + Qt::Horizontal + + + + + + + + + Egg Rotation + + + + + + + -450 + + + 450 + + + + + + + + + + + + + + + + 20 + 20 + 275 + 30 + + + + + + + Connect + + + false + + + + + + + + + + R + + + + + + + + + 0 + 0 + 2 + 2 + + + + + + + + 0 + 0 + 2 + 2 + + + + + + + + 20 + 290 + 541 + 155 + + + + + + + + + + + + Send + + + + + + + + + + + + + Tranceived Data + + + + + + + false + + + QAbstractItemView::NoSelection + + + + + + + + + + + Received Data + + + + + + + + + + + + + + + + 570 + 10 + 461 + 431 + + + + + + + + + + + + + + + + + + + + + false + + + Undo + + + + + + + false + + + Redo + + + + + + + + + + + + + + Load File + + + + + + + false + + + Save File + + + + + + + false + + + Send File + + + + + + + false + + + Restart + + + + + + + + + + + false + + + 0 + + + + + + + + + 1040 + 80 + 351 + 291 + + + + + + + 1040 + 60 + 101 + 16 + + + + Output File + + + + + + TopToolBarArea + + + false + + + + + + + + + diameterSlider + valueChanged(int) + diameterpinBox + setValue(int) + + + 61 + 178 + + + 71 + 249 + + + + + diameterpinBox + valueChanged(int) + diameterSlider + setValue(int) + + + 91 + 245 + + + 66 + 149 + + + + + servospinBox + valueChanged(int) + servoSlider + setValue(int) + + + 300 + 269 + + + 272 + 237 + + + + + servoSlider + valueChanged(int) + servospinBox + setValue(int) + + + 272 + 179 + + + 300 + 269 + + + + + penRotationBox + valueChanged(int) + penSlider + setValue(int) + + + 553 + 146 + + + 554 + 96 + + + + + penSlider + valueChanged(int) + penRotationBox + setValue(int) + + + 554 + 96 + + + 498 + 143 + + + + + eggRotationBox + valueChanged(int) + eggSlider + setValue(int) + + + 482 + 249 + + + 500 + 193 + + + + + eggSlider + valueChanged(int) + eggRotationBox + setValue(int) + + + 555 + 193 + + + 499 + 245 + + + + + servoFeedrateSlider + valueChanged(int) + FeedratespinBox + setValue(int) + + + 178 + 228 + + + 206 + 269 + + + + + FeedratespinBox + valueChanged(int) + servoFeedrateSlider + setValue(int) + + + 206 + 269 + + + 178 + 184 + + + + + diff --git a/Spherebot_UI/spherebot.cpp b/Spherebot_UI/spherebot.cpp new file mode 100644 index 0000000..b4605e9 --- /dev/null +++ b/Spherebot_UI/spherebot.cpp @@ -0,0 +1,66 @@ +#include "spherebot.h" + +spherebot::spherebot(QObject *parent) : + QObject(parent) +{ + port = NULL; + port_connected = false; +} + +bool spherebot::connectWithBot(QString portName) +{ + port = new QextSerialPort(portName , QextSerialPort::Polling); //we create the port + + + port->open(QIODevice::ReadWrite); //we open the port + if(!port->isOpen()) + { + //QMessageBox::warning(this, "port error", "Impossible to open the port!"); + return 0; + } + + //we set the port properties + port->setBaudRate(BAUD115200);//modify the port settings on your own + port->setFlowControl(FLOW_OFF); + port->setParity(PAR_NONE); + port->setDataBits(DATA_8); + port->setStopBits(STOP_1); + port->setRts( true ); + port->setDtr( true ); + //port->setQueryMode( QextSerialPort::EventDriven ); + port_connected = true; + return 1; +} + +bool spherebot::disconnectWithBot() +{ + qDebug("port closed"); + port->close(); + port_connected = false; + return 1; +} + +bool spherebot::send(QString cmd) +{ + if(port->isOpen()) + { + port->flush(); + if(cmd[cmd.size()-1] != '\n') cmd.append("\n"); + qDebug()<<"Sending: " + cmd; + port->write((const char*)cmd.toUtf8(),cmd.length()); + + } + else + { + qDebug()<errorString(); + return false; + } + cmd.chop(1); + emit dataSent(cmd); + return true; +} + +bool spherebot::isConnected() +{ + return port_connected; +} diff --git a/Spherebot_UI/spherebot.h b/Spherebot_UI/spherebot.h new file mode 100644 index 0000000..a74b6da --- /dev/null +++ b/Spherebot_UI/spherebot.h @@ -0,0 +1,29 @@ +#ifndef SPHEREBOT_H +#define SPHEREBOT_H + +#include +#include +#include +#include +#include +#include + +class spherebot : public QObject +{ + Q_OBJECT +public: + QextSerialPort *port; + + bool isConnected(); + bool send(QString cmd); + explicit spherebot(QObject *parent = 0); +signals: + void dataSent(QString data); +public slots: + bool connectWithBot(QString portName); + bool disconnectWithBot(); +private: + bool port_connected; +}; + +#endif // SPHEREBOT_H diff --git a/Spherebot_UI/spherebot_ui_plugin_import.cpp b/Spherebot_UI/spherebot_ui_plugin_import.cpp new file mode 100644 index 0000000..39acb25 --- /dev/null +++ b/Spherebot_UI/spherebot_ui_plugin_import.cpp @@ -0,0 +1,4 @@ +// This file is autogenerated by qmake. It imports static plugin classes for +// static plugins specified using QTPLUGIN and QT_PLUGIN_CLASS. variables. +#include +Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin) diff --git a/Spherebot_UI/txthread.cpp b/Spherebot_UI/txthread.cpp new file mode 100644 index 0000000..1614b71 --- /dev/null +++ b/Spherebot_UI/txthread.cpp @@ -0,0 +1,100 @@ +#include "txthread.h" + +txThread::txThread() +{ + lineCounter = 0; + bufferCounter = 0; + checkSendBufferTimer = new QTimer(this); + connect(checkSendBufferTimer,SIGNAL(timeout()),this,SLOT(checkBuffer())); +} + +txThread::~txThread() +{ + +} + +QString removeComments(QString intext) +{ + ////////////////////////////////////////////////remove comments + QString outTmp1,outTmp2; + bool state=1; //1= send, 0 = ignore + for(int i=0;istart(SENDBUFFERINTERVAL); +} + +void txThread::checkBuffer() +{ + //qDebug()<<"buffer check timer timeout"; + if(lineCounter <= lineMax) + { + //qDebug()<<"linecounter: " + QString::number(lineCounter); + qDebug()<<"buffercounter: " + QString::number(bufferCounter); + //qDebug()<<"drawcounter: " + QString::number(drawCounter); + if(bufferCounter <= MAXBUFFERCOUNTER) + { + QString tmp = textfile.section("\n",lineCounter,lineCounter); + tmp.append("\n"); + bot->send(tmp); + double progress= (double) lineCounter/(double)lineMax; + emit progressChanged(progress*100); + bufferCounter++; + lineCounter++; + } + } + else + { + checkSendBufferTimer->stop(); + emit fileTransmitted(); + } +} + +int txThread::getLineCounter() +{ + return lineCounter; +} + +void txThread::checkResponse(QString msg) +{ + // if(msg.count("G") > 1 || msg.count("M") > 1) + if(msg.contains("ok")) + { + qDebug()<<"processed: " + msg + "\n"; + drawCounter++; + bufferCounter--; + } +} diff --git a/Spherebot_UI/txthread.h b/Spherebot_UI/txthread.h new file mode 100644 index 0000000..1330304 --- /dev/null +++ b/Spherebot_UI/txthread.h @@ -0,0 +1,39 @@ +#ifndef TXTHREAD_H +#define TXTHREAD_H +#include +#include +#include "spherebot.h" +#include +#include + +#define MAXBUFFERCOUNTER 1 +#define SENDBUFFERINTERVAL 30 + +class txThread : public QThread +{ + Q_OBJECT +public: + txThread(); + void set(QString textfile,spherebot &bot); + void run(); + ~txThread(); + int getLineCounter(); + QTimer *checkSendBufferTimer; + +signals: + void progressChanged(int); + void fileTransmitted(); + +public slots: + void checkResponse(QString msg); + void checkBuffer(); +private: + QString textfile; + int lineCounter; + int lineMax; + int bufferCounter; + int drawCounter; + spherebot *bot; +}; + +#endif // TXTHREAD_H diff --git a/Spherebot_UI/ui_mainwindow.h b/Spherebot_UI/ui_mainwindow.h new file mode 100644 index 0000000..f3f8702 --- /dev/null +++ b/Spherebot_UI/ui_mainwindow.h @@ -0,0 +1,627 @@ +/******************************************************************************** +** Form generated from reading UI file 'mainwindow.ui' +** +** Created by: Qt User Interface Compiler version 5.0.2 +** +** WARNING! All changes made in this file will be lost when recompiling UI file! +********************************************************************************/ + +#ifndef UI_MAINWINDOW_H +#define UI_MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE + +class Ui_MainWindow +{ +public: + QWidget *centralWidget; + QGroupBox *controllBox; + QWidget *layoutWidget; + QHBoxLayout *horizontalLayout_6; + QVBoxLayout *verticalLayout_15; + QPushButton *setDiameterButton; + QHBoxLayout *horizontalLayout_9; + QSpacerItem *verticalSpacer; + QSlider *diameterSlider; + QSpacerItem *verticalSpacer_2; + QVBoxLayout *verticalLayout_7; + QSpinBox *diameterpinBox; + QLabel *label_4; + QFrame *line_2; + QVBoxLayout *verticalLayout_13; + QHBoxLayout *horizontalLayout_11; + QSpacerItem *verticalSpacer_5; + QSlider *servoFeedrateSlider; + QSpacerItem *verticalSpacer_6; + QSpinBox *FeedratespinBox; + QLabel *label_5; + QFrame *line; + QVBoxLayout *verticalLayout_3; + QHBoxLayout *horizontalLayout_12; + QSpacerItem *verticalSpacer_7; + QSlider *servoSlider; + QSpacerItem *verticalSpacer_8; + QSpinBox *servospinBox; + QLabel *label; + QVBoxLayout *verticalLayout_6; + QVBoxLayout *verticalLayout_5; + QVBoxLayout *verticalLayout_4; + QSlider *penSlider; + QHBoxLayout *horizontalLayout_5; + QLabel *penslider; + QSpinBox *penRotationBox; + QSlider *eggSlider; + QHBoxLayout *horizontalLayout_4; + QLabel *penslider_2; + QSpinBox *eggRotationBox; + QWidget *layoutWidget1; + QHBoxLayout *horizontalLayout; + QPushButton *connectButton; + QComboBox *portBox; + QPushButton *resetButton; + QWidget *layoutWidget2; + QVBoxLayout *verticalLayout_9; + QWidget *layoutWidget3; + QVBoxLayout *verticalLayout_10; + QWidget *layoutWidget4; + QVBoxLayout *verticalLayout_11; + QHBoxLayout *horizontalLayout_3; + QLineEdit *sendString; + QPushButton *sendButton; + QHBoxLayout *horizontalLayout_2; + QVBoxLayout *verticalLayout; + QLabel *label_2; + QListWidget *txList; + QVBoxLayout *verticalLayout_2; + QLabel *label_3; + QListWidget *rxList; + QWidget *layoutWidget5; + QVBoxLayout *verticalLayout_12; + QVBoxLayout *verticalLayout_8; + QHBoxLayout *horizontalLayout_8; + QLabel *fileName; + QHBoxLayout *horizontalLayout_10; + QPushButton *undoButton; + QPushButton *redoButton; + QTextEdit *fileTextEdit; + QHBoxLayout *horizontalLayout_7; + QPushButton *loadFileButton; + QPushButton *saveFileButton; + QPushButton *sendFileButton; + QPushButton *restartButton; + QProgressBar *fileSendProgressBar; + QTextEdit *outputText; + QLabel *label_6; + QToolBar *mainToolBar; + QStatusBar *statusBar; + + void setupUi(QMainWindow *MainWindow) + { + if (MainWindow->objectName().isEmpty()) + MainWindow->setObjectName(QStringLiteral("MainWindow")); + MainWindow->resize(1427, 497); + centralWidget = new QWidget(MainWindow); + centralWidget->setObjectName(QStringLiteral("centralWidget")); + controllBox = new QGroupBox(centralWidget); + controllBox->setObjectName(QStringLiteral("controllBox")); + controllBox->setEnabled(false); + controllBox->setGeometry(QRect(10, 60, 551, 231)); + controllBox->setCheckable(false); + controllBox->setChecked(false); + layoutWidget = new QWidget(controllBox); + layoutWidget->setObjectName(QStringLiteral("layoutWidget")); + layoutWidget->setGeometry(QRect(8, 0, 541, 221)); + horizontalLayout_6 = new QHBoxLayout(layoutWidget); + horizontalLayout_6->setSpacing(6); + horizontalLayout_6->setContentsMargins(11, 11, 11, 11); + horizontalLayout_6->setObjectName(QStringLiteral("horizontalLayout_6")); + horizontalLayout_6->setContentsMargins(0, 0, 0, 0); + verticalLayout_15 = new QVBoxLayout(); + verticalLayout_15->setSpacing(6); + verticalLayout_15->setObjectName(QStringLiteral("verticalLayout_15")); + setDiameterButton = new QPushButton(layoutWidget); + setDiameterButton->setObjectName(QStringLiteral("setDiameterButton")); + + verticalLayout_15->addWidget(setDiameterButton); + + horizontalLayout_9 = new QHBoxLayout(); + horizontalLayout_9->setSpacing(6); + horizontalLayout_9->setObjectName(QStringLiteral("horizontalLayout_9")); + verticalSpacer = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + horizontalLayout_9->addItem(verticalSpacer); + + diameterSlider = new QSlider(layoutWidget); + diameterSlider->setObjectName(QStringLiteral("diameterSlider")); + diameterSlider->setLayoutDirection(Qt::LeftToRight); + diameterSlider->setMinimum(5); + diameterSlider->setMaximum(120); + diameterSlider->setValue(20); + diameterSlider->setOrientation(Qt::Vertical); + diameterSlider->setInvertedAppearance(false); + + horizontalLayout_9->addWidget(diameterSlider); + + verticalSpacer_2 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + horizontalLayout_9->addItem(verticalSpacer_2); + + + verticalLayout_15->addLayout(horizontalLayout_9); + + verticalLayout_7 = new QVBoxLayout(); + verticalLayout_7->setSpacing(6); + verticalLayout_7->setObjectName(QStringLiteral("verticalLayout_7")); + diameterpinBox = new QSpinBox(layoutWidget); + diameterpinBox->setObjectName(QStringLiteral("diameterpinBox")); + diameterpinBox->setMinimum(5); + diameterpinBox->setMaximum(120); + diameterpinBox->setSingleStep(1); + diameterpinBox->setValue(20); + + verticalLayout_7->addWidget(diameterpinBox); + + label_4 = new QLabel(layoutWidget); + label_4->setObjectName(QStringLiteral("label_4")); + + verticalLayout_7->addWidget(label_4); + + + verticalLayout_15->addLayout(verticalLayout_7); + + + horizontalLayout_6->addLayout(verticalLayout_15); + + line_2 = new QFrame(layoutWidget); + line_2->setObjectName(QStringLiteral("line_2")); + line_2->setFrameShape(QFrame::VLine); + line_2->setFrameShadow(QFrame::Sunken); + + horizontalLayout_6->addWidget(line_2); + + verticalLayout_13 = new QVBoxLayout(); + verticalLayout_13->setSpacing(6); + verticalLayout_13->setObjectName(QStringLiteral("verticalLayout_13")); + horizontalLayout_11 = new QHBoxLayout(); + horizontalLayout_11->setSpacing(6); + horizontalLayout_11->setObjectName(QStringLiteral("horizontalLayout_11")); + verticalSpacer_5 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + horizontalLayout_11->addItem(verticalSpacer_5); + + servoFeedrateSlider = new QSlider(layoutWidget); + servoFeedrateSlider->setObjectName(QStringLiteral("servoFeedrateSlider")); + servoFeedrateSlider->setLayoutDirection(Qt::LeftToRight); + servoFeedrateSlider->setMinimum(10); + servoFeedrateSlider->setMaximum(6000); + servoFeedrateSlider->setValue(2000); + servoFeedrateSlider->setOrientation(Qt::Vertical); + servoFeedrateSlider->setInvertedAppearance(false); + + horizontalLayout_11->addWidget(servoFeedrateSlider); + + verticalSpacer_6 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + horizontalLayout_11->addItem(verticalSpacer_6); + + + verticalLayout_13->addLayout(horizontalLayout_11); + + FeedratespinBox = new QSpinBox(layoutWidget); + FeedratespinBox->setObjectName(QStringLiteral("FeedratespinBox")); + FeedratespinBox->setMinimum(10); + FeedratespinBox->setMaximum(6000); + FeedratespinBox->setValue(2000); + + verticalLayout_13->addWidget(FeedratespinBox); + + label_5 = new QLabel(layoutWidget); + label_5->setObjectName(QStringLiteral("label_5")); + + verticalLayout_13->addWidget(label_5); + + + horizontalLayout_6->addLayout(verticalLayout_13); + + line = new QFrame(layoutWidget); + line->setObjectName(QStringLiteral("line")); + line->setFrameShape(QFrame::VLine); + line->setFrameShadow(QFrame::Sunken); + + horizontalLayout_6->addWidget(line); + + verticalLayout_3 = new QVBoxLayout(); + verticalLayout_3->setSpacing(6); + verticalLayout_3->setObjectName(QStringLiteral("verticalLayout_3")); + horizontalLayout_12 = new QHBoxLayout(); + horizontalLayout_12->setSpacing(6); + horizontalLayout_12->setObjectName(QStringLiteral("horizontalLayout_12")); + verticalSpacer_7 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + horizontalLayout_12->addItem(verticalSpacer_7); + + servoSlider = new QSlider(layoutWidget); + servoSlider->setObjectName(QStringLiteral("servoSlider")); + servoSlider->setLayoutDirection(Qt::LeftToRight); + servoSlider->setMinimum(23); + servoSlider->setMaximum(120); + servoSlider->setValue(35); + servoSlider->setOrientation(Qt::Vertical); + servoSlider->setInvertedAppearance(true); + + horizontalLayout_12->addWidget(servoSlider); + + verticalSpacer_8 = new QSpacerItem(20, 40, QSizePolicy::Minimum, QSizePolicy::Expanding); + + horizontalLayout_12->addItem(verticalSpacer_8); + + + verticalLayout_3->addLayout(horizontalLayout_12); + + servospinBox = new QSpinBox(layoutWidget); + servospinBox->setObjectName(QStringLiteral("servospinBox")); + servospinBox->setMinimum(23); + servospinBox->setValue(35); + + verticalLayout_3->addWidget(servospinBox); + + label = new QLabel(layoutWidget); + label->setObjectName(QStringLiteral("label")); + + verticalLayout_3->addWidget(label); + + + horizontalLayout_6->addLayout(verticalLayout_3); + + verticalLayout_6 = new QVBoxLayout(); + verticalLayout_6->setSpacing(6); + verticalLayout_6->setObjectName(QStringLiteral("verticalLayout_6")); + verticalLayout_5 = new QVBoxLayout(); + verticalLayout_5->setSpacing(6); + verticalLayout_5->setObjectName(QStringLiteral("verticalLayout_5")); + verticalLayout_4 = new QVBoxLayout(); + verticalLayout_4->setSpacing(6); + verticalLayout_4->setObjectName(QStringLiteral("verticalLayout_4")); + penSlider = new QSlider(layoutWidget); + penSlider->setObjectName(QStringLiteral("penSlider")); + penSlider->setMinimum(-112); + penSlider->setMaximum(112); + penSlider->setSingleStep(1); + penSlider->setValue(0); + penSlider->setSliderPosition(0); + penSlider->setOrientation(Qt::Horizontal); + penSlider->setInvertedAppearance(true); + + verticalLayout_4->addWidget(penSlider); + + horizontalLayout_5 = new QHBoxLayout(); + horizontalLayout_5->setSpacing(6); + horizontalLayout_5->setObjectName(QStringLiteral("horizontalLayout_5")); + penslider = new QLabel(layoutWidget); + penslider->setObjectName(QStringLiteral("penslider")); + + horizontalLayout_5->addWidget(penslider); + + penRotationBox = new QSpinBox(layoutWidget); + penRotationBox->setObjectName(QStringLiteral("penRotationBox")); + penRotationBox->setMinimum(-112); + penRotationBox->setMaximum(112); + penRotationBox->setSingleStep(1); + + horizontalLayout_5->addWidget(penRotationBox); + + + verticalLayout_4->addLayout(horizontalLayout_5); + + + verticalLayout_5->addLayout(verticalLayout_4); + + eggSlider = new QSlider(layoutWidget); + eggSlider->setObjectName(QStringLiteral("eggSlider")); + eggSlider->setMinimum(-450); + eggSlider->setMaximum(450); + eggSlider->setValue(0); + eggSlider->setSliderPosition(0); + eggSlider->setOrientation(Qt::Horizontal); + + verticalLayout_5->addWidget(eggSlider); + + horizontalLayout_4 = new QHBoxLayout(); + horizontalLayout_4->setSpacing(6); + horizontalLayout_4->setObjectName(QStringLiteral("horizontalLayout_4")); + penslider_2 = new QLabel(layoutWidget); + penslider_2->setObjectName(QStringLiteral("penslider_2")); + + horizontalLayout_4->addWidget(penslider_2); + + eggRotationBox = new QSpinBox(layoutWidget); + eggRotationBox->setObjectName(QStringLiteral("eggRotationBox")); + eggRotationBox->setMinimum(-450); + eggRotationBox->setMaximum(450); + + horizontalLayout_4->addWidget(eggRotationBox); + + + verticalLayout_5->addLayout(horizontalLayout_4); + + + verticalLayout_6->addLayout(verticalLayout_5); + + + horizontalLayout_6->addLayout(verticalLayout_6); + + layoutWidget1 = new QWidget(centralWidget); + layoutWidget1->setObjectName(QStringLiteral("layoutWidget1")); + layoutWidget1->setGeometry(QRect(20, 20, 275, 30)); + horizontalLayout = new QHBoxLayout(layoutWidget1); + horizontalLayout->setSpacing(6); + horizontalLayout->setContentsMargins(11, 11, 11, 11); + horizontalLayout->setObjectName(QStringLiteral("horizontalLayout")); + horizontalLayout->setContentsMargins(0, 0, 0, 0); + connectButton = new QPushButton(layoutWidget1); + connectButton->setObjectName(QStringLiteral("connectButton")); + connectButton->setCheckable(false); + + horizontalLayout->addWidget(connectButton); + + portBox = new QComboBox(layoutWidget1); + portBox->setObjectName(QStringLiteral("portBox")); + + horizontalLayout->addWidget(portBox); + + resetButton = new QPushButton(layoutWidget1); + resetButton->setObjectName(QStringLiteral("resetButton")); + + horizontalLayout->addWidget(resetButton); + + layoutWidget2 = new QWidget(centralWidget); + layoutWidget2->setObjectName(QStringLiteral("layoutWidget2")); + layoutWidget2->setGeometry(QRect(0, 0, 2, 2)); + verticalLayout_9 = new QVBoxLayout(layoutWidget2); + verticalLayout_9->setSpacing(6); + verticalLayout_9->setContentsMargins(11, 11, 11, 11); + verticalLayout_9->setObjectName(QStringLiteral("verticalLayout_9")); + verticalLayout_9->setContentsMargins(0, 0, 0, 0); + layoutWidget3 = new QWidget(centralWidget); + layoutWidget3->setObjectName(QStringLiteral("layoutWidget3")); + layoutWidget3->setGeometry(QRect(0, 0, 2, 2)); + verticalLayout_10 = new QVBoxLayout(layoutWidget3); + verticalLayout_10->setSpacing(6); + verticalLayout_10->setContentsMargins(11, 11, 11, 11); + verticalLayout_10->setObjectName(QStringLiteral("verticalLayout_10")); + verticalLayout_10->setContentsMargins(0, 0, 0, 0); + layoutWidget4 = new QWidget(centralWidget); + layoutWidget4->setObjectName(QStringLiteral("layoutWidget4")); + layoutWidget4->setGeometry(QRect(20, 290, 541, 155)); + verticalLayout_11 = new QVBoxLayout(layoutWidget4); + verticalLayout_11->setSpacing(6); + verticalLayout_11->setContentsMargins(11, 11, 11, 11); + verticalLayout_11->setObjectName(QStringLiteral("verticalLayout_11")); + verticalLayout_11->setContentsMargins(0, 0, 0, 0); + horizontalLayout_3 = new QHBoxLayout(); + horizontalLayout_3->setSpacing(6); + horizontalLayout_3->setObjectName(QStringLiteral("horizontalLayout_3")); + sendString = new QLineEdit(layoutWidget4); + sendString->setObjectName(QStringLiteral("sendString")); + + horizontalLayout_3->addWidget(sendString); + + sendButton = new QPushButton(layoutWidget4); + sendButton->setObjectName(QStringLiteral("sendButton")); + + horizontalLayout_3->addWidget(sendButton); + + + verticalLayout_11->addLayout(horizontalLayout_3); + + horizontalLayout_2 = new QHBoxLayout(); + horizontalLayout_2->setSpacing(6); + horizontalLayout_2->setObjectName(QStringLiteral("horizontalLayout_2")); + verticalLayout = new QVBoxLayout(); + verticalLayout->setSpacing(6); + verticalLayout->setObjectName(QStringLiteral("verticalLayout")); + label_2 = new QLabel(layoutWidget4); + label_2->setObjectName(QStringLiteral("label_2")); + + verticalLayout->addWidget(label_2); + + txList = new QListWidget(layoutWidget4); + txList->setObjectName(QStringLiteral("txList")); + txList->setAutoScroll(false); + txList->setSelectionMode(QAbstractItemView::NoSelection); + + verticalLayout->addWidget(txList); + + + horizontalLayout_2->addLayout(verticalLayout); + + verticalLayout_2 = new QVBoxLayout(); + verticalLayout_2->setSpacing(6); + verticalLayout_2->setObjectName(QStringLiteral("verticalLayout_2")); + label_3 = new QLabel(layoutWidget4); + label_3->setObjectName(QStringLiteral("label_3")); + + verticalLayout_2->addWidget(label_3); + + rxList = new QListWidget(layoutWidget4); + rxList->setObjectName(QStringLiteral("rxList")); + + verticalLayout_2->addWidget(rxList); + + + horizontalLayout_2->addLayout(verticalLayout_2); + + + verticalLayout_11->addLayout(horizontalLayout_2); + + layoutWidget5 = new QWidget(centralWidget); + layoutWidget5->setObjectName(QStringLiteral("layoutWidget5")); + layoutWidget5->setGeometry(QRect(570, 10, 461, 431)); + verticalLayout_12 = new QVBoxLayout(layoutWidget5); + verticalLayout_12->setSpacing(6); + verticalLayout_12->setContentsMargins(11, 11, 11, 11); + verticalLayout_12->setObjectName(QStringLiteral("verticalLayout_12")); + verticalLayout_12->setContentsMargins(0, 0, 0, 0); + verticalLayout_8 = new QVBoxLayout(); + verticalLayout_8->setSpacing(6); + verticalLayout_8->setObjectName(QStringLiteral("verticalLayout_8")); + horizontalLayout_8 = new QHBoxLayout(); + horizontalLayout_8->setSpacing(6); + horizontalLayout_8->setObjectName(QStringLiteral("horizontalLayout_8")); + + verticalLayout_8->addLayout(horizontalLayout_8); + + fileName = new QLabel(layoutWidget5); + fileName->setObjectName(QStringLiteral("fileName")); + + verticalLayout_8->addWidget(fileName); + + horizontalLayout_10 = new QHBoxLayout(); + horizontalLayout_10->setSpacing(6); + horizontalLayout_10->setObjectName(QStringLiteral("horizontalLayout_10")); + undoButton = new QPushButton(layoutWidget5); + undoButton->setObjectName(QStringLiteral("undoButton")); + undoButton->setEnabled(false); + + horizontalLayout_10->addWidget(undoButton); + + redoButton = new QPushButton(layoutWidget5); + redoButton->setObjectName(QStringLiteral("redoButton")); + redoButton->setEnabled(false); + + horizontalLayout_10->addWidget(redoButton); + + + verticalLayout_8->addLayout(horizontalLayout_10); + + fileTextEdit = new QTextEdit(layoutWidget5); + fileTextEdit->setObjectName(QStringLiteral("fileTextEdit")); + + verticalLayout_8->addWidget(fileTextEdit); + + horizontalLayout_7 = new QHBoxLayout(); + horizontalLayout_7->setSpacing(6); + horizontalLayout_7->setObjectName(QStringLiteral("horizontalLayout_7")); + loadFileButton = new QPushButton(layoutWidget5); + loadFileButton->setObjectName(QStringLiteral("loadFileButton")); + + horizontalLayout_7->addWidget(loadFileButton); + + saveFileButton = new QPushButton(layoutWidget5); + saveFileButton->setObjectName(QStringLiteral("saveFileButton")); + saveFileButton->setEnabled(false); + + horizontalLayout_7->addWidget(saveFileButton); + + sendFileButton = new QPushButton(layoutWidget5); + sendFileButton->setObjectName(QStringLiteral("sendFileButton")); + sendFileButton->setEnabled(false); + + horizontalLayout_7->addWidget(sendFileButton); + + restartButton = new QPushButton(layoutWidget5); + restartButton->setObjectName(QStringLiteral("restartButton")); + restartButton->setEnabled(false); + + horizontalLayout_7->addWidget(restartButton); + + + verticalLayout_8->addLayout(horizontalLayout_7); + + + verticalLayout_12->addLayout(verticalLayout_8); + + fileSendProgressBar = new QProgressBar(layoutWidget5); + fileSendProgressBar->setObjectName(QStringLiteral("fileSendProgressBar")); + fileSendProgressBar->setEnabled(false); + fileSendProgressBar->setValue(0); + + verticalLayout_12->addWidget(fileSendProgressBar); + + outputText = new QTextEdit(centralWidget); + outputText->setObjectName(QStringLiteral("outputText")); + outputText->setGeometry(QRect(1040, 80, 351, 291)); + label_6 = new QLabel(centralWidget); + label_6->setObjectName(QStringLiteral("label_6")); + label_6->setGeometry(QRect(1040, 60, 101, 16)); + MainWindow->setCentralWidget(centralWidget); + mainToolBar = new QToolBar(MainWindow); + mainToolBar->setObjectName(QStringLiteral("mainToolBar")); + MainWindow->addToolBar(Qt::TopToolBarArea, mainToolBar); + statusBar = new QStatusBar(MainWindow); + statusBar->setObjectName(QStringLiteral("statusBar")); + MainWindow->setStatusBar(statusBar); + + retranslateUi(MainWindow); + QObject::connect(diameterSlider, SIGNAL(valueChanged(int)), diameterpinBox, SLOT(setValue(int))); + QObject::connect(diameterpinBox, SIGNAL(valueChanged(int)), diameterSlider, SLOT(setValue(int))); + QObject::connect(servospinBox, SIGNAL(valueChanged(int)), servoSlider, SLOT(setValue(int))); + QObject::connect(servoSlider, SIGNAL(valueChanged(int)), servospinBox, SLOT(setValue(int))); + QObject::connect(penRotationBox, SIGNAL(valueChanged(int)), penSlider, SLOT(setValue(int))); + QObject::connect(penSlider, SIGNAL(valueChanged(int)), penRotationBox, SLOT(setValue(int))); + QObject::connect(eggRotationBox, SIGNAL(valueChanged(int)), eggSlider, SLOT(setValue(int))); + QObject::connect(eggSlider, SIGNAL(valueChanged(int)), eggRotationBox, SLOT(setValue(int))); + QObject::connect(servoFeedrateSlider, SIGNAL(valueChanged(int)), FeedratespinBox, SLOT(setValue(int))); + QObject::connect(FeedratespinBox, SIGNAL(valueChanged(int)), servoFeedrateSlider, SLOT(setValue(int))); + + QMetaObject::connectSlotsByName(MainWindow); + } // setupUi + + void retranslateUi(QMainWindow *MainWindow) + { + MainWindow->setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0)); + controllBox->setTitle(QString()); + setDiameterButton->setText(QApplication::translate("MainWindow", "set Diameter", 0)); + label_4->setText(QApplication::translate("MainWindow", "Obj. Diameter", 0)); + label_5->setText(QApplication::translate("MainWindow", "Feedrate", 0)); + label->setText(QApplication::translate("MainWindow", "Servo", 0)); + penslider->setText(QApplication::translate("MainWindow", "Pen Rotation", 0)); + penslider_2->setText(QApplication::translate("MainWindow", "Egg Rotation", 0)); + connectButton->setText(QApplication::translate("MainWindow", "Connect", 0)); + resetButton->setText(QApplication::translate("MainWindow", "R", 0)); + sendButton->setText(QApplication::translate("MainWindow", "Send", 0)); + label_2->setText(QApplication::translate("MainWindow", "Tranceived Data", 0)); + label_3->setText(QApplication::translate("MainWindow", "Received Data", 0)); + fileName->setText(QString()); + undoButton->setText(QApplication::translate("MainWindow", "Undo", 0)); + redoButton->setText(QApplication::translate("MainWindow", "Redo", 0)); + loadFileButton->setText(QApplication::translate("MainWindow", "Load File", 0)); + saveFileButton->setText(QApplication::translate("MainWindow", "Save File", 0)); + sendFileButton->setText(QApplication::translate("MainWindow", "Send File", 0)); + restartButton->setText(QApplication::translate("MainWindow", "Restart", 0)); + label_6->setText(QApplication::translate("MainWindow", "Output File", 0)); + } // retranslateUi + +}; + +namespace Ui { + class MainWindow: public Ui_MainWindow {}; +} // namespace Ui + +QT_END_NAMESPACE + +#endif // UI_MAINWINDOW_H