Arduino Mega controlling large servo, noise/grounding issue

I am trying to use an Arduino Mega to control a DMM DYN4 servo to a 1kw servo to open and close a door on a cnc machine to automate loading and unloading with a robot. Everything is functional but I am having unreliable results from my digital inputs. I have it temporarily setup with push buttons to open and close. Relay output from the machine will eventually be controlling open and close.
I have input pins setup using

pinMode(53, INPUT_PULLUP)

Touching the wires with my hand wires will cause level change for input, I have also seen it randomly change by itself.

I have NOT been able to replicate the issue with the drive powered off.

See link to video.. https://youtube.com/shorts/YC4QfvFmyBA?si=kf8oR6aGaymWz1Ty

Is this a noise issue? If yes, how do I isolate?

Thanks

Welcome to the forum

How is the servo powered ?
I assume that it has a common GND with the Mega

Welcome

Shielded wires might be a solution.
In my track bag I carried a EMF meter and one other frequency meter for higher bands.
In vintage race cars when wire insulation starts to break down it emits noise.

Servo Is powered by 110vac thru a power on relay and a circuit breaker.

Don't assume anything, I don't really know what I'm doing. Should I have a common ground between the drive and Arduino?

Thanks

Welcome to the forum.

Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.
Can you please post your code?

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

I'll do my best, won't be pretty.

/*
  DYN232M_Arduino_SourceCode.ino - DMM Technology Corp. DYN2 and DYN4 AC Servo drive Arduino UART RS232 communication code.
  
  Version 1.0 - Release May 2018
  
  Distributed By: DMM Technology Corp.
                  www.dmm-tech.com
*/


/**/
#define Set_Origin              0x00
#define Go_Absolute_Pos         0x01
#define Go_Relative_Pos         0x03
#define Is_AbsPos32             0x1b
#define General_Read            0x0e 
#define Is_TrqCurrent           0x1E
#define Read_MainGain           0x18
#define Set_MainGain            0x10
#define Set_SpeedGain           0x11
#define Set_IntGain             0x12
#define Set_HighSpeed           0x14
#define Set_HighAccel           0x15
#define Set_Pos_OnRange         0x16
#define Is_MainGain             0x10
#define Is_SpeedGain            0x11
#define Is_IntGain              0x12
#define Is_TrqCons              0x13
#define Is_HighSpeed            0x14
#define Is_HighAccel            0x15
#define Is_Driver_ID            0x16
#define Is_Pos_OnRange          0x17
#define Is_Status               0x19
#define Is_Config               0x1a
// Add additional function code according to user requirement
/*Variables*/
char InputBuffer[256];                          //Input buffer from RS232,
char OutputBuffer[256];                         //Output buffer to RS232,
unsigned char InBfTopPointer, InBfBtmPointer;   //input buffer pointers
unsigned char OutBfTopPointer, OutBfBtmPointer; //output buffer pointers
unsigned char Read_Package_Buffer[8], Read_Num, Read_Package_Length, Global_Func;
unsigned char MotorPosition32Ready_Flag, MotorTorqueCurrentReady_Flag, MainGainRead_Flag;
unsigned char Driver_MainGain, Driver_SpeedGain, Driver_IntGain, Driver_TrqCons, Driver_HighSpeed, Driver_HighAccel,Driver_ReadID,Driver_Status,Driver_Config,Driver_OnRange;
long Motor_Pos32, MotorTorqueCurrent;
/*Prototypes*/
void move_rel32(char ID, long pos);
void ReadMotorTorqueCurrent(char ID);
void ReadMotorPosition32(char ID);
void move_abs32(char MotorID, long Pos32);
void Turn_const_speed(char ID, long spd);
void ReadPackage(void);
void Get_Function(void);
long Cal_SignValue(unsigned char One_Package[8]);
long Cal_Value(unsigned char One_Package[8]);
void Send_Package(char ID , long Displacement);
void Make_CRC_Send(unsigned char Plength, unsigned char B[8]);
/**/


void setup()
{
  Serial.begin(38400);         // Serial0 used to write to Serial Monitor
  Serial3.begin(38400);        // Servo drive connected to Serial3
  pinMode(13, OUTPUT);
  pinMode(53, INPUT_PULLUP);   //configure pin 53 as an input and enable the internal pull-up resistor (down)
  pinMode(52, INPUT_PULLUP);   //configure pin 52 as an input and enable the internal pull-up resistor (up)
  pinMode(51, INPUT_PULLUP);   //configure pin 51 as an input and enable the internal pull-up resistor (door is open sensor)
  pinMode(50, INPUT_PULLUP);   //configure pin 50 as an input and enable the internal pull-up resistor (door is closed sensor)
  Serial.println("PROGRAM STARTING");
  Set_Speed(1,0030);
  Set_Accel(1,0003);
  Set_MainG(1,0040);
  Set_SpeedG(1,0040);
  Set_IntG(1,0005);
}


