Draw Wire Encoder Sensitivity and Mega2560 Freezing

Hey guys. I have a project going on where I'm trying to operate a sawmill with a phone app which I've created in MIT App Inventor. The mill has various motions that are controlled with electric motors or Hydraulic cylinders that are controlled by a SainSmart 16 relay module and a Mega2560 board via an HC05 BT module. My code is looking for a value of "A,a,B,b...etc." sent from my Android phone to control the various operations on the machine. This part seems to be working ok, except an occasional freezing of the Mega. I also have an Adafruit light ring to tell me the status of the machine. Blue for connected, amber for not connected and red for emergency stop mode.

My only guess for why the Mega is freezing is excessive current draw from a solenoid that controls a hydraulic lift. Although, if it were drawing more than the rated 10amps of the relay module, I would assume I would have a burned board. I believe the starter relay is only pulling around 3 amps. Does anyone have any experience with the Mega freezing? And, what am I doing wrong to cause it? It seems like the Arduino freezes right around the time I'm using the hydraulic pump.

Next issue, I'm using a Calt pull cable encoder to measure the thickness of wood i'm cutting. It's mounted to a carriage where the engine and saw blade sit and is raised and lowered with the hydraulic pump.

It's specs are:

Measuring Range :0~1000mm
Detection method : Incremental encoder
Revolution:0.1mm/pulse Rope :wire rope 0.6mm dia, Plastic coated wire rope ,rope maximum load: 16KG
Supply Voltage :5-26V Dc
Signals output : Pushpull with A B Z 3 channels

I'm getting the readings fine on my lcd display and on the phone but with the engine running the encoder is bouncing around so much that I can hardly tell at what position I'm located. Is there a simple way to change the sensitivity or how often it's displaying said reading so I can actually read the numbers? Or, is that a bad implementation of the encoder altogether?

Please keep in mind I'm very green to the Arduino world but I've tried to fumble my way thru to get an operational prototype machine. I know my code isn't up to many people's expectations but hopefully some sense can be made of it. Any help would be greatly appreciated. I'm including my entire code so hopefully someone will see an obvious error.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <AccelStepper.h>

