Arduino-project 003 - Toggling LED

This project shows the basics of how to get your Arduino to react to external events. In this case we use a push button to toggle a LED on and off. The circuit is similar to that for projekct 001, but we've added a push button.

The circuit

Just as in project 001 the LED has to be connected in the right direction, i.e. the long leg to the resistor and the shorter leg to ground (minus).

Arduino project 003 - toggling LED

At startup

We begin our program by setting the in- and outputs. The input is set to "INPUT_PULLUP" which means that the internal so called pull-up-resistor is activated for this input. This is simply a resistor of a few kiloohms connected between the input and plus (Vcc) guaranteeing that the input will always have a high value (logic one) if nothing else is connected. The inputs of Arduinons are very sensitive and if nothing is connected to them they will pick up interference from light fixtures, radio transmitters and other electrical devices leading to the input toggling between high and low on its own randomly. The pull-up-resistor prevents this by forcing the input to always be a one if nothing else is connected. In our circuit the input is connected to a push button, but when the button isn't pressed there is no voltage on the input and without the pull-up-resistor the input would, as mentioned, catch random interference. When the button actually is pushed it will pull the input to ground and become a logic zero. You might think that this would cause a short circuit as the input is already connected to plus, but since the connection to plus is through a rather large resistor very little current will actually flow through the resistor and the chip will not be damaged and there will be no short cicuit.

The main program

The rest of the program consists of Arduinos usual loop()-function that runs its code over and over again as fast as possible. The loop reads the state of the push button and if the button is pressed the input will become low. That the input becomes low may seem a bit weird but it is a consequence of the pull-up-resistor always forcing the input to plus (high) and the push button therefore has to be connected to ground. If the input is low the code checks if the variable led_state is 1 or 0. led_state is then changed to the opposite value and the output for the LED is set to either high or low. The last thing that happens is that the code waits 250ms before continuing. This short delay is required because the micro controller is incredibly fast and can run the code in loop() thousands of times per second and if the button is pressed the LED will toggle between on and off so quickly it is impossible to see. The delay also protects us from another phenomena that is a common trap for beginners: contact bounce. When a push button is pressed or a switch is toggled it doesn't happen cleanly but the contact elements will bounce against each other a little. To the human eye it happens so fast that we never notices it, but to a micro controller that can read the button many thousand times a second it will look as if you're pressing and releasing the button many times very fast. This can be solved using electronics, but if you're using a micro controller it's easier and cheaper to fix it using code instead. There are many ways to solve it and a delay as in our example is one of the simplest, but it works well for our application.

The code

// Reserve memory for storing variables in
int led_state = LOW;
int button_state;

void setup() {
  // Set pin 2 to be an output.
  pinMode(2, OUTPUT);
  // Set pin 3 to be an input with a pull-up resistor.
  pinMode(3, INPUT_PULLUP);
}


void loop() {
  // Read the state of the button.
  button_state = digitalRead(3);
  // If the button is pressed the input goes low.
  if (button_state == LOW) {
    // Toggle the LED
    if (led_state == LOW) {
      led_state = HIGH;
    }
    else {
      led_state = HIGH;
    }
    digitalWrite(2, led_state); 
    // Wait a bit to surpress contact bounce
    delay(250);
  }
}

Arduino-project 004 - Dimmer

In project 003 we saw how you read external digital events and values, i.e. whether something is active or not. In this project we will learn how to read analog values, meaning values that can be almost anything, not just one or zero. This can for example be the water level, light intensity or a distance.  To start off simple we make a dimmer that reads the position of a potentiometer and then sets the light intensity on a LEDto the corresponding value.

The circuit

The circuit we need is very similar to that of project 001, but it also has a potentiometer connected to one of the analog inputs. The value of the potentiometer is not very important in this case, as long as it is somewhere between 1KΩ and 100 KΩ.

Arduino-project 004 - Dimmer

Description

