Skip to content

9. Output Devices

For this week we had to:

  • Group assignment:

    • Measure the power consumption of an output device.
    • Document your work on the group work page and reflect on your individual page what you learned.
  • Individual assignment:

    • Add an output device to a microcontroller board you’ve designed and program it to do something.

Group assignment

Link to group assignment page.

As part of group work, together with our instructor Babken Chugaszyan, we worked with two devices

  • Multimeter

  • Power supply

Multimeter

When working with a multimeter, there are two options for connecting wires. Since when calculating the current strength, you need to connect the device in series, then the red cable must be inserted into the appropriate place

Multimeter Serial connection

In other connection cases, the Multimeter is switched on in parallel

Multimeter Parallel connection

Power supply

Power supply is a great device to measure the power consumption of a device. Our power supply has 2 channels of DC power supply. Basically we use one channel.

LED Strip Light

In our laboratory, we have an LED strip designed to work with a constant voltage of 12 Volts. On channel 1, we set the values ​​to 12 Volts and 0.5 Amps and turned on the device, but there was not enough current. Then we added the Amps values and at the end we found the maximum value, which is 1.44 Amps.

Fan

Characteristics: 24 Volts and 0.4 Amps. I learned from this experiment that the motor uses the most energy during the start. And when it is in its learning state of operation, the power consumption is stabilized.

DC Motor

During the experiment with the DC Motor, I noted the following for myself, that it is not enough to turn on the motor and see the amount of electricity consumed, since it works with minimal overload. In order to find out the maximum value of the current, you need to somehow stop the motor. In our case, we stopped the motor with a screwdriver. If, in the event that the motor is simply spinning, the current strength is 0.35 Amps, then in the most loaded state it is 1.46 Amps.

Individual assignment

Bootloader Installation

At this stage, my board is unrecognizable to the computer. To make it recognizable for the computer, you need to load the bootloader into it. A bootloader is a program that is executed when a device is turned on or restarted and is responsible for loading the main program into the device’s memory.

For me, working in the Arduino IDE is comfortable. For this reason, I want to install and download the arduino bootloader which will allow the IDE and Arduino compiler to send programs to the board for execution. Here there is a good guide that explains how everything works.

First of all, I will download and install the EDGB software, with which I can program my microcontroller using the tool CMSIS-DAP (debug interface for microcontrollers).

Since my board uses an ATSAMD11D14A-SS microcontroller, I need to download ATSAMD11D bootloader binary.

ATSAMD11D bootloader binary

Now you need to move the downloaded file to the folder with edbg.exe.

Next, you need to connect the board to the computer via a USB port for power and connect the board’s SWCLK, SWDIO, RESET, and GND pins to the corresponding pins on the programmer.

Bootloader

Then in this folder open the terminal GIT BUSH.

And write the following command:

./edbg.exe -b -t samd11 -pv -f sam_ba_SAMD11D14AS.bin

If the download is successful, the board will already be visible to computers.

Git Bush upload

Setting up the Arduino IDE

The second step is to get the Arduino IDE to work with SAMD microcontrollers. There is a detailed instruction about this .

Generic

There is a good guide for pinouts

Pinout

Everything goes well, but when I connect it to the computer via USB, write a program and try to upload it to the microcontroller, I notice that the device is not detected by the computer. And here Babken Chugaszyan comes to my rescue. We opened the documentation of the microcontroller and found that I had mixed up the D+ and D- pins. There are 2 ways to solve this issue:

  1. Redraw and print the board
  2. Directly on the board, make a cut of these two tracks and make connections crosswise using a wire.

I chose the second option, and as a result my board got the following look

Board type

When I turn on the board to the computer via the USB port, two LEDs light up.

Connecting an external LED to the board

Now that all the technical questions are resolved, I want to make my board do something. I want to connect an external LED to my board and make it blink.

LED selection

First and foremost, it is important to select an LED and review its documentation. In this case, I would like to connect a blue LED that is available in our lab. By referring to the LED datasheet, we can observe that the specifications vary for different LED colors.

For the blue LED, the minimum forward voltage required for it to illuminate is 2.8V. The maximum forward voltage for continuous operation is 3.8V, while the recommended forward voltage is 3.2V. The forward current for this LED is specified as 20mA.

Fortunately, we have a power supply available in our lab. Let’s connect the LED to it and provide these voltage and current values to verify its operation.

LED test

The test initially demonstrated that the LED corresponds to the mentioned Datasheet. It starts to illuminate from a voltage value of 2.4V. At 2.8V, the LED lights up, although not as brightly as at 3.2V, but still performs its function. When comparing the LED’s illumination at 3.8V and 3.2V, there is no significant difference in brightness noticeable in the photographs. However, if the LED consumes a current significantly exceeding its recommended values, it can lead to overheating, reduced brightness, shortened lifespan, or even failure.

