Notifications
Clear all

Wheel encoder B83609 problem -- ESP32 ?


Phil_2020
(@phil_2020)
Eminent Member
Joined: 2 years ago
Posts: 26
Topic starter  

Hi All,

I have the B83609  ir wheel encoder  (20 holes per disk). It is hooked up to an ESP32 ala the Dronebot tutorial. However, I am getting consistently 10x higher click counts  than I should be getting. Furthermore, the click count varies when run on a measured 2 meter distance.

Has anyone run into this problem ? 

My thoughts are: 

1. ESP32 is sampling too fast

2. There is debounce

3. There is ringing. 

4. My jumper wires are too long

I need to get this working so I can start multiply my problems by tacking on an IMU.

Best regards,

Phil

 

 


Quote
Ruplicator
(@ruplicator)
Estimable Member
Joined: 2 years ago
Posts: 130
 

Since no one has responded maybe answers to a few questions will help spur someone more familiar with this setup to answer.

First the B83609 sensor is designed to measure rotational speed.  You indicated that your getting 10x more counts than expected. What are you using to measure the turning disk besides the B83609 for reference? The B83609 will provide 20 high and 20 low pulses for every revolution. 

You also mentioned that the click count varied on a 2 meter distance. Does this mean you are trying to measure distance traveled? Are there belts, wheels or tracks that could slip, so there is not a one to one relationship with the rotating disk?

To be helpful more information is needed? What is the general application? How do you have the B83609 wired to the ESP32? What is the content of your program?


ReplyQuote
Phil_2020
(@phil_2020)
Eminent Member
Joined: 2 years ago
Posts: 26
Topic starter  

@ruplicator

Hi Ruplicator,

The encoders are part of a DIY robot car.

The black 'slotted' disks are attached to the axles that spin the wheels.  That is to say, not to the motor axle. Thus 1 revolution of the axle = 1 revolution of the disk = 20 pulses (THEORETICALLY) because there are 20 holes in black disk.  The connections were ok, as far as I could tell. +5v,GND and OUT. Here is the code for a node mcu ESP-32s:


#include <WiFi.h>
#include <PubSubClient.h>
const char* ssid = "";
const char* password = "";


const char* mqtt_server = "";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

#define interruptPin1 32
#define interruptPin2 33

volatile int Counter1 = 0;
volatile int Counter2 = 0;
int numberOfInterrupts = 0;
float circumference = 7.0 * PI;

portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;

void IRAM_ATTR ISR_count1() {
portENTER_CRITICAL_ISR(&mux);
Counter1++;
portEXIT_CRITICAL_ISR(&mux);

}
void IRAM_ATTR ISR_count2() {
portENTER_CRITICAL_ISR(&mux);
Counter2++;
portEXIT_CRITICAL_ISR(&mux);

}

const int trigPin = 16;
const int echoPin = 17;

int brate = 115200;

// Motor A
int motor1Pin1 = 26;
int motor1Pin2 = 27;
int enable1Pin = 14;

//Motor B
int motor2Pin1 = 18;
int motor2Pin2 = 19;
int enable2Pin = 5;
int stbyPin = 22;


// Setting PWM properties
const int freq = 30000;
const int pwmChannel = 0;
const int resolution = 8;
int dutyCycle = 100;
long duration;
int distance;

//----------------------------------------------------

void setup() {
// sets the pins as outputs:
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(enable1Pin, OUTPUT);
pinMode(motor2Pin1, OUTPUT);
pinMode(motor2Pin2, OUTPUT);
pinMode(enable2Pin, OUTPUT);
pinMode(stbyPin, OUTPUT);
pinMode(trigPin,OUTPUT);
pinMode(echoPin,INPUT);

digitalWrite(stbyPin,HIGH);


pinMode(interruptPin1, INPUT_PULLUP);
pinMode(interruptPin2, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin1),
ISR_count1, RISING);
attachInterrupt(digitalPinToInterrupt(interruptPin2),
ISR_count2, RISING);

// configure LED PWM functionalitites
ledcSetup(pwmChannel, freq, resolution);

// attach the channel to the GPIO to be controlled
ledcAttachPin(enable1Pin, pwmChannel);
ledcAttachPin(enable2Pin, pwmChannel);

Serial.begin(115200);

// testing
Serial.print("Testing DC Motor...");
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);

}

//-------------------------------------------------