The code is quite simple - we read the voltage on the analog input A0 with the analogRead()function as an integer between 0 and 1023 and we use this value to set the intensity of the LED. Since the outputs of the Arduino uses values between 0 and 255 we use the map() function to scale the value. Unlike in project 003 we don't activate the pull-up-resistor on the input. The potentiometer is connected to both plus and ground which means that it's output and therefore also the input of the Arduinon will always have a stable voltage and it won't pick up interference. Also when reading analog values the pull-up resistor is disabled anyway. Note that it is only the dedicated analog inputs A0-A5 that can measure voltages, all other inputs are digital only.

The code

// Reserve memory for variables to store data in.
int value_in;
int value_out;

void setup() {
  // Set pin 2 to be an output.
  pinMode(2, OUTPUT);
  // Set pi A0 to be an input.
  pinMode(A0, INPUT);
}


void loop() {
  // Read the position of the potentiometer. This gives a value between 0 and 1023.
  value_in = analogRead(A0);
  // Scale the value so it's between 0 and 255.
  value_out = map(value_in, 0, 1023, 0, 255);
  // Set the intensity of the LED.
  analogWrite(2, value_out);
}

Arduino-project 007 - Multitasking

For simple projects it's no problem to do only one thing at a time and waiting until it is done before doing the next thing, but for more advanced projects you sometimes need to do several things at the same time, so called multitasking. You may for example want to read in data from a radio reciever, drive a stepper motor, flash a LED and show status text on a display, all at the same time. There are several ways to accomplish this, but the method we show here is very popular because it is relatively simple to understand and program and gives good results. The method is in fact inspired by how professional industrial systems work and is therefore very well tested. The basic idea is to make sure that all tasks that the Arduino board should perform are kept small and as fast as possible to execute and that you never actively wait for anything. It is therefore vital to never use the delay()-function in your code as this will completely block any other task from being run. Instead you let the processor continuously compare timer values and perform the different tasks whenever the appropriate amount of time has passed.

How is it done?

Simply put, you have a series of if-statements that compares time values and let the processor run through them over and over again as fast as possible. When a timer value exceeds a preset threshold the associated function is called and executed and then the control is returned to the main program with the If-statements. The threshold is then set to the next point in time when the function should be run and the main program continues its loop.

The circuit

In our example we want three LEDs to blink at different speeds. This may at first seem simple, but if we want them to blink independently of each other we need to use some sort of multitasking. Start by building the circuit in the diagram below. Then enter the code from below into Arduinos development environment and upload it to the Arduino board.

Arduino-project 007 – Multitasking

Description of the code

In the code we set up three separate functions, blink_1()blink_2() and blink_3() that we will run in parallel. You can of course use this code as basis for other projects and switch the functions for your own or add more. We also set up a number of variables to keep track of how often each function should run and to keep track of the state of each LED (on or off). The main program resides in loop() as usual and this code will run as fast as possible, thousands of times per second. The loop begins with getting the current time with the millis()function. This function returns the number of milliseconds that have elapsed since the Arduino board was powered on, or since the last reset. After this follows three separate if-statements where we compare the current time with the different timer values for the blink functions. The first time all these values will be 0 meaning that all three if-statements will be true and the three blink-functions will be run. When each blink function has finished running we set the timer values to be current time plus the number milliseconds we want to wait until we run it the next time.

The next time the loop runs current_time will have increased slightly, exactly how much depends on how long it took to run the three blink-functions, but not so much that current_time is greater than any of the timer variables. Therefore all if-statements will be false and won't run their associated function. This will now repeat over and over again until current_time has increased so much that it is greater than one of the timer values and the associated function is run and its timer value is again increased. Most of the time the processor will do nothing but running around the main loop and comparing timer values, but occasionally one of the blink functions will run. It's important to remember that even though this method makes it seem as if the processor do multiple things at the same time it will never do more than once thing at a time. It's just so very fast that it seems to use it's doing them concurrently. This is what makes it so important that all functions are fast and to never use delay() as this will bind up the processor and prevent the other functions from running.

The code

// Settings for which pins the LEDs are connected to.
const int led_pin_1 = 2;
const int led_pin_2 = 3;
const int led_pin_3 = 4;

// Blinking speed for the LEDs in milliseconds.
const int blink_time_1 = 500;
const int blink_time_2 = 400;
const int blink_time_3 = 150;