void loop()
{
  //read the pushbutton value into a variable
  bool dooropen = digitalRead(53);  
  bool doorclose = digitalRead(52);
  bool isopen = digitalRead(51);
  bool isclosed = digitalRead(50);
  //print out the value of the pushbutton

 // Keep in mind the pull-up means the pushbutton's logic is inverted. It goes
  // HIGH when it's open, and LOW when it's pressed. Turn on pin 13 when the
  // button's pressed, and off when it's not:
  //if ((sensorVal == 0) && (isopenVal == 0)) {
   if (dooropen == 0) { 
    move_abs32(1, -400);  
    Serial.println("doorclose");
    delay(1500);
  }
   //else if ((sensorVal == 1) && (isclosedVal == 0)) {
    else if (doorclose == 0) {
    move_abs32(1, -59400);  
    Serial.println("dooropen");
    delay(1500);
  }
  else {}
}


/////////////////////////// SAMPLE COMMAND FUNCTIONS  ////////////////////////////////////

void Set_Speed(char ID, long pos)
{
  char Axis_Num = ID;
  Global_Func = (char)Set_HighSpeed;
  Send_Package(Axis_Num, pos);
}

void Set_Accel(char ID, long pos)
{
  char Axis_Num = ID;
  Global_Func = (char)Set_HighAccel;
  Send_Package(Axis_Num, pos);
}

void Set_MainG(char ID, long pos)
{
  char Axis_Num = ID;
  Global_Func = (char)Set_MainGain;
  Send_Package(Axis_Num, pos);
}

void Set_SpeedG(char ID, long pos)
{
  char Axis_Num = ID;
  Global_Func = (char)Set_SpeedGain;
  Send_Package(Axis_Num, pos);
}

void Set_IntG(char ID, long pos)
{
  char Axis_Num = ID;
  Global_Func = (char)Set_IntGain;
  Send_Package(Axis_Num, pos);
}

void move_rel32(char ID, long pos)
{
  char Axis_Num = ID;
  Global_Func = (char)Go_Relative_Pos;
  Send_Package(Axis_Num, pos);
}
void ReadMotorTorqueCurrent(char ID) 
{
  Global_Func = General_Read;
  Send_Package(ID , Is_TrqCurrent);
  MotorTorqueCurrentReady_Flag = 0xff;
  while(MotorTorqueCurrentReady_Flag != 0x00) 
  {
    ReadPackage();
  }
}
void ReadMotorPosition32(char ID) 
{
  Global_Func = (char)General_Read;
  Send_Package(ID , Is_AbsPos32);
  MotorPosition32Ready_Flag = 0xff;
  while(MotorPosition32Ready_Flag != 0x00)
  {
    ReadPackage();
  }
}
void move_abs32(char MotorID, long Pos32) 
{
  char Axis_Num = MotorID;
  Global_Func = (char)Go_Absolute_Pos;
  Send_Package(Axis_Num, Pos32);
}

void Turn_const_speed(char ID, long spd)
{
      char Axis_Num = ID;
      Global_Func = 0x0a;
      Send_Package(Axis_Num, spd);
}



////////////////////// DYN232M SERIAL PROTOCOL PACKAGE FUNCTIONS  ///////////////////////////////

void ReadPackage(void) 
{
  unsigned char c, cif;
 
  while (Serial3.available() > 0) {
    InputBuffer[InBfTopPointer] = Serial3.read(); //Load InputBuffer with received packets
    InBfTopPointer++;
  }
  while (InBfBtmPointer != InBfTopPointer)
  {
    c = InputBuffer[InBfBtmPointer];
    InBfBtmPointer++;
    cif = c & 0x80;
    if (cif == 0) {
      Read_Num = 0;
      Read_Package_Length = 0;
    }
    if (cif == 0 || Read_Num > 0) {
      Read_Package_Buffer[Read_Num] = c;
      Read_Num++;
      if (Read_Num == 2) {
        cif = c >> 5;
        cif = cif & 0x03;
        Read_Package_Length = 4 + cif;
        c = 0;
      }
      if (Read_Num == Read_Package_Length) {
        Get_Function();
        Read_Num = 0;
        Read_Package_Length = 0;
      }
    }
  }
}

