Hello all,
I apologize in advance if this is a topic that has been covered other forums that I have not grasped the concepts of. This is my first project utilizing Arduino, or the C++ coding structure, and was something I was handed to try to make work, so I may be running into compilation issues I don't understand. That being said I will provide as much information as possible to eliminate variables.
This project utilizes a Teknic ClearCore controller that utilizes a variety of sensors and ClearPath motors to intake precut ignitor wires and produce shunts at predetermined distances on the wires in preparation for final production runs of creating ignitors for pyrotechnic articles. This part of the program does work well, and has been successfully tested prior to my efforts to integrate the next part of this project. The working program is illustrated from Line 155 of the code onwards.
The next step is to integrate a HMI into the system in order to allow for the critical variables of the wire to adjusted without having to reprogram the code externally every time a different wire is used. The HMI that is used is a Maple Systems HMI5040B, and I am using the EasyBuilder Pro software for programming. I'll focus on one variable as I can worry about the rest later, but in Line 157 of the code, a float variable is defined regarding the length of the wire in Inches. In the HMI, this value can be typed in and is stored as a float in the memory location LW-4001.
Here is where I am having trouble, I have gotten the HMI and ClearCore to communicate via ethernet protocol (verified via WireShark), however, I don't understand what the next code needs to be to read the float value from the memory location and then assigning it to the variable in the code.
Can I simply use the serial read/parseFloat function with the name of the saved variable in the memory location to read the value? Or, do I need to write in a pointer function above the defining variable to tell the code to go look at the memory location and then assign that pointer as the serial read/parseFloat function to read?
Thank you in advance for your assistance. Code and Memory Locations are shown below for reference.
#include <ethernet-examples.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetManager.h>
#include <IpAddress.h>
#include "ClearCore.h" // Include the ClearCore library
#include "EthernetTcpServer.h"
// The port number on the server over which packets will be sent/received
#define PORT_NUM 8888
// The maximum number of characters to receive from an incoming packet
#define MAX_PACKET_LENGTH 100
// Buffer for holding received packets
unsigned char packetReceived[MAX_PACKET_LENGTH];
// Set usingDhcp to false to use user defined network settings
bool usingDhcp = false;
int main(void) {
// Set up serial communication between ClearCore and PC serial terminal
ConnectorUsb.Mode(Connector::USB_CDC);
ConnectorUsb.Speed(9600);
ConnectorUsb.PortOpen();
uint32_t timeout = 5000;
uint32_t startTime = Milliseconds();
while (!ConnectorUsb && Milliseconds() - startTime < timeout) {
continue;
}
// Set connector IO0 as a digital output
// When IO0 state is true, a LED will light on the
// ClearCore indicating a successful connection to a client
ConnectorIO0.Mode(Connector::OUTPUT_DIGITAL);
// Make sure the physical link is active before continuing
while (!EthernetMgr.PhyLinkActive()) {
ConnectorUsb.SendLine("The Ethernet cable is unplugged...");
Delay_ms(1000);
}
// To configure with an IP address assigned via DHCP
EthernetMgr.Setup();
if (usingDhcp) {
// Use DHCP to configure the local IP address
bool dhcpSuccess = EthernetMgr.DhcpBegin();
if (dhcpSuccess) {
ConnectorUsb.Send("DHCP successfully assigned an IP address: ");
ConnectorUsb.SendLine(EthernetMgr.LocalIp().StringValue());
}
else {
ConnectorUsb.SendLine("DHCP configuration was unsuccessful!");
while (true) {
// TCP will not work without a configured IP address
continue;
}
}
} else {
// Configure with a manually assigned IP address
// Set ClearCore's IP address
IpAddress ip = IpAddress(192, 168, 1, 100);
EthernetMgr.LocalIp(ip);
ConnectorUsb.Send("Assigned manual IP address: ");
ConnectorUsb.SendLine(EthernetMgr.LocalIp().StringValue());
// Optionally set additional network addresses if needed
//IpAddress gateway = IpAddress(192, 168, 1, 1);
//IpAddress netmask = IpAddress(255, 255, 255, 0);
//EthernetMgr.GatewayIp(gateway);
//EthernetMgr.NetmaskIp(netmask);
}
// Initialize the ClearCore as a server that will listen for
// incoming client connections on specified port (8888 by default)
EthernetTcpServer server = EthernetTcpServer(PORT_NUM);
// Initialize a client object
// This object will hold a connected client's information
// allowing the server to interact with the client
EthernetTcpClient client;
// Start listening for TCP connections
server.Begin();
ConnectorUsb.SendLine("Server now listening for client connections...");
// Connect to clients, and send/receive packets
while(true){
// Obtain a reference to a connected client with incoming data available
// This function will only return a valid reference if the connected device
// has data available to read
client = server.Available();
// Check if the server has returned a connected client with incoming data available
if (client.Connected() || client.BytesAvailable() > 0) {
// Flash on LED if a client has sent a message
ConnectorIO0.State(true);
// Delay to allow user to see the LED
// This example will flash the LED each time a message from a client is received
Delay_ms(100);
// Read packet from the client
ConnectorUsb.Send("Read the following from the client: ");
while (client.BytesAvailable() > 0) {
// Send the data received from the client over a serial port
client.Read(packetReceived, MAX_PACKET_LENGTH);
ConnectorUsb.Send((char *)packetReceived);
// Clear the message buffer for the next iteration of the loop
for(int i=0; i<MAX_PACKET_LENGTH; i++){
packetReceived[i]= NULL;
}
}
ConnectorUsb.SendLine();
// Send response message to client
if (client.Send("Hello client ")>0){
ConnectorUsb.SendLine("Sent 'Hello Client' response");
}
else{
ConnectorUsb.SendLine("Unable to send reply");
}
} else{
// Turn off LED if a message has not been received
ConnectorIO0.State(false);
if(client.ConnectionState()->state == CLOSING){
client.Close();
}
// Make sure the physical link is active before continuing
while (!EthernetMgr.PhyLinkActive()) {
ConnectorUsb.SendLine("The Ethernet cable is unplugged...");
Delay_ms(1000);
}
}
// Broadcast message to all clients
//server.Send("Hello all clients ");
// Perform any necessary periodic ethernet updates
// Must be called regularly when actively using ethernet
EthernetMgr.Refresh();
}
}
// UPDATE THESE
float WireLengthFeet = 0; // Total number of feet/inches for wire leads. Decimal values can be set if desired
float WireLengthInches = Serial.parseFloat(); // Please set empty values to 0
float ShuntLocation = 0.50; // Distance (inches) of stripped section from end of wire leads
float ShuntRotations = 1.0; // Number of Full (360 degree) twists.
// Can use 1/2 values (0.5, 1.5, 2.5, etc), but no other decimals
// IF TROUBLESHOOTING, UPDATE THESE
# define baudRate 9600 // This value sets transmission rate to computer. 9600 is standard. Does NOT require semicolon
// Used for cmputer monitoring (see top right hand corner of Arduino IDE, magnifying glass)
float MachineOffset = 8.6; // Approximate distance (inches) between the blades on the Schleuniger stripper and the PG-602 Sensor (Sensor #1)
// If too low, wheel slippage may occur
// If too high, the system won't pull the wires far enough, causing bunching between machines
float SmallJump = 0.15; // Length of Section to be twisted
float IGOffset = 8; // Approximate distance (inches) between the PG-602 Sensor (Sensor #1) and IG-010 Sensor (Sensor #2)
// If too low, shunt location may not be detected
// If too high, slows entire system down
float ShuntOffset = 2.50; // Approximate distance (inches) between IG-010 Sensor (Sensor #2) stop location & proper alignment within shunt wheel
// If wire twist is too close to the beginning of the wire, increase distance (usually by 0.10 or so solves issue)
// If wire twist is too close to the end of the wire, decrease distance
float IV3Offset = 2.25; // Approximate distance (inches) between the center of the shunt wheel and the IV3-G500MA (Sensor #3)
// Increase/Decrease as see fit for IV3 Detection
// Shunt location should be as close to the center of the plate as reasonable
float ExpelOffset = 5; // Approximate distance (inches) between the IV3-G500MA (Sensor #3) and the end of the machine
// Increase if wire is still trapped in last translational wheel
// Decrease to optimize time between wires
int StripTime = 1000*1.22; // Time required for the Schleuniger to strip the wire
// If too high, wire bunching will occur in the entry tube
// If too low, Neoprene wheels wear down quickly
int BladePullBack = 1000*0.11; // Time for Blades to be removed from wire
int IV3Time = 1000*0.25; // Time required for IV3-G500MA (Sensor #3) to determine if wire is shunted correctly
// If bypassing IV3, set to 0
int velLimitTrans = 1000*3.72; // Motor Speed for translation motors (counts/sec)
// Start low, if the wire is bunching up in the, slowly increase value bunching is mitigated
// If too high, the neoprene wheels will get destroyed from the wire slipping within them
int velIG = 1000*4; // Motor Speed for when the IG is trying to detect where the stripped section is
// Decrease if IG fails to detect stripped section
int SecondaryVelocity = 1000*8; // Motor Speed for after the IG has deteced the stripped section
// Decrease if wire slips in system
int accelLimitTrans = 1000*3000; // Motor acceleration rate
// Increase if the 1st translation motor starts to curl the wire up, preventing it from entering the shunt wheel.
/* Code Below
* If editing, please save as new file to avoid writing over original code
*/
// Initiate ClearCore Library
# include "ClearCore.h"
// Define Pins
# define TransMotor1 ConnectorM0
# define TransMotor2 ConnectorM2
# define ShuntMotor ConnectorM1
# define PG_Detect A12 // Black Wire
# define PG_Error A11 // Orange Wire
# define IG_Low DI8 // White Wire
# define IG_Go DI7 // Gray Wire
# define IG_High DI6 // Black Wire
# define IG_Laser IO5 // Pink Wire
# define IV3_Trigger IO4 // White Wire
# define IV3_Ruling IO3 // Pink Wire
# define IV3_Busy IO2 // Blue Wire
# define IV3_Error IO1 // Green Wire
# define IV3_Running IO0 // Gray Wire
// Initiate Various Variables
// Shunt Motor
int CountsPerRotationShunt = 1440; // Counts Per Rotation
int ShuntCounts = (ShuntRotations + 0.5)*CountsPerRotationShunt; // Counts Per Requested Rotations
// Translation Motors
float InchesPerRotation = 1.5*3.1415; // Inches Per Rotation
int CountsPerRotation = 800; // Counter Per Rotation
int CountsPerInch = CountsPerRotation/InchesPerRotation; // Counts Per Inch
float WireLengthNet = WireLengthFeet*12 + WireLengthInches; // Total Wire Length in Inches
int MachineCounts = MachineOffset*CountsPerInch; // Counts Between Schlueniger Strip Location & IG Sensor Location
int AcceptWire = (WireLengthNet - MachineOffset - ShuntLocation)*CountsPerInch; // Counts to Move Before Stopping for Schlueniger
int SmallJumpCounts = SmallJump*CountsPerInch;
int IGCounts = IGOffset*CountsPerInch; //
int ShuntMoveCounts = ShuntOffset*CountsPerInch; // Counts Between IG Sensor & Proper Shunt Alignment
int IV3Counts = IV3Offset*CountsPerInch; // Counts Between Shunt Location & IV3 Alignment Location
int ExpelCounts = ExpelOffset*CountsPerInch; // Counts Between IV3 & Proper Wire Expulsion
// Timing Constant
int HLFBDelay = 10; // Milliseconds to Allow Motors to Deassert HLFB
// Set Motor Velocity and Acceleration Limits
int velLimitShunt = 1000*100;
int accelLimitShunt = 1000*1000;
// User Defined Helper Functions (See bottom of code for
bool Errrors();
bool MoveAccept();
bool MoveIG();
bool MoveShunt();
bool MoveIV3();
bool MoveExpel();
// Counter Value Initiations
bool z = false;
int i = 0;
int success = 0;
int unsuccess = 0;
void setup() {
// Initialize Motors
// Sets input clocking rate (use normal)
MotorMgr.MotorInputClocking(MotorManager::CLOCK_RATE_NORMAL);
// Sets motor connections to step & direction mode
MotorMgr.MotorModeSet(MotorManager::MOTOR_ALL,
Connector::CPM_MODE_STEP_AND_DIR);
// Sets HLFB mode to bipolar PWM
TransMotor1.HlfbMode(MotorDriver::HLFB_MODE_STATIC);
TransMotor2.HlfbMode(MotorDriver::HLFB_MODE_STATIC);
ShuntMotor.HlfbMode(MotorDriver::HLFB_MODE_STATIC);
// Sets HLFB frequency to 482 Hz
TransMotor1.HlfbCarrier(MotorDriver::HLFB_CARRIER_482_HZ);
TransMotor2.HlfbCarrier(MotorDriver::HLFB_CARRIER_482_HZ);
ShuntMotor.HlfbCarrier(MotorDriver::HLFB_CARRIER_482_HZ);
// Sets velocity & acceleration limits
TransMotor1.VelMax(velLimitTrans);
TransMotor1.AccelMax(accelLimitTrans);
TransMotor2.VelMax(velLimitTrans);
TransMotor2.AccelMax(accelLimitTrans);
ShuntMotor.VelMax(velLimitShunt);
ShuntMotor.AccelMax(accelLimitShunt);
// Enable Motors
TransMotor1.EnableRequest(true);
// Serial.println("Translation Motor 1: Enabled");
while (TransMotor1.HlfbState() != MotorDriver::HLFB_ASSERTED) {
continue;
}
// Serial.println("Translation Motor 1: Ready\n");
TransMotor2.EnableRequest(true);
// Serial.println("Translation Motor 2: Enabled");
while (TransMotor2.HlfbState() != MotorDriver::HLFB_ASSERTED) {
continue;
}
// Serial.println("Translation Motor 2: Ready\n");
ShuntMotor.EnableRequest(true);
// Serial.println("Shunt Motor Enabled");
while (ShuntMotor.HlfbState() != MotorDriver::HLFB_ASSERTED) {
continue;
}
ShuntMotor.Move(-16);
delay(HLFBDelay);
while (ShuntMotor.HlfbState() != MotorDriver::HLFB_ASSERTED) {
continue;
}
// Serial.println("Shunt Motor Ready\n");
// Sensor Adjustments
// Turn Off IG-010 Laser
pinMode(IG_Laser, OUTPUT);
digitalWrite(IG_Laser, HIGH);
// Serial.println("Laser Off\n");
// Wait for IV3 to Turn On
// Serial.println("Checking IV3 is Ready");
while (digitalRead(IV3_Running) != true) {
if (digitalRead(IV3_Error) == true) {
// Serial.println("IV3 Start-up Error");
while (digitalRead(IV3_Error) == true) {
// Serial.println("Please Restart System\n");
continue;
}
break;
}
continue;
}
pinMode(IO4, OUTPUT);
digitalWrite(IV3_Trigger, LOW);
// Serial.println("IV3 Ready\n");
// Print Confirmation
Serial.println("System Ready\n\n\n");
}
void loop() {
/* +-+-+-+-+-+-+-+-+-+-
* Main Code Loop
* 0. Serial Print
* 1. Error Check
* 2. Wire Detection (PG Sensor)
* 3. Accept Wire Action
* 4. Turn On IG Sensor
* 5. IG Shunt Location Detection
* 6. Turn Off IG Sensor
* 7. Shunt Wire
* 8. Move Inline with IV3
* 9. Activate IV3
* 10. Expel Wire
*/
// 0. Serial Print Current Shunt & Confirmation Value
i = i + 1;
Serial.print("Shunt Number: ");
Serial.println(i);
Serial.print("\n");
// Reset Shunt Confirmation
z = false;
// 1. Error Check
// Serial.println("Checking for System Errors");
while (Errors() != true) {
continue;
}
// Serial.println("No Errors Detected\n");
// 2. Wire Detection (PG Sensor);
// Serial.println("Waiting for Wire");
while (digitalRead(PG_Detect) == LOW) {
continue;
}
// Serial.println("Wire Detected\n\n");
delay(10*1000);
// 3. Accept Wire Action
// Serial.println("Accepting Wire");
MoveAccept();
// Serial.println("Wire Accepted\n\n");
// 4. Turn On IG Sensor
digitalWrite(IG_Laser, LOW);
// Serial.println("IG Sensor ON\n\n");
// 5. IG Shunt Location Detection
// Serial.println("Looking for Stripped Section");
MoveIG();
// Serial.println("Shunt Detected\n\n");
// 6. Turn Off IG Sensor
digitalWrite(IG_Laser, HIGH);
// Serial.println("IG Sensor OFF\n\n");
// 7. Shunt Wire
// Serial.println("Shunting Wire");
MoveShunt();
// Serial.println("Wire Shunted\n\n");
// 8. Move Inline with IV3
// Serial.println("Moving to IV3");
MoveIV3();
// Serial.println("IV3 Aligned\n\n");
// 9. Activate IV3
// Serial.println("Triggering IV3");
digitalWrite(IV3_Trigger, HIGH);
delay(20);
digitalWrite(IV3_Trigger, LOW);
delay(IV3Time);
// Serial.println("IV3 Triggered\n\n");
// Wait Until IV3 Ruling Decided
while (digitalRead(IV3_Busy) == LOW) {
continue;
}
// Read Ruling
if (digitalRead(IV3_Ruling) == HIGH) {
z = true;
}
else {
z = false;
}
// 10. Expel Wire
// Serial.println("Expelling Wire");
MoveExpel();
// Serial.println("Wire Expelled\n\n");
// 11. Serial Print
if (z == true) {
success = success + 1;
Serial.println("Shunt: SUCCESSFUL\n");
}
else {
unsuccess = unsuccess + 1;
Serial.println("Shunt: UNSUCCESSFUL\n");
}
Serial.print("Number Successful: ");
Serial.println(success);
Serial.print("Number Unsuccessful: ");
Serial.println(unsuccess);
Serial.print("\n\n\n\n\n\n");
}