// State variables for the LEDs.
// These keeps track of whether the LEDs are on or off.
int led_1 = LOW;
int led_2 = LOW;
int led_3 = LOW;

// Timer-variables for the LEDs.
// These keep track of when it's time to change the state of each LED.
double led_timer_1;
double led_timer_2;
double led_timer_3;

// Function for turning LED 1 on or off.
void blink_1() {
  if (led_1 == LOW) {
    led_1 = HIGH;
  }
  else {
    led_1 = LOW;
  }
  digitalWrite(led_pin_1, led_1);
}

// Function for turning LED 2 on or off. 
void blink_2() {
  if (led_2 == LOW) {
    led_2 = HIGH;
  }
  else {
    led_2 = LOW;
  }
  digitalWrite(led_pin_2, led_2);
}

// Function for turning LED 3 on or off. 
void blink_3() {
  if (led_3 == LOW) {
    led_3 = HIGH;
  }
  else {
    led_3 = LOW;
  }
  digitalWrite(led_pin_3, led_3);
}

// Setup makes sure the pins that the LEDs are connected to are set as outputs.
void setup() {
  pinMode(led_pin_1, OUTPUT);
  pinMode(led_pin_2, OUTPUT);
  pinMode(led_pin_3, OUTPUT);
}

// Loop will be run through over and over again as fast as possible.
// If a function takes too long to finish it will prevent the other functions from
// running when they should.
void loop() {
  // Get the current time. This value is the number of milliseconds since
  // the Arduino board was powered on or since the last reset.
  double current_time = millis();
  // Check if it's time to change state of LED 1.
  if (current_time > led_timer_1) {
    blink_1();
    // Update the timer value for the next event
    led_timer_1 = current_time + blink_time_1;
  }
  // Check if it's time to change state of LED 2. 
  if (current_time > led_timer_2) {
    blink_2();
    // Update the timer value for the next event 
    led_timer_2 = current_time + blink_time_2;
  }
  // Check if it's time to change state of LED 3. 
  if (current_time > led_timer_3) {
    blink_3();
    // Update the timer value for the next event 
    led_timer_3 = current_time + blink_time_3;
  }
}

Arduino-project 008 - Control motors with the motor shield

A robot needs to be able to move and for that you need motors. But motors require alot of current so you can't connect them directly to a Arduino board. Therefore you need some sort of motor driver. One of the easiest to use is the Arduino Motor Shield R3. As this is a so called  shield it can be mounted directly on top of (or under) a standard Arduino board and you don't need to connect a lot of wires on a bread board. The chip on this card is a L298P which can drive two DC motors of up to 2A each which is enough for most smaller robots. To control the the motors with this card you use three signals per motor called PWM, DIR and BREAK. PWM is used for setting the speed of the motor, DIR controls the direction and BREAK short circuits the motor (safely) which acts as a breaking mechanism. As the name implies the speed is controlled with the pulse-width modulation, i.e. you use the analogWrite() function.

The circuit

Mount the motor shield on top of the Arduino board and connect the motors and batteries (or other power source) for the motors according to the diagram below. The batteries must have the same total voltage that the motors are made for (but no more than 12 V). The Arduino board can take power directly from the batteries, but for safer operation it is better to power the Arduino separately. Otherwise there is the risk of the voltage dropping when the motors draw a lot of current causing the Arduino to reboot. This circuit and the code below assumes that the robot is using so called tank drive where the wheels on each side of the robot are driven separately and the robot turns by changing the speed/direction of the motors. This is by far the most common way for controlling smaller robots and this project is suitable for most of our robot chasis. For robots that have four motors (two on each side) you connect both motors on each side together to the same outputs on the motor shield.

Arduino-project 008 – Controling motors

Description of the code

The code is simple and doesn't really do anything useful, but works well for testing the circuit and forms a good ground for programming your own robots. First we define which connections on the Arduino board are used to what. These are of course determined by the motor sield and you shouldn't change them, but we add them as constants so that in the rest of the code we can use the names instead of having to type numbers. It's much easier to remember dir_a thn tht the function is on pin 12. The motor shield has a few additional connections, but these are not necessary for basic usage.

