Good afternoon everyone I've finally bitten the bullet and joined the forum. I was hoping I'd be able to figure this out as it's my first project, but unfortunately I've been beaten. :-[
My circuit is as follows, it's being driven by a 12V battery.
I've got the Arduino receiving power from an L298 motor driver's 5V output.
Non-latching Hall effect sensor (A3144) to ground on the arduino, but sharing the 5V output of the motor driver.
The hall effect sensor has a 10k resistor across it's Supply and Output pins as per what I've read in other topics.
The premise of my project is this:
The circuit powers on and does nothing at all.
At the first push of a button it turns a motor one way for a set time.
At the second push of the same button it turns the motor the opposite way continually until a magnet triggers the hall effect sensor and it stops.
And then back to waiting for the first button press option.
I've got most of that working with the code below, I just can't get the motor to stop when the magnet approaches the sensor. I've checked and double, triple checked the north/south pole, and I've tried the sensor alone so it's likely to be an issue with the code as everything up until that point works nicely.
Thankyou in advance for any help you can guys can give.
const int inPin = 2; // the number of the input pin for the button switch
const int outPin1 = 10; // the number of the output1 pin
const int outPin2 = 11; // the number of the output2 pin
const int hallPin = 8; // Hall sensor pin 3rd leg on the right to Arduino 8
int enA = 12;
int state1; // the current state of the output1 pin
int reading; // the current reading from the input pin
int previous = LOW; // the previous reading from the input pin
long time = 0; // the last time the output pin was toggled
long debounce = 200; // the debounce time, increase if the output flickers
int pressCount = 1;
int hallState = 0;
void setup()
{
pinMode(inPin, INPUT_PULLUP);
pinMode(outPin1, OUTPUT);
pinMode(outPin2, OUTPUT);
pinMode(enA, OUTPUT);
pinMode(hallPin, INPUT_PULLUP);
}
void loop()
{
reading = digitalRead(inPin);
if (reading == HIGH && previous == LOW && millis() - time > debounce)
{
state1 = !state1; // Toggle the state
pressCount++;
time = millis();
switch (pressCount % 2)
{
case 0:
digitalWrite(outPin1, HIGH); // Turn on motor direction 1
digitalWrite(outPin2, LOW); //
analogWrite(enA, 10); // Sets motor speed (value between 0-255)
delay (1000); // Runs motor for 1 second
digitalWrite(outPin1, LOW); // Turn off motor direction 1
digitalWrite(outPin2, LOW);
break;
case 1:
hallState = digitalRead(hallPin);
while (hallState == HIGH) // No Magnet
{
digitalWrite(outPin1, LOW); // Run motor direction 2
digitalWrite(outPin2, HIGH);
analogWrite(enA, 10);
}
break;
}
}
previous = reading;
}
I am not going to study your program. You need to write a program dealing ONLY with the Hall sensor. When you get that program to work with the sensor, you will be able to debug the original program.
Perhaps light a LED when you recognize the Hall sensor being on. OR Serial.println to the monitor, etc.
Point taken Paul, sound advice and I came up with a little example which was this:
const int hallPin = 8; // the number of the hall effect sensor pin
int ledPin = 13; // the number of the LED pin
// variables will change:
int hallState = 1; // variable for reading the hall sensor status
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the hall effect sensor pin as an input:
pinMode(hallPin, INPUT);
}
void loop() {
// read the state of the hall effect sensor:
hallState = digitalRead(hallPin);
if (hallState == HIGH)
{
digitalWrite(ledPin, HIGH);
}
if (hallState == LOW) {
digitalWrite(ledPin, LOW);
}
}
This worked well, and sure enough the magnet turns the LED off as it should. I've applied that now to my new code but unfortunately I'm still getting the same issue. Any ideas as to where I should be looking?
const int inPin = 2; // the number of the input pin for the button switch
const int outPin1 = 10; // the number of the output1 pin
const int outPin2 = 11; // the number of the output2 pin
const int hallPin = 8; // Hall sensor pin 3rd leg on the right to Arduino 8
int enA = 12;
int state1; // the current state of the output1 pin
int reading; // the current reading from the input pin
int previous = LOW; // the previous reading from the input pin
long time = 0; // the last time the output pin was toggled
long debounce = 200; // the debounce time, increase if the output flickers
int pressCount = 1;
int hallState = 0;
void setup()
{
pinMode(inPin, INPUT_PULLUP);
pinMode(outPin1, OUTPUT);
pinMode(outPin2, OUTPUT);
pinMode(enA, OUTPUT);
pinMode(hallPin, INPUT);
}
void loop()
{
reading = digitalRead(inPin);
if (reading == HIGH && previous == LOW && millis() - time > debounce)
{
state1 = !state1; // Toggle the state
pressCount++;
time = millis();
switch (pressCount % 2)
{
case 0:
digitalWrite(outPin1, HIGH); // Turn on motor direction 1
digitalWrite(outPin2, LOW); //
analogWrite(enA, 10); // Sets motor speed (value between 0-255)
delay (1000); // Runs motor for 1 second
digitalWrite(outPin1, LOW); // Turn off motor direction 1
digitalWrite(outPin2, LOW);
break;
case 1:
hallState = digitalRead(hallPin);
if (hallState == HIGH) // No Magnet
{
digitalWrite(outPin1, LOW); // Run motor direction 2
digitalWrite(outPin2, HIGH);
analogWrite(enA, 10);
}
if (hallState == LOW) {
digitalWrite(outPin1, LOW);
digitalWrite(outPin2, LOW);
}
break;
}
}
previous = reading;
}
Ok my mistake there, Pin 12 on the Arduino isn't PWM obviously... I have now corrected that to Pin 6~.
That's just controlling the motor speed, and works fine.
What I'm struggling with is the Case 1 part of the code. At the first push of the button the motor runs in one direction for 1000ms at a set speed and then turns off. Perfect.
The second button press starts the motor running indefinitely again that's fine. What I'm then trying to do is have the hall effect sensor stop the motor from spinning.
Ok, the board can control two motors. Pin 7 is the enable pin for one motor, pin 12 is the enable for the other motor. So you need to set pin 7 HIGH to run your motor and set pin 7 to LOW to stop the motor.
Again, thankyou for your time Paul I do appreciate it mate. I had changed the while statement to two If statements as per the second set of coding I posted to reflect the fact I had followed your advice and had a go with just the hall sensor on it's own.
But for some reason when I include that code in "case 1" it simply doesn't work for a reason I can't yet fathom and it's probably something dead obvious to someone on here.
As per Paul's suggestion here's a little bump for the thread, if anyone can help me out that would be grand. Thanks.
const int inPin = 2; // the number of the input pin for the button switch
const int outPin1 = 10; // the number of the output1 pin
const int outPin2 = 11; // the number of the output2 pin
const int hallPin = 8; // Hall sensor pin 3rd leg on the right to Arduino 8
int enA = 6;
int state1; // the current state of the output1 pin
int reading; // the current reading from the input pin
int previous = LOW; // the previous reading from the input pin
long time = 0; // the last time the output pin was toggled
long debounce = 200; // the debounce time, increase if the output flickers
int pressCount = 1;
int hallState = 0;
void setup()
{
pinMode(inPin, INPUT_PULLUP);
pinMode(outPin1, OUTPUT);
pinMode(outPin2, OUTPUT);
pinMode(enA, OUTPUT);
pinMode(hallPin, INPUT);
}
void loop()
{
reading = digitalRead(inPin);
if (reading == HIGH && previous == LOW && millis() - time > debounce)
{
state1 = !state1; // Toggle the state
pressCount++;
time = millis();
switch (pressCount % 2)
{
case 0:
digitalWrite(outPin1, HIGH); // Turn on motor direction 1
digitalWrite(outPin2, LOW); //
analogWrite(enA, 100); // Sets motor speed (value between 0-255)
delay (1000); // Runs motor for 1 second
digitalWrite(outPin1, LOW); // Turn off motor direction 1
digitalWrite(outPin2, LOW);
break;
case 1:
hallState = digitalRead(hallPin);
if (hallState == HIGH) // No Magnet
{
digitalWrite(outPin1, LOW); // Run motor direction 2
digitalWrite(outPin2, HIGH);
analogWrite(enA, 100);
}
if (hallState == LOW) {
digitalWrite(outPin1, LOW);
digitalWrite(outPin2, LOW);
}
break;
}
}
previous = reading;
}
As a further note to the above, I've also tried an if else statement but again I can't get the motor to stop when the magnet has been passed in front of the hall sensor.
Your
if (hallState == LOW) {
block is inside the button push block. That means that the hall effect sensor can only be read if the button is pushed.
You need to separate the motor return/hall effect check from the button checking code. Maybe only allow one or the other.
Search the forum for "state machine" and study some of the guidance and code examples. If you are going to expand your code further, then better understand such techniques first.
Arduarn thanks for taking the time to look the code over.
I only want the hall effect sensor to be read after the second button press, and not during the first. So logically in my mind that is right. But I'll mull it over and see what I can do.
Trust me, all I've done for the past two weeks trying to figure this out is read and try to get my head round these concepts. It's totally new to me, and the forum was my last point of call, but point taken.
yome:
Trust me, all I've done for the past two weeks trying to figure this out is read and try to get my head round these concepts. It's totally new to me, and the forum was my last point of call, but point taken.
Ok then, since I'm now at a PC and not posting from my phone, here is roughly what I mean:
const int inPin = 2; // the number of the input pin for the button switch
const int outPin1 = 10; // the number of the output1 pin
const int outPin2 = 11; // the number of the output2 pin
const int hallPin = 8; // Hall sensor pin 3rd leg on the right to Arduino 8
const int enA = 6;
const unsigned long DebounceTime = 200; // the debounce time, increase if the output flickers
byte buttonReading; // the current reading from the input pin
byte previousButtonReading = LOW; // the previous reading from the input pin
unsigned long lastButtonToggleTime = 0; // the last time the output pin was toggled
byte hallState = LOW;
bool buttonPressed;
unsigned long goingAwayStartTime;
enum MotorState { HOME, GOINGAWAY, AWAY, COMINGHOME };
MotorState currentMotorState = HOME;
void setup()
{
pinMode(inPin, INPUT_PULLUP);
pinMode(outPin1, OUTPUT);
pinMode(outPin2, OUTPUT);
pinMode(enA, OUTPUT);
pinMode(hallPin, INPUT);
}
void loop()
{
// Read button state
buttonPressed = false;
buttonReading = digitalRead(inPin);
if (buttonReading == HIGH && previousButtonReading == LOW && millis() - lastButtonToggleTime > DebounceTime) {
lastButtonToggleTime = millis();
buttonPressed = true;
}
previousButtonReading = buttonReading;
// Read Hall effect sensor state
hallState = digitalRead(hallPin);
// Do state machine actions
switch (currentMotorState) {
case HOME:
if (buttonPressed) {
currentMotorState = GOINGAWAY;
goingAwayStartTime = millis();
digitalWrite(outPin1, HIGH); // Turn on motor direction 1
digitalWrite(outPin2, LOW); //
analogWrite(enA, 100); // Sets motor speed (value between 0-255)
}
break;
case GOINGAWAY:
if (millis() - goingAwayStartTime > 1000) { // Runs motor for 1 second
currentMotorState = AWAY;
digitalWrite(outPin1, LOW); // Turn off motor direction 1
digitalWrite(outPin2, LOW);
}
break;
case AWAY:
if (buttonPressed) {
if (hallState == HIGH) { // No Magnet
currentMotorState = COMINGHOME;
digitalWrite(outPin1, LOW); // Run motor direction 2
digitalWrite(outPin2, HIGH);
analogWrite(enA, 100);
} else {
// motor broken? failed sensor? possible error case
currentMotorState = HOME; // or perhaps have a separate ERROR state where nothing happens
}
}
break;
case COMINGHOME:
if (hallState == LOW) {
currentMotorState = HOME;
digitalWrite(outPin1, LOW);
digitalWrite(outPin2, LOW);
} else {
// maybe add a safety timeout?
}
break;
}
// Do other stuff while the motor is doing its thing
// but make sure that nothing blocks so long that a
// change in the Hall effect sensor could be missed
}
Utterly untested, but you should get the idea. I would encourage you to use more descriptive names for variables etc. It will make things easier as your sketch gets larger.
Wow, I can't believe you actually took the time to write all that out!
It works like a charm, thankyou so much for your time and effort Arduarn. I'll study what you've added, as there's some new terms in there I had no idea about, and it's definitely far more complex than what I'd managed to come up with.