/*------------------------------------------------------------------------------------ Program: port_select Description: Allows a serial port to be selected and connected to graphically. Has the following buttons: Up - scrolls up through the serial port list Down - scrolls down through the serial port list Connect - connects to the selected serial port Disconnect - disconnects from the serial port allowing a new serial port to be connected to Refresh - refreshes the list of serial ports. Useful if a new serial device is connected to the PC after this app- lication is started Purpose: Allows the serial port to be selected within an application instead of hard-coding the port number Hardware: Can be used to connect to Arduino or other serial devices Software: Developed using Processing 2.2.1 (processing.org) Uses the Button class from: http://blog.startingelectronics.com/a-simple-button-for-processing-language-code/ Date: 21 July 2015 Author: W.A. Smith, http://startingelectronics.org ------------------------------------------------------------------------------------*/ import processing.serial.*; import interfascia.*; GUIController c; IFTextField tpause, tvalues, cmdstring; // textfields : pause time, X values, command string. IFLabel lpause, lnext, lvalues, lcmd; // labels of textfields Serial serial_port = null; // the serial port // serial port buttons Button btn_serial_up; // move up through the serial port list Button btn_serial_dn; // move down through the serial port list Button btn_serial_connect; // connect to the selected serial port Button btn_serial_disconnect; // disconnect from the serial port Button btn_serial_list_refresh; // refresh the serial port list // other buttons Button btn_serial_STOP; Button btn_serial_Home; Button btn_serial_mup; Button btn_serial_mdn; Button btn_serial_mlft; Button btn_serial_mrgt; Button btn_next; Button btn_sequence; // Blinking alert messages BlinkingText bkm_moving; BlinkingText bkm_ready; BlinkingText bkm_waiting; String serial_list; // list of serial ports int serial_list_index = 0; // currently selected serial port int num_serial_ports = 0; // number of serial ports in the list int refreshPeriod = 10; // GUI refresh period in ms. float posX; // X position float posZ; // Z position String inString; // Input string from serial port int lf = 10; // ASCII linefeed boolean isHoming = false; boolean isHomingZ = false; boolean isHomingX = false; boolean isMoving = false; boolean isSequence = false; boolean isNext = false; boolean isReady = false; boolean isWaiting = false; boolean isUp = false; boolean isLeft = false; boolean isConnected = false; boolean hasGoals = false; String action = ""; String result = ""; int posNum = 0; int pauseDuration = 0; int Xtargets[]; int panelColor = 218; int lastRefresh = 0; int waitStart, waitEnd; void setup() { // set the window size size (640, 480); background(51); c = new GUIController(this); lpause = new IFLabel("Pause duration / seconds", 400, 220); tpause = new IFTextField("pause", 400, 236, 60, ""); lvalues = new IFLabel("X positions list, in mm - Space separated - No . no , no ;", 152, 162); lnext = new IFLabel("Next goal:", 186, 220); tvalues = new IFTextField("xvalues", 152, 178, 474, ""); lcmd = new IFLabel("Send command:", 420, 390); cmdstring = new IFTextField("cmdsrting", 420, 410, 100, "S"); // create the buttons btn_serial_up = new Button("^", 340, 50, 40, 20); btn_serial_dn = new Button("v", 340, 80, 40, 20); btn_serial_connect = new Button("Connect", 500, 60, 100, 25); btn_serial_disconnect = new Button("Disconnect", 500, 90, 100, 25); btn_serial_list_refresh = new Button("Refresh", 500, 30, 100, 25); btn_serial_Home = new Button("Home", 20, 160, 100, 25); btn_serial_STOP = new Button("STOP", 100,400, 50, 25); btn_serial_mup = new Button("^", 40, 390, 40, 20); btn_serial_mdn = new Button("v", 40, 414, 40, 20); btn_serial_mlft = new Button("<", 170, 402, 40, 20); btn_serial_mrgt = new Button(">", 218, 402, 40, 20); btn_next = new Button("GO NEXT", 186, 280, 80, 25); btn_sequence = new Button("ALL SEQUENCE", 400, 280, 100, 25); bkm_moving = new BlinkingText("MOVING", 4, 280, 80, 25, #FF0000); bkm_ready = new BlinkingText("READY", 4, 295, 80, 25, #00FF00); bkm_waiting = new BlinkingText("WAITING", 490, 280, 80, 25, #00FF00); // get the list of serial ports on the computer serial_list = Serial.list()[serial_list_index]; //println(Serial.list()); //println(Serial.list().length); // get the number of serial ports in the list num_serial_ports = Serial.list().length; c.add(tpause); c.add(lpause); c.add(tvalues); c.add(lvalues); c.add(lnext); c.add(cmdstring); c.add(lcmd); tpause.addActionListener(this); tvalues.addActionListener(this); cmdstring.addActionListener(this); } void mousePressed() { // up button clicked if (btn_serial_up.MouseIsOver()) { if (serial_list_index > 0) { // move one position up in the list of serial ports serial_list_index--; serial_list = Serial.list()[serial_list_index]; } } // down button clicked if (btn_serial_dn.MouseIsOver()) { if (serial_list_index < (num_serial_ports - 1)) { // move one position down in the list of serial ports serial_list_index++; serial_list = Serial.list()[serial_list_index]; } } // Connect button clicked if (btn_serial_connect.MouseIsOver()) { if (serial_port == null) { // connect to the selected serial port serial_port = new Serial(this, Serial.list()[serial_list_index], 115200); println("Info: connected"); isConnected = ( serial_port != null ); serial_port.bufferUntil(lf); } } // Disconnect button clicked if (btn_serial_disconnect.MouseIsOver()) { if (isConnected) { // disconnect from the serial port serial_port.stop(); serial_port = null; isConnected = false; } } // Refresh button clicked if (btn_serial_list_refresh.MouseIsOver()) { // get the serial port list and length of the list serial_list = Serial.list()[serial_list_index]; num_serial_ports = Serial.list().length; } // S button clicked if (isConnected) { if (btn_serial_STOP.MouseIsOver()) { serial_port.write("S\n"); println("cmd: S"); isSequence = false; isNext = false; isHoming = false; } } // Home button clicked if (isConnected) { if (btn_serial_Home.MouseIsOver()) { isHoming = true; isHomingZ = true; serial_port.write("IZ\n"); println("cmd: IZ"); } } // > button clicked if (isConnected) { if (btn_serial_mrgt.MouseIsOver()) { serial_port.write("+X\n"); println("cmd: +X"); } } // < button clicked if (isConnected) { if (btn_serial_mlft.MouseIsOver()) { serial_port.write("-X\n"); println("cmd: -X"); } } // ^ button clicked if (isConnected) { if (btn_serial_mup.MouseIsOver()) { serial_port.write("+Z\n"); println("cmd: +Z"); } } // v button clicked if (isConnected) { if (btn_serial_mdn.MouseIsOver()) { serial_port.write("-Z\n"); println("cmd: -Z"); } } // Proceed button clicked if ( isConnected && hasGoals ) { if (btn_sequence.MouseIsOver()) { isSequence = true; posNum = 0; } } // Next button clicked if ( isConnected && hasGoals ) { if (btn_next.MouseIsOver()) { isNext = true; } } } void serialEvent(Serial p) { if (isConnected) { inString = p.readString(); serial_port.clear(); String[] q = split(inString, " "); inString = ""; // println(q.length + " values found"); // debug info, no longer needed. switch(trim(q[0])) { case "R:": action = trim(q[1]); result = trim(q[2]); println(action, result); break; case "K:": isUp = !boolean(int(q[1])); posX = float(q[2]); isLeft = (posX < 125 ); posZ = float(q[3]); DisplayXZ(posX, posZ); isMoving = boolean(int(trim(q[4]))); default: break; } } } void draw() { if( isWaiting ) { if (currentTime() < waitEnd ) { isWaiting = true; } else { isWaiting = false; println("waiting time elapsed"); } } if( hasGoals ) { hasGoals = posNum < Xtargets.length; } if( millis() - lastRefresh > refreshPeriod) { lastRefresh = millis(); DrawPanelTitle("1 - USB setup", 4,4,632,120); // draw the text box containing the selected serial port DrawTextBox("Select Port:", serial_list, 10, 36, 320, 60); // draw the buttons in the first panel btn_serial_up.Draw(panelColor); btn_serial_dn.Draw(panelColor); btn_serial_connect.Draw(panelColor); if ( isConnected ) { btn_serial_disconnect.Draw(#00FF00); } else { btn_serial_disconnect.Draw(panelColor); } btn_serial_list_refresh.Draw(panelColor); DrawPanelTitle("2 - Activate", 4,128,140,200); if( isConnected && !( isUp && isLeft )) { btn_serial_Home.Draw(#00FF00); } else { btn_serial_Home.Draw(panelColor); } DisplayXZ(posX, posZ); DisplayEndStop(isUp); bkm_moving.Set(isMoving); bkm_moving.Draw(); bkm_ready.Set(isReady); bkm_ready.Draw(); DrawPanelTitle("3 - Automated moves", 148,128, 488, 200); if( hasGoals ) { fill(panelColor); rect(186, 220, 40, 20); fill(0); textAlign(LEFT); textSize(12); text(str(Xtargets[posNum]), 186, 240, 40, 20); } if ( hasGoals && isConnected && !isSequence ) { btn_next.Draw(#00FF00); } else { btn_next.Draw(panelColor); } if ( hasGoals && isConnected && !isSequence && (pauseDuration > 10) ) { btn_sequence.Draw(#00FF00); } else { btn_sequence.Draw(panelColor); } bkm_waiting.Set(isWaiting); bkm_waiting.Draw(); DrawPanelTitle("4 - Manual commands - use with caution", 4,334,632,138); btn_serial_STOP.Draw(#FF0000); btn_serial_mup.Draw(panelColor); btn_serial_mdn.Draw(panelColor); btn_serial_mrgt.Draw(panelColor); btn_serial_mlft.Draw(panelColor); } if( isHoming && isHomingZ && isUp) { isHomingZ = false; isHomingX = true; serial_port.write("GX 120\n"); } if( isHoming && isHomingX && (action.equals("MX")) && (result.equals("success"))) { isHomingX = false; isHoming = false; println("Homing completed"); } if( isNext && !isMoving && isUp ) { String cmdToSend = "GX " + str(Xtargets[posNum]) + "\n"; println(cmdToSend); serial_port.write(cmdToSend); } if( isNext && (action.equals("MX")) && (result.equals("success"))) { println("received MX success: going down"); action = ""; result = ""; serial_port.write("Z 40\n"); } if( isNext && (action.equals("MZ")) && (result.equals("success")) ) { println("received MZ success: ready"); action = ""; result = ""; isReady = true; isNext = false; } if( isNext && !isMoving && !isUp ) { serial_port.write("IZ\n"); } if( isSequence && hasGoals && !isMoving && !isWaiting && isUp) { String cmdToSend = "GX " + str(Xtargets[posNum]) + "\n"; println(cmdToSend); serial_port.write(cmdToSend); posNum++; } if( isSequence && (action.equals("MZ")) && (result.equals("success")) && !isUp) { println("received MZ success: ready"); action = ""; result = ""; isReady = true; } if( isSequence && isReady && !isWaiting ) { waitStart = currentTime(); waitEnd = waitStart + pauseDuration; isWaiting = true; isReady = false; println("started waiting"); } if( isSequence && (action.equals("MX")) && (result.equals("success")) && !isHoming) { println("received MX success: going down"); action = ""; result = ""; serial_port.write("Z 40\n"); } if( isSequence && (posNum >= Xtargets.length)) { println("Sequence completed"); isSequence = false; } if( isSequence && (posNum < Xtargets.length) && !isMoving && !isWaiting && !isUp) { serial_port.write("IZ\n"); } } // function for drawing a panel with the title void DrawPanelTitle(String title, int x, int y, int w, int h) { fill(panelColor); rect(x, y, w, h); fill(0); textAlign(CENTER); textSize(14); text(title, x + 10, y+10, w - 20, 28); } // function for drawing a text box with title and contents void DrawTextBox(String title, String str, int x, int y, int w, int h) { fill(240); rect(x, y+16, w, h - 10); fill(64); textAlign(LEFT); textSize(12); text(title, x + 10, y, w - 20, h - 10); textSize(12); text(str, x + 10, y + 20, w - 20, h - 10); } // button class used for all buttons class Button { String label; float x; // top left corner x position float y; // top left corner y position float w; // width of button float h; // height of button // constructor Button(String labelB, float xpos, float ypos, float widthB, float heightB) { label = labelB; x = xpos; y = ypos; w = widthB; h = heightB; } // draw the button in the window void Draw(int ink) { fill(ink); stroke(0); rect(x, y, w, h, 10); textAlign(CENTER, CENTER); fill(0); text(label, x + (w / 2), y + (h / 2)); } // returns true if the mouse cursor is over the button boolean MouseIsOver() { if (mouseX > x && mouseX < (x + w) && mouseY > y && mouseY < (y + h)) { return true; } return false; } } void actionPerformed (GUIEvent e) { if ((e.getSource() == tvalues )&&(e.getMessage() == "Completed")) { Xtargets = int(splitTokens(tvalues.getValue(), " ")); println("Info: Number of positions: ",Xtargets.length); for (int i = 0; i 0) { posNum = 0; hasGoals = true; } println(""); } if ((e.getSource() == tpause )&&(e.getMessage() == "Completed")) { pauseDuration = int(tpause.getValue()); println("Pause duration: ",pauseDuration); } if ((e.getSource() == cmdstring )&&(e.getMessage() == "Completed")) { println("cmd: " + cmdstring.getValue()); serial_port.write(cmdstring.getValue() + "\n"); switch(cmdstring.getValue()) { case "IZ": isHomingZ = true; case "IX": isHomingX = true; break; default: break; } } } void DisplayXZ(float valx, float valz) { DrawTextBox("PosX: ", str(valx), 10, 240, 60, 30); DrawTextBox("DistZ: ", str(valz), 80, 240, 60, 30); } void DisplayEndStop(boolean state) { textAlign(LEFT); textSize(12); text("Upper end stop : ", 18, 210, 90, 20); color c = color(255*int(state),255*(1-int(state)),0); fill(c); rect(108, 210, 10,10); } int currentTime() { int current_s = second(); int current_m = minute(); int current_h = hour(); int current = 3600*current_h + 60*current_m + current_s; return current; } class BlinkingText { String label; float x; // top left corner x position float y; // top left corner y position float w; // width of button float h; // height of button boolean a; // active color c; // color // constructor BlinkingText(String labelB, float xpos, float ypos, float widthB, float heightB, color highlightC) { label = labelB; x = xpos; y = ypos; w = widthB; h = heightB; a = false; c = highlightC; } void Set(boolean state) { a = state; } void Draw() { if(a) { fill(panelColor); if( second() % 2 == 1 ) { fill(c); } else { fill(0); } text(label, x + (w / 2), y + (h / 2)); } else { fill(panelColor); stroke(panelColor); rect(x + (w / 2), y, w, h); } } }