To limit the current flow, it is necessary to connect a current-limiting resistor in series. Since the current-limiting resistor is connected in series, according to the law of series connection in circuits, the total voltage in the circuit is equal to the sum of the voltages across individual elements. The voltage drop across the current-limiting resistor can be calculated using the following formula:

U = 3.3V - 3.2V = 0.1V.
In the LED Datasheet, the recommended forward current is specified as 20 mA. Since the current is the same at any point in a series circuit, the current passing through the resistor will also be the same: 20 mA.

I = 20 mA = 0.02 A.
Ohm’s law:

U = RI

Where U is voltage, R is resistance, I is current.

Let’s use Ohm’s law and calculate the resistance of the required current-limiting resistor:

R = U / I = 0.1 / 0.02 = 5 Ohm

However, the closest resistor in our laboratory to the value of 5 Ohms is a resistor of 68 Ohms, and the next one is 390 Ohms.

Let’s conduct an experiment using the Power supply with output values of 3.3V and 0.02A:

One LED will be connected directly to the power supply without a resistor, the second one with a 68 Ohm resistor, and the third one with a 390 Ohm resistor. Let’s observe the brightness of the LEDs:

LED test

In this case, the best solution in terms of utilizing the LED’s potential would be to choose the current-limiting resistor of 68 Ohms. However, since this is an experimental setup and the LED will be near my eyes, I will use the LED that is connected in series with a 390 Ohm resistor.

LED test

Writing and uploading code

In order for the LED to start blinking, it is enough to use the example code that is present in the Arduino IDE. I will use the example File -> Examples -> 01.Basics -> Blink. The only thing I need to do is change the pin number.