LiquidCrystal_I2C lcd(0x27,20,4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

char Incoming_value = 'A,a,B,b,C,c,D,d,E,e,F,f,G,g,H,h,J,j,K,k,L,l,M,m,N,n,P,p,Q,q,R,r,Z'; // Values to be received from smartphone app via HC-05 BT module.
//Motor functions will be operated with directional buttons within MIT App Inventor App and send values to Arduino Uno board.
//Sainsmart 16 module relay board has 12v power connected as well as jumpers from Mega2560 to Relay module.

volatile signed int temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder


int Distance = (counter * 0.0019685039370079);

String inputs;
#define relay1 45 //Connect relay1 to pin 30
#define relay2 44 //Connect relay2 to pin 31
#define relay3 43 //Connect relay3 to pin 32
#define relay4 42 //Connect relay4 to pin 33
#define relay5 41 //Connect relay5 to pin 34
#define relay6 40 //Connect relay6 to pin 35
#define relay7 39 //Connect relay7 to pin 36
#define relay8 38 //Connect relay8 to pin 37
#define relay9 37 //Connect relay9 to pin 38
#define relay10 36 //Connect relay10 to pin 39
#define relay11 35 //Connect relay11 to pin 40
#define relay12 34 //Connect relay12 to pin 41
#define relay13 33 //Connect relay13 to pin 42
#define relay14 32 //Connect relay13 to pin 43
#define relay15 31 //Connect relay13 to pin 44
#define relay16 30 //Connect relay13 to pin 45


bool BTState = false;

bool Emer_Stop = false;

//LED LIGHTS__________________________________________________________________________________________________

#include <Adafruit_NeoPixel.h>

// Pattern types supported:
enum  pattern { NONE, RAINBOW_CYCLE, THEATER_CHASE, COLOR_WIPE, SCANNER, FADE };
// Pattern directions supported:
enum  direction { FORWARD, REVERSE };

// NeoPattern Class - derived from the Adafruit_NeoPixel class
class NeoPatterns : public Adafruit_NeoPixel
{
    public:

    // Member Variables:  
    pattern  ActivePattern;  // which pattern is running
    direction Direction;     // direction to run the pattern
    
    unsigned long Interval;   // milliseconds between updates
    unsigned long lastUpdate; // last update of position
    
    uint32_t Color1, Color2, Color3, Color4;  // What colors are in use
    uint16_t TotalSteps;  // total number of steps in the pattern
    uint16_t Index;  // current step within the pattern
    
    void (*OnComplete)();  // Callback on completion of pattern
    
    // Constructor - calls base-class constructor to initialize strip
    NeoPatterns(uint16_t pixels, uint8_t pin, uint8_t type, void (*callback)())
    :Adafruit_NeoPixel(pixels, pin, type)
    {
        OnComplete = callback;
    }
    
    // Update the pattern
    void Update()
    {
        if((millis() - lastUpdate) > Interval) // time to update
        {
            lastUpdate = millis();
            switch(ActivePattern)
            {
                case RAINBOW_CYCLE:
                    RainbowCycleUpdate();
                    break;
                case THEATER_CHASE:
                    TheaterChaseUpdate();
                    break;
                case COLOR_WIPE:
                    ColorWipeUpdate();
                    break;
                case SCANNER:
                    ScannerUpdate();
                    break;
                case FADE:
                    FadeUpdate();
                    break;
                default:
                    break;
            }
        }
    }
  
    // Increment the Index and reset at the end
    void Increment()
    {
        if (Direction == FORWARD)
        {
           Index++;
           if (Index >= TotalSteps)
            {
                Index = 0;
                if (OnComplete != NULL)
                {
                    OnComplete(); // call the comlpetion callback
                }
            }
        }
        else // Direction == REVERSE
        {
            --Index;
            if (Index <= 0)
            {
                Index = TotalSteps-1;
                if (OnComplete != NULL)
                {
                    OnComplete(); // call the comlpetion callback
                }
            }
        }
    }
    
    // Reverse pattern direction
    void Reverse()
    {
        if (Direction == FORWARD)
        {
            Direction = REVERSE;
            Index = TotalSteps-1;
        }
        else
        {
            Direction = FORWARD;
            Index = 0;
        }
    }
    
    // Initialize for a RainbowCycle
    void RainbowCycle(uint8_t interval, direction dir = FORWARD)
    {
        ActivePattern = RAINBOW_CYCLE;
        Interval = interval;
        TotalSteps = 255;
        Index = 0;
        Direction = dir;
    }
    
    // Update the Rainbow Cycle Pattern
    void RainbowCycleUpdate()
    {
        for(int i=0; i< numPixels(); i++)
        {
            setPixelColor(i, Wheel(((i * 256 / numPixels()) + Index) & 255));
        }
        show();
        Increment();
    }

    // Initialize for a Theater Chase                                                                           Theater Chase
    void TheaterChase(uint32_t color2, uint32_t color3, uint8_t interval, direction dir = FORWARD)
    {
        ActivePattern = THEATER_CHASE;
        Interval = interval;
        TotalSteps = numPixels();
        Color2 = color2;
        Color3 = color3;
        Index = 0;
        Direction = dir;
   }
    
    // Update the Theater Chase Pattern
    void TheaterChaseUpdate()
    {
        for(int i=0; i< numPixels(); i++)
        {
            if ((i + Index) % 2 == 0)
            {
                setPixelColor(i, Color2);
            }
            else
            {
                setPixelColor(i, Color3);
            }
        }
        show();
        Increment();
    }

    // Initialize for a ColorWipe
    void ColorWipe(uint32_t color, uint8_t interval, direction dir = FORWARD)
    {
        ActivePattern = COLOR_WIPE;
        Interval = interval;
        TotalSteps = numPixels();
        Color1 = color;
        Index = 0;
        Direction = dir;
    }
    
    // Update the Color Wipe Pattern
    void ColorWipeUpdate()
    {
        setPixelColor(Index, Color1);
        show();
        Increment();
    }
    
    // Initialize for a SCANNNER
    void Scanner(uint32_t color2, uint8_t interval)
    {
        ActivePattern = SCANNER;
        Interval = interval;
        TotalSteps = (numPixels() - 1) * 2;
        Color2 = color2;
        Index = 0;
    }

    // Update the Scanner Pattern
    void ScannerUpdate()
    { 
        for (int i = 0; i < numPixels(); i++)
        {
            if (i == Index)  // Scan Pixel to the right
            {
                 setPixelColor(i, Color2);
            }
            else if (i == TotalSteps - Index) // Scan Pixel to the left
            {
                 setPixelColor(i, Color2);
            }
            else // Fading tail
            {
                 setPixelColor(i, DimColor(getPixelColor(i)));
            }
        }
        show();
        Increment();
    }
    
    // Initialize for a Fade
    void Fade(uint32_t color1, uint32_t color2, uint16_t steps, uint8_t interval, direction dir = FORWARD)
    {
        ActivePattern = FADE;
        Interval = interval;
        TotalSteps = steps;
        Color1 = color1;
        Color2 = color2;
        Index = 0;
        Direction = dir;
    }
    
    // Update the Fade Pattern
    void FadeUpdate()
    {
        // Calculate linear interpolation between Color1 and Color2
        // Optimise order of operations to minimize truncation error
        uint8_t red = ((Red(Color1) * (TotalSteps - Index)) + (Red(Color2) * Index)) / TotalSteps;
        uint8_t green = ((Green(Color1) * (TotalSteps - Index)) + (Green(Color2) * Index)) / TotalSteps;
        uint8_t blue = ((Blue(Color1) * (TotalSteps - Index)) + (Blue(Color2) * Index)) / TotalSteps;
        
        ColorSet(Color(red, green, blue));
        show();
        Increment();
    }
   
    // Calculate 50% dimmed version of a color (used by ScannerUpdate)
    uint32_t DimColor(uint32_t color)
    {
        // Shift R, G and B components one bit to the right
        uint32_t dimColor = Color(Red(color) >> 1, Green(color) >> 1, Blue(color) >> 1);
        return dimColor;
    }

    // Set all pixels to a color (synchronously)
    void ColorSet(uint32_t color)
    {
        for (int i = 0; i < numPixels(); i++)
        {
            setPixelColor(i, color);
        }
        show();
    }

    // Returns the Red component of a 32-bit color
    uint8_t Red(uint32_t color)
    {
        return (color >> 16) & 0xFF;
    }

    // Returns the Green component of a 32-bit color
    uint8_t Green(uint32_t color)
    {
        return (color >> 8) & 0xFF;
    }

    // Returns the Blue component of a 32-bit color
    uint8_t Blue(uint32_t color)
    {
        return color & 0xFF;
    }
    
    // Input a value 0 to 255 to get a color value.
    // The colours are a transition r - g - b - back to r.
    uint32_t Wheel(byte WheelPos)
    {
        WheelPos = 255 - WheelPos;
        if(WheelPos < 85)
        {
            return Color(255 - WheelPos * 3, 0, WheelPos * 3);
        }
        else if(WheelPos < 170)
        {
            WheelPos -= 85;
            return Color(0, WheelPos * 3, 255 - WheelPos * 3);
        }
        else
        {
            WheelPos -= 170;
            return Color(WheelPos * 3, 255 - WheelPos * 3, 0);
        }
    }
};

void Ring1Complete();
//void Ring2Complete();
//void StickComplete();

// Define some NeoPatterns for the two rings and the stick
//  as well as some completion routines
NeoPatterns Ring1(48, 7, NEO_GRB + NEO_KHZ800, &Ring1Complete);
//NeoPatterns Ring2(16, 6, NEO_GRB + NEO_KHZ800, &Ring2Complete);
//NeoPatterns Stick(16, 7, NEO_GRB + NEO_KHZ800, &StickComplete);

//LED LIGHTS__________________________________________________________________________________________________

// Define a stepper and the pins it will use
AccelStepper stepper(1,9,8); //ENABLE PIN 13, PULSE PIN 9, DIRECTION PIN 8
    

void setup(){
 //LED LIGHTS__________________________________________________________________________________________________

  Ring1.begin();
 
 Ring1.TheaterChase(Ring1.Color(0,10,100), Ring1.Color(0,0,50), 100);

  
 //LED LIGHTS__________________________________________________________________________________________________
 
  
  {
  lcd.init();                   // initialize the lcd 
  lcd.init();
  // Print a message to the LCD.
  lcd.backlight();
  delay(1000);
  lcd.setCursor(0,0);
  lcd.print("----Wood Militia----");
  lcd.setCursor(0,1);
  lcd.print("Let's Cut Some Wood!");
   lcd.setCursor(0,2);
  lcd.print("*Wood Militia 2021*");
   lcd.setCursor(0,3);
  lcd.print("Prgm. By Trent Wadle");
  delay(4000);
  lcd.clear();
  delay(250);
  lcd.setCursor(0,0);
  lcd.print("Wood Miliita I-Mill");
  lcd.setCursor(0,1);
  lcd.print("---Blade Position---");
  lcd.setCursor(9,2);
  lcd.print(": Inches");
 
}



Serial.begin (9600);

  pinMode(6, INPUT);

  pinMode(2, INPUT_PULLUP); // internal pullup input pin 2 
  
  pinMode(3, INPUT_PULLUP); // internal pullup input pin 3

//Setting up interrupt
  //A rising pulse from encoder activated ai0(). AttachInterrupt 0 is DigitalPin 2 on Arduino.
  attachInterrupt(0, ai0, RISING);
   
  //B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin 3 on Arduino.
  attachInterrupt(1, ai1, RISING);
 
  pinMode(relay1, OUTPUT);   //Set pins as outputs
  pinMode(relay2, OUTPUT);
  pinMode(relay3, OUTPUT);
  pinMode(relay4, OUTPUT);
  pinMode(relay5, OUTPUT);
  pinMode(relay6, OUTPUT);
  pinMode(relay7, OUTPUT);
  pinMode(relay8, OUTPUT);
  pinMode(relay9, OUTPUT);
  pinMode(relay10, OUTPUT);
  pinMode(relay11, OUTPUT);
  pinMode(relay12, OUTPUT);
  pinMode(relay13, OUTPUT);
  pinMode(relay14, OUTPUT);
  pinMode(relay15, OUTPUT);
  pinMode(relay16, OUTPUT);
  


  digitalWrite(relay1, HIGH); //Switch relay1 off
  digitalWrite(relay2, HIGH); //Swtich relay2 off
  digitalWrite(relay3, HIGH); //Switch relay3 off
  digitalWrite(relay4, HIGH); //Swtich relay4 off
  digitalWrite(relay5, HIGH); //Switch relay5 off
  digitalWrite(relay6, HIGH); //Swtich relay6 off
  digitalWrite(relay7, HIGH); //Switch relay7 off
  digitalWrite(relay8, HIGH); //Swtich relay8 off
  digitalWrite(relay9, HIGH); //Swtich relay9 off
  digitalWrite(relay10, HIGH); //Swtich relay10 off
  digitalWrite(relay11, HIGH); //Swtich relay11 off
  digitalWrite(relay12, HIGH); //Swtich relay12 off
  digitalWrite(relay13, HIGH); //Swtich relay13 off
  digitalWrite(relay14, HIGH); //Swtich relay14 off
  digitalWrite(relay15, HIGH); //Swtich relay15 off
  digitalWrite(relay16, HIGH); //Swtich relay16 off

//Stepper Configuration_______________________________________
    stepper.setMaxSpeed(1000.0);
    stepper.setAcceleration(900.0);
    stepper.runToNewPosition(500);
    
}


void loop()
{
 //LED LIGHTS__________________________________________________________________________________________________
     
        Ring1.Update();
     
 //LED LIGHTS__________________________________________________________________________________________________
     
    byte Distance = (counter * 0.0019685039370079);
    
    if (digitalRead(6) == HIGH)
    {
      BTState=true;
      Ring1.Color2 = (0,0,255);
      //Ring1.Color2 = (0,255,255);
        //Ring1.ColorSet(Ring1.Color(0,0,255));
        //Ring1.Interval = 300;
        //Ring1.TheaterChase(Ring1.Color(0,10,100), Ring1.Color(0,0,50), 100);
      //Ring1.ActivePattern = SCANNER;
      //Ring1.Interval = 10;
      //Ring1.Update();
      Ring1.ActivePattern = FADE;
        Ring1.Interval = 2;
    }
    else {
      BTState=false;
      digitalWrite(relay1, HIGH);
      digitalWrite(relay2, HIGH);
      digitalWrite(relay3, HIGH);
      digitalWrite(relay4, HIGH);
      digitalWrite(relay5, HIGH);
      digitalWrite(relay6, HIGH);
      digitalWrite(relay7, HIGH);
      digitalWrite(relay8, HIGH);
      digitalWrite(relay9, HIGH);
      digitalWrite(relay10, HIGH);
      digitalWrite(relay11, HIGH);
      digitalWrite(relay12, HIGH);
      digitalWrite(relay13, HIGH);
      digitalWrite(relay14, HIGH);
      digitalWrite(relay15, HIGH);
      digitalWrite(relay16, HIGH);
      lcd.setCursor(0,3);
      lcd.print("  BT DISCONNECTED  ");
      //Ring1.TheaterChase(Ring1.Color(255,204,0), Ring1.Color(204,51,0),200);
      //Ring1.Color1 = (255,150,0);
      //Ring1.Color2 = (255,250,0);
        //Ring1.ColorSet(Ring1.Color(0,0,255));
        //Ring1.Interval = 100;
        //Ring1.Update();
        //Ring1.show();
       
        Ring1.TheaterChase(Ring1.Color(244,100,0), Ring1.Color(255,245,75), 18);
        //Ring1.Interval = 22;
        Ring1.Update();
      }
  
  
 
    
    
   if ((Serial.available() > 0) && (BTState == true));
      {
        Incoming_value = Serial.read();  //Using If Function to switch relays on/off.
       
   
        if(Incoming_value == 'A')
        {
            digitalWrite(relay1, LOW);
            //Serial.println("Engine Starting");
            lcd.setCursor(2,3);
            lcd.print("Engine Starting");
        }
        else if(Incoming_value == 'a')
        {
            digitalWrite(relay1, HIGH);
            //Serial.println("Engine Start Released");
            lcd.setCursor(2,3);
            lcd.print("                  ");//End of Relay
        }
        else if(Incoming_value == 'B')
        {
            digitalWrite(relay2, LOW);
            //Serial.println("Engine Relay Engaged");  
        }
        else if(Incoming_value == 'b')
        {
            digitalWrite(relay2, HIGH);
            //Serial.println("Engine Relay Disengaged");   //End of Relay
        }
      
        else if(Incoming_value == 'C')
        {
            stepper.setMaxSpeed(720);
            stepper.setAcceleration(672);
            stepper.runToNewPosition(384);
            stepper.stop();
            //Serial.println("Engine High Rpm");
            lcd.setCursor(2,3);
            lcd.print("Engine High RPM");
        }
        else if(Incoming_value == 'c')
        {
            stepper.setMaxSpeed(720);
            stepper.setAcceleration(672);
            stepper.runToNewPosition(0);
            stepper.stop();
            //Serial.println("Engine Low Rpm");   //End of Relay
            lcd.setCursor(2,3);
            lcd.print("                  ");//End of Relay
        }
        else if(Incoming_value == 'D')
        {
            digitalWrite(relay4, LOW);
            //Serial.println("Carriage Going Up");
            lcd.setCursor(2,3);
            lcd.print("Carriage Going Up");
        }
        else if(Incoming_value == 'd')
        {
            digitalWrite(relay4, HIGH);
            //Serial.println("Carriage Stopped");   //End of Relay
            lcd.setCursor(2,3);
            lcd.print("                  ");//End of Relay
        }
        else if(Incoming_value == 'E')
        {
            digitalWrite(relay5, LOW);
            digitalWrite(relay4, LOW);
            //Serial.println("Carriage Going Down");
            lcd.setCursor(0,3);
            lcd.print("Carriage Going Down");
        }
        else if(Incoming_value == 'e')
        {
            digitalWrite(relay4, HIGH);
            digitalWrite(relay5, HIGH);
            //Serial.println("Carriage Stopped");   //End of Relay
            lcd.setCursor(0,3);
            lcd.print("                    ");//End of Relay
        }
        else if(Incoming_value == 'F')
        {
            digitalWrite(relay12, LOW);
            //Serial.println("Blade Adjust Moving In");
            lcd.setCursor(3,3);
            lcd.print("Blade Guide In");
        }
        else if(Incoming_value == 'f')
        {
            digitalWrite(relay12, HIGH);
            //Serial.println("Blade Adjust Stopped");   //End of Relay
            lcd.setCursor(3,3);
            lcd.print("                 ");//End of Relay
        }
        else if(Incoming_value == 'G')
        {
            digitalWrite(relay11, LOW);
            //Serial.println("Blade Adjust Moving Out");
            lcd.setCursor(2,3);
            lcd.print("Blade Guide Out");
        }
        else if(Incoming_value == 'g')
        {
            digitalWrite(relay11, HIGH);
            //Serial.println("Blade Adjust Stopped");   //End of Relay
            lcd.setCursor(2,3);
            lcd.print("                  ");//End of Relay
        }
        else if(Incoming_value == 'H')
        {
            digitalWrite(relay7, LOW);
            //Serial.println("Carriage Traverse FWD");
            lcd.setCursor(2,3);
            lcd.print("Carriage FWD Cut");
        }
        else if(Incoming_value == 'h')
        {
            digitalWrite(relay7, HIGH);
            //Serial.println("Carriage Traverse Stopped");   //End of Relay
            lcd.setCursor(2,3);
            lcd.print("                  ");//End of Relay
        }
        else if(Incoming_value == 'J')
        {
            digitalWrite(relay8, LOW);
            //Serial.println("Carriage Traverse REV");
            lcd.setCursor(2,3);
            lcd.print("Carriage Return");
        }
        else if(Incoming_value == 'j')
        {
            digitalWrite(relay8, HIGH);
            //Serial.println("Carriage Traverse Stopped");   //End of Relay
            lcd.setCursor(2,3);
            lcd.print("                  ");//End of Relay
        }
        else if(Incoming_value == 'K')
        {
            digitalWrite(relay14, LOW);
            //Serial.println("Backstop Raise");
            lcd.setCursor(2,3);
            lcd.print("Backstop Raising");
        }
        else if(Incoming_value == 'k')
        {
            digitalWrite(relay14, HIGH);
            //Serial.println("Backstop Paused");   //End of Relay
            lcd.setCursor(2,3);
            lcd.print("                  ");//End of Relay
        }
        else if(Incoming_value == 'L')
        {
            digitalWrite(relay13, LOW);
            //Serial.println("Backstop Lower");
            lcd.setCursor(1,3);
            lcd.print("Backstop Lowering");
        }
        else if(Incoming_value == 'l')
        {
            digitalWrite(relay13, HIGH);
            //Serial.println("Backstop Pause");   //End of Relay
            lcd.setCursor(1,3);
            lcd.print("                   ");//End of Relay
        }
        else if(Incoming_value == 'M')
        {
            digitalWrite(relay6, LOW);
            //Serial.println("Blade Engaged");
            lcd.setCursor(2,3);
            lcd.print("Blade Engaged");
        }
        else if(Incoming_value == 'm')
        {
            digitalWrite(relay6, HIGH);
            //Serial.println("Blade Disengaged");   //End of Relay
            lcd.setCursor(2,3);
            lcd.print("                  ");//End of Relay
        }
        else if(Incoming_value == 'N')
        {
            digitalWrite(relay10, LOW);
            //Serial.println("Coolant On");
        }
        else if(Incoming_value == 'n')
        {
            digitalWrite(relay10, HIGH);
            //Serial.println("Coolant Off");   //End of Relay
        }
        else if(Incoming_value == 'P')
        {
            digitalWrite(relay3, LOW);
            //Serial.println("Choke ON");
            lcd.setCursor(2,3);
            lcd.print("Choke ON");
        }
        else if(Incoming_value == 'p')
        {
            digitalWrite(relay3, HIGH);
            //Serial.println("Choke OFF");
            lcd.setCursor(2,3);
            lcd.print("Choke OFF");
        }
        else if(Incoming_value == 'Q')
        {
            digitalWrite(relay15, LOW);
            //Serial.println(" ");
        }
        else if(Incoming_value == 'q')
        {
            digitalWrite(relay15, HIGH);   //End of Relay
            //Serial.println(" ");
        }
        else if(Incoming_value == 'S')
        {
            digitalWrite(relay16, LOW);
            //Serial.println(" ");
        }
        else if(Incoming_value == 's')
        {
            digitalWrite(relay16, HIGH);   //End of Relay
            //Serial.println(" ");
        }
        else if(Incoming_value == 'R')
        {
            //Serial.println(" ");
            counter= 0;
            lcd.setCursor(0,3);
            lcd.print("  Encoder Reset  ");
            delay(500);
            lcd.setCursor(0,0);
            lcd.print("Wood Miliita I-Mill");
            lcd.setCursor(0,1);
            lcd.print("---Blade Position---");
            lcd.setCursor(9,2);
            lcd.print(": Inches");
        }
        else if(Incoming_value == 'r')
        {
            //Serial.println(" ");
            lcd.setCursor(0,3);
            lcd.print("                 ");
        }
         else if(Incoming_value == 'Z')
        {
            Ring1.clear();
            Emer_Stop= true;
            //Serial.println(" ");
            lcd.setCursor(0,3);
            lcd.print("   EMERGENCY STOP   ");
            //LED LIGHTS__________________________________________________________________________________________________
          //     Ring1.TheaterChase(Ring1.Color(255,20,0), Ring1.Color(255,0,0),200);
      //Ring1.Color1 = (255,150,0);
      //Ring1.Color2 = (255,250,0);
        //Ring1.ColorSet(Ring1.Color(0,0,255));
        //Ring1.Interval = 100;
        //Ring1.Update();
        //Ring1.show();
            //LED LIGHTS__________________________________________________________________________________________________
          //   delay(2000);           
        }
        else if(Incoming_value != 'Z')
        {
            Emer_Stop= false;
            //Serial.println(" ");
            lcd.setCursor(0,3);
            lcd.print("                    ");
            //strip.clear();
            //Ring1.Update();
       // Ring1.show();
      //Ring1.TheaterChase(Ring1.Color(0,0,255), Ring1.Color(0,150,255), 200);
            
        }

if (Emer_Stop == true)
{
  Ring1.TheaterChase(Ring1.Color(244,0,0), Ring1.Color(255,50,0), 18);
        //Ring1.Interval = 22;
        Ring1.Update();
        
        delay(20000);
}
else (Emer_Stop = false);


  
        float Dim = counter*0.0019685039370079;
        
      
        // Send the value of counter
        if( counter != temp ){
        //Serial.println ("Board Thickness");
        //Serial.print("\n");
        lcd.setCursor(4,2);
        lcd.print(Dim, 2);
        Serial.println (Dim);
        //Serial.print("\n");
        //Serial.println ("Inches");
        //Serial.print("\n");
        
        temp = counter;
      }
    }
} 
 

char letters[] = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrR";


void ai0() {
  // ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
  // Check pin 3 to determine the direction
  if(digitalRead(3)==LOW) {
  counter++;
  }else{
  counter--;
  }
  }
   
  void ai1() {
  // ai0 is activated if DigitalPin nr 3 is going from LOW to HIGH
  // Check with pin 2 to determine the direction
  if(digitalRead(2)==LOW) {
  counter--;
  }else{
  counter++;
  }}

//LED LIGHTS__________________________________________________________________________________________________

  void Ring1Complete()
{
 Ring1.Reverse();
}

//LED LIGHTS__________________________________________________________________________________________________

The Mega can't provide much current, so if you are driving the relay coils from it, you may see a failure when you have several energized at the same time.

The board thickness is measured in tenths of a millimeter (about 2 thousandths of an inch) and is displayed to the nearest hundredth of an inch. The thickness measurement should NOT be 'jumping around'.

You say it only happens when the motor is running. Are the wires from the encoder to the Arduino shielded? Is the shield grounded at one end?

The Sainsmart specs say that each coil requires 15-20 mA current and the Mega can provide 40 mA if I'm reading the correct information. Does this seem right?

The encoder wire is shielded but I didn't realize it needs to be grounded?
Speaking of that, my lcd display sometimes acts funny as well so I thought about adding some shielding to the wires but would it need to be grounded as well? Sry, I'm only a wanna-be electrician...

I think that cable shields are supposed to be grounded at one end.

It depends how many are on - IIRC, the Mega has a cap of 150mA and some of that is consumed by the device itself, to say nothing of the LCD. I'd provide separate power to the relay coils.

Also, those relay boards tend to use the same old Songle relays and again, from memory, I think they pull rather more than 15-20.

The Mega2560 is in fact a processor with terminals connected to it. There is no protection from electrical noise coming in on any and all I/O lines. Much of this is physical as well as electrical.

EVERY wire going from and to the Mega must be filtered for hi frequency spikes and voltage surges. Something like this:

image

Well that makes sense. I have probably 40 wires running into the mega with no noise filter. Can I run all the wires they one big filter or must each wire have a filter? Thank
you

Hi wildbill, johnwasser, JohnRob, twdrummer,
it's not very easy to filter multiple input or output links (processor ports) with the same filter... at worst, an RF choke can receive multiple signal lines, looping through a ferrite ring (I'm not very fluent at explaining this in English, but others will respond). I think, as you suspect, that it is the power control lines that freeze the processor. You could start by filtering these lines, by interconnecting a VK200 type HF filter, and for transient current spikes, use bi-directional P6KE suppression diodes, you can find these at RS or farnell. Maybe it will be enough to filter only one line, or the few power lines, to correct the problem. The ideal is to filter everything, but 40 lines is a lot!
40 wires around the board, I'm not surprised that you have problems, they are all antennas that bring back high frequency spikes, or overheads to the processor, which doesn't like it at all!
But the culprits to suspect are the power control lines.

