I just started learning Arduino. I thought about going hands on with a Robot which I want to get some autonomy in. I got stuck trying to understand the motor control for the DC motor. I've tried to look up resources but can't find one that adequately explains my problem.
I can't understand (being a comp sci undergrad) how or what I am doing wrong writing the code for the motor.
My code just for running the motors for a test is :
// MotorA
int dir1PinA = 7;
int dir2PinA = 5;
int speedPinA = 6;
//motor B
int dir1PinB = 4;
int dir2PinB = 2;
int speedPinB = 3;
void setup() {
//Serial.begin(9600);
pinMode (dir1PinA, OUTPUT);
pinMode (dir2PinA, OUTPUT);
pinMode (speedPinA,OUTPUT);
pinMode (dir1PinB, OUTPUT);
pinMode (dir2PinB, OUTPUT);
pinMode(speedPinB, OUTPUT);
// put your setup code here, to run once:
}
void loop() {
analogWrite(speedPinA, 500);
analogWrite(speedPinB, 500);
digitalWrite (dir1PinA, LOW);
digitalWrite (dir2PinA, HIGH);
digitalWrite (dir1PinB,HIGH);
digitalWrite (dir2PinB, LOW);
// put your main code here, to run repeatedly:
}
I am just trying to run the motor at a certain speed to no avail. I found a sample code that uses the same method to control the motor but has just an extra loop and variable speed.
The test code which works is :
//Motor A
int dir1PinA = 7;
int dir2PinA = 5;
int speedPinA = 6;
//motor B
int dir1PinB = 4;
int dir2PinB = 2;
int speedPinB = 3;
unsigned long time;
int speed;
int dir;
void setup ()
{
pinMode (dir1PinA, OUTPUT);
pinMode (dir2PinA, OUTPUT);
pinMode (speedPinA, OUTPUT);
pinMode (dir1PinB, OUTPUT);
pinMode (dir2PinB, OUTPUT);
pinMode (speedPinB, OUTPUT);
time = millis ();
speed = 0;
dir = 1;
}
void loop ()
{
analogWrite (speedPinA, speed);
analogWrite (speedPinB, 555 - speed);
// set direction
if (1 == dir)
{
digitalWrite (dir1PinA , LOW);
digitalWrite (dir2PinA, HIGH);
digitalWrite (dir1PinB, HIGH);
digitalWrite (dir2PinB, LOW);
}
else
{
digitalWrite (dir1PinA, HIGH);
digitalWrite (dir2PinA, LOW);
digitalWrite (dir1PinB, LOW);
digitalWrite (dir2PinB, HIGH);
}
if (millis () - time> 5000)
{
time = millis ();
speed += 20;
if (speed> 555) {speed = 0;}
if (1 == dir)
{dir = 0;}
else
{dir = 1;}
}
}
Now I understand there are loops and extra variables but theoretically they shouldn't be required to just run a motor at a certain speed. My question is that What am I missing from the top sketch that is in the second one but is absolutely critical to the running of the motor?
I want to apologize in advance if this is a noob moment but I tried and can't find any logic lol.
In the "working" Arduino code ( c++ , yes it's compiled by a c++ compiler ) one of your both motors (B) starts immediately, and the other one 5 sec after reset (or even later)?
And the immediately started motor changes direction after 5 sec?
Else, try small modifications to the working sample, towards your simplification, to get some more understanding.
E.g. first remove the "dir" change and "else" part
Okay first I will debug your code, I will make a some assumptions about your hardware since you didn't post any photos or schematics, finally I will provide a working solution.
Your Code:
So my first assumption is that your Motor has 3 pins because you're toggling two between high and low, presumably to reverse current, and then one to set the speed.
As I am guessing you know, in order to get a motor to reverse you need to flip the direction the current is going. Setting these pins high and low won't actually reverse the current. Also, the Arduino doesn't really have enough output current to drive a DC motor. You can probably slowly run one. If you want to do more you'll need an external power source.
Drive a DC motor in one direction:
This is probably the easiest one to do. You just need a transistor, diode and resistor. Here is a tutorial
Drive up to four DC motors in both directions
If you want to drive your DC motor in two directions then you need to flip the direction the current is going. This seems complex at first until you realize they've already built something for you to do this exact thing. It's called a Motor Control. It's just a shield with a few H-Bridges on it. They're pretty cheap.
I like AdaFruit's. I have a couple and I built a robot with it not to long ago.
Tutorial on how to use the Adafruit MotorShield
Related
I have made a hardware development based on an ATmega328P and programmed with the Arduino IDE.
The board has one relay output that switchs an AC load.
From time to time, the microcontroller is restarted when the load is switched ON or OFF. No mystery so far. It is probably some EMI interference that is causing the reboot.
BUT, sometimes the microcontroller freezes completely. I canĀ“t figure out why, as I have enabled the watchdog timer. There shouldn't be any freezing. As far as I know, the watchdog timer should restart the microcontroller after 2 seconds.
I would need help understanding WHY I am getting this behaviour and of course, if there could be any software fix.
This is a simple code to show this behaviour. I already tried to change some fuses configurations (brownout, wdton, etc) but no luck so far.
Any help would be much appreciated
Thanks in advance
#include <avr/wdt.h>
#define R0 3
#define R1 4
#define R2 5
unsigned int delayTime = 200;
unsigned int counter = 0;
//--------------------------------------------------------------------
void setup() {
MCUSR = 0;
wdt_disable();
Serial.begin (9600);
delay (1000);
Serial.println ("********************RESTARTING*****************");
pinMode (R0, OUTPUT);
pinMode (R1, OUTPUT);
pinMode (R2, OUTPUT);
delay (2000);
wdt_enable (WDTO_2S);
}
//--------------------------------------------------------------------
void loop() {
wdt_reset();
digitalWrite (R1, HIGH);
counter++;
Serial.print ("R1 activated, counter = "); Serial.println (counter);
delay (delayTime);
digitalWrite (R1, LOW);
Serial.print ("R1 deactivated, counter = "); Serial.println (counter);
delay (delayTime);
}
You not have enabled watchdog from reset for three second. I recomend use WDR activation by fuse bit WDTON, not by sw after three second.
void setup() {
MCUSR = 0;
wdt_disable(); //WDR disabled
Serial.begin (9600);
delay (1000); //one second delay
Serial.println ("********************RESTARTING*****************");
pinMode (R0, OUTPUT);
pinMode (R1, OUTPUT);
pinMode (R2, OUTPUT);
delay (2000); //two second delay
wdt_enable (WDTO_2S);
I need to write a program in Arduino that turns ON or OFF two LEDs independently depending on the data received via serial communication. For example, the first LED will turn on if the Arduino board receives a1,and it will turn OFF if a2 is received. but I require help on doing this. i havent started on this yet but i am trying to do it using 2 blinking light code. I am new to Arduino programming and i don't understand some concepts. but i can definitely use help on doing this.
int LEDred = 3;
int LEDgreen = 6;
void setup() {
pinMode (LEDred, OUTPUT);
pinMode (LEDgreen, OUTPUT);
}
void loop() {
digitalWrite (LEDred, HIGH);
digitalWrite (LEDgreen, LOW);
delay (1000);
digitalWrite (LEDred, LOW);
digitalWrite (LEDgreen, HIGH);
delay (1000);
}
Use 1 or 2 instead of a1 and a2. Because it's easier to process.Consider you send 1 via serial port. Read the signal by
byte val;
if(Serial.available()>0){
val=Serial.read();
}
Then use another if statement in order to blink red or green LED
I was getting to know this ultrasonic detector with a simple code. All I was looking for was an output (my LED) to light up whenever the detector sensed an object within so many centimetres.
However the LED remains lit and the serial monitor just keeps spitting out the value '0.00cm'
I would appreciate any help, thanks.
(I do apologise if there is a very simple error I have overlooked)
#include <NewPing.h>
int TriggerPIN = 2;
int EchoPIN = 3;
int LEDPIN = 7;
void setup()
{
Serial.begin(9600);
//That started the distance monitor
pinMode(LEDPIN, OUTPUT);
pinMode(TriggerPIN, OUTPUT);
pinMode(EchoPIN, INPUT);
}
void loop()
{
float Distance, Duration;
digitalWrite(TriggerPIN, LOW);//These three blink the distance LED
delayMicroseconds(2);
digitalWrite(TriggerPIN, HIGH);
delayMicroseconds(10);
digitalWrite(TriggerPIN, LOW);
Duration = pulseIn(EchoPIN, HIGH); //Listening and waiting for wave
Distance = (Duration*0.034/2);//Converting the reported number to CM
if (Distance > 50)
{
digitalWrite(LEDPIN,LOW);
}
else
{
digitalWrite(LEDPIN,HIGH);
}
Serial.print(Distance);Serial.print("cm");
Serial.println(" ");
delay(200);
}
A couple of things to try:
Change the serial print to display 'Duration', to see if the problem lies in the centimetre conversion.
If this is not the problem:
(Assuming you are using the NewPing 1.7 library, as found here. )
The NewPing library has a built in 'Ping' function, along with distance conversion.
Try replacing the start of your code with this:
#include <NewPing.h>
#define TRIGGER_PIN 2
#define ECHO_PIN 3
#define MAX_DISTANCE 200 // Maximum distance to ping for (cm). Up to ~450cm
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum distance.
You do not need to then set the Trigger and Echo pins as outputs in your setup.
In your main loop, use these methods to get time and distance in microsecs and centimetres:
unsigned int pingTime = sonar.ping(); //Gets the ping time in microseconds.
Serial.print(sonar.convert_cm(pingTime)); // Convert ping time in cm, serial out.
I hope this helps.
I am doing a basic project in Arduino UNO connecting an Ultra Sonic sensor (HC-SR04) which should print in the serial monitor the distance of the closest object but it always print 0.
This is my code:
long distance;
long time;
void setup(){
Serial.begin(9600);
pinMode(4, OUTPUT);
pinMode(2, INPUT);
}
void loop(){
digitalWrite(2,LOW);
delayMicroseconds(5);
digitalWrite(2, HIGH);
delayMicroseconds(10);
time = pulseIn(4, HIGH);
distance = int(0.017*time);
Serial.print("Distance: ");
Serial.print(distance);
Serial.println(" cm.");
delay(1000);
}
And this is the breadboard:
The primary issue that I see is that your code doesn't match your wiring diagram.
For example, your diagram shows Trig connected to pin 4. The Trig should be the output from your Arduino but you have it defined as an input.
The Echo is connected to pin 2 and it should be an input, but you have it defined as an output.
Finally, in your loop(), you are not even using pin 2 or pin 4, but pins 9 and 8. Another issue is the timing you use in setting the trigger pulse - it does not match the datasheet. I would do something like this (assuming that you are actually connected to the pins shown in your diagram):
#define sensorTrigPin 4
#define sensorEchoPin 2
void setup()
{
Serial.begin(9600);
pinMode(sensorTrigPin, OUTPUT);
pinMode(sensorEchoPin, INPUT);
}
void loop()
{
int pulseWidth = 0;
digitalWrite(sensorTrigPin, HIGH);
delayMicroseconds(10);
digitalWrite(sensorTrigPin, LOW);
pulseWidth = pulseIn(sensorEchoPin, HIGH);
Serial.print("Pulse Width: ");
Serial.print(pulseWidth);
delay(1000);
}
Note that pulseWidth is just the amount of time that it takes from the beginning of the Echo pulse going high to the end of the same pulse (when it goes low). You would still have to calculate the distance based on the value of pulseWidth.
UPDATE BASED ON RECENT EDIT TO THE QUESTION
If you change a portion of your loop() code to this, it should work:
void loop(){
digitalWrite(4, HIGH); //was (2, LOW)
delayMicroseconds(10); //was (5)
digitalWrite(4, LOW); //was (2, HIGH)
//REMOVED EXTRA DELAY
time = pulseIn(2, HIGH); //was (4,HIGH);
... //Keep the rest of your code the same.
}
Try connecting your VCC of the sensor to 3V3 instead of 5V. This might sound odd, but I tried it and it worked well. Also, please make sure that your echo and trig pin match the code.
I would like to restart the arduino board but keeping values of some variable. My solution would be calling setup() whenever I would like to restart. Something like this:
int led = 13;
int led2 = 50;
boolean restart = false;
void setup() {
pinMode(led, OUTPUT);
pinMode(led2, OUTPUT);
if(!restart){
digitalWrite(led, LOW); // will only happen once
delay(3000);
}
digitalWrite(led, HIGH); // turn the LED on (and will be always on even after reset)
restart = true;
delay(3000);
digitalWrite(led2, HIGH); // indicate restart is called
delay(1000);
digitalWrite(led2, LOW);
setup();}
void loop() { }
I was thinking if this will cause any heavy usage in RAM. Or is there any better methods?
Thank you.
Use the EEPROM library. Have a button with an interrupt that saves the variable then read the variable in the setup() routine.
If you are getting or changing information slow enough you could constantly write the value but beware EEPROM on this chip is only certified to 100,000 writes per byte.