void Get_Function(void) {
  char ID, ReceivedFunction_Code, CRC_Check;
  long Temp32;
  ID = Read_Package_Buffer[0] & 0x7f;
  ReceivedFunction_Code = Read_Package_Buffer[1] & 0x1f;
  CRC_Check = 0;
 
  for (int i = 0; i < Read_Package_Length - 1; i++) {
    CRC_Check += Read_Package_Buffer[i];
  }
 
  CRC_Check ^= Read_Package_Buffer[Read_Package_Length - 1];
  CRC_Check &= 0x7f;
  if (CRC_Check != 0) {
  }
  else {
    switch (ReceivedFunction_Code) 
    {
      case  Is_AbsPos32:
        Motor_Pos32 = Cal_SignValue(Read_Package_Buffer);
        MotorPosition32Ready_Flag = 0x00;
        break;
      case  Is_TrqCurrent:
	      MotorTorqueCurrent = Cal_SignValue(Read_Package_Buffer);
	    break;
      case  Is_Status:
        Driver_Status = (char)Cal_SignValue(Read_Package_Buffer);
        // Driver_Status=drive status byte data
        break;
      case  Is_Config:
        Temp32 = Cal_Value(Read_Package_Buffer);
        //Driver_Config = drive configuration setting
        break;
      case  Is_MainGain:
        Driver_MainGain = (char)Cal_SignValue(Read_Package_Buffer);
        Driver_MainGain = Driver_MainGain & 0x7f;
        break;
      case  Is_SpeedGain:
        Driver_SpeedGain = (char)Cal_SignValue(Read_Package_Buffer);
        Driver_SpeedGain = Driver_SpeedGain & 0x7f;
        break;
      case  Is_IntGain:
        Driver_IntGain = (char)Cal_SignValue(Read_Package_Buffer);
        Driver_IntGain = Driver_IntGain & 0x7f;
        break;
      case  Is_TrqCons:
        Driver_TrqCons = (char)Cal_SignValue(Read_Package_Buffer);
        Driver_TrqCons = Driver_TrqCons & 0x7f;
        break;
      case  Is_HighSpeed:
        Driver_HighSpeed = (char)Cal_SignValue(Read_Package_Buffer);
        Driver_HighSpeed = Driver_HighSpeed & 0x7f;
        break;
      case  Is_HighAccel:
        Driver_HighAccel = (char)Cal_SignValue(Read_Package_Buffer);
        Driver_HighAccel = Driver_HighAccel & 0x7f;
        break;
      case  Is_Driver_ID:
        Driver_ReadID = ID;
        break;
      case  Is_Pos_OnRange:
        Driver_OnRange = (char)Cal_SignValue(Read_Package_Buffer);
        Driver_OnRange = Driver_OnRange & 0x7f;
        break;        
    }
  }
}

