digitalWrite()
If the pin has been configured as an OUTPUT with pinMode() , its voltage will be set to the corresponding value: 5V (or 3.3V on 3.3V boards) for HIGH , 0V (ground) for LOW .
If the pin is configured as an INPUT , digitalWrite() will enable ( HIGH ) or disable ( LOW ) the internal pullup on the input pin. It is recommended to set the pinMode() to INPUT_PULLUP to enable the internal pull-up resistor. See the Digital Pins tutorial for more information.
If you do not set the pinMode() to OUTPUT , and connect an LED to a pin, when calling digitalWrite(HIGH) , the LED may appear dim. Without explicitly setting pinMode() , digitalWrite() will have enabled the internal pull-up resistor, which acts like a large current-limiting resistor.
Функции digitalWrite() и delay() в Arduino IDE на примере мигания светодиода.
В статье познакомимся с платой Arduino Uno, пинами платы. Напишем программу мигания светодиода в Arduino IDE.
Сборка схемы
Плата Arduino Uno
Для начала разберемся с платой, с которой будем работать. Для примера используем Arduino Uno — плата с микроконтроллером, то есть микросхемой. Она нужна для управления электронными устройствами.
Плата Arduino Nano
На изображении видно устройство данной платы. В этой статье нас интересуют цифровые выводы. Они также называются пины или «ножки» платы. Данные пины используются для подключения к плате различных электронных компонентов.
Каждый из пинов имеет своё обозначение. Для работы нам нужны пин 3 и Gnd. Пин 3 мы используем для вывода, а пин Gnd для заземления. Gnd — это сокращение слова ground, в переводе на русский — земля.
Чтобы ток куда-то шел, цепь должна быть замкнута. Для этого есть обозначения + и —. Ток перемещается от + к —
Сборка схемы на макетной плате
Для сборки нам нужны:
- плата Arduino Uno
- макетная плата
- светодиод
- резистор
- провода
Короткую ножку подключаем к пину GND. Длинную ножку светодиода соединяем с резистором. Второй конец резистора соединяем проводом с пином 3.
Программирование светодиода
Для начала разберемся, что такой ввод и вывод. Есть команды, которые мы даем компьютеру. Например, мы вводим какой-то текст, который хотим распечатать. В этом случае клавиатура — это устройство ввода, так как с ее помощью мы передаем команду компьютеру. Принтер — устройство вывода, он «выводит» наш результат на бумагу.
Теперь разберемся с кодом для мигания светодиода. Нам нужно настроить нашу ножку на вывод. Для этого используем команду pinMode. Эта команда говорит плате, как она будет работать: на вход или на вывод. Команда является настройкой программы, поэтому она пишется в первом блоке setup(). Общий вид кода:
В скобках после функции pinMode мы указываем номер пина, с которым мы будем работать. После точки с запятой указываем, на что будет работать наш пин: на ввод INPUT или на вывод OUTPUT. В нашем случае пин 3 работает на вывод, это мы и пишем в коде.
Не забывайте после каждой функции ставить знак «;», например:
pinMode(3; OUTPUT);
Функция digitalWrite()
Функция digitalWrite даёт команду подать напряжение на определённый пин платы. Номер этого пина мы указываем в скобках. У функции есть параметры HIGH и LOW. Параметр HIGH (с английского — высоко) включает напряжение, параметр LOW (с английского — низко) отключает.
Нам нужно включить светодиод. Для этого мы включаем напряжение на 3-ий пин, поэтому код будет выглядеть так:
Это уже готовый код. На его основе мы можем включить светодиод. Если загрузить этот код на плату, то светодиод загорится.
Для выключения светодиода мы используем ту же функцию. Для этого в скобках после функции задаем параметр LOW. Функция выглядет так: digitalWrite(3; LOW)
Функция delay()
Delay с английского переводится как «задерживать». Эту задачу и выполняет функция: она приостанавливает выполнение программы на указанный промежуток времени. В скобках мы указываем время остановки в миллисекундах. 1 секунда = 1000 миллисекунд, поэтому если нам нужно установить задержку в секунду, пишем: delay(1000).
Теперь допишем наш код с использованием функции delay() и функцией digitalWrite() для выключения светодиода:
Arduino
Устанавливает режим работы пина (вход/выход). Значение по-умолчанию для цифровых пинов — INPUT , его устанавливать не нужно.
Синтаксис
Параметры
pin — номера пина
mode — режим. Одно из двух значений: INPUT или OUTPUT (вход и выход соответственно)
Возвращаемое значение
Пример
Функция digitalWrite()
Описание
Подает на цифровой пин значение HIGH (включено) или LOW (выключено).
Синтаксис
Параметры
pin — номера пина
value — значение HIGH или LOW
Возвращаемое значение
Пример
Если установлен режим пина INPUT , то функция digitalWrite() включает или выключает нагрузочный резистор.
DigitalWrite
Note: The oscilloscope waveforms below show how to speed up digitalWrite operation. However, this is not always needed. In fact most applications chug along quite happily using the standard digitalWrite function.
This faster macro operation is shown here so only so you know about it (see later macro definitions) — for instance you might want to speed up an operation due to time constraints in the application.
The oscilloscope shots below show the difference in using digitalWrite() on the left and using macros on the right. The period on the left is 7us while on the right it is
17 times faster than digitalWrite().
Using digitalWrite in Arduino
For the function to work you must first set the pin direction to output. This is usually done once in the setup() function. All pins default to inputs on power upi so if you don’t set the pin as output it won’t do anything.
Here’s the basic use of the function.
Why is digitalwrite useful?
The function digitalWrite() is the cornerstone of the Arduino system creating a simple interface, with external Arduino connections described by referring to a number (the Arduino pin). The pin number is printed on the development board so its easy to see which output is being controlled.
Note: An Arduino pin is not the same as the chip pin number.
That does not sound too useful, but if you think about an Arduino Uno processor (14 I/O pins, with ATMega328p processor) and the Arduino Due (54 I/O pins, with Atmel SAM3X8E ARM Cortex-M3 CPU). These processors are very different e.g. the Uno is an 8 bit processor and runs at 16MHz whereas the Due is a 32 bit processor running at 84MHz.
Using the digitalWrite function you can run the same code on different processors quite easily because you can select a pin to use e.g. put an LED on pin 5, and turn it on and off. In both the DUE and UNO versions (or another Arduino type board) you can use the same code to turn on and off pin 5 as a digital output.
This means code re-use is easy and does not require you to know anything about the underlying hardware (and how to access digital I/O).
Cost of using DigitalWrite
However this flexibility does come at a small cost, and that cost is speed. It takes time to figure out which «real» pin and which «real» port is being used and to convert the pin number to a port and port mask. Since the processors are running fast anyway — the Uno has 16MIPS and the Due has 100 MIPS — loosing a small number of MIPS is not a big disadvantage. Even for the Uno 16MHz allows you to waste a few cycles to get the easy digitalWrite operation.
The only time it becomes a problem is when you absolutely have to toggle a pin on and off at a very fast and precise rate — this will depend on the chip specification of a chip you are trying to control.
DigtalWrite Advantages and Disadvantages
Advantages
Code is cross processor compatible.
Code is easy to understand.
Code controls a named pin on the board and is therefore easy to wire up.
Changing code to use different pins is trivial.
Disadvantages
Code is slower than accessing the ports directly.
Can not perform multiple bit read or write in a single action.
Using digitalWrite
You can either read from a pin, or write to a pin, but you can’t do both at the same time as separate internal hardware is used for each operation. The processor needs to know how the pin is to be used by your program.
You use the function pinMode() to tell the processor to configure the pin for reading or writing.
Note: The default state of a pin is INPUT.
For writing, you setup the pin for digital output as follows:
const byte thispin 1;
pinMode( thispin, OUPTUT);
You can place the above code in the setup() function since you only set the pin direction at the start of the program and it usually remains the same. I say usually, since sometimes you may need to change the pin direction to allow some devices to operate e.g. Dallas 1 wire system is bidirectional on one pin. You can change the pin direction at anytime if you need to do so.
So How Does digitalwrite Work
For this explanation we will look at the Aruduino Uno code base (the code will be different for the Due and any other processor, but the same principles will apply).
Digital write source code
Digitalwrite internal structure
- Is there a hardware PWM associated with the pin?
- The bit mask for the pin.
- The port that the pin is located on.
- Invalid port so exit.
- Turn off the PWM output if the pin is PWM capable.
- if val is low then set the output pin state to zero volts.
- if val is high then set the output pin state to high volts.
First the part that figures out ports and pins
The first part of this code is where the magic happens in translating the abstract pin number into a port and a bit mask. In addition there is also a timer parameter which is associated with PWM outputs.
report this ad
Use of digitalPinToTimer
- pins 0 to 7 map to PD0 to PD7
- pins 8 to 13 map to PB0 to PB5
Note: The definition __AVR_ATmega8__ is for the ATmega8 Version of the chip that was used in the R0 version of the Arduino Uno. It is unlikely that you will see one these today; You can find a picture of one on the Wikipedia page here.
- pin 3, hwpin 5 (PD3),
- pin 5, hwpin 11 (PD5),
- pin 6, hwpin 12 (PD6),
- pin 9, hwpin 15 (PB1),
- pin 10, hwpin 16 (PB2),
- pin 11, hwpin 17 (PB3).
The issue here is that if a pin is being used as a digital output pin then it can not be used as a PWM output and the desire to use the digital output overrides PMW use.
The array allows the code to check if the pin can ever be a PWM output and which timer is associated with that pin.
Note: If it is a PWM pin then hardware dictates which timer is used. These are fixed in the ATMega328 hardware architecture.
If the pin has an associated timer (indicated by the array value) output then the function turns off the PWM output associated with that timer. i.e. if an array value is not equal to NOT_ON_TIMER then turn off the PWM output for that pin. For example
If you were using pin 2 then the array returns NOT_ON_TIMER — there is no PWM for pin 2. No action is taken.
If you were using pin 3 then the array returns TIMER2B indicating there is PWM on the pin and that it is using Timer2. The code then turns off the PWM output for pin 2 using the function turnOffPWM(timer).
Use of digitalPinToBitMask
Finds out the bitmask value for a specific Arduino pin.
_BV(n) is a macro that returns an 8 bit bit-mask (or bit value) and is defined by the compiler. The _BV(n) macro performs an equivalent bit shift operation but returns a value so there is no run time penalty in operating code i.e. there is no shift left command used — it is pre calculated as below. Examples:
_BV(0) returns 0x01 // operation was (1<<0)
_BV(1) returns 0x02 // operation was (1<<1)
_BV(7) returns 0x80 // operation was (1<<7)
So digitalPinToBitMask simply returns the bit value for a pin.
Use of digitalPinToPort
Finds out the port address for a specific Arduino pin.
- The first 8 values are PD (portD) — pins 0 to 7,
- The next 6 values are PB (port B) — for pins 8 ro 13,
- The next 6 values are PC (port C) — for pins 14 to 19 — These are the analogue pins.
Finally, the part that does the actual work
) and logical AND (&) and logical OR (|). These use the standard bit set or reset mask techniques.
Final part code explanation
Why is digitalWrite so Slow?
DigitalWrite is slower because it is written to allow access to the Arduino pins and it does some housekeeping tasks PWM detection, port calculation, and bit mask calculation (as explored above).
However, digitalWrite is not that slow (
6us toggle) and you can control most devices using digitalWrite. It only appears slow when you are trying to control more demanding interfaces. In this case use the fast macros shown below to get a
20x speed increase.
How to speed up DigitalWrite
This section comes with a caveat — and that is: if you use the following for a speed increase then you are going into unprotected code area. This is simply the default programming method that software engineers/hardware designers are well used to.
What it simply means is that if you do stupid things then stupid things are going to happen!
The Arduino code above at the start of digitalWrite protects users from turning on the PWM outputs while at the same time trying to use them as normal digital I/O. In addition the code converts a simple number to a port and pin mask.
In a commercial engineered system pins are set for specific tasks and it up to the designer to use them appropriately. So if a pin is used as a PWM output to control a motor then it won’t be used for anything else. So in that case you would not access the pin as normal digital I/O so you wont need protective code.
The protective code is there to allow inexperienced/careless engineering, so you really don’t need it if you specify and setup the system as you want it to be. That means you can do away with these protections and gain a speed advantage. However note that digitalWrite is very convenient and in most cases it is fast enough.
The following two oscilloscope images show the difference in speed between digitalWrite() on left and simpler macro code on the right (They use the same scale: 1us per division):
These oscilloscope images are for an Arduino Uno running at 16MHz.
As you can see there is quite a speed difference. On the left the high period is about 3.5us high and 3.5us low. For the time it takes digitalWrite to toggle once, the macro has toggled about 18 times. Toggling on the right takes about 0.4us.
Zooming in on the right hand one:
The scope settings were 0.5us/div and x5 multiplier. So it is high for 0.1us and low for 0.3us. The difference in M:S ratio is due to the jump instruction needed to return to the start of the while loop.
Example Sketch DigitalWrite and fast Macros
The code used for comparing digitalWrite() and macro versions is shown below:
The fast macros work for pins 0 to 13 . To extend them to PORTC would need another condition similar to the following (not tested):
This adds another condition so will be slower. It does not check for an input greater than the maximum pin 19, so you could make it go wrong!
Note: For interrupt safe macros wrap the macros in the SRG code as in digital write. All it means is that outputs will not be interrupted i.e. won’t be extended by an executing interrupt.
Some FAQs
Why digitalwrite doesn’t work?
This is likely because you forgot to set the pin as OUTPUT using pinMode before using digitalWrite.
Do I need digitalwrite include?
No Arduino is different in that respect. In most compiler systems you have to include everything that you will need, but in Arduino this function is built in (as are many others — See Arduino reference). You only need ‘includes’ to incorporate external library functions.
Can I use digitalwrite in an interrupt?
Yes it is safe to use in an interrupt since it does not itself rely on any other interrupts.
Can I use digitalwrite in the setup function?
Can I use digitalwrite for multiple pins?
No: You have to individually write to each pin. If you want to write multiple pins at the same time they must be on the same port. The you use the bitwise operators to set or clear multiple pins at the same time (just set the bit mask to the pins you want to control).
My arduino digitalwrite is not 5v
The physical interface has limits (specifically current). If you load the pin with a large current drawing load the output voltage will drop even though the output is high. This is normal.