void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}

Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}

void callback(char* topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
//Serial.print(". Message: ");
//String messageTemp;

//for (int i = 0; i < length; i++) {
//Serial.print((char)message[i]);
//messageTemp += (char)message[i];
//}
//Serial.println();
}

void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("ESP8266Client")) {
Serial.println("connected");
// Subscribe
client.subscribe("#");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}

void forward() {
Serial.println("forward");
ledcWrite(pwmChannel, dutyCycle);
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
}

void stop() {
// Stop the DC motor
Serial.println("Motor stopped");
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, LOW);
}

void backward() {
// Move DC motor backwards at maximum speed
Serial.println("Moving Backwards");
ledcWrite(pwmChannel, dutyCycle);
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
}
void left() {
Serial.println("Moving Left");
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
}
void right() {
Serial.println("Moving right");
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
}
void backout() {
stop();
delay(1000);
backward();
delay(1000);
left();
delay(1000);
}

void get_distance() {
digitalWrite(trigPin,LOW);
delayMicroseconds(5);
digitalWrite(trigPin,HIGH);
delayMicroseconds(10);
digitalWrite(trigPin,LOW);

duration = pulseIn(echoPin,HIGH);
distance = duration*0.034/2;
}


void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();


get_distance();
Serial.print("DISTANCE : ");
Serial.println(distance);
if (distance < 40) {
backout();
}
ledcWrite(pwmChannel, dutyCycle);
forward();
delay(200);
Serial.print("COUNTERS ");
Serial.print(Counter1);
Serial.print("/");
Serial.println(Counter2);
float rpms1 = 0.0;
float rpms2 = 0.0;
float turns1 = 0.0;
float turns2 = 0.0;

turns1 = Counter1/20.0;
turns2 = Counter2/20.0;
rpms1 = turns1 * 60.0;
rpms2 = turns2 * 60.0;

Serial.print(" RPMS: ");
Serial.print(rpms1);
Serial.print("/");
Serial.println(rpms2);

Serial.print(" TURNS: ");
Serial.print(turns1);
Serial.print("/");
Serial.println(turns2);

Serial.print(" DISTANCE: ");
float dt1 = 0.0;
float dt2 = 0.0;

dt1 = turns1 * circumference;
dt2 = turns2 * circumference;

Serial.print(dt1);
Serial.print("/");
Serial.println(dt2);


if (dt1 > 100.0 || dt2 > 100.0) {
portENTER_CRITICAL(&mux);
Counter1=0;
Counter2=0;
portEXIT_CRITICAL(&mux);

}
char message_out[40];
sprintf(message_out,"%04d/%0f10/%0f10",distance,dt1,dt2);
Serial.println(message_out);

client.publish("topic/state",message_out);

}



 



ReplyQuote
Ruplicator
(@ruplicator)
Estimable Member
Joined: 2 years ago
Posts: 130
 

I have not used any of the parts involved in your project so you are probably helping more than I'm helping you. I found your problem interesting and did some research on the components you indicated you were using. I noticed that in Bill's video he indicated that the raw signal from the B83609 sensor was  and not very clean and required a circuit to clean it up before feeding into the processor board. You may already have this but I thought I would mention it as it could cause the eradicate counts. 

I also noticed that you take both turns1 and turns2 times 60 to get rpms. But I didn't see anything that actually measured the time that the Counter1 and Counter2 were accumulated in.

Posted by: @phil_2020

float rpms1 = 0.0;
float rpms2 = 0.0;
float turns1 = 0.0;
float turns2 = 0.0;

turns1 = Counter1/20.0;
turns2 = Counter2/20.0;
rpms1 = turns1 * 60.0;
rpms2 = turns2 * 60.0;

 

 


ReplyQuote
Ruplicator
(@ruplicator)
Estimable Member
Joined: 2 years ago
Posts: 130
 

Also is there a chance the optical pickups are not aligned with the slotted wheels? Or maybe there is something loose in how the two are mounted.


ReplyQuote
Phil_2020
(@phil_2020)
Eminent Member
Joined: 2 years ago
Posts: 26
Topic starter  

@ruplicator

Hi, 

Thank you for your input. I will have to check later in the year. It could be something was loose. The DIY robot car is stored away in the attic in preparation for Summer. Alternatively, I will try to find some motors with built in encoders.

Best regards,

Phil

 


ReplyQuote