long Cal_SignValue(unsigned char One_Package[8]) //Get data with sign - long
{
  char Package_Length,OneChar,i;
  long Lcmd;
  OneChar = One_Package[1];
  OneChar = OneChar>>5;
  OneChar = OneChar&0x03;
  Package_Length = 4 + OneChar;
  OneChar = One_Package[2]; /*First byte 0x7f, bit 6 reprents sign */
  OneChar = OneChar << 1;
  Lcmd = (long)OneChar; /* Sign extended to 32bits */
  Lcmd = Lcmd >> 1;
  for(i=3;i<Package_Length-1;i++)
  {
  OneChar = One_Package[i];
  OneChar &= 0x7f;
  Lcmd = Lcmd<<7;
  Lcmd += OneChar;
  }
  return(Lcmd); /* Lcmd : -2^27 ~ 2^27 - 1 */
}
long Cal_Value(unsigned char One_Package[8])
{
  char Package_Length,OneChar,i;
  long Lcmd;
  OneChar = One_Package[1];
  OneChar = OneChar>>5;
  OneChar = OneChar&0x03;
  Package_Length = 4 + OneChar;

  OneChar = One_Package[2];   /*First byte 0x7f, bit 6 reprents sign      */
  OneChar &= 0x7f;
  Lcmd = (long)OneChar;     /*Sign extended to 32bits           */
  for(i=3;i<Package_Length-1;i++)
  {
    OneChar = One_Package[i];
    OneChar &= 0x7f;
    Lcmd = Lcmd<<7;
    Lcmd += OneChar;
  }
  return(Lcmd);         /*Lcmd : -2^27 ~ 2^27 - 1           */
}
void Send_Package(char ID , long Displacement) {
  unsigned char B[8], Package_Length, Function_Code;
  long TempLong;
  B[1] = B[2] = B[3] = B[4] = B[5] = (unsigned char)0x80;
  B[0] = ID & 0x7f;
  Function_Code = Global_Func & 0x1f;
  TempLong = Displacement & 0x0fffffff; //Max 28bits
  B[5] += (unsigned char)TempLong & 0x0000007f;
  TempLong = TempLong >> 7;
  B[4] += (unsigned char)TempLong & 0x0000007f;
  TempLong = TempLong >> 7;
  B[3] += (unsigned char)TempLong & 0x0000007f;
  TempLong = TempLong >> 7;
  B[2] += (unsigned char)TempLong & 0x0000007f;
  Package_Length = 7;
  TempLong = Displacement;
  TempLong = TempLong >> 20;
  if (( TempLong == 0x00000000) || ( TempLong == 0xffffffff)) { //Three byte data
    B[2] = B[3];
    B[3] = B[4];
    B[4] = B[5];
    Package_Length = 6;
  }
  TempLong = Displacement;
  TempLong = TempLong >> 13;
  if (( TempLong == 0x00000000) || ( TempLong == 0xffffffff)) { //Two byte data
    B[2] = B[3];
    B[3] = B[4];
    Package_Length = 5;
  }
  TempLong = Displacement;
  TempLong = TempLong >> 6;
  if (( TempLong == 0x00000000) || ( TempLong == 0xffffffff)) { //One byte data
    B[2] = B[3];
    Package_Length = 4;
  }
  B[1] += (Package_Length - 4) * 32 + Function_Code;
  Make_CRC_Send(Package_Length, B);
}

void Make_CRC_Send(unsigned char Plength, unsigned char B[8]) {
  unsigned char Error_Check = 0;
  char RS232_HardwareShiftRegister;
 
  for (int i = 0; i < Plength - 1; i++) {
    OutputBuffer[OutBfTopPointer] = B[i];
    OutBfTopPointer++;
    Error_Check += B[i];
  }
  Error_Check = Error_Check | 0x80;
  OutputBuffer[OutBfTopPointer] = Error_Check;
  OutBfTopPointer++;
  while (OutBfBtmPointer != OutBfTopPointer) {
    RS232_HardwareShiftRegister = OutputBuffer[OutBfBtmPointer];
    //Serial.print("RS232_HardwareShiftRegister: ");
    //Serial.println(RS232_HardwareShiftRegister, DEC);
    Serial3.write(RS232_HardwareShiftRegister);
    OutBfBtmPointer++; // Change to next byte in OutputBuffer to send
  }
}

Drawing should show that the servo drive is grounded as well.

When we did harness testing one of the tests was the shake test. If connections were lost or gained there was a bad connection. If it has been in service check for a damaged wire crushed, bends or pulls can give you hardware issues.

HI, @gszwaya
Thankyou for the diagram, it shows what we need to know.

Question, how do you turn the contactor coil on, if the contactor is OFF and there is not supply to the 24V supply?

Do the proxys work with the relays reliably, it looks like you have to be PNP output type proxy.
How long are the leads between your buttons and proxy/relay and the MEGA?

You may need lower value pullup resistors that what the value of the internal MEGA pullups.
Lower value pullups will help with noise immunity.
Also 0.1uF capacitors between each of the four digital inputs and gnd.

Thanks.. Tom... :grinning: :+1: :coffee: :australia:

That was a mistake in the diagram, as was the npn sensor. I changed the drawing.

As far as I can tell the proxies are working fine. I can see the relays switching on and off. I do not have any logic in the sketch related to the proxies yet, I will.

Wire leads to push buttons and relays are about 8-10 inches.

Where can I find examples of capacitors used on digital inputs?

Thanks for all your help.

There is this application called Google;

noise suppression capacitors on switches arduino

Thanks.. Tom... :grinning: :+1: :coffee: :coffee: :coffee: :australia:

I have a similar project, where radio signals interfered binary inputs and outputs, during transmission. I had to use 10k pulldown resistor (mega have only pullup resistors..) for input and output, in order to get them stable. I made my own IO shield for this. The code use "red flags" when a input is set high by +5V and perform a task within a "cooldown" time. In that way, I can use mechanical switches to the inputs, without need of other electric parts, as rc limitors etc.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.