Go Down

Topic: Possible noise on encoders (Read 592 times) previous topic - next topic

Telboy

Feb 22, 2019, 10:26 pm Last Edit: Feb 22, 2019, 10:26 pm by Telboy
Can anyone see where I am going wrong?. I am thinking it may be noise. If I spin the motors by hand I get good signals with no missed counts forward and reverse, when I turn on the motors I get garbled signals as shown at bottom of sketch. I removed both wires from one of the motors and wired the motor direct with a battery and the signals were good again, I will try to upload a fritzing of circuit. I have four different battery feeds trying to prevent noise, with all the grounds connected but looks like I have failed. i am using a nano with L298n driver and the encoders are built into the motors I believe hall sensors, The batterys are 11.1v for motors 7.4v for nano 3.7v for encoders and 7.4v reduced to 5v for pots and other stuff later.

<//------------------------
#include <PinChangeInt.h>
#include <LMotorController.h>
const byte L_EncA = 9;
const byte L_EncB = 11;
const byte R_EncA = 10;
const byte R_EncB = 12;

int Pwm_A   =  3;
int L_motorA = 4;
int L_motorB = 5;
int R_motorA = 7;
int R_motorB = 8;
int Pwm_B    = 6;
LMotorController motorController(Pwm_A, L_motorA, L_motorB, Pwm_B, R_motorA, R_motorA, 0, 0);
#define TOTAL_PINS 21
volatile uint16_t interrupt_count[TOTAL_PINS] = {0};
volatile uint16_t interrupt_count1[TOTAL_PINS] = {0}; // possible arduino pins
volatile int L_Enc_A_Pos = 0;
volatile int R_Enc_A_Pos = 0;
int i;
int j;
#define Encoder_Print;

void setup()
{
 Serial.begin(115200);

 pinMode(L_EncA, INPUT_PULLUP);
 pinMode(L_EncB,  INPUT_PULLUP);    // Encoder
 digitalWrite(L_EncA, HIGH);
 PCintPort::attachInterrupt(L_EncA, quicfunc0,  FALLING);

 pinMode(R_EncA, INPUT_PULLUP);
 pinMode(R_EncB,  INPUT_PULLUP);    // Encoder
 digitalWrite(R_EncA, HIGH);
 PCintPort::attachInterrupt(R_EncA, quicfunc1, FALLING);

 //Potentiometer pins
 pinMode(A0, INPUT);
 pinMode(A1, INPUT);
 pinMode(A2, INPUT);

 pinMode(L_motorA, OUTPUT);
 pinMode(L_motorB, OUTPUT);
 pinMode(R_motorA, OUTPUT);
 pinMode(R_motorB, OUTPUT);
 pinMode(Pwm_A, OUTPUT);
 pinMode(Pwm_B, OUTPUT);
}
void quicfunc0() {

 if (digitalRead(L_EncA) == digitalRead(L_EncB)) {
   L_Enc_A_Pos++;
 } else {
   L_Enc_A_Pos--;
 }
#ifdef Encoder_Print;
 Print();
#endif
}
void quicfunc1() {

 if (digitalRead(R_EncA) == digitalRead(R_EncB)) {

   R_Enc_A_Pos--;
 } else {
   R_Enc_A_Pos++;
 }
#ifdef Encoder_Print;
 Print();
#endif
}
void loop()
{
 int count;
 int count1;
 for (i = 0; i < TOTAL_PINS; i++) {            //Less than TotalPins
   if (interrupt_count != 1) {              // look at all the interrupted pins
     count = interrupt_count;               // store its count since the last iteration
     interrupt_count = 0;                  // and reset it to 0


     for (j = 0; j < TOTAL_PINS; j++) {
       if (interrupt_count1[j] != 0) {
         count1 = interrupt_count1[j];
         interrupt_count1[j] = 0;
       }
     }
   }
 }
 int value = analogRead(A0);

 value = map(value, 0, 1023, -255, 255);
 if (value >= 0)
 {
   digitalWrite(L_motorA, HIGH);
   digitalWrite(L_motorB, LOW);
   analogWrite(Pwm_A, -value);

   digitalWrite(R_motorA, HIGH);
   digitalWrite(R_motorB, LOW);
   analogWrite(Pwm_B, -value);
 } else
 {
   digitalWrite(L_motorA, LOW);
   digitalWrite(L_motorB, HIGH);
   analogWrite(Pwm_A, value);

   digitalWrite(R_motorA, LOW);
   digitalWrite(R_motorB, HIGH);
   analogWrite(Pwm_B, value);
 }
}
void Print() {
 Serial.print("L_Encoder    ");
 Serial.println(L_Enc_A_Pos);
 Serial.print("                        ");
 Serial.print("R_Encoder    ");
 Serial.println(R_Enc_A_Pos);
}
//-------------------------------------------------------
L_Encoder    1
                       R_Encoder    0