You could try a large ferrite bead (torrid) like those on some USB cables but it will minimal effect (maybe enough but not robust).

Something like this would work and not be too hard to make.

Or maybe a piece of the below making every other strip ground and a really good connection between the grounds. You wouldn't need the whole length of the board just a few holes worth.

Such a design will get rid of the high frequencies that likely cause your problems. Very "fat" spikes (i.e. long time and with some current behind them) would take more protection but I'd try the filter first.

Maybe like this:

image

Yes JR! and as drawn, gather the 40 wires together, and keep them away from the board; what would be ideal, is that each conductor is accompanied by a ground wire, the best would be a twisted pair. This makes 40 twisted pairs put together, away from the processor, and passing through the filter described above. And a conductive (metal) housing for the processor.

If twisted pairs are convenient then yes but if not the filter should pretty well.

I has approached a forum member some time ago to make such a board for sale. He had a small business making different electronic hobby board offerings. He didn't seem interested.

Thank you all so much! I suspected noise to be the culprit for my freezing issues so I'm going to order some filters and get to work on the power lines first, then re-route wires to keep them away from my Mega. Any suggestions on shielding that I can apply to the lcd wires? I'm currently using 19" long Dupont wires to connect the lcd to the Mega. I needed them this long to reach the mounting location in my electrical cabinet. They had to pass near other power wires(at least when I wired everything, that's how it worked out), I if I could just wrap with a foil of some type that would be great.

