enter image description hereI am using a 4wd robotic car to measure straight distances. I have attached two encoders on the front two wheels to measure the distance and I am using the back two wheels to adjust the car and keep it driving straight by using a compass as a reference. The Problem is that when my program is executing the section that drives the back wheels this somehow triggers the interrupt and increments the number of ticks. What is causing this issue?
volatile unsigned long enc_l = 0;
volatile unsigned long enc_r = 0;
void driveStraight(float drive_distance, int motor_power)
{
Serial.print("\n");
Serial.println("num_tick_l \t num_tick_r \t diff_l \t diff_r \t enc_1_prev \t enc_r_prev \t Power_l \t Power_r \t Power_a \t Power_b ");
unsigned long num_ticks_l;
unsigned long num_ticks_r;
// Set initial motor power
int power_l = motor_power;
int power_r = motor_power;
// Used to determine which way to turn to adjust
unsigned long diff_l;
unsigned long diff_r;
// Reset encoder counts
enc_l = 0;
enc_r = 0;
// Remember previous encoder counts
unsigned long enc_l_prev = enc_l;
unsigned long enc_r_prev = enc_r;
// Calculate targer number of ticks
float num_rev = (drive_distance * 10) / wheel_c; // Convert to mm
unsigned long target_count = 29; //num_rev * counts_per_rev;
/*
// Debug
Serial.print("Driving for ");
Serial.print(drive_distance);
Serial.print(" cm(");
Serial.print(target_count);
Serial.print(" ticks) at ");
Serial.print(motor_power);
Serial.println(" Motor Power");
*/
//Drive until on of the encoders reaches desired count
while ((enc_l < target_count) && (enc_r < target_count))
{
bluetooth(); // if new bluetooth value received break from loop
if (blueToothVal == 5) {
break; // If a 'Stop' Bluetooth command is received then break from the Loop
}
// Sample number of encoder ticks
num_ticks_l = enc_l;
num_ticks_r = enc_r;
// Sample out current number of ticks
Serial.print(num_ticks_l);
Serial.print(" \t\t");
Serial.print(num_ticks_r);
// Drive
drive(power_l, power_r);
// Number of ticks counted since last time
const int StraightDriveOffset = 1; // Increase this or even make it a negatie number to tweak the
diff_l = num_ticks_l - enc_l_prev; // + StraightDriveOffset;
diff_r = num_ticks_r - enc_r_prev;
Serial.print(" \t\t");
Serial.print(diff_l);
Serial.print(" \t \t");
Serial.print(diff_r);
// Store current ticks counter for next time
enc_l_prev = num_ticks_l;
enc_r_prev = num_ticks_r;
Serial.print(" \t \t");
Serial.print(enc_l_prev);
Serial.print(" \t \t");
Serial.print(enc_r_prev);
// If left is faster, slow it down and speed up right
if ( diff_l > diff_r) {
power_l -= motor_offset;
power_r += motor_offset;
}
// If right is faster, slow it down and speed up right
if ( diff_l < diff_r) {
power_l += motor_offset;
power_r -= motor_offset;
}
// Debugging
Serial.print(" \t\t");
Serial.print(power_l);
Serial.print(" \t\t");
Serial.println(power_r);
// Brif pause to let motors respond
delay(20);
}
StopCar();
//Buzzer();
}
void drive(int power_a, int power_b)
{
getCompass(); // Update Compass Heading
bluetooth(); // Check to see if any Bluetooth commands have been sent
if (blueToothVal == 5) {
break; // If a Stop Bluetooth command ('5') is received then break from the Loop
}
// Constrain power to between -255 and 255
power_a = constrain(power_a, -255, 255);
power_b = constrain(power_b, -255, 255);
if ( abs(desired_heading - compass_heading) <= compass_dev ) // If the Desired Heading and the Compass Heading are within the compass deviation, X degrees of each other then Go Forward
// otherwise find the shortest turn radius and turn left or right
{
// Left motor direction
if ( power_a < 0)
{
motor2.setSpeed(abs(power_a)); // Motor is the front left wheel
motor2.run(BACKWARD);
}
else
{
motor2.setSpeed(abs(power_a)); // Motor is the front left wheel
motor2.run(FORWARD);
}
// Right Motor direction
if ( power_b < 0)
{
motor4.setSpeed(abs(power_b)); // Motor is the front left wheel
motor4.run(BACKWARD);
}
else
{
motor4.setSpeed(abs(power_b)); // Motor is the front left wheel
motor4.run(FORWARD);
}
}
else
{
int x = (desired_heading - 359); // x = the GPS desired heading - 360
int y = (compass_heading - (x)); // y = the Compass heading - x
int z = (y - 360); // z = y - 360
if ((z <= 180) && (z >= 0)) // if z is less than 180 and not a negative value then turn left
{ // otherwise turn right
motor1.setSpeed(190);
motor3.setSpeed(190);
motor1.run(BACKWARD);
motor3.run(FORWARD);
}
else
{
motor1.setSpeed(190);
motor3.setSpeed(190);
motor1.run(FORWARD);
motor3.run(BACKWARD);
}
}
}
void countLeft()
{
enc_l ++;
}
void countRight()
{
enc_r ++;
}
and this is what is on the setup function
const int enc_l_pin = 18;
const int enc_r_pin = 19;
void setup()
{
Serial.begin(115200); // Serial 0 is for communication with the computer
Serial3.begin(9600); // Serial 1 is for Bluetooth communication - DO NOT MODIFY - JY-MCU HC-06 v1.40
Wire.begin(); // Join I2C bus used for the HMC5883L compass
compass.begin(); // initialize the compass (HMC5883L)
compass.setRange(HMC5883L_RANGE_1_3GA); // Set measurement range
compass.setMeasurementMode(HMC5883L_CONTINOUS); // Set measurement mode
compass.setDataRate(HMC5883L_DATARATE_30HZ); // Set data rate
compass.setSamples(HMC5883L_SAMPLES_8); // Set number of samples averaged
compass.setOffset(118, 473); // Set calibration offset
// Buzzer
pinMode(Buzzer_pin, OUTPUT);
// Set up pins
pinMode(enc_l_pin, INPUT);
pinMode(enc_r_pin, INPUT);
// Set up interrupts
attachInterrupt(digitalPinToInterrupt(enc_l_pin), countLeft, CHANGE);
attachInterrupt(digitalPinToInterrupt(enc_r_pin), countRight, CHANGE);
-
I don't see any interrupt code. Please provide a complete (!) working minimal example code, that shows your problem.chrisl– chrisl2019年02月12日 07:55:26 +00:00Commented Feb 12, 2019 at 7:55
-
Yes, sorry I just added them inNoName123– NoName1232019年02月12日 08:13:04 +00:00Commented Feb 12, 2019 at 8:13
-
Do you have a pullup or pulldown resistor? If not, the pin will be floating.chrisl– chrisl2019年02月12日 08:17:48 +00:00Commented Feb 12, 2019 at 8:17
-
When I try to put a pull up resistor accross the +vcc and output pin of the hall effect sensor as shown in the picture the voltage stays constantNoName123– NoName1232019年02月12日 09:05:12 +00:00Commented Feb 12, 2019 at 9:05
-
What type of hall sensor do you use exactly?chrisl– chrisl2019年02月12日 09:54:52 +00:00Commented Feb 12, 2019 at 9:54
1 Answer 1
I think you have 2 problems:
The used Hall sensor is an analog device, not a digital one. This means it will not output either Vcc or 0V, but instead an analog (continuous) voltage depending on the magnetic field. With zero magnetic field, it will output about half the supply voltage (in this case 2.5V, since Vcc is 5V for you). For analog signals pullups or pulldowns do not make sense. Digital pins have a hysteris, which means, that they will detect a LOW between 0V and 1.67V and a HIGH between 3.33V and 5V (see this answer). This is also called a Schmitt trigger. I assume, that you just want to measure, that the magnet comes near the sensor (so only one polarity matters). This means, that the voltage will stay - let's say - above 2.5V (depending on polarity) and only going from 2.5V to 5V and back. In this condition the pin state will stay high, since it is set high, but never reaches voltage low enough for setting it to low. No interrupt will be triggered. Depending on what you want and the next problem, you can instead use a comparator (which is a special peripheral of the microcontroller) to trigger the incrementation, when a specified threshold voltage is reached (this also mean it would trigger due to small changes around the threshold), or you can buy or build an external Schmitt trigger, where you can change the threshold voltages for LOW and HIGH changes.
Motors send out quite a bunch of electromagnetic noise, which can distort analog Signals nearby. Most likely the noise from the motors is high enough to falsely trigger a state change at the pin. Maybe you should look at the analog signal with an oscilloscope, which can show you, how much noise do you really have in this situation. There are many ways to reduce noise on an analog signal. One is to add a low pass filter to cancel out the mostly higher frequency noise. This only works, if the frequency of your signal is considerably lower (so that you can trim the low pass filter to let your signal pass).
From the picture I cannot see, how the magnets and the sensors are moving in the car. Be sure to measure the different voltages in the different states (magnet near sensor, magnet for away). If the sensor is too sensitive or your magnet too strong, you might end up with an even smaller voltage range, than the 2.5V, that you already have.
-
Thanks for the valuable information. I will work on designing the schmitt trigger and let you know how I go.NoName123– NoName1232019年02月13日 03:54:55 +00:00Commented Feb 13, 2019 at 3:54
-
I built a non-inverting Schmitt Trigger. The circuit diagram can be seen in the post. The issue I am having is that once I connect the output pin of the hall effect sensor to the input of the schmitt trigger the input stays 3.3V and the output reads about 4.22V.NoName123– NoName1232019年02月13日 11:06:39 +00:00Commented Feb 13, 2019 at 11:06