After this we create a couple of functions for setting the speed of the motors and to run them forward, backward and for turning and stopping. The stop function is strictly not required as the only thing it does is setting the speed to 0, but it does make the rest of the code easier to read and understand.

In setup()we specify which connections on the Arduino that should be outputs, i.e. th four control signals that the motor shield uses. In loop()we find the main algorithm. This is very simple and uses the functions we created earlier for driving and turning in a simple sequence. This is of course just a basic example to make sure everything is working. You will replace this code with something more exciting, e.g. letting the robot accept commands via a bluetooth module, or you could connect an ultra-sonic range sensor so that the robot can drive around and avoid obstacles on its own.

If the robot runs the wrong way

If the robot doesn't move quite the way you expect it to do there are several possible reasons. The direction a DC motor rotates depends on which way the current through it flows. So if a motor rotates the wrong way it is enough to switch around the two wires to it. I.e. if the robot rotates left when it should go forward then switch the wires on the left motor; and vice verse, switch the wires to the right motor if it rotates right. If the robot moves backwards when it should go forward you switch the wires for both motors. Each motor should still be connected to the same pair of contacts, i.e. one should use A+ and A1 and the other B+ and B-.

If the robot moves forward and backward as it should, but turns left when it should turn right and vice versa it means that the motors are on the wrong side of the robot. You would think that it would be enough to switch places of the motors, but if you do that the robot will go backwards when it should go forward. Instead you switch the wires to the motors around so that the motor connected to A+ and A- is instead connected to B+ and B- (without changing places of + and -), and the motor connected to B+ ans B- is moved to A+ and B- (again keeping track of + and -).

If your robot has four motors, two on each side, and one motor on one side rotates the wrong way you switch around the wires to that motor. You of course also hav to make sure that both motors on one side are connected to the same connectors, e.g. both left motors connected to A+ and A- and both right motors connected to B+ and B-.

The code

// Settings for motor signals. Determined by the motor shield so don't change!
const int dir_a = 12;
const int dir_b = 13;
const int pwm_a = 3;
const int pwm_b = 11;

// Function for setting the speed for both motors.
void speed(int v) {
  analogWrite(pwm_a, v);
  analogWrite(pwm_b, v);
}

// Function for driving forward.
void drive() {
  digitalWrite(dir_a, HIGH);
  digitalWrite(dir_b, HIGH);
}

// Function for backing up
void back_up() {
  digitalWrite(dir_a, LOW);
  digitalWrite(dir_b, LOW);
}

// Function for turning left.
void turn_left() {
  digitalWrite(dir_a, LOW);
  digitalWrite(dir_b, HIGH);
}

// Function for turning right 
void turn_right() {
  digitalWrite(dir_a, HIGH);
  digitalWrite(dir_b, LOW);
}

// Function for stopping
void stop() {
  speed(0);
}

// In setup we tell the controller which connections should be outputs.
void setup() {
  // Set all control pins to outputs.
  pinMode(dir_a, OUTPUT);
  pinMode(dir_b, OUTPUT);
  pinMode(pwm_a, OUTPUT);
  pinMode(pwm_b, OUTPUT);
}

// Loop runs a simple sequence where the robot drives forward, backwards and turns.
// This is where you put your own code to make the robot do more interesting things.
void loop(){
  // Drive forward for 5 seconds at full speed.
  speed(255);
  drive();
  delay(5000);
  // Back up for 2 seconds at a slower speed.
  speed(180);
  back_up();
  delay(2000);
  // Rotate left for 5 seconds.
  speed(255);
  turn_left();
  delay(5000);
  // Stop and wait for 4 seconds.
  stop();
  delay(4000);
}

Arduino-project 006 - Display text on a LCD