L_Encoder    2
                       R_Encoder    0
L_Encoder    3
                       R_Encoder    0
L_Encoder    3
                       R_Encoder    1
L_Encoder    4
                       R_Encoder    1
L_Encoder    5
                       R_Encoder    1
L_Encoder    5
                       R_Encoder    0
L_Encoder    6
                       R_Encoder    0
L_Encoder    6
                       R_Encoder    -1
L_Encoder    6
                       R_Encoder    0
L_Encoder    6
                       R_Encoder    1
L_Encoder    5
                       R_Encoder    1
L_Encoder    5
                       R_Encoder    2
L_Encoder    5
                       R_Encoder    3
L_Encoder    4
//-------------------------------------------------->

jremington

Please edit your post to add code tags, as described in "How to use this forum".

Telboy

Code: [Select]
//------------------------
#include <PinChangeInt.h>
#include <LMotorController.h>
const byte L_EncA = 9;
const byte L_EncB = 11;
const byte R_EncA = 10;
const byte R_EncB = 12;

int Pwm_A   =  3;
int L_motorA = 4;
int L_motorB = 5;
int R_motorA = 7;
int R_motorB = 8;
int Pwm_B    = 6;
LMotorController motorController(Pwm_A, L_motorA, L_motorB, Pwm_B, R_motorA, R_motorA, 0, 0);
#define TOTAL_PINS 21
volatile uint16_t interrupt_count[TOTAL_PINS] = {0};
volatile uint16_t interrupt_count1[TOTAL_PINS] = {0}; // possible arduino pins
volatile int L_Enc_A_Pos = 0;
volatile int R_Enc_A_Pos = 0;
int i;
int j;
#define Encoder_Print;

void setup()
{
 Serial.begin(115200);

 pinMode(L_EncA, INPUT_PULLUP);
 pinMode(L_EncB,  INPUT_PULLUP);    // Encoder
 digitalWrite(L_EncA, HIGH);
 PCintPort::attachInterrupt(L_EncA, quicfunc0,  FALLING);

 pinMode(R_EncA, INPUT_PULLUP);
 pinMode(R_EncB,  INPUT_PULLUP);    // Encoder
 digitalWrite(R_EncA, HIGH);
 PCintPort::attachInterrupt(R_EncA, quicfunc1, FALLING);

 //Potentiometer pins
 pinMode(A0, INPUT);
 pinMode(A1, INPUT);
 pinMode(A2, INPUT);

 pinMode(L_motorA, OUTPUT);
 pinMode(L_motorB, OUTPUT);
 pinMode(R_motorA, OUTPUT);
 pinMode(R_motorB, OUTPUT);
 pinMode(Pwm_A, OUTPUT);
 pinMode(Pwm_B, OUTPUT);
}
void quicfunc0() {

 if (digitalRead(L_EncA) == digitalRead(L_EncB)) {
   L_Enc_A_Pos++;
 } else {
   L_Enc_A_Pos--;
 }
#ifdef Encoder_Print;
 Print();
#endif
}
void quicfunc1() {

 if (digitalRead(R_EncA) == digitalRead(R_EncB)) {

   R_Enc_A_Pos--;
 } else {
   R_Enc_A_Pos++;
 }
#ifdef Encoder_Print;
 Print();
#endif
}
void loop()
{
 int count;
 int count1;
 for (i = 0; i < TOTAL_PINS; i++) {            //Less than TotalPins
   if (interrupt_count != 1) {              // look at all the interrupted pins
     count = interrupt_count;               // store its count since the last iteration
     interrupt_count = 0;                  // and reset it to 0


     for (j = 0; j < TOTAL_PINS; j++) {
       if (interrupt_count1[j] != 0) {
         count1 = interrupt_count1[j];
         interrupt_count1[j] = 0;
       }
     }
   }
 }
 int value = analogRead(A0);

 value = map(value, 0, 1023, -255, 255);
 if (value >= 0)
 {
   digitalWrite(L_motorA, HIGH);
   digitalWrite(L_motorB, LOW);
   analogWrite(Pwm_A, -value);

   digitalWrite(R_motorA, HIGH);
   digitalWrite(R_motorB, LOW);
   analogWrite(Pwm_B, -value);
 } else
 {
   digitalWrite(L_motorA, LOW);
   digitalWrite(L_motorB, HIGH);
   analogWrite(Pwm_A, value);

   digitalWrite(R_motorA, LOW);
   digitalWrite(R_motorB, HIGH);
   analogWrite(Pwm_B, value);
 }
}
void Print() {
 Serial.print("L_Encoder    ");
 Serial.println(L_Enc_A_Pos);
 Serial.print("                        ");
 Serial.print("R_Encoder    ");
 Serial.println(R_Enc_A_Pos);
}
//-------------------------------------------------------
L_Encoder    1
                       R_Encoder    0
