(EN CONSTRUCCIÓN…….)
Mi siguienta etapa personal de conocimiento es entender Marlin para su uso con mi robot Scara,que ya mencione en entradas anteriores que es una copia modificada de HowtoMecatronics by Jean
Voy a utilizar la archiconocida Ramps 1.4, montada sobre arduino Mega2560
pero repasemos las caracteristicas de esta placa con este dossier:
https://www.reprap.org/mediawiki/images/0/06/RAMPS_dossier.pdf
USO DE SCARA CON UNA VERSION DE FIRMWARE ANTIGUA DE MARLIN CON ARDUINO IDE. (Marlin 1.1.0.RC3)
Esta versión la encontre en el canal de Youtube «Mundo C.N.C con arduino», teniendo que modificar algunos de sus sketchs para el uso de Ramps 1.4, posibilidad de uso de 4 servos entre otras.Sin embargo fracase al intentar usar Scara con la cinemática inversa propia de este firmware. Por este motivo ,he usado Blynk IOT para diseñar una GUI que controla dicha cinematica a través de un módulo wifi esp8266 enlazado por puerto serial con el firmware de Marlin. Los resultados son mucho mejores que usando AccelStepper y la CNC Shield V3. Bien tengo que aclarar que se trata de un control manual cuyo objetivo principal es el aprendizaje. Nada que ver,por ejemplo, con el uso de scara como drawing machine
Descarga de Marlin 1.1.0.RC3 modificado :
COMENTARIOS DE LA CONFIGURACION;
<configuration.h
#ifndef CONFIGURATION_H
#define CONFIGURATION_H
#include "boards.h"
#include "macros.h"
#if ENABLED(USE_AUTOMATIC_VERSIONING)
#include "_Version.h"
#else
#include "Default_Version.h"
#endif
#define STRING_CONFIG_H_AUTHOR "(MY_SCARA)"
#define SHOW_BOOTSCREEN
#define STRING_SPLASH_LINE1 SHORT_BUILD_VERSION
#define SERIAL_PORT 0
//======================= Configura baudios y define placa =====================
#define BAUDRATE 115200 de transmisión
#ifndef MOTHERBOARD
#define MOTHERBOARD 43 // Placa Mega 2560 con Ramps 1.4
// ==========//NO TOCAR ESTA PARTE ===============================
#endif
#define EXTRUDERS 1
#define POWER_SUPPLY 1
#define TEMP_SENSOR_0 1
#define TEMP_SENSOR_1 0
#define TEMP_SENSOR_2 0
#define TEMP_SENSOR_3 0
#define TEMP_SENSOR_BED 0
#define MAX_REDUNDANT_TEMP_SENSOR_DIFF 10
#define TEMP_RESIDENCY_TIME 10
#define TEMP_HYSTERESIS 3
#define TEMP_WINDOW 1
#define HEATER_0_MINTEMP 0
#define HEATER_1_MINTEMP 0
#define HEATER_2_MINTEMP 0
#define HEATER_3_MINTEMP 0
#define BED_MINTEMP 0
#define HEATER_0_MAXTEMP 100
#define HEATER_1_MAXTEMP 100
#define HEATER_2_MAXTEMP 100
#define HEATER_3_MAXTEMP 100
#define BED_MAXTEMP 100
#define PIDTEMP
#define BANG_MAX 255
#define PID_MAX BANG_MAX
#if ENABLED(PIDTEMP)
#define PID_FUNCTIONAL_RANGE 10
#define PID_INTEGRAL_DRIVE_MAX PID_MAX
#define K1 0.95
#define DEFAULT_Kp 22.2
#define DEFAULT_Ki 1.08
#define DEFAULT_Kd 114
#endif
#define MAX_BED_POWER 255
#if ENABLED(PIDTEMPBED)
#define PID_BED_INTEGRAL_DRIVE_MAX MAX_BED_POWER
#define DEFAULT_bedKp 10.00
#define DEFAULT_bedKi .023
#define DEFAULT_bedKd 305.4
#endif // PIDTEMPBED
#define PREVENT_DANGEROUS_EXTRUDE
#define PREVENT_LENGTHY_EXTRUDE
#define EXTRUDE_MINTEMP 0
#define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH)
#define THERMAL_PROTECTION_HOTENDS
#define THERMAL_PROTECTION_BED
============================ Puntos para configurar =========================
//===============================================================================
#define ENDSTOPPULLUPS // Comenta esto (usando // al comienzo de la línea) para deshabilitar las resistencias pullup de fin de carrera
#if DISABLED(ENDSTOPPULLUPS)
#endif
// El final de carrera mecánico con COM a tierra y NC a la señal usa "falso" aquí (configuración más común).
const bool X_MIN_ENDSTOP_INVERTING = false; // establecido en verdadero para invertir la lógica del final de carrera.
const bool Y_MIN_ENDSTOP_INVERTING = false; // establecido en verdadero para invertir la lógica del final de carrera.
const bool Z_MIN_ENDSTOP_INVERTING = false; //establecido en verdadero para invertir la lógica del final de carrera.
const bool X_MAX_ENDSTOP_INVERTING = true;
const bool Y_MAX_ENDSTOP_INVERTING = true;
const bool Z_MAX_ENDSTOP_INVERTING = true;
const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false;
//#define DISABLE_MAX_ENDSTOPS
//#define DISABLE_MIN_ENDSTOPS
// If you want to enable the Z probe pin, but disable its use, uncomment the line below.
// This only affects a Z probe endstop if you have separate Z min endstop as well and have
// activated Z_MIN_PROBE_ENDSTOP below. If you are using the Z Min endstop on your Z probe,
// this has no effect.
//#define DISABLE_Z_MIN_PROBE_ENDSTOP
// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1
// :{0:'Low',1:'High'}
#define X_ENABLE_ON 0
#define Y_ENABLE_ON 0
#define Z_ENABLE_ON 0
#define E_ENABLE_ON 0 // For all extruders
// Disables axis when it's not being used.
// WARNING: When motors turn off there is a chance of losing position accuracy!
#define DISABLE_X false
#define DISABLE_Y false
#define DISABLE_Z false
// sección de la extrusora
#define DISABLE_E false // For all extruders
#define DISABLE_INACTIVE_EXTRUDER true //disable only inactive extruders and keep active extruder enabled
// @section machine
// Invertir la dirección paso a paso. (o revertir el conector del motor.
#define INVERT_X_DIR true
#define INVERT_Y_DIR true
#define INVERT_Z_DIR true
// For direct drive extruder v9 set to true, for geared extruder set to false.
#define INVERT_E0_DIR false
//#define INVERT_E1_DIR false
//#define INVERT_E2_DIR false
//#define INVERT_E3_DIR false
// @section homing
// ENDSTOP SETTINGS:
// Sets direction of endstops when homing; 1=MAX, -1=MIN
// :[-1,1]
#define X_HOME_DIR -1
#define Y_HOME_DIR -1
#define Z_HOME_DIR -1
#define min_software_endstops true // If true, axis won't move to coordinates less than HOME_POS.
#define max_software_endstops true // If true, axis won't move to coordinates greater than the defined lengths below.
// @section machine
// Travel limits after homing (units are in mm)
#define X_MIN_POS -14
#define Y_MIN_POS 24
#define Z_MIN_POS 0
#define X_MAX_POS 179
#define Y_MAX_POS 359
#define Z_MAX_POS 150
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
const bool FIL_RUNOUT_INVERTING = true;
#define ENDSTOPPULLUP_FIL_RUNOUT
#define FILAMENT_RUNOUT_SCRIPT "M600"
#endif
#endif
//#define MANUAL_HOME_POSITIONS
#if ENABLED(MANUAL_HOME_POSITIONS)
#define MANUAL_X_HOME_POS 141
#define MANUAL_Y_HOME_POS 45
#define MANUAL_Z_HOME_POS 5
#endif
#define HOMING_FEEDRATE {5*200, 5*200, 5*50, 0}
#define DEFAULT_AXIS_STEPS_PER_UNIT { 177.7777777, 142.2222222, 400, 36 }//{20,20,400,3200} // Pasos por grado y por mm.
#define DEFAULT_MAX_FEEDRATE {1000, 2000, 500, 10} // Velocidades maximas
#define DEFAULT_MAX_ACCELERATION {3000,3000,1000,100} // Aceleraciones maximas
#define DEFAULT_ACCELERATION 3000
#define DEFAULT_RETRACT_ACCELERATION 3000
#define DEFAULT_TRAVEL_ACCELERATION 3000
#define DEFAULT_XYJERK 15.0
#define DEFAULT_ZJERK 0.3
#define DEFAULT_EJERK 0.3
#define CUSTOM_M_CODES
/*********************************************************************\
* R/C SERVO support
* Sponsored by TrinityLabs, Reworked by codexmas
**********************************************************************/
// Number of servos
//
// If you select a configuration below, this will receive a default value and does not need to be set manually
// set it manually if you have more servos than extruders and wish to manually control some
// leaving it undefined or defining as 0 will disable the servo subsystem
// If unsure, leave commented / disabled
//
#define NUM_SERVOS 4 // Servo index starts with 0 for M280 command
// Servo Endstops
//
// This allows for servo actuated endstops, primary usage is for the Z Axis to eliminate calibration or bed height changes.
// Use M206 command to correct for switch height offset to actual nozzle height. Store that setting with M500.
//
//#define SERVO_ENDSTOPS {-1, -1, 0} // Servo index for X, Y, Z. Disable with -1
//#define SERVO_ENDSTOP_ANGLES {0,0, 0,0, 70,0} // X,Y,Z Axis Extend and Retract angles
//===========================================================================
//========================= No tocar ==========================
//===========================================================================
#if ENABLED(CUSTOM_M_CODES)
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#define CUSTOM_M_CODE_SET_Z_PROBE_OFFSET 851
#define Z_PROBE_OFFSET_RANGE_MIN -20
#define Z_PROBE_OFFSET_RANGE_MAX 20
#endif
#if ENABLED(MANUAL_BED_LEVELING)
#define MBL_Z_STEP 0.025
#endif
#if ENABLED(MESH_BED_LEVELING)
#define MESH_MIN_X 10
#define MESH_MAX_X (X_MAX_POS - MESH_MIN_X)
#define MESH_MIN_Y 10
#define MESH_MAX_Y (Y_MAX_POS - MESH_MIN_Y)
#define MESH_NUM_X_POINTS 3
#define MESH_NUM_Y_POINTS 3
#define MESH_HOME_SEARCH_Z 4
#endif // MESH_BED_LEVELING
#define Z_MIN_PROBE_REPEATABILITY_TEST
#if ENABLED(AUTO_BED_LEVELING_FEATURE)
#define AUTO_BED_LEVELING_GRID
#if ENABLED(AUTO_BED_LEVELING_GRID)
#define LEFT_PROBE_BED_POSITION 15
#define RIGHT_PROBE_BED_POSITION 170
#define FRONT_PROBE_BED_POSITION 20
#define BACK_PROBE_BED_POSITION 170
#define MIN_PROBE_EDGE 10
#define AUTO_BED_LEVELING_GRID_POINTS 2
#else
#define ABL_PROBE_PT_1_X 15
#define ABL_PROBE_PT_1_Y 180
#define ABL_PROBE_PT_2_X 15
#define ABL_PROBE_PT_2_Y 20
#define ABL_PROBE_PT_3_X 170
#define ABL_PROBE_PT_3_Y 20
#endif
#define X_PROBE_OFFSET_FROM_EXTRUDER -25
#define Y_PROBE_OFFSET_FROM_EXTRUDER -29
#define Z_PROBE_OFFSET_FROM_EXTRUDER -12.35
#define Z_RAISE_BEFORE_HOMING 4
#define XY_TRAVEL_SPEED 8000
#define Z_RAISE_BEFORE_PROBING 15
#define Z_RAISE_BETWEEN_PROBINGS 5
#define Z_RAISE_AFTER_PROBING 15
#define Z_SAFE_HOMING
#if ENABLED(Z_SAFE_HOMING)
#define Z_SAFE_HOMING_X_POINT ((X_MIN_POS + X_MAX_POS) / 2)
#define Z_SAFE_HOMING_Y_POINT ((Y_MIN_POS + Y_MAX_POS) / 2)
#endif
#endif
#if ENABLED(EEPROM_SETTINGS)
#define EEPROM_CHITCHAT // Please keep turned on if you can.
#endif
#define PLA_PREHEAT_HOTEND_TEMP 180
#define PLA_PREHEAT_HPB_TEMP 70
#define PLA_PREHEAT_FAN_SPEED 250
#define ABS_PREHEAT_HOTEND_TEMP 240
#define ABS_PREHEAT_HPB_TEMP 110
#define ABS_PREHEAT_FAN_SPEED 0
#define LANGUAGE_INCLUDE GENERATE_LANGUAGE_INCLUDE(es)
#define SOFT_PWM_SCALE 0
#if ENABLED(DEACTIVATE_SERVOS_AFTER_MOVE)
#define SERVO_DEACTIVATION_DELAY 300
#endif
#define FILAMENT_SENSOR_EXTRUDER_NUM 0
#define MEASUREMENT_DELAY_CM 14
#define DEFAULT_NOMINAL_FILAMENT_DIA 3.00
#define MEASURED_UPPER_LIMIT 3.30
#define MEASURED_LOWER_LIMIT 1.90
#define MAX_MEASUREMENT_DELAY 20
#define DEFAULT_MEASURED_FILAMENT_DIA DEFAULT_NOMINAL_FILAMENT_DIA
#include "Configuration_adv.h"
#include "thermistortables.h"
#endif //CONFIGURATION_H
GUI CON BLYNK
Cargaremos nuestro esp8266 con este programa para enlazar con Blynk cloud y nuestrodispositivo remoto que controlara la cinematica del brazo robotico:
#define BLYNK_TEMPLATE_ID "TMPLoFTs4H8E"
#define BLYNK_TEMPLATE_NAME "MySCARA MARLIN"
#define BLYNK_AUTH_TOKEN "e4OE0ODLb4bYcGQqSLEPIo0tYSOs_5OT"
#include <BlynkSimpleEsp8266.h>
#include <Arduino.h>
#include <Wire.h>
#include <WiFiClient.h>
//char ssid[] = "blynkiot";
char ssid[] = "xxxxxxxx";//NOMBRE DE NUESTRA RED WIFI
char pass[] = "xxxxxxxxxxxx";//Contraseña
char auth[] ="e4OE0ODLb4bYcGQqSLEPIo0tYSOs_5OT";
boolean controlIK = false;
int run,grip,homing,a=0,speed,stp_off,stp_on,rst,w,b;
float L1 = 228; // L1 = 228mm
float L2 = 145; // L2 = 145mm
float xP,yP,z,x,y,theta1,theta2,theta1F, theta2F,inputx,inputy,Inputx,Inputy;
String data,data2,G1,X,Y,Z,F,M17,M18,G28;
BLYNK_WRITE(V0){homing=param.asInt();}
BLYNK_WRITE(V1){grip=param.asInt();}
BLYNK_WRITE(V2){run=param.asInt();}
BLYNK_WRITE(V5){z=param.asDouble();}
BLYNK_WRITE(V6){theta1=param.asDouble();}
BLYNK_WRITE(V7){theta2=param.asDouble();}
BLYNK_WRITE(V8){w=param.asInt();}
BLYNK_WRITE(V9){speed=param.asInt();}
BLYNK_WRITE(V13){controlIK=param.asInt();}
BLYNK_WRITE(V14){inputx=param.asDouble();}
BLYNK_WRITE(V15){inputy=param.asDouble();}
BLYNK_WRITE(V16){stp_off=param.asInt();}
BLYNK_WRITE(V17){stp_on=param.asInt();}
BLYNK_WRITE(V18){rst=param.asInt();}
BlynkTimer timer1,timer2;
void SV3(){ Blynk.virtualWrite(V3,xP); }
void SV4(){ Blynk.virtualWrite(V4,yP);}
void SV10(){ Blynk.virtualWrite(V10,w); }
void SV11(){ Blynk.virtualWrite(V11,theta1);}
void SV12(){ Blynk.virtualWrite(V12,theta2); }
void setup(){
Blynk.begin(auth, ssid, pass);
Serial.begin(115200);
timer1.setInterval(1000L, SV3);
timer1.setInterval(1000L, SV4);
timer2.setInterval(1500L, SV10);
timer2.setInterval(100L, SV11);
timer2.setInterval(100L, SV12);
G1=String ("G1");
X=String ("X");
Y=String ("Y");
Z=String ("Z");
F=String ("F");
M17=String("M17");
M18=String("M18");
G28=String("G28");
}
void loop() {
Blynk.run();
timer1.run();
timer2.run();
if (controlIK==false){forwardKinematics();}
else if (controlIK==true){inverseKinematics();}
data=("G1 X"+String(theta1)+ " "+"Y"+String(theta2)+ " "+"Z"+String(z)+ " "+"F"+String(speed));
if (stp_on){Serial.println(M17);delay(100);}
if (stp_off){Serial.println(M18);delay(100);}
while (homing&&a==0) {data=0;Serial.println(G28);delay(100);a=1;}//orden homing
if(run&&b==0){Serial.println(data);delay(50);}//RUN
if(rst){a=0;}
}
void forwardKinematics() {
float theta1F=(theta1*PI/180);
float theta2F=((theta2)*PI/180)+PI;
xP = ((L1 * cos(theta1F)) + (L2 * cos(theta1F + theta2F)));
yP = ((L1 * sin(theta1F)) + (L2 * sin(theta1F + theta2F)))-offset y;
}
void inverseKinematics(){
Inputy= inputy+offset y;//
Inputx=inputx;
theta2F = acos((sq(Inputx) + sq(Inputy) - sq(L1) - sq(L2)) / (2 * L1 * L2));// en radianes,,si inputx,y es 1
theta1F =atan(Inputx / Inputy) - atan((L2 * sin(theta2F)) / (L1 + L2 * cos(theta2F)));
theta2 = (-1)* ((theta2F * 180 / PI)-180); //paso de radianes a grados y hace que el sentido eje x sea correcto
theta1 = (theta1F * 180 / PI);//SI SE + SE RESTA AL FINAL
if (Inputx >= 0 && Inputy >= 0) { // 1st quadrant
theta1 = 90- theta1;
}
if (Inputx < 0 && Inputy > 0) { // 2nd quadrant
theta1 = 90- theta1;
}
if (Inputx < 0 && Inputy< 0) { // 3nd quadrant
theta1 = 270- theta1;
theta2 = (-1) * theta2;
}
if (Inputx > 0 &&Inputy < 0) { //4nd quadrant
theta1 = -90- theta1;
theta2 = (-1) *theta2;
}
if (Inputx > 0 &&Inputy == 0) {
theta1 = 270+ theta1;
}
}