Sometimes you want to give more information to the user of your devices than what can be conveyed with a couple of LEDs. For that an alphanumeric LCD is a very convenient solution. These displayes can show text and very simple graphics. There are many different sizes and colors but the most common ones have 2 lines with 16 characters , or 4 lines 20 characters and are blue/white or green/black. Some also have built-in background light making it possible to read the display when it's dark. These displays usually have a large number of connectors for controlling them, but there exists very cheap modules with a PCF8574-chip that can be soldered to the back of the display giving you a I²C-interface instead so that the while display can be controlled using only to wires.

Code library

In this example we use a display with 16x2 characters and background light with a I²C-module, but the code is easily adaptable for other displays. The only requirement is that the display uses a control chip that us compatible with the very popular Hitachi HD44780-chip. The code library we use is not included in the default Arduino environment, but it's very easy to install using only a few mouse cliks. Start the Arduino development environment program and go to the menu Sketch > Include library > Manage Libraries... This opens the library manager and here you can search for the library "LiquidCrystal_PCF8574". Once you've found it you click on it and click the install button. Once the library has been downloaded an installed you can close the library manager. You only need to do this once, and the library will then always be available on this computer.

The circuit

Connect the display to the Arduino board as below:

Arduino-project 006 - Display text on a LCD

Description of the code

The code doesn't contain any real surprises. First we include the code libraryfor controlling the display and create an object for the display that keeps track of settings and provides all functions needed, such as write text, erase text and activating the backlight. In setup() we start the display and make all preparations, such as clearing the display, turning on the backlight and write a first line of text. The main program consists of a for-loop that defines a variabel i that is set to 10. It then executes its code and decreases i with 1 (i--) and if i is still greater than zero the cde is executed once more. This means that the code inside the for-loopen will run 11 times and count from 10 to 0. Each time around the for-loopen we erase the second line on the display and print out the value of the counter, i.e. the i variable and then wait for one second. When the for-loopen is done we clear the display completely and print out a new message. The last thing happening is that we enter a while-loop with a constant true value and without any code. This is something of a special construction which makes the micro controller hang and prevents it from doing anything else until you reset it using the reset button or disconnect the power.

The code

// Include the library for controlling ASCII-displays via I2C
#include <LiquidCrystal_PCF8574.h>

// Create object for controlling the display.
// Use I2C-address 0x27 (standard)
LiquidCrystal_PCF8574 display(0x27);

void setup() {
  // Start the display and specify the size - 16 characters in 2 lines.
  display.begin(16, 2);
  // Clear all old text (if any).
  display.clear();
  // Place the cursor in the upper left corner.
  display.home();
  // Turn on the backlight of the display and set it to max brightness.
  display.setBacklight(255);
  // Print text on the first line
  display.print("Countdown...");
}

void loop() {
  for (int i = 10; i > 0; i--) {
    // Move the cursor to the beginning of the second line (character 0, line 1)
    display.setCursor(0, 1);
    // Clear the line by writing 16 spaces.
    display.print("                ");
    // Move the cursor back to the beginning of the line.
    display.setCursor(0, 1);
    // Print the counter value
    display.print(i);
    // Wait one second
    delay(1000);
  }
  // Clear the display
  display.clear();
  // Set the cursor a small way into the first line (character 4, line 0)
  display.setCursor(4, 0);
  // Print out the final text.
  display.print("KA-BOOM!");
  // Halt the program
  while (1);
}

Arduino-projekt 005 - Controlling a servo motor

Controlling the position of a servo is very similar to controlling the intensity of a LED.The circuit is therefore very similar to the one used in project 004. Just like in that project the total resistance of the potentiometer is not important as long as it is somewhere between 1 KΩ and 100 KΩ.

The circuit

For this project you need to build the following circuit.

Arduino-project 005 - Servo

Description

A servo expects a pulse-width-modulated (PWM) signal just like the one we used to contorl the LED in project 002 och 004, but the servo has a little higher requirements and to solve this there are ready-made code available so we don't have to do this ourselves every time we want to control a servo. The first thing we do in our code is to include this ready-made code and then create an object representing the servo. An object in programming context is basically a variable that has different functions connected to it for doing various operations on the data that the variable contains. In this example we use the function attach() to tell the object which output the servot is connected to and write() to set the position of the servo. The position is given as an angle between 0 and 180 degrees. This means that we need to scale the value read from the potentiometer, just like in project 004.