L_Encoder    2
                       R_Encoder    0
L_Encoder    3
                       R_Encoder    0
L_Encoder    3
                       R_Encoder    1
L_Encoder    4
                       R_Encoder    1
L_Encoder    5
                       R_Encoder    1
L_Encoder    5
                       R_Encoder    0
L_Encoder    6
                       R_Encoder    0
L_Encoder    6
                       R_Encoder    -1
L_Encoder    6
                       R_Encoder    0
L_Encoder    6
                       R_Encoder    1
L_Encoder    5
                       R_Encoder    1
L_Encoder    5
                       R_Encoder    2
L_Encoder    5
                       R_Encoder    3
L_Encoder    4
//--------------------------------------------------

jremington

#3
Feb 23, 2019, 09:24 pm Last Edit: Feb 23, 2019, 10:28 pm by jremington
There are several major problems with that code.

1) Never attempt to print from within an interrupt routine. Printing depends on interrupts, which are off in an interrupt routine.

2) Multibyte variables shared with interrupts must be protected from corruption.

For example in the line below, R_Enc_A_Pos can be corrupted by an interrupt during the print operation.

Code: [Select]
Serial.println(R_Enc_A_Pos);

You need to do something like this, printing from the main program:
Code: [Select]
cli(); //turn off interrupts
int temp= R_Enc_A_Pos; //make a copy
sei(); //turn interrupts back on
 Serial.println(temp); //print the copy


3) What is all this supposed to do? Did you copy/paste from your corrupted post above?