// the setup function runs once when you press reset or power the board
void setup() {
  // initialize digital pin LED_BUILTIN as an output.
  pinMode(2, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  digitalWrite(2, HIGH);  // turn the LED on (HIGH is the voltage level)
  delay(1000);                      // wait for a second
  digitalWrite(2, LOW);   // turn the LED off by making the voltage LOW
  delay(1000);                      // wait for a second
}

The result will be the following

Until I write another logic for blinking the LED. If you wish, you can use codes written in Embedded programming week for the Arduino UNO board.

Servomotor connection

The time has come to work with the servomotor. I decided to use the HobbyKing servo HK15138 as the servo to test. I did not find a separate documentation for it, but I found a description.

LED test

At this point, I’m interested in the voltage with which the servo works. It is within 4.8v~6V. My board has the ability to output 5V.

The second thing that interests me is the current strength at which the motor will work. Since the computer has the ability to supply 5V current at 500mA, and the required current strength when operating without load is 60mA, it will suit me to check the performance of the servo motor.

Connecting the servomotor to the board

Now you need to make connections.

The servomotor has three wires: power (red), ground (brown) and signal (yellow).

My board has an output that outputs 5V and a pin that is connected to GND, I need to connect the red wire of the servo to the output on the board 5V and the black wire to GND. And connect the signal wire to PIN 2, which can send a signal to the servomotor.

Code for servo operation

First of all, I tried to download ready-made Example for a robot with a servo motor, which is present in the Arduino IDE. The example is called Sweep and it uses the Servo.h library*

/* Sweep
 by BARRAGAN <http://barraganstudio.com>
 This example code is in the public domain.

 modified 8 Nov 2013
 by Scott Fitzgerald
 https://www.arduino.cc/en/Tutorial/LibraryExamples/Sweep
*/

#include <Servo.h>

Servo myservo;  // create servo object to control a servo
// twelve servo objects can be created on most boards

int pos = 0;    // variable to store the servo position

void setup() {
  myservo.attach(9);  // attaches the servo on pin 9 to the servo object
}

void loop() {
  for (pos = 0; pos <= 180; pos += 1) { // goes from 0 degrees to 180 degrees
    // in steps of 1 degree
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
  for (pos = 180; pos >= 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos);              // tell servo to go to position in variable 'pos'
    delay(15);                       // waits 15 ms for the servo to reach the position
  }
}

But unfortunately, when trying to upload the code to the board, an error is generated. I did not fully understand the error, in my opinion this is due to the use of the Servo.h library.

Trying to find a solution, I turned to the GPT chat so that it would give me the code that controls the servo motor without using libraries. And it produced the following code:

const int servoPin = 9; // set the pin number for the servo
int angle = 0; // variable for rotation angle

void setup() {
   pinMode(servoPin, OUTPUT); // set servo pin as output
}

void loop() {
   for(angle = 0; angle < 180; angle += 1){ // rotate the servo from 0 to 180 degrees
     digitalWrite(servoPin, HIGH); // send a high signal to the servo pin
     delayMicroseconds(500 + (angle * 11)); // set the delay corresponding to the angle of rotation
     digitalWrite(servoPin, LOW); // send low signal to servo pin
     delay(20); // delay to stabilize the servo
   }
   for(angle = 180; angle > 0; angle -= 1){ // rotate the servo from 180 to 0 degrees
     digitalWrite(servoPin, HIGH);
     delayMicroseconds(500 + (angle * 11));
     digitalWrite(servoPin, LOW);
     delay(20);
   }
}
I changed the pin number to 2 (I connect the motor to pin number 2). This code was successfully uploaded to my board.

The result of the code can be seen in this video:

The servomotor rotates from 0 to 180 degrees and then back.

Let’s take a look at what this code does step by step.

  1. The number of the pin to which the servo is connected is determined, and a variable for storing the angle of rotation.
const int servoPin = 9; // set the pin number for the servo
int angle = 0; // variable for rotation angle
  1. In the setup() function, the pin for the servo is set as the output.
void setup() {
   pinMode(servoPin, OUTPUT); // set servo pin as output
}
  1. The loop() function runs two loops in which the servo rotates from 0 to 180 degrees and 180 to 0 degrees, respectively.
void loop() {
   for(angle = 0; angle < 180; angle += 1){ // rotate the servo from 0 to 180 degrees
     ...
   }
   for(angle = 180; angle > 0; angle -= 1){ // rotate the servo from 180 to 0 degrees
     ...
   }
}
  1. Within each cycle, the following happens:

  2. A high signal is sent to the servo pin.

digitalWrite(servoPin, HIGH); // send a high signal to the servo pin
  • Sets the delay corresponding to the angle of rotation.
delayMicroseconds(500 + (angle * 11)); // set the delay corresponding to the angle of rotation
  • A low signal is sent to the servo pin.
digitalWrite(servoPin, LOW); // send low signal to servo pin
  • A delay is set for the servo to stabilize.
delay(20); // delay to stabilize the servo

A delay of 20 milliseconds between two cycles is needed to stabilize the servo.

In my opinion the key part is the delayMicroseconds() function. To control the servomotor, signals in the range from 500 to 2500 microseconds are used. When a signal is applied with a duration of 500 microseconds, the motor rotates 0 degrees, and with a duration of 2500 microseconds, it rotates 180 degrees. With a signal duration of 1500 microseconds, the motor stops in the middle. At other values between 500 and 2500 microseconds, the motor rotates by the appropriate angle.

I want to emphasize one more point. In the delay corresponding to the angle of rotation, the maximum value can reach 500 + (angel * 11) = 500 + (11 * 180) = 2480. This means that a perfect 180 degree position cannot be, for this reason I will slightly modify the code by writing:

delayMicroseconds(500 + (angle * 2000 / 180));

Thus, the delayMicroseconds() function will take values from 500 to 2500, and this will ensure the movement of the servo motor in the range from 0° up to 180°.

So my final code will look like this:

const int servoPin = 2; // set the pin number for the servo
int angle = 0; // variable for rotation angle

void setup() {
   pinMode(servoPin, OUTPUT); // set servo pin as output
}

void loop() {
   for(angle = 0; angle < 180; angle += 1){ // rotate the servo from 0 to 180 degrees
     digitalWrite(servoPin, HIGH); // send a high signal to the servo pin
     delayMicroseconds(500 + (angle * 2000 / 180)); // set the delay corresponding to the angle of rotation
     digitalWrite(servoPin, LOW); // send low signal to servo pin
     delay(20); // delay to stabilize the servo
   }
   for(angle = 180; angle > 0; angle -= 1){ // rotate the servo from 180 to 0 degrees
     digitalWrite(servoPin, HIGH);
     delayMicroseconds(500 + (angle * 2000 / 180));
     digitalWrite(servoPin, LOW);
     delay(20);
   }
}

Conclusion

This week has been special in that the mistakes that have been made in the past weeks have come to light. It took a lot of effort to solve them. I hope that these difficulties will serve as a lesson for me to approach the development of the board more deliberately. And errors that may occur in the future have been prevented in advance. Also important is the convenient organization of the pins and the provision of the required number of power and GND pins.

Files

KiCad project files

SVG files for carving and cutting the board

INO - flashing external LED

INO - servomotor control


Last update: May 26, 2023