Koden

// Include the code library for controlling servos.
#include <Servo.h>

// Create a servo-object for controlling the servo motor.
Servo my_servo;

// Reserve memory for variables to store data in.
int value_in;
int angle;

void setup() {
  // Tell the servo object which output the servo is connected to.
  my_servo.attach(2);
  // Set pin A0 to be an input.
  pinMode(A0, INPUT);
}

void loop() {
  // Read the position of the potentiometer. This gives a value between 0 and 1023.
  value_in = analogRead(A0);
  // Scale the value so that it lies between 0 and 180.
  angle = map(value_in, 0, 1023, 0, 180);
  // Set the position of the servo.
  my_servo.write(angle);
  // Wait a bit for the servo to move to the corrected position.
  delay(15);
}

Arduino-project 002 - Pulsating LED

A blinking LED is perhaps not the most exciting thing in the world, but if you can get it to pulsate instead it would be a little more interesting. Build the circuit from project 001, but use the code below instead. Here we use a for-loop to gradually increase the intensity of the LED and when we've reached the maximum we use a new loop to lower the intensity again.

Analogue values in a digital world.

Earlier we used digitalWrite() to activate the LED, but with that function we can only set anoutput to either 0 volts or the full voltage of the power supply, i.e. 5 volts. In order to set the light intensity instead we use analogWrite() which makes it possible to set an output to what appears to be any voltage between 0 and 5 volts in 256 steps. It is however important to note that the an Arduino board really can't give out anything other than digital signals, i.e. 0 or 5 volts, but by switching very fast between 0 and 5 volts it looks as if the voltage is somewhere in between. This is called PWM - Pulse Width Modulation. For this project with our LEDit doesn't matter that the output pulses because the switching is too fast for our eyes to see and the same is true if we want to control a motor - the pulses are too fast for the motor to vibrate and it will instead just run at a speed proportional to the pulses. There are however times when this won't work so it is important to verify that whatever you connect to your Arduino board can actually handle PWM-signals or if it requires a genuine analogue signal. To create proper analogue signals a special circuit or module is required which logically is called a Digital to Analog Converter or DAC for short.

The code

void setup() {
  // Set pin 2 to be an output.
  pinMode(2, OUTPUT);
}

void loop() {
  // Increase the intensity of the LED from completely off to fully lit.
  for (int i = 0; i < 255; i++) {
    // Set the intensity of the LED.
    analogWrite(2, i);
    // Wait 10ms.
    delay(10);
  }
  // Decrease the intensity of the LED from fully lit to completely off.
  for (int i = 255; i > 0; i--) {
    // Set the intensity of the LED.
    analogWrite(2, i);
    // Wait 10ms.
    delay(10);
  } 
}

 

Arduino-project 001 - Blinking LED

The circuit

A very good project to start with if you're new to Arduino is to get a LED to blink. The first you need to do is connect it physically to the Arduino board. Do this according to the schematics below. Please note that the LED only works in one direction. The long leg connects to plus (the resistor) and the short leg connects to minus (GND). A LED may never be connected directly yo a battery or other power source without a suitable resistor or other protection. In this instance we're using a resistor of 220 ohm (red-red-black-black) which is a good compromise for most LEDs connected to 5 volts. White and blue LEDs may need a smaller resistor, say 100 ohm, in order to shine at full power, but will work with 220 ohm.

Arduino exempel 001 - blinkande lysdiod

Arduino example 001 - blinking LED

Description

Copy the code below to the Arduino development environment, compile and upload to the Arduino board. When the board is powered the processor will first run setup(). The only thing setup() does is telling the processor that we want connection 2 to be an output. All digital connections on the Arduino board are set to be inputs at startup.

After this the loop()function takes over. This function will be called over and over again infinitely until the power to the board is removed or you push the reset-button. In loop() we first turn on the LED by setting connection 2 to high (5 Volts). Then we wait for half a second (500 ms). Then we turn the LED off by writing a zero on connection 2 and then we wait half a second again. After this the program ends, but as previously noted the loop() function will automatically be called again meaning that the program starts all over again, and so the LED will flash once per second.