Does anyone have a suggestion for helping the encoder readings from bounces around so much from the vibration of the engine nearby? Should I maybe add a millis timer or something so I can at least have a half second or so to read my numbers? Or, have I used the wrong measuring method altogether? Thanks so much for everyone's help...

For the LCD wires, try to move away the power wires which pass in the vicinity? yes, to surround the wires of the LCD sheet with an alu sheet can improve the resistance (sometimes not! it is complicated, the parasites :wink: ); put at the OV (gnd) of only one side.

If the bounces of the encoder are due to a mechanical origin (the vibrations of the motor), they are real, and it will be difficult to separate them from the real edges... it would be necessary first to try to damp them mechanically, and then maybe to try other detection functions of the encoder ? the one you use is good, maybe it doesn't filter enough the possibility of wrong edges configuration? I use this one, but I react on rising and falling edges (you on rising edges): maybe with only rising edges, you already remove part of the bounces? I don't know, you have to try. It is possible that my function is also sensitive to mechanical bounces, and it may give you double the value of the thickness reading, but this can be corrected.

  // in define zone ---------------
  #define SignalA          B00000100                          // encoder signal pin 2 (port D)
  #define SignalB          B00001000                          // encoder signal pin 3 (port D)
  #define SignalAB         B00001100                          // both signals
  volatile int             counter ;                          // encoder position
  volatile byte            LastPortD = SignalA;               // previous A/B state 



  // in setup ---------------------
  attachInterrupt(digitalPinToInterrupt(2), ExtInt, CHANGE);  // encoder pin 2 interrupt vector
  attachInterrupt(digitalPinToInterrupt(3), ExtInt, CHANGE);  // encoder pin 3 interrupt vector 



  // at ai1, ai0 position in the code
