Introduction: Peel Test Machine

This is a machine that was designed to measure peel of strength of construction materials.

Essentially the machine will peel at a 90 degree angle at a specified rate and measure the force.

The linear motion is driven using a ball-screw mounted along rails that is connected to a NEMA 23 motor.

The force in measured using a strain gauge.

Step 1: Arduino Code

Use the accel stepper, HX711 libraries.

#include <AccelStepper.h>

#include "HX711.h"

#define DOUT 4 #define CLK 5

HX711 scale(DOUT, CLK);

float calibration_factor = 33580;

AccelStepper stepper(1,2,3); int sign = 1; // Either 1, 0 or -1 int spd = 0; // The current speed in steps/second int dir = 0; int idx = 0; int limitState = 0; // variable for reading the pushbutton status

const int limitPin = 6; // the number of the limit switch pin const int ledPin = 13; // the number of the LED pin

long x = 0; long y = 0;

const byte numChars = 32; byte dLen = 0;

char receivedChars[numChars]; char messageFromPC[32] = {0}; char messageFromPC1; char recvChar; char tempChars[32]; // temporary array for use by strtok() function

boolean newData; boolean newData2;

void setup() { Serial.begin(74880); stepper.setCurrentPosition(0); strcpy(tempChars, receivedChars);

stepper.setAcceleration(250);

scale.set_scale(); scale.tare(); //Reset the scale to 0

long zero_factor = scale.read_average(); //Get a baseline reading //Serial.print("Zero factor: "); //This can be used to remove the need to tare the scale. Useful in permanent scale projects. //Serial.println(zero_factor); scale.set_scale(calibration_factor); //Serial.print("Calibration factor: "); //This can be used to remove the need to tare the scale. Useful in permanent scale projects. //Serial.println(calibration_factor);

// initialize the LED pin as an output: pinMode(ledPin, OUTPUT); // initialize the pushbutton pin as an input: pinMode(limitPin, INPUT);

}

void loop() {

recvWithStartEndMarkers();

//showNewData(); strcpy(tempChars, receivedChars);

parseData(); // showParsedData();

if (idx == 2) {

returnofjedi();

}

if (idx == 1) {

moved(); }

}