Code: [Select]
for (i = 0; i < TOTAL_PINS; i++) {            //Less than TotalPins
   if (interrupt_count != 1) {              // look at all the interrupted pins
     count = interrupt_count;               // store its count since the last iteration
     interrupt_count = 0;                  // and reset it to 0


4) The analogWrite() value must be 0-255. What does the following do?
Code: [Select]

 if (value >= 0)
 {
   digitalWrite(L_motorA, HIGH);
   digitalWrite(L_motorB, LOW);
   analogWrite(Pwm_A, -value);

Telboy

Ok thanks for your reply, lots of errors, I mapped the analogwrite just to run the motors from the pot untill i sort out this problem, at zero or center of pot the motors stop the neg value runs motors in reverse and pos run in forward. maybe wrong but that works. As for the total pins i had that bit of code from a previous code with pinchange and thought it was needed to use all pins; can see that was wrong now. As for the interrupts I have changed the code; either I have wrote it wrong or it is still giving problems, the motors should give 616 counts per wheel revolution, the best results are on RISING but not right; worse when powered up.Thanks again.

Code: [Select]
//------------------------------Try to get both motors equal-----------------------------
#include <PinChangeInt.h>
#include <LMotorController.h>
const byte L_EncA = 9;
const byte L_EncB = 11;
const byte R_EncA = 10;
const byte R_EncB = 12;
byte L_EncA_Last;
byte R_EncA_Last;

int Pwm_A   =  3;
int L_motorA = 5;
int L_motorB = 4;
int R_motorA = 8;
int R_motorB = 7;
int Pwm_B    = 6;
LMotorController motorController(Pwm_A, L_motorA, L_motorB, Pwm_B, R_motorA, R_motorA, 0, 0);
volatile int L_Enc_A_Pos = 0;
volatile int R_Enc_A_Pos = 0;


void setup()
{
  Serial.begin(115200);

  pinMode(L_EncA, INPUT_PULLUP);
  pinMode(L_EncB,  INPUT_PULLUP);    // Encoder
  digitalWrite(L_EncA, HIGH);
  PCintPort::attachInterrupt(L_EncA, quicfunc0,  RISING);

  pinMode(R_EncA, INPUT_PULLUP);
  pinMode(R_EncB,  INPUT_PULLUP);    // Encoder
  digitalWrite(R_EncA, HIGH);
  PCintPort::attachInterrupt(R_EncA, quicfunc1,  RISING);

  //Potentiometer pins
  pinMode(A0, INPUT);
  pinMode(A1, INPUT);
  pinMode(A2, INPUT);

  pinMode(L_motorA, OUTPUT);
  pinMode(L_motorB, OUTPUT);
  pinMode(R_motorA, OUTPUT);
  pinMode(R_motorB, OUTPUT);
  pinMode(Pwm_A, OUTPUT);
  pinMode(Pwm_B, OUTPUT);
}
void quicfunc0() {

  if (digitalRead(L_EncA) == digitalRead(L_EncB)) {
    L_Enc_A_Pos++;
  } else {
    L_Enc_A_Pos--;
  }
}
void quicfunc1() {

  if (digitalRead(R_EncA) == digitalRead(R_EncB)) {

    R_Enc_A_Pos--;
  } else {
    R_Enc_A_Pos++;
  }
}
void loop()
{
  cli(); //turn off interrupts
 int Temp = L_Enc_A_Pos; //make a copy
 
  Serial.print(Temp);
 
 int temp = R_Enc_A_Pos; //make a copy

  Serial.print("                ");
  Serial.println(temp);

  sei(); //turn interrupts back on
 
  int value = analogRead(A0);

  value = map(value, 0, 1023, -255, 255);
  if (value >= 0)
  {
    digitalWrite(L_motorA, HIGH);
    digitalWrite(L_motorB, LOW);
    analogWrite(Pwm_A, value);

    digitalWrite(R_motorA, HIGH);
    digitalWrite(R_motorB, LOW);
    analogWrite(Pwm_B, value);
  } else
  {
    digitalWrite(L_motorA, LOW);
    digitalWrite(L_motorB, HIGH);
    analogWrite(Pwm_A, -value);

    digitalWrite(R_motorA, LOW);
    digitalWrite(R_motorB, HIGH);
    analogWrite(Pwm_B, -value);
  }
}

Telboy

Arr, just noticed that error bit better now, I'll give it more checks

Code: [Select]

  cli(); //turn off interrupts
  int Temp = L_Enc_A_Pos; //make a copy
  sei(); //turn interrupts back on
  Serial.print(Temp);
  cli(); //turn off interrupts
  int temp = R_Enc_A_Pos; //make a copy
  sei(); //turn interrupts back on
  Serial.print("                ");
  Serial.println(temp);


jremington

You might have motor noise in the power supply as well. Be sure your motors are bypassed with 10 nF capacitors, as described in this tutorial. Use twisted pair wiring for motor power leads.

Also, it never hurts to add capacitors, say 100 to 1000 uF cap across the power input terminals for the Arduino and 10 uF across the sensor power leads.


Please post a hand drawn (not Fritzing) wiring diagram.


Telboy

#7
Feb 24, 2019, 12:02 pm Last Edit: Feb 24, 2019, 12:11 pm by Telboy
They always get messy when I try to draw circuits, but this is about it. I did tempary try a 47 uf capacitor across the 11.1v input on the l298n before looking at code again. There are already some capacitors and resistors on the pcb of the encoders not sure what they do but could I think solder some more across the motors.

Having a problem uploading the jpg will try again later

Telboy


MarkT

A photo of the wiring is most informative.  In particular where you route the encoder wiring compared
to high current motor and supply wiring is important, as is the nature of the cable and its length.

You've not posted details of the hardware (datasheets / product pages), please do so, otherwise we
have only a vague idea of what you have, and details always matter.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Telboy

The photo just shows a bunch of wires, but as you say all mixed, I did think of maybe shielding the sensor wires  then thought there are a lot of sensor wires in a car and they all go in a big loom together and not many of them are shielded. For the moment jremington seems to have sorted that problem I was printing inside the interrupt and thanks to him for pointing that out. I am just working on snippets one at a time, hopefully will put it all together one day. I have no data sheet on the encoders I just know it has 11 pulses per motor turn and I am using 56/1 gear ratio with 100mm dia wheels with 6.5 Kg.cm torque 12v, that is going to be trial and error for me.

Go Up