I am making a code to run a 12V DC motor, every 60 seconds change direction.
The problem is that the code does not work without the delay, if removing the dalay of the first IF does not work the first IF
If you remove the IF from below, the second IF does not work.
I would like to make it work without using the delay because the motors do not work well.
Algem knows some logic that works the motor without the delay in the code?
Thank you very much in advance
#include <TimerOne.h>
#define IN1MotorA 3
#define IN2MotorA 2
#define pinA 5
#define pinB 4
bool dtl2;
int dtl;
int set = 60;
void setup() {
//Serial.begin(9600);
pinMode(set, INPUT_PULLUP);
pinMode(pinA, INPUT_PULLUP);
pinMode(pinB, INPUT_PULLUP);
pinMode(IN2MotorA, OUTPUT);
pinMode(IN1MotorA, OUTPUT);
Timer1.initialize(1000000);
Timer1.attachInterrupt(interrup);
}
void interrup()
{
dtl++;
if (dtl == set)
{
dtl2 = !dtl2;
dtl = 0;
}
}
void loop() {
if (dtl2 == 0&& digitalRead(pinA))//if dtl2 == 0 and pinA == 1 turns the motor in one direction
{
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA, HIGH);
}
else ////if dtl2 == 0 and pinA == 0 stops the motor
{
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA,LOW);
}
delay(150);//Without this delay the upper IF does not work
if (dtl2 == 1&& digitalRead(pinB)) {
digitalWrite(IN1MotorA,HIGH);
digitalWrite(IN2MotorA,LOW);
}
else
{
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA,LOW);
}
delay(100);//Without this delay the upper IF does not work
}
if (dtl2 == 0&& digitalRead(pinA))//if dtl2 == 0 and pinA == 1 turns the motor in one direction
{
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA, HIGH);
}
else ////if dtl2 == 0 and pinA == 0 stops the motor
You've missed two more possibilities on your comment for the else. it could be that dtl2 is not 0.
Same with the other set of if - else.
Think about it, if dtl2 is 1 and pinB is HIGH then the second if tries to turn the motor on. But then loop repeats and the first if statement isn't true because dtl2 isn't 0 so it runs the else part and turns them right back off.
Or if the first if is true and tries to turn on the motor then the second if can't be so it hits the else and turns them right back off.
You need to rethink your logic. Put the code aside for a minute and draw yourself a diagram of all the possible states of dtl2 and the pins and what should happen in each one.
Hi Delta_G
Thanks for answering.
Everything you said is right, but I do not understand is the reason that if you have the delay works. I've lost enough time to think the reason for this and I can not understand the logic!
Can someone give me some details how can I make this code correctly?
Thank you very much in advance
Although I do not have much experience in programming, I consider myself an apprentice, when I enter this forum to ask for help, I do not want to do anything for free or to do the code for me, but rather that they correct my code, which give me tips on how to make the code and if possible a draft of the code so I can understand the logic!
Before I ask for help, I do a lot of research on google, I study the books I have and when I have no other way I can do my code, I ask the forum for help! and effort I do much to learn!
Although you have already helped me a lot.
You should also note the (poorly written) recommendation on that page:
use the ATOMIC_BLOCK macro
Your dtl variable is 16 bits. An 8 bit microcontroller can only read or write 8 bits in an operation. So if the interrupt fires while the loop() code is 1/2 of the way through reading dtl then the read value of dtl ends up being corrupted because it's partly the pre-interrupt value and partly the post-interrupt value. That will only happen if the interrupt fires at just the right time but your interrupt is going to be firing over and over again so it's really not so unlikely. That would not be a problem if dtl was an 8 bit byte type but if you need to use a larger type then you should wrap any reads or writes of the variable in ATOMIC_BLOCK: https://www.nongnu.org/avr-libc/user-manual/group__util__atomic.html
You should also note the (poorly written) recommendation on that page:Your dtl variable is 16 bits. An 8 bit microcontroller can only read or write 8 bits in an operation. So if the interrupt fires while the loop() code is 1/2 of the way through reading dtl then the read value of dtl ends up being corrupted because it's partly the pre-interrupt value and partly the post-interrupt value. That will only happen if the interrupt fires at just the right time but your interrupt is going to be firing over and over again so it's really not so unlikely. That would not be a problem if dtl was an 8 bit byte type but if you need to use a larger type then you should wrap any reads or writes of the variable in ATOMIC_BLOCK: avr-libc: <util/atomic.h> Atomically and Non-Atomically Executed Code Blocks
Hi pert
Thanks for helping
This is difficult to do a lot of tests and still does not work, the variable I already did as I said "volatile byte dtl;" and it still does not work!
thank
@pert, But blink without delay is hard. I don't know how to use a clock. These interrupts were supposed to hide all that from me and make things easier. Now I have to learn even harder stuff to do that right? I might as well just learn to use a clock and write normal BWoD code.
As I was writing that I was thinking about how these are very advanced concepts for a beginner. Eventually there is a time when interrupts are absolutely needed but I don't think it's a good idea to jump into them from the very start.
Fiasgardone:
This is difficult to do a lot of tests and still does not work, the variable I already did as I said "volatile byte dtl;" and it still does not work!
Post the updated code and explain exactly what you mean by "does not work".
pert:
As I was writing that I was thinking about how these are very advanced concepts for a beginner. Eventually there is a time when interrupts are absolutely needed but I don't think it's a good idea to jump into them from the very start.
Post the updated code and explain exactly what you mean by "does not work".
Hi! pert Thank you for your support.
As I said I did several tests changing the code and the result was the same in the LOOP the first IF does not work, ie when the variable "dtl" is at 0 the motor is stopped, only when the variable "dtl" goes to 1 then the engine turns.
If I between the two IFs put a delay (150); the first IF works, but I did not want to use the delay because the delay stops the LOOP, so I'd like to make the engine work in both directions without the delay.
I am using the Serial to control the dtl2 variable, and the timer is working fine and the dtl2 variable changes state as programmed in the timer Interrupt
Below is the code with the last update, I hope you can help me.
Note: I am using the L298 module for motor control
#include <TimerOne.h>
#define IN1MotorA 3
#define IN2MotorA 2
#define pinA 5
#define pinB 4
bool dtl2=false;
volatile byte dtl=0;
byte set = 15;
void setup() {
Serial.begin(9600);
pinMode(pinA, INPUT_PULLUP);
pinMode(pinB, INPUT_PULLUP);
pinMode(IN2MotorA, OUTPUT);
pinMode(IN1MotorA, OUTPUT);
Timer1.initialize(1000000);
Timer1.attachInterrupt(interrup);
}
void interrup()
{
dtl++;
if (dtl == set)
{
dtl2 = !dtl2;
dtl = 0;
}
}
void loop() {
//******************************First IF******************************************
if (dtl2 == 0 && digitalRead(pinA)==HIGH)//if dtl2 == 0 and pinA == 1 turns the motor in one direction
{
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA, HIGH);
}
else //if dtl2 == 0 and pinA == 0 stops the motor
{
if (dtl2 == 0 && digitalRead(pinA)==LOW)
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA,LOW);
}
//delay(150);//Without this delay the upper IF does not work
//******************************* Second IF********************************************
if (dtl2 == 1&& digitalRead(pinB)==HIGH) {
digitalWrite(IN1MotorA,HIGH);
digitalWrite(IN2MotorA,LOW);
}
else
{
if (dtl2 == 1&& digitalRead(pinB)==LOW)
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA,LOW);
}
Serial.println(dtl2);
//delay(100);//Without this delay the upper IF does not work
}
Even though the first IF does not work, I think by programming logic in the LOOP, when the condition of the first If is true, it does the first If, if dtl2 is zero and pinA for 1 true condition should execute the first IF, but it does not happen that.
If the condition of the second IF is true then the second IF.
Because the controller of the two IFs is the dtl2 variable according to the state of the dtl2 variable of 0 or 1 at the timer interrupt
The timer interrupt works fine and the dtl2 variable changes state as programmed, I control as serial said the dtl2 variable.
the updated code
#include <TimerOne.h>
#define IN1MotorA 3
#define IN2MotorA 2
#define pinA 5
#define pinB 4
//volatile byte dtl2=false;
volatile bool dtl2=false;
volatile byte dtl=0;
byte set = 15;
void setup() {
Serial.begin(9600);
pinMode(pinA, INPUT_PULLUP);
pinMode(pinB, INPUT_PULLUP);
pinMode(IN2MotorA, OUTPUT);
pinMode(IN1MotorA, OUTPUT);
Timer1.initialize(1000000);
Timer1.attachInterrupt(interrup);
}
void interrup()
{
dtl++;
if (dtl == set)
{
dtl2 = !dtl2;
dtl = 0;
}
}
void loop() {
//******************************First IF******************************************
if (dtl2 == 0 && digitalRead(pinA)==HIGH)//if dtl2 == 0 and pinA == 1 turns the motor in one direction
{
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA, HIGH);
}
else //if dtl2 == 0 and pinA == 0 stops the motor
{
if (dtl2 == 0 && digitalRead(pinA)==LOW)
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA,LOW);
}
//delay(150);//Without this delay the upper IF does not work
//******************************* Second IF********************************************
if (dtl2 == 1&& digitalRead(pinB)==HIGH) {
digitalWrite(IN1MotorA,HIGH);
digitalWrite(IN2MotorA,LOW);
}
else
{
if (dtl2 == 1&& digitalRead(pinB)==LOW)
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA,LOW);
}
Serial.println(dtl2);
//delay(100);//Without this delay the upper IF does not work
}
Delta_G:
Do you want to get this fixed? I will help you if you will do what I asked.
Hi Delta_G
Yes I need help, to see where the error is and solve the problem, but as I said in other posts, I have tested all my knowledge, if I have not been able to find where the error or what I am doing wrong, it is because I have no knowledge to do better,
I do not want anything ready, but if possible a draft how should I do, tips some piece of code that can help me etc, I hope you understand this!
Thanks for the contact
You need to rethink your logic. Put the code aside for a minute and draw yourself a diagram of all the possible states of dtl2 and the pins and what should happen in each one.
Hi Delta_G
To do what you ask in the first post, I'll do what I really want to do! I do not know if that's what I really wanted you to do.
It is to make move a motor from a certain time to a lada and after that time to the opposite side
That is, 30 seconds anticlockwise after that time 30 clockwise
1-SETUP
timer as 1-second counter to count the desired time.
every 30 seconds changes the stay of the variable dtl2 between 0 and 1
The variable dtl2 I declared as bool so it only has 2 possible states 0 or 1
2- LOOP
if the variable dtl2 is 0
if dtl2 == 0 and pinA == 1
starts the engine in one
if dtl2 == 0 and pinA == 0
stops the engine
if the variable dtl2 is 1
if dtl2 == 1 and pinB for 1
starts the engine in one
if dtl2 == 1 and pinB == 0
stops the engine
repeat the cycle until necessary
As I said I do not know if this is what you want me to do but I think you can understand the logic in the diagram
Simple things that sometimes give us major headaches, now does work just fine, just like I wanted it to work itself out.
This will serve for future thinking logic, I would like if it clarifies to me that you wrote below as I have 3 input, and 8 possible states.
So you have 3 binary inputs. That means you have 8 possible states.
I'm going to post the updated code, it might help here.
#include <TimerOne.h>
#define IN1MotorA 3
#define IN2MotorA 2
#define pinA 5
#define pinB 4
volatile bool dtl2=false;
volatile byte dtl=0;
byte set = 60;
void setup() {
Serial.begin(9600);
pinMode(pinA, INPUT_PULLUP);
pinMode(pinB, INPUT_PULLUP);
pinMode(IN2MotorA, OUTPUT);
pinMode(IN1MotorA, OUTPUT);
Timer1.initialize(1000000);
Timer1.attachInterrupt(interrup);
}
void interrup()
{
dtl++;
if (dtl == set)
{
dtl2 = !dtl2;
dtl = 0;
}
}
void loop() {
if (dtl2 == 0 )//if dtl2 == 0
{
if(digitalRead(pinA)==1 )//if pinA== 1 turns the motor in one direction
{
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA, HIGH);
}
else // pinA == 0 stops the motor
{
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA,LOW);
}
}
if (dtl2 == 1 )//if dtl2 == 1
{
if(digitalRead(pinB)==1 )//if pinB == 1 turns the motor in back direction
{
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA, HIGH);
}
else // pinB == 0 stops the motor
{
digitalWrite(IN1MotorA, LOW);
digitalWrite(IN2MotorA,LOW);
}
}
Serial.println(dtl2);
//delay(100);
}
Just to re-iterate the very good advice offered by Delta_G, and for future reference, any time you have n possible states that may result, you need to have test cases that cover all of them. If you only address half of the possible outcomes, you may only get lucky with the the cases you do test. Even if you lump the remaining cases into a series of do-nothing statements, for de-bugging you can always slip a print in just to see what's happening. Makes the flow easier to follow when it doesn't do what it's supposed to.