void moved(){ long z = 0; stepper.setCurrentPosition(0); while(z > -50000){ x=stepper.currentPosition(); z=x; stepper.setMaxSpeed(spd); stepper.moveTo(-50001); stepper.run();

if (x < y-400) { //read steps and force at every 400 steps, serial print. This only works in the positive direction. Serial.print(abs(x)); Serial.print(" , "); Serial.println(scale.get_units(), 1); y=x ; limitState = digitalRead(limitPin); if (limitState == HIGH) { x=0; y=0; z=0; break; } }

} x=0; y=0; z=0; stepper.setCurrentPosition(0);

while(x < 800) { x=stepper.currentPosition(); stepper.setMaxSpeed(1000); stepper.moveTo(4000); stepper.run(); }

}

void returnofjedi() {

long z = 0; stepper.setCurrentPosition(0); while(z < 50000){ x=stepper.currentPosition(); z=x; stepper.setMaxSpeed(spd); stepper.moveTo(50001); stepper.run();

if (x > y+400) { //read steps and force at every 1000 steps, serial print. This only works in the positive direction.

y=x ; limitState = digitalRead(limitPin); if (limitState == HIGH) { x=0; y=0; z=0; break; } }

} x=0; y=0; z=0; stepper.setCurrentPosition(0);

while(x > -800) { x=stepper.currentPosition(); stepper.setMaxSpeed(1000); stepper.moveTo(-4000); stepper.run(); }

}

void recvWithStartEndMarkers() { static boolean recvInProgress = false; static byte ndx = 0; char startMarker = '<'; char endMarker = '>'; char rc;

newData = false; while (newData == false) { if (Serial.available() > 0) { rc = Serial.read(); if (recvInProgress == true) { if (rc != endMarker) { receivedChars[ndx] = rc; ndx++; if (ndx >= numChars) { ndx = numChars - 1; } } else { receivedChars[ndx] = '\0'; // terminate the string recvInProgress = false; ndx = 0; newData = true; } } else if (rc == startMarker) { recvInProgress = true; } } } }

void parseData() { // split the data into its parts char * strtokIndx; // this is used by strtok() as an index

strtokIndx = strtok(tempChars,","); // get the first part - the string idx = atoi(strtokIndx); // convert this part to an integer strtokIndx = strtok(NULL, ","); // this continues where the previous call left off dir = atoi(strtokIndx); // convert this part to an integer strtokIndx = strtok(NULL, ","); // this continues where the previous call left off spd = atoi(strtokIndx); // convert this part to an integer

if( dir == 1) { sign = 1; }

if( dir == 0) { sign = -1; }

}

Step 2: Processing Code

This will allow you to control the motor and save an output file when ran in the forward direction.

import controlP5.*; //import ControlP5 library
import processing.serial.*;

Serial port;

Table dataTable; int numReadings = 110; int readingCounter = 0;

ControlP5 cp5; //create ControlP5 object PFont font; String url1, val; int n, speed, direction; // ******** added a varaibe for dir

void setup() { //same as arduino program

//******* set up serial port Make sure the right port is selected (Arduino port). port = new Serial(this, "COM3", 74880); dataTable = new Table();

size(800, 600); //window size, (width, height)

cp5 = new ControlP5(this); font = createFont("calibri light bold", 20); // custom fonts for buttons and title

cp5.addSlider("Speed") .setPosition(50, 100) .setWidth(400) .setRange(10, 1700) // values can range from big to small as well .setValue(1200) ;

ButtonBar b = cp5.addButtonBar("Direction") .setPosition(50, 175) .setSize(400, 100) .addItems(split("a b", " ")) ; println(b.getItem("a")); b.changeItem("a", "text", "Forward"); b.changeItem("b", "text", "Reverse");

cp5.addTextfield("Test File Name").setPosition(140, 350).setSize(200, 40).setAutoClear(false);

cp5.addBang("Submit").setPosition(200, 450).setSize(80, 40).setColorForeground(color(125, 0, 0)); dataTable.addColumn("id"); //This column stores a unique identifier for each record. We will just count up from 0 - so your first reading will be ID 0, your second will be ID 1, etc. //the following adds columns for time. You can also add milliseconds. See the Time/Date functions for Processing: https://www.processing.org/reference/ dataTable.addColumn("Distance"); dataTable.addColumn("Force (LBS)"); }

void draw() { //same as loop in arduino

background(137); // background color of window (r, g, b) or (0 to 255)

//lets give title to our window fill(17, 2, 13); //text color (r, g, b) textFont(font); text("MOTOR CONTROL", 170, 30); // ("text", x coordinate, y coordinat)

//lets give title to our window fill(1, 1, 5); //text color (r, g, b) textFont(font, 20); text("Motor Speed", 200, 80); // ("text", x coordinate, y coordinat)

//lets give title to our window fill(19, 19, 36); //text color (r, g, b) textFont(font, 20); text("Motor Direction", 180, 165); // ("text", x coordinate, y coordinat)

//lets give title to our window fill(19, 19, 36); //text color (r, g, b) textFont(font, 20); text("Test File Name", 180, 340); // ("text", x coordinate, y coordinat) }

//lets add some functions to our buttons //so whe you press any button, it sends perticular char over serial port

public void Speed(int theValue) { speed = theValue; println("Speed", speed); }

void Direction(int theValue) { println("direction value " + theValue); if (theValue == 0) { direction = 1; // forward } else { direction = 2; // reverse }

println("<" + "DIR" + "," + direction + ">"); // port.write("<" + 1 +","+direction+","+speed+ ">");

}

void Submit() { print("the following text was submitted :"); url1 = cp5.get(Textfield.class, "Test File Name").getText(); //print(" Test File Name = " + url1); println("<" + "speed" + "," + speed + ">"); // output packet to serial port port.write("<" + direction + "," + 1 +"," + speed+ url1 + ">"); }

void serialEvent(Serial port){ try { val = port.readStringUntil('\n'); //The newline separator separates each Arduino loop. We will parse the data by each newline separator. if (val!= null) { //We have a reading! Record it. val = trim(val); //gets rid of any whitespace or Unicode nonbreakable space println(val); //Optional, useful for debugging. If you see this, you know data is being sent. Delete if you like. float sensorVals[] = float(split(val, ',')); //parses the packet from Arduino and places the valeus into the sensorVals array. I am assuming floats. Change the data type to match the datatype coming from Arduino.

TableRow newRow = dataTable.addRow(); //add a row for this new reading newRow.setInt("id", dataTable.lastRowIndex());//record a unique identifier (the row’s index)

newRow.setFloat("Distance", sensorVals[0]); newRow.setFloat("Force (LBS)", sensorVals[1]);

readingCounter++; //optional, use if you’d like to write your file every numReadings reading cycles

//saves the table as a csv in the same folder as the sketch every numReadings. if (readingCounter % numReadings ==0)//The % is a modulus, a math operator that signifies remainder after division. The if statement checks if readingCounter is a multiple of numReadings (the remainder of readingCounter/numReadings is 0) { saveTable(dataTable, url1, "csv"); //Woo! save it to your computer. It is ready for all your spreadsheet dreams. } } } catch(RuntimeException e) { e.printStackTrace(); } }