The code

void setup() {
  // Set pin 2 to be an output.
  pinMode(2, OUTPUT);
}

void loop() {
  // Turn the LED on.
  digitalWrite(2, HIGH);
  // Wait half a second (500ms).
  delay(500);
  // Turn the LED off.
  digitalWrite(2, LOW);
  // Wait another half a second before the program restarts.
  delay(500);
}

Arduino-projekt 008 - Styr motorer med motor shield

En robot behöver kunna röra sig och för det behöver man motorer. Men motorer kräver mycket ström och det går inte att koppla in dem direkt till ett Arduino-kort. Därför behöver man en motor-drivare av något slag. Den enklaste att använda är Arduino Motor Shield R3. Efterom detta är en s.k. sköld (shield) så passar den att monteras direkt på (eller under) ett standard Arduino-kort. Man behöver därför inte koppla massa sladdar på en kopplingsplatta. Kretsen på det här kortet heter L298P och kan driva två likströmsmotorer på 2A stycket vilket är gott och väl tillräckligt för mindre robotar. För att styra varje motor med det här kortet använder man sig av tre signaler kallad PWM, DIR och BREAK. PWM använder man för att sätta hastigheten på motorn, DIR för att välja riktining och BREAK kortsluter motorn (på säkert sätt) vilket fungerar som en broms. Som namnet antyder så styr man hastigheten på PWM-anslutningen med pulsbreddsmodulering (PWM), dvs du använder funktionen analogWrite().

Kopplingen

Montera motor-skölden ovanpå Arduino-kortet och koppla in motorer och batterier (eller annan strömförsörjning) för motorerna enligt bild nedan. Batterierna behöver ha samma totala spänning som motorerna är gjorda för (men max 12V). Arduinon kan ta ström direkt från batterierna, men för säkrare drift är det bäst att ge ström till Arduinon separat. Annars finns det risk att när motorerna drar mycket ström så sjunker spänningen så pass mycket att Arduino-kortet startar om. Den här uppkopplingen och koden nedan förväntar sig att roboten använder s.k. tank-styrning där hjulen på var sida drivs av var sin motor och roboten svänger genom att ändra hastighet/riktning på motorn (motorerna) på ena sidan. Detta är det absolut vanligaste sättet att driva och styra mindre robotar och det här projektet lämpar sig mycket väl för de flesta av våra robotchassin. För robotar som har fyra motorer (två på var sida) kopplar man in båda motorerna på var sidan till samma utgångar på motor-skölden.

Arduino-projekt 008 – Styr motorer

Beskrivning av koden

Koden är enkel och gör inte något direkt användbart, men fungerar bra för att testa kopplingen och bildar en bra grund för dina egna robotar. Först definierar vi vilka anslutningar på Arduino-kortet som används till vad. Dessa bestäms så klart av själva motor-skölden och du ska inte ändra dem, men vi lägger in dem som konstanter så att vi i resten av koden inte behöver ange siffrorna utan istället kan skriva namnen. Det är mycket lättare att komma ihåg dir_a än att den funktionen ligger på pinne 12. Motor-skölden har ytterligare några anslutningar, men dessa är inte nödvändiga att använda. Därefter skapar vi ett antal funktioner för att sätta hastighet på motorerna och för att köra fram, bak, svänga och att stanna. Stanna-funktionen är egentligen inte nödvändig eftersom det enda den gör är att sätta hastigheten till 0, men den gör resten av koden lite mer lättläst.

I setup() ställer vi bara in vilka anslutningar på Arduino som ska vara utgångar, dvs de fyra kontrollsignaler som motor-skölden använder. I loop() ligger själva huvud-algoritmen. Denna är mycket enkel och använder de funktioner vi skapade för att köra framåt och bakåt och svänga runt i en enkel sekvens. Detta är bara till som exempel och för att se att allt fungerar som det sak. Denna kod ersätter du sedan lämpligen med din egna mer spännande kod. T.ex. kan du låta roboten ta emot kommandon från en bluetooth-modul, eller så kan du koppla in en ultraljudssensor så att roboten kan köra runt själv och undvika hinder.