void ExtInt() {                                               // OPTICAL ENCODER ext. interrupt pin 2, 3
  byte PortD =      PIND  & SignalAB;                         // 
  if ((PortD ^ LastPortD) & SignalA)   counter++;             // Rotation ->    {encodPos++; Sense = 1;}
  if ((PortD ^ LastPortD) & SignalB)   counter--;             // Rotation <-    {encodPos--; Sense = 0;}
  if ((PortD) &&  (PortD != SignalAB)) PortD ^= SignalAB;     //                            (swap T0-T1)
   LastPortD  =    PortD;                                     //                  mieux vaut faire court
}

LCD: Just keep the LCD wires away from anything that can add noise, even grounds.

Encoder: What type of encoder do you have? I've used an optical encoder (industrial grade) on an automotive fuel pump with no issues.

It's a Calt wire rope pull encoder mounted on a stationary surface. The rope attaches to a hanging carriage where the engine is mounted. The carriage has a little play in the guides to allow it to slide up and down but not excessive play. But the. 02" or so movement constantly causes the reading to fluctuate at 9600 pulse rate? So the numbers are almost impossible to read

I see. How fast are you trying to read the data? Perhaps some averaging would be in order.

Please forgive my ignorance but I can't remember how I set it up, again, I'm very new to this so I fumbled my way thru until I got it to work. I looked back thru my code and can't see where I'm defining how often so I assumed it's 9600 bps? Would that be right? Averaging sounds like it would be great

