Hi everyone,
I'm using Arduino Mega.
Problem - Arduino is placed on a golf cart with an encoder attached to the arduino. When I press the accelerator on the cart, the interrupt pin is picking that noise and calling the Interrupt routine again and again.
Setup - Encoder is attached to the steering wheel to keep track of the angle. The encoder wires run below the cart along with the accelerator wires. Encoder has 5 wires, I'm using 4 of them (VCC, GND, Channel A and Channel B). When the steering rotates, the encoder gives proper interrupts on Channel A and B, allowing me to track the angle it rotated. When I press the accelerator, it takes random interrupts, leading to a wrong angle.
Encoder specification -
MH38-10-128-5-26F-1MTR
METRONIX MAKE HOLLOW SHAFT ENCODER
RESOLUTION:100 PPR
O/P: LINE-DRIVER
MOUNTING:SERVO
OUTER DIA:38MM
BORE DIA: 10MM
SUPPLY VOLT:5-26VDC
CHANNEL:A,B,Z,
CONNECTION:RADIAL CABLE 1 MTR LONG
Circuit -
I'm using single core wires connected to the encoder's multicore wires at one-end and to the breadboard at another end. I'm using 1k ohm Pull down resistor as shown in the image, but it isn't helping.
How can remove the noise completely? (because even a small wrong angle can break the whole code, it needs to be perfect)
Do I need to change the wires? I've tried connecting the wires from above (not under the cart) and it still picks noise.
Full Code -
// Zen Cruise Steering module v1.0
// @author - Himanshu Pahadia (52954)
// Contact - h.pahadia@zensar.com
#define encoderPinA 2
#define encoderPinB 3
#define ppr 100
#define pi_val 3.14159265359
#define THRESHOLD 0.5
// length of the actual message
#define LEN 6
// Motor relay - To break the circuit
// NO - Connected to positive of battery, NC - NILL, COM - NO of other two relays
// Clockwise relays - Change polarity of the current going to motor
// NO - COM of motor relay, NC - negative of battery
// COM1 of clockwise - +ve of motor
// COM2 of anticlockwise - -ve of motor
// messages expected
// Stop - b000000e
// Rotate clockwsie - b000001e
// Clockwise - b-00001e
int motorRelay = 52;
int clockwiseRelay = 50;
int anticlockwiseRelay = 48;
// Input from vision system
// Message from serial communication
// Position message
char msg[LEN];
//char pos_msg[LEN];
// Current steering position
float current_steering_value = 0.0;
// Steering value
float steering_value;
// Steering direction
volatile boolean dir;
volatile int counter = 0;
//volatile int count = 0;
volatile boolean flag;
//int buffer_angle = 0.5;
volatile int var_degrees = 0;
void pulseAtPinA(){
flag = true;
if(digitalRead(encoderPinA) == HIGH){
if(digitalRead(encoderPinB) == LOW){
counter = counter +1; //Counter-clockwise
}
else{
counter = counter -1; //Clockwise
}
}
else{
if(digitalRead(encoderPinB) == LOW){
counter = counter - 1; //CW
}
else{
counter = counter + 1 ; //CCW
}
}
if(flag == true){
var_degrees = ((360/100.0)*counter);
var_degrees = var_degrees/3.0;
current_steering_value = getRadianFromDegree(var_degrees);
Serial.print("Current steering value is ");
Serial.print(current_steering_value);
}
if(dir == 1){
// Clockwise
if(current_steering_value >= steering_value){
stopMotor();
}
}
else if(dir == 0){
// Anti Clockwise
if(current_steering_value <= steering_value){
stopMotor();
}
}
}
float getRadian(int c){
return (float)(c*2.0*pi_val) / 100.0;
}
float getRadianFromDegree(int degree){
return (float)degree*(pi_val/180.0);
}
void setup() {
Serial.begin(9600);
// Initialize to the neutral position of the steering
current_steering_value = 0.0;
steering_value = 0.0;
counter = 0;
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
// Orginal
attachInterrupt(digitalPinToInterrupt(encoderPinA), pulseAtPinA, RISING);
pinMode(motorRelay, OUTPUT);
pinMode(clockwiseRelay, OUTPUT);
pinMode(anticlockwiseRelay, OUTPUT);
digitalWrite(motorRelay, LOW);
// NO direction
digitalWrite(clockwiseRelay, LOW);
digitalWrite(anticlockwiseRelay, LOW);
}
void loop() {
// Serial.println(counter);
if (Serial.read() == 'b') {
Serial.readBytes(msg, LEN);
delay(10);
if (Serial.read() == 'e') {
// if (msg[6] == 'e') {
steering_value = atof(msg);
// Check direction of rotation
// Clock wise
if((steering_value - current_steering_value) > 0){
dir = 1;
if(steering_value > 2.2* pi_val){
steering_value = 2.2*pi_val;
}
}
else{
dir = 0;
if(steering_value < -2.2* pi_val){
steering_value = -2.2*pi_val;
}
}
if(abs(steering_value - current_steering_value) > THRESHOLD){
if(dir == 1){
turnAntiClockwise();
}
else if(dir == 0){
turnClockwise();
}
}
}
}
}
void turnClockwise(){
// NO direction
digitalWrite(clockwiseRelay, LOW);
digitalWrite(anticlockwiseRelay, HIGH);
// Start motor
digitalWrite(motorRelay, HIGH);
}
void turnAntiClockwise(){
// NO direction
digitalWrite(clockwiseRelay, HIGH);
digitalWrite(anticlockwiseRelay, LOW);
// Start motor
digitalWrite(motorRelay, HIGH);
}
void stopMotor(){
// Turn the motor off
digitalWrite(motorRelay, LOW);
// Clockwise direction
digitalWrite(clockwiseRelay, LOW);
digitalWrite(anticlockwiseRelay, LOW);
}
Interrupt routine -
void pulseAtPinA(){
flag = true;
if(digitalRead(encoderPinA) == HIGH){
if(digitalRead(encoderPinB) == LOW){
counter = counter +1; //Counter-clockwise
}
else{
counter = counter -1; //Clockwise
}
}
else{
if(digitalRead(encoderPinB) == LOW){
counter = counter - 1; //CW
}
else{
counter = counter + 1 ; //CCW
}
}
if(flag == true){
var_degrees = ((360/100.0)*counter);
var_degrees = var_degrees/3.0;
current_steering_value = getRadianFromDegree(var_degrees);
Serial.print("Current steering value is ");
Serial.print(current_steering_value);
}
if(dir == 1){
// Clockwise
if(current_steering_value >= steering_value){
stopMotor();
}
}
else if(dir == 0){
// Anti Clockwise
if(current_steering_value <= steering_value){
stopMotor();
}
}
}
Thank you.