Om roboten går fel

Om roboten skulle visa sig inte röra sig som du tänkt dig så finns det många möjliga orsaker. Vilket håll som en likströmsmotor snurrar på beror på vilket håll som strömmen genom den går. Så om en motor snurrar åt fel håll räcker det med att byta plats på de två sladdarna till den. Så om roboten svänger åt vänster när den ska gå framåt så byt pats på sladdarna till den vänstra motorn; och omvänt om den svänger åt höger. Om roboten går bakåt när den ska gå framåt byter du plats på sladdarna på båda motorerna, men håll reda på så att du inte växlar runt sladdarna mellan motorerna. Den ena motorn ska fortfarande använda anslutningarna A+ och A- och den andra ska använda B+ och B-. Om roboten går framåt och bakåt korrekt, men svänger höger när den egentligen ska svänga vänster och vice versa så betyder det att motorena sitter på fel sida. Man skulle kunna tro att det då räcker att byta plats på motorerna, men om du gör det kommer roboten att gå bakåt när den ska gå framåt. Istället behöver du byta plats på sladdarna så att motorn som är kopplad till utgångarna A+ och A- kopplas till utgångarna B+ och B- (utan att byta plats på + och -) och att motorn kopplad till B+ och B- kopplas in på A+ och A- (återigen så att + och - bibehålls). Om din robot har fyra motorer, dvs två på var sida, och ena motorn på en sida snurrar åt fel håll byter du runt sladdarna på bara den motorn. Se också till att båda motorerna på en sida är kopplade till samma utgångar, t.ex. motorerna på vänster sida till A+ och A- och motorerna på höger till B+ och B-.

Koden

// Inställningar för motorsignaler. Förutbestämda av motor-skölden så ändra ej!
const int dir_a = 12;
const int dir_b = 13;
const int pwm_a = 3;
const int pwm_b = 11;

// Funktion för att sätta hastigheten på båda motorerna
void hastighet(int v) {
  analogWrite(pwm_a, v);
  analogWrite(pwm_b, v);
}

// Funktion för att köra framåt
void kor() {
  digitalWrite(dir_a, HIGH);
  digitalWrite(dir_b, HIGH);
}

// Funktion för att backa
void backa() {
  digitalWrite(dir_a, LOW);
  digitalWrite(dir_b, LOW);
}

// Funktion för att svänga åt vänster
void svang_vanster() {
  digitalWrite(dir_a, LOW);
  digitalWrite(dir_b, HIGH);
}

// Funktion för att svänga åt höger 
void svang_hoger() {
  digitalWrite(dir_a, HIGH);
  digitalWrite(dir_b, LOW);
}

// Funktion för att stanna
void stanna() {
  hastighet(0);
}

// I setup ställer vi in vilka anslutningar som är utgångar
void setup() {
  // Sätt alla kontrollpinnar till utgångar
  pinMode(dir_a, OUTPUT);
  pinMode(dir_b, OUTPUT);
  pinMode(pwm_a, OUTPUT);
  pinMode(pwm_b, OUTPUT);
}

// Loop kör en enkel sekvens där roboten kör fram, bak och svänger efter ett enkelt mönster.
// Här lägger du in din egen kod för att få roboten att göra mer intressanta saker.
void loop(){
  // Kör framåt i full fart i 5 sekunder
  hastighet(255);
  kor();
  delay(5000);
  // Backa i lägre hastighet i 2 sekunder
  hastighet(180);
  backa();
  delay(2000);
  // Snurra runt åt vänster i 5 sekunder
  hastighet(255);
  svang_vanster();
  delay(5000);
  // Stanna och stå still i 4 sekunder
  stanna();
  delay(4000);
}

More power with Arduino Due

Do you have a project that needs a little extra computing power? Then we have the solution: Arduino Due.This board is programmed like all other Arduino boards, but at its heart lies a 32-bit ARM Coretx-3 processor running at 84MHz which gives far more power than an ordinary 8-bit Arduino board. And to top it all off we currently give you 100SEK rebate on it!

Kundvagn