I'm not a good code guy but 9600 appears the speed in which you communicate with something, not the sample rate.

Others can see the sample rate in a moment. For me I would add a LED blink when the encoder is read, then look at the light.

Good idea to light the LED at the time of the reading. However, it is not the program that initiates a reading of the encoder (and that could light an LED), it is the encoder variations that force (by interruptions) the program to display the last value of the encoder (towards lines 795 of the code). As the encoder variations are permanent (because of the motor vibrations), the program spends its time displaying a value that is constantly changing.
A question for twdrummer: when the motor is not running (does not disturb the encoder by its vibrations), is the position display more stable?
Here is a way to display the encoder position once a second (easily modifiable value). there are 3 or 4 lines to add at the bottom of the code (including one at the very top of the code), be careful to place the { and } properly!

      float Dim = counter*0.0019685039370079;
        
      
      if (millis() - prevmillis > 1000 ) {     // 1000 = 1 seconde
        prevmillis = millis();                 // add  "unsigned long prevmillis; " on the top  of code, i.e. ligne 16
        
        // Send the value of counter
        if( counter != temp ){
          //Serial.println ("Board Thickness");
          //Serial.print("\n");
          lcd.setCursor(4,2);
          lcd.print(Dim, 2);
          Serial.println (Dim);
          //Serial.print("\n");
          //Serial.println ("Inches");
          //Serial.print("\n");
        
          temp = counter;
        }
      }
      
      
    }
} 
 

char letters[] = "aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrR";