Hello,
I am trying to use my Arduino as an EtherCAT Slave to control a motor. I use the EasyCAT Shield to connect my Arduino with the PLC.
My problem:
I have already tried to send measurements from a gyroscope to the PLC and everything works just fine. Now I am trying to send measurements form my encoders (SPI to Arduino) to the PLC run them through a controller and send the target value back to the Arduino. If I am using the following code, the Arduino will randomly stop working (sometimes after a few seconds, sometimes it takes longer).
// include header
#include <Arduino.h>
#include <math.h>
#include <SimpleFOC.h>
#include <MegunoLink.h>
#include "Filter.h"
// ------------------------------------------------------------
// ---------- EasyCAT declaration -----------------------------
// ------------------------------------------------------------
// include header for EasyCAT configuration
#include <EasyCAT_Pendulum_config.h>
// set to Custom mode
#define CUSTOM
// include EasyCAT header to interface the LAN9252
#include <EasyCAT.h>
// EasyCAT istantiation with SPI chip select pin 7
EasyCAT EASYCAT(7);
// ------------------------------------------------------------
// ---------- Simple FOC declaration --------------------------
// ------------------------------------------------------------
// BLDC motor init
BLDCMotor motor = BLDCMotor(11);
// driver instance
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
// Motor encoder init
MagneticSensorSPI encoder = MagneticSensorSPI(12, 14);
// pendulum encoder init
MagneticSensorSPI pendulum = MagneticSensorSPI(11, 14);
float pendulumoffset = 0;
// ------------------------------------------------------------
// ---------- Filter declaration ------------------------------
// ------------------------------------------------------------
ExponentialFilter<long>PendulumVelocityFilter(10,0);
ExponentialFilter<long>MotorShaftVelocityFilter(10,0);
void setup() {
Serial.begin(9600);
// initialise motor encoder hardware
encoder.init();
// init the pendulum encoder
pendulum.init();
pendulum.update();
pendulumoffset = pendulum.getAngle();
// set control loop type to be used
motor.controller = MotionControlType::torque;
// link the motor to the encoder
motor.linkSensor(&encoder);
// driver
driver.voltage_power_supply = 24;
driver.init();
// link the driver and the motor
motor.linkDriver(&driver);
// limiting motor movements
motor.phase_resistance = 11.1; // [Ohm]
motor.current_limit = 1.5; // [Amps] - if phase resistance defined
motor.voltage_limit = 20; // [Volts]
motor.motion_cnt = 0;
// initialize motor
motor.init();
// align encoder and start FOC
motor.initFOC();
// setup EasyCAT
setup_EasyCAT();
}
// loop downsampling counter
long loop_count = 0;
float targetVoltage;
float anglesend=0;
float pendulumVelsend=0;
float motorVelsend=0;
void loop() {
// ~1ms
// Simple FOC main task
motor.loopFOC();
// EasyCAT main task
EASYCAT.MainTask();
// control loop each ~25ms
if(loop_count++ > 25){
//EASYCAT.MainTask();
// updating the pendulum angle sensor
// NECESSARY for library versions > v2.2
pendulum.update();
encoder.update();
// calculate the pendulum angle
float pendulumAngle = constrainAngle((pendulum.getAngle()-pendulumoffset) + PI);
// filter the measurements
PendulumVelocityFilter.Filter(pendulum.getVelocity());
MotorShaftVelocityFilter.Filter(motor.shaftVelocity());
anglesend=pendulumAngle;
pendulumVelsend=PendulumVelocityFilter.Current();
motorVelsend=MotorShaftVelocityFilter.Current();
// send new measurements to EtherCAT Master
EASYCAT.BufferIn.Cust.PendulumAngle = anglesend;
EASYCAT.BufferIn.Cust.PendulumVelocity = pendulumVelsend;
EASYCAT.BufferIn.Cust.MotorShaftVelocity = motorVelsend;
loop_count=0;
}
if (targetVoltage != EASYCAT.BufferOut.Cust.MotorVoltage){
// get new values from EtherCAT Master
targetVoltage = EASYCAT.BufferOut.Cust.MotorVoltage;
// set the target voltage to the motor
motor.move(targetVoltage);
}
}
// function constraining the angle in between -pi and pi, in degrees -180 and 180
float constrainAngle(float x){
x = fmod(x + PI, _2PI);
if (x < 0)
x += _2PI;
return x - PI;
}
void setup_EasyCAT()
{
// print the banner
Serial.print ("\nEasyCAT - Generic EtherCAT slave\n");
//---- initialize the EasyCAT board -----
// initialization
if (EASYCAT.Init() == true)
{
// succesfully completed
Serial.print ("initialized");
}
else
{
// initialization failed
// the EasyCAT board was not recognized
Serial.print ("initialization failed");
// The most common reason is that the SPI
// chip select choosen on the board doesn't
}
}// setup_EasyCAT()
I have also tried to create a new test project. In this project I send the same measurements to the PLC and send the target value back.
I started with nothing but the sending the values and everything works fine.
In the next step included the SimpleFOC.h and implemented the closed loop test project. As soon as the the SimpleFOC is included the same thing as before happens the Arduino just stops working randomly.
#include <SimpleFOC.h>
#include "EasyCAT_Pendulum_config.h"
#define CUSTOM
#include "EasyCAT.h"
EasyCAT EASYCAT(7);
// BLDC motor & driver instance
BLDCMotor motor = BLDCMotor(11);
BLDCDriver3PWM driver = BLDCDriver3PWM(9, 5, 6, 8);
// encoder instance
MagneticSensorSPI encoder = MagneticSensorSPI(12, 14);
void setup() {
Serial.begin(9600);
// initialize encoder sensor hardware
encoder.init();
// link the motor to the sensor
motor.linkSensor(&encoder);
// driver config
// power supply voltage [V]
driver.voltage_power_supply = 24;
driver.init();
// link driver
motor.linkDriver(&driver);
// set motion control loop to be used
motor.torque_controller = TorqueControlType::voltage;
motor.controller = MotionControlType::torque;
// add current limit
motor.phase_resistance = 11.1; // [Ohm]
motor.current_limit = 1.5; // [Amps] - if phase resistance defined
//motor.motion_cnt = 0;
// initialize motor
motor.init();
motor.initFOC();
setup_EasyCAT();
}
float targetVoltage=0;
int loopcount=0;
float toTwin1=0;
float toTwin2=100;
float toTwin3=200;
void loop() {
// main FOC algorithm function
motor.loopFOC();
EASYCAT.MainTask();
if(loopcount++>25){
// send new measurements to EtherCAT Master
EASYCAT.BufferIn.Cust.PendulumAngle = toTwin1++;
EASYCAT.BufferIn.Cust.PendulumVelocity = toTwin2++;
EASYCAT.BufferIn.Cust.MotorShaftVelocity = toTwin3++;
targetVoltage = EASYCAT.BufferOut.Cust.MotorVoltage;
motor.move(targetVoltage);
loopcount=0;
}
}
void setup_EasyCAT()
{
// print the banner
Serial.print ("\nEasyCAT - Generic EtherCAT slave\n");
//---- initialize the EasyCAT board -----
// initialization
if (EASYCAT.Init() == true)
{
// succesfully completed
Serial.print ("initialized");
}
else
{
// initialization failed
// the EasyCAT board was not recognized
Serial.print ("initialization failed");
// The most common reason is that the SPI
// chip select choosen on the board doesn't
}
}// setup_EasyCAT()
I have tried to change the baudrate but couldn’t find a setting which worked.
Does the simpleFOC interfere with the Serial communication?
Has anybody an idea what I can try to solve this problem?