If you insist - it's a longer read
The BACKW, HOME, TIME, STEPS and Timelapse Button are from an older version of the sketch and thus mostly commented out. I'm modifying a project from another author. NORMAL, ACCELERATED and SPEED are working fine.
/* Slider Control V1 Variant for 3.5" Parallel TFT-tft Shield Display with Adafruit_GFX
// Original by Mega-Testberichte.de - Marco Kleine-Albers
// Variant by gregorurabl.at - Gregor Urabl
//docs
//https://www.pjrc.com/teensy/td_libs_AccelStepper.html
//https://www.airspayce.com/mikem/arduino/AccelStepper/
//http://domoticx.com/arduino-library-accelstepper/
//good example https://www.brainy-bits.com/setting-stepper-motors-home-position-using-accelstepper/
//example: http://www.schmalzhaus.com/EasyDriver/Examples/EasyDriverExamples.html
//1,8°, 360/1,8 = 200
//200 steps is a full turn in fullstep mode
//use microstepping for smoother motion. see later in code
Standard TFT tft Pin Mappings:
*pin usage as follow:
* tft_CS tft_CD tft_WR tft_RD tft_RST SD_SS SD_DI SD_DO SD_SCK
* Arduino Uno A3 A2 A1 A0 A4 10 11 12 13
*Arduino Mega2560 A3 A2 A1 A0 A4 10 11 12 13
* tft_D0 tft_D1 tft_D2 tft_D3 tft_D4 tft_D5 tft_D6 tft_D7
* Arduino Uno 8 9 2 3 4 5 6 7
*Arduino Mega2560 8 9 2 3 4 5 6 7
*Remember to set the pins to suit your display module!
*/
#include <Adafruit_GFX.h> // Core graphics library
#include <Adafruit_TFTLCD.h> // tft Library
#include <TouchScreen.h> // Touchscreen Library
#include <MCUFRIEND_kbv.h> // Touchscreen Hardware-specific library
#include <AccelStepper.h>
#define tft_CS A3 // Chip Select goes to Analog 3
#define tft_CD A2 // Command/Data goes to Analog 2
#define tft_WR A1 // tft Write goes to Analog 1
#define tft_RD A0 // tft Read gies to Analog 0
#define tft_RESET A4 // Can alternately just connect to Arduino's reset pin
// define pins for resistive touchscreen
#define YP A1 // must be an analog pin, use "an" notation!
#define XM A2 // must be an analog pin, use "an" notation!
#define YM 7 // can be a digital pin
#define XP 6 // can be a digital pin
// define touchscreen pressure points
#define MINPRESSURE 10
#define MAXPRESSURE 1000
// Define touchscreen parameters
// Use test sketch to refine if necessary
#define TS_MINX 930
#define TS_MAXX 130
#define TS_MINY 200
#define TS_MAXY 970
#define STATUS_X 10
#define STATUS_Y 65
// Colors
#define BLACK 0x0000
#define WHITE 0xFFFF
#define RED 0xF800
#define ORANGE 0xFD20
#define BLUE 0x001F
#define DARKCYAN 0x03EF
#define GREEN 0x07E0
#define DARKGREEN 0x03E0
#define LIGHTGREY 0xC618
#define DARKGREY 0x7BEF
#define MAGENTA 0xF81F
//motor pins
int ENABLE_PIN = 23;
int STEP_PIN = 25;
int DIR_PIN = 27;
//microstepping Pins M1 =A8, M2=A9, M3=A10
//TABELLE, Abschnitt Software: https://www.mega-testberichte.de/testbericht/einen-kameraslider-motorisieren-arduino-a4988-steppermotor-touchdisplay-do-it-yourself
//pin mappings
int M1 = A8;
int M2 = A9;
int M3 = A10;
//when we do 1/2. 1/4, 1/8 odr 1/16 we multiply the base fullsteps with 2,4,5 or 16
//fullstep set to 1
int step_multiplier = 16;
//1 is the DRIVER interface as i use a driver board
AccelStepper stepper(1, STEP_PIN, DIR_PIN);
// Define object for TFT display
MCUFRIEND_kbv tft;
// Define object for touchscreen
// Last parameter is X-Y resistance, measure or use 300 if unsure
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
//debug/msg
int x, y;
String msg="";
char text_buffer[80];
//--button for speed
long int speed_set = 10*step_multiplier;
long int raise_speed_by = 10*step_multiplier;
long int speed_max = 400*step_multiplier;
//--needed for timelapse, buttons
int time_set = 60; //later multiplied with 1000, because the delay funct want millisec
int raise_time_by = 10;
int time_max = 400;
//--steps for timelapse
long int steps_set = 10*step_multiplier; //200 steps is a full turn in fullstep mode, in 1/16 a full turn is 16*200=3200
long int steps_max = 200*step_multiplier;
long int raise_steps_by = 10*step_multiplier; //raised by steps
//--slider length in steps
//slider length is 90 cm = 4000 fullsteps, with 1/16 it is 4000*16=64000
// Shorter Slider 64 cm = 2844 fullsteps , with 1/16 it is 2844*16=45511
long int slider_length = 45500;
//1/16 31000
//fullstep 4000
/*************************
** Draw UI **
*************************/
char buttonRadius = 10;
char buttonHeight = 60;
char buttonSpacing = 10;
uint16_t smallButtonWidth = 147;
uint16_t bigButtonWidth = 303;
// Define button array object
Adafruit_GFX_Button buttons[9];
void drawButtons() {
tft.setTextColor(WHITE);
tft.setTextSize(3);
// Create Buttons - initButton would create a Button from x and y coordinates in it's center. initButtonUL uses the top left corner
buttons[0].initButtonUL(&tft, buttonSpacing, buttonSpacing, bigButtonWidth, buttonHeight, WHITE, GREEN, WHITE, "NORMAL", 3); // NORMAL Button
int_to_string(speed_set, text_buffer);
buttons[1].initButtonUL(&tft, bigButtonWidth+2*buttonSpacing, buttonSpacing, smallButtonWidth, buttonHeight, WHITE, DARKCYAN, WHITE, text_buffer, 3); // SPEED Button
buttons[2].initButtonUL(&tft, buttonSpacing, buttonHeight+2*buttonSpacing, bigButtonWidth, buttonHeight, WHITE, ORANGE, WHITE, "", 3); // ACCELETATE Button - Due to a limitation in the Adafruit_GFX_Button Object the Label of a Button is limited to 9 Characters. So we draw this one without label and add it with tft.print afterwards
buttons[3].initButtonUL(&tft, buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, DARKCYAN, WHITE, "START", 3); // START Button
int_to_string(time_set, text_buffer);
buttons[4].initButtonUL(&tft, smallButtonWidth+2*buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, BLUE, WHITE, text_buffer, 3); // TIME Button (set number)
int_to_string(steps_set, text_buffer);
buttons[5].initButtonUL(&tft, 2*smallButtonWidth+3*buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, MAGENTA, WHITE, text_buffer, 3);// STEPS Button (set number)
buttons[6].initButtonUL(&tft, buttonSpacing, 3*buttonHeight+4*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, GREEN, WHITE, "TIMELAP", 3);// TIMELAPSE START Button
buttons[7].initButtonUL(&tft, smallButtonWidth+2*buttonSpacing, 3*buttonHeight+4*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, ORANGE, WHITE, "BACKW", 3);// BACKW Button
buttons[8].initButtonUL(&tft, 2*smallButtonWidth+3*buttonSpacing, 3*buttonHeight+4*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, RED, WHITE, "HOME", 3); // HOME Button
// Draw Buttons
for(uint8_t buttonCounter = 0; buttonCounter <= 8; buttonCounter++)
{
buttons[buttonCounter].drawButton();
}
tft.setCursor(40, 100);
tft.print("ACCELERATED");
}
/*************************
** Required functions **
*************************/
void setup() {
tft.reset();
//motor
pinMode(ENABLE_PIN, INPUT);
digitalWrite(ENABLE_PIN, HIGH);
//mircosteppin
pinMode(M1, OUTPUT);
pinMode(M2, OUTPUT);
pinMode(M3, OUTPUT);
//1/16 had the lowest vibration
//see table for step values: https://forum.arduino.cc/index.php?topic=415724.0
digitalWrite(M1, HIGH);
digitalWrite(M2, HIGH);
digitalWrite(M3, HIGH);
// Setup the Display
tft.begin(tft.readID());
tft.setRotation(1);
tft.fillScreen(BLACK);
//call function to draw our gui
drawButtons();
Serial.begin(9600);
Serial.println("Starting Stepper Test\r\n");
Serial.print("TFT size is "); Serial.print(tft.width()); Serial.print("x"); Serial.println(tft.height());
//Setup for motor
//disable the power of the motor
stepper.disableOutputs();
//Set Max Speed and Acceleration of each Steppers at startup
stepper.setMaxSpeed(1000); //Set Max Speed of Stepper (Slower to get better accuracy). Steps per second
stepper.setAcceleration(100); // Set Acceleration of Stepper
stepper.setSpeed(1000);
//debug test
/*
digitalWrite(ENABLE_PIN, LOW);
stepper.runToNewPosition(0); Serial.println(stepper.currentPosition());
stepper.runToNewPosition(45500); Serial.println(stepper.currentPosition());
stepper.runToNewPosition(0); Serial.println(stepper.currentPosition());
digitalWrite(ENABLE_PIN, HIGH); */
}
void loop() {
//touchscreen
uint16_t i;
digitalWrite(13, HIGH);
TSPoint p = ts.getPoint();
digitalWrite(13, LOW);
pinMode(XM, OUTPUT);
pinMode(YP, OUTPUT);
if (p.z > MINPRESSURE && p.z < MAXPRESSURE)
{
p.x = map(p.x, TS_MINX, TS_MAXX, tft.width(),0);
p.y = map(p.y, TS_MINY, TS_MAXY, tft.height(),0);
//debug
//check the area where we drew the buton for touch
/*
Serial.print("Touch X is:");
Serial.print(p.x);
Serial.print("\r\n");
Serial.print("Touch Y is:");
Serial.print(p.y);
Serial.print("\r\n");*/
//--------------------------NORMAL button
if ((p.y >= 10) && (p.x >= 40) && (p.y <= 220) && (p.x <= 100) ) {
touchBorder(buttonSpacing, buttonSpacing, bigButtonWidth, buttonHeight, p.z);
updateStr("Starting Motor");
//enable disable power manuelly
digitalWrite(ENABLE_PIN, LOW);
stepper.setCurrentPosition(0); //must be set to 0 because manual moving START/BACKW/HOME may have changed the position and normal must always begin at start/0
stepper.moveTo(slider_length);
/****************************************************************************************************/
/* IMPROTANT: DO NOT USE Serial.print in hihly repeated loops. Slows down everything. See code above
/****************************************************************************************************/
while (stepper.currentPosition() != slider_length) {
//Serial.print("START"); //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY
//Serial.print(stepper.currentPosition()); //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY
//Serial.print("\r\n"); //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY
stepper.setSpeed(speed_set);
stepper.run();
}
//after the run move back to position 0. that happens with acceleration
//Serial.print("END");
stepper.runToNewPosition(0);
digitalWrite(ENABLE_PIN, HIGH);
}
//---------------------ACCELERATE button
if ((p.y >= 10) && (p.x >= 140) && (p.y <= 220) && (p.x <= 210) ) {
touchBorder(buttonSpacing,buttonHeight+2*buttonSpacing, bigButtonWidth, buttonHeight, p.z);
updateStr("Accelerate Motor");
digitalWrite(ENABLE_PIN, LOW);
stepper.setCurrentPosition(0); //must be set to 0 because manual moving START/BACKW/HOME may have changed the position and normal must always begin at start/0
stepper.setSpeed(speed_set);
stepper.runToNewPosition(slider_length);
//after the run move back to position 0
stepper.runToNewPosition(0);
digitalWrite(ENABLE_PIN, HIGH);
}
//---------------------START button
if ((p.y >= 10) && (p.x >= 250) && (p.y <= 100) && (p.x <= 310) ) {
buttons[3].press(true);
//touchBorder(10, 170, 100, 220, p.z); //can not use that here because it will block because we press and hold
if (buttons[3].justPressed()){ // code to run at press time
updateStr("START");
digitalWrite(ENABLE_PIN, LOW);
Serial.print("start run start at pos ");
Serial.print(stepper.currentPosition());
Serial.print("\r\n");
stepper.setAcceleration(100);
stepper.setSpeed(speed_set);
}
if (buttons[3].isPressed() ) { // code to run while the button is held
stepper.run();
Serial.print("running:");
Serial.print(stepper.currentPosition());
Serial.print("\r\n");
}
if ( buttons[3].justReleased() ) { // code to run at release time
stepper.stop();
Serial.print("normal run stopped \r\n");
Serial.print(stepper.currentPosition());
Serial.print("\r\n");
digitalWrite(ENABLE_PIN, HIGH);
}
}
//---------------------BACKW button
if ((p.y >= 125) && (p.x >= 360) && (p.y <= 220) && (p.x <= 420) ) {
//touchBorder(110, 170, 200, 220); //can not use that here because it will block
updateStr("BACKWARDS");
digitalWrite(ENABLE_PIN, LOW);
Serial.print("backward run start at pos \r\n");
Serial.print(stepper.currentPosition());
Serial.print("\r\n");
stepper.setAcceleration(100);
stepper.setSpeed(speed_set);
/* while (Touch.dataAvailable() == true) {
stepper.setSpeed(-speed_set);
stepper.run();
//Serial.print("running by button pressed backwards"); //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY
}
*/
Serial.print("backward run stopped \r\n");
Serial.print(stepper.currentPosition());
Serial.print("\r\n");
//stop completely after, otherwise movement is still there
stepper.stop();
//Serial.print("backward run stopped");
digitalWrite(ENABLE_PIN, HIGH);
}
//--------------------->HOME button
if ((p.y >= 230) && (p.x >= 360) && (p.y <= 310) && (p.x <= 410) ) {
touchBorder(2*smallButtonWidth+3*buttonSpacing, 220, smallButtonWidth, buttonHeight, p.z);
updateStr("HOME");
digitalWrite(ENABLE_PIN, LOW);
Serial.print("Home start, current POS is:");
Serial.print(stepper.currentPosition());
Serial.print("\r\n");
stepper.setSpeed(speed_set);
stepper.setCurrentPosition(stepper.currentPosition()); //set correct position because its not known by default
//after the run move back to position 0
stepper.runToNewPosition(0);
digitalWrite(ENABLE_PIN, HIGH);
}
//------------------------SPEED button with UPDATE of number
if ((p.y >= 240) && (p.x >= 40) && (p.y <= 330) && (p.x <= 110) ) {
//one touch raises speed by X up to "speed_max"
if(speed_set < speed_max) {
speed_set = speed_set + raise_speed_by;
}
else {
speed_set = 10;
}
//if i dont set that here the manual START/REWIND will not work after i change the speed and press them again. why....
stepper.setSpeed(speed_set);
int_to_string(speed_set, text_buffer);
buttons[1].initButtonUL(&tft, bigButtonWidth+2*buttonSpacing, buttonSpacing, smallButtonWidth, buttonHeight, WHITE, DARKCYAN, WHITE, text_buffer, 3); // SPEED Button
buttons[1].drawButton();
touchBorder(bigButtonWidth+2*buttonSpacing, buttonSpacing, smallButtonWidth, buttonHeight, p.z);
String speedMsg = "Speed set to ";
speedMsg.concat(text_buffer);
updateStr(speedMsg);
}
//------------------------TIMELAPSE START button START
if ((p.y >= 10) && (p.x >= 350) && (p.y <= 100) && (p.x <= 420) ) {
int_to_string(speed_set, text_buffer);
tft.setCursor(237, 26);
tft.print(text_buffer);
Serial.print("Starting Timelapse\r\n");
//@good blog, method for using a cable to the camera for timalapse https://photoscs.wordpress.com/2014/03/25/arduino-stepper-code-time-lapse/
//enable disable power manually
digitalWrite(ENABLE_PIN, LOW); //motor an
Serial.print("Timelapse start, current POS is:");
Serial.print(stepper.currentPosition());
Serial.print("\r\n");
//see: http://forum.arduino.cc/index.php?topic=206796.0
//multiplied with 1000, we need millicseconds //use millis() instead later, non blocking
long ms_time = time_set*1000L;
Serial.print("Delay time set in MS:\r\n");
Serial.print(ms_time);
Serial.print("\r\n");
while (stepper.currentPosition() != slider_length) {
stepper.runToNewPosition(steps_set);
steps_set = steps_set+ raise_steps_by;
stepper.run();
digitalWrite(ENABLE_PIN, HIGH); //motor aus
delay(ms_time); //wait, delay
digitalWrite(ENABLE_PIN, LOW); //motor an
//Serial.print("Timelapse running, current POS is:"); //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY
//Serial.print(stepper.currentPosition()); //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY
//Serial.print("\r\n"); //DO NOT ACTIVATE THIS IT WILL SLOW DOWN THE LOOP MASSIVELY
}
digitalWrite(ENABLE_PIN, HIGH); //finish. motor off
//we start the timelapse. Move Motor by x
touchBorder(10, 130, 150, 170, p.z);
updateStr("TIMELAPSE");
}
//------------------------TIME button with UPDATE of number
if ((p.y >= 125) && (p.x >= 245) && (p.y <=220) && (p.x <= 315) ) {
//one touch raises time by X up to time_max
if(time_set < time_max) {
time_set = time_set + raise_time_by;
}
else {
time_set = 10;
}
int_to_string(time_set, text_buffer);
buttons[4].initButtonUL(&tft, smallButtonWidth+2*buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, BLUE, WHITE, text_buffer, 3);
buttons[4].drawButton();
touchBorder(smallButtonWidth+2*buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, p.z);
String timeMsg = "Time set to ";
timeMsg.concat(text_buffer);
updateStr(timeMsg);
}
//------------------------STEPS button with UPDATE of number 230, 130, 310, 170
if ((p.y >= 235) && (p.x >= 250) && (p.y <=325) && (p.x <= 320) ) {
//one touch raises steps by 10 up to steps_max
if(steps_set < steps_max) {
steps_set = steps_set + raise_steps_by;
}
else {
steps_set = 10;
}
int_to_string(steps_set, text_buffer);
buttons[5].initButtonUL(&tft, 2*smallButtonWidth+3*buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, WHITE, MAGENTA, WHITE, text_buffer, 3);
buttons[5].drawButton();
touchBorder(2*smallButtonWidth+3*buttonSpacing, 2*buttonHeight+3*buttonSpacing, smallButtonWidth, buttonHeight, p.z);
String stepsMsg = "Steps set to ";
stepsMsg.concat(text_buffer);
updateStr(stepsMsg);
}
}
}
/***************************************************************************
* update string so we see what has been touched - debug help
****************************************************************************/
void updateStr(String msg){
tft.fillRect(0, tft.height()-30, tft.width(), 30, LIGHTGREY);
tft.setCursor(20,tft.height()-22);
tft.setTextSize(2);
tft.setTextColor(BLACK);
tft.print(msg);
}
/****************************************************************************
* Draw a border while a button is touched
****************************************************************************/
void touchBorder(int x1, int y1, int x2, int y2, int touched) {
//while (touched > MINPRESSURE && touched < MAXPRESSURE){
tft.drawRoundRect (x1, y1, x2, y2, buttonRadius, RED);
//}
/* while (Touch.dataAvailable())
Touch.read();*/
// tft.fillRoundRect (x1, y1, x2, y2, buttonRadius, RED);
}
/*****************************************************************************
* convert X to String
****************************************************************************/
void int_to_string(int val, char* string) {
if(string)
sprintf(string, "%d", val);
return;
}