Arduino ide настройка ацп
В отличие от остальных функций, ускорение функции analogRead() достигается не модификацией её исходного кода, а настройкой режима работы АЦП. Но обо всем по порядку и начнем с описания работы АЦП микроконтроллера Atmega 328P.
По умолчанию, у Arduino, в качестве ИОН выступает напряжение пиитания МК — 5 В. Для использования в качестве ИОН других источников референсного внешнего напряжения у микроконтроллера есть дополнительный вход AREF. Перед преобразованием аналогового сигнала, при использовании внешнего ИОН необходимо вызвать функцию analogReference() .
Сигнал, поданный на вход АЦП должен быть в границах заданного диапазона 0 (GND). ИОН . 10-битный означает, что заданный диапазон будет разбит на $2^=1024$ значения, и входной сигнал будет оцифрован в соответствующее цифровое значение из диапазона 0. 1023 :
Схема работы 10-битного АЦП последовательного приближения $$U_<АЦП_>=\begin \frac< 1> < 2>U_ & \text n=1 \\ U_>+\frac< 1> < 2^n>U_ & \textn>1, U_><U_ \\ U_>-\frac< 1> < 2^n>U_ & \textn>1, U_>>U_ \end$$АЦП_Исходя из вышеизложенного и данных представленных на рисунке, нетрудно посчитать результат:
$512\times1+256\times0+128\times0+64\times1+32\times0+16\times1+8\times0+4\times0+2\times1+1\times0=594$
- в ручном режиме — единичное преобразование
- а автоматическом режиме — по сигналам из различных источников
Для управления АЦП существует 5 основных восьмибитных регистров:
Регистры | Биты | |||||||
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
ADCSRA | ADEN | ADSC | ADATE(ADFR2) | ADIF | ADIE | ADPS[2:0] | ||
ADMUX | REFS[1:0] | ADLAR | × | MUX[3:0] | ||||
ADCSRB | ADTS[2:0] | × | × | × | × | × | ||
ADCL | Результат преобразования. Значение имеют только 10 бит. Старшие или младшие - зависит от значения бита ADLAR. | |||||||
ADCH |
Напишем первый скетч, в котором используется родная функция analogRead() . Но отличие будет заключаться в том, что перед использованием, режим работы АЦП будет перенастроен:
int pinIn = A0; // Пин аналогового входа void setup () < pinMode (pinIn, INPUT ); ADCSRA |= (1 << ADPS2); //Биту ADPS2 присваиваем единицу - коэффициент деления 16((1 << ADPS1) | (1 << ADPS0)); //Битам ADPS1 и ADPS0 присваиваем нули
analogRead(). Total time: 160052 microsec, AVG time: 16.00 microseconds. (iterations 10000) Ускорение в 7 раз. int pinIn = A0; // Пин аналогового входа void setup () < pinMode (pinIn, INPUT ); cbi(ADCSRA, ADPS1); //Битам ADPS1 и ADPS0 присваиваем нулиВспомним какие биты содержатся в регистре ADMUX:
Регистры | Биты | |||||||
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |
ADMUX | REFS[1:0] | ADLAR | MUX[3:0] |
У регистра ADCSRB всего одна группа битов — ADTS[2:0]. О ней упоминалось в контексте описания бита ADATE. Биты ADTS[2:0] отвечают за выбор источника автоматического запуска АЦП.
// . // Запуск преобразования sbi(ADCSRA, ADSC); // Ожидание сброса бита ADSC, свидетельствующее об окончании преобразованияДля того, чтобы разгрузить микроконтроллер необходимо заставить АЦП самостоятельно заниматься оцифровкой, а по завершении преобразования АЦП сообщит об окончании прерыванием.
Но полную мощь АЦП проявляет в связке с прерываниями — обособленный от ядра МК режим работы АЦП, при котором АЦП прерыванием информирует МК о завершенном преобразовании. Пока осуществляется преобразование, Arduino занимается своими делами — исполняет заданную программу.
12
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
((1 << ADPS1) | (1 << ADPS0)); //Битам ADPS1 и ADPS0 присваиваем нули ADCSRA |= (1 << ADATE); // Включаем автоматическое преобразование ADCSRA |= (1 << ADIE); // Разрешаем прерывания по завершении преобразования ADCSRA |= (1 << ADEN); // Включаем АЦП ADCSRA |= (1 << ADSC); // Запускаем преобразование >
В данном примере переменная result объявлена как int , а значит будет сразу преобразована к числу диапазона 0. 255 или 0. 1023.
В случае использования в процедуре обработки прерывания переменной объявленной вне её, нельзя забывать использовать описатель volatile для корректной обработки переменной компилятором.Если необходимо собирать данные с нескольких датчиков, то нужно после считывания преобразованного значения в процедуре ISR(ADC_vect) изменить входящий аналоговый пин на следующий:
Но запустив код, будет ждать разочарование — результаты каждый раз будут некорректными. Это связано с тем, в момент считывания преобразованного значения и переключения регистра ADMUX на другой аналоговый вход, АЦП уже начал новый процесс преобразования. Поэтому получается, что результат состоит из начала предыдущего преобразования и конца следующего. Чтобы устранить такое поведение, нужно пропускать первое после переключения входов преобразование — следующий результат будет достоверным:
volatile int analogPin = A0; volatile bool trueValue = false ; ISR(ADC_vect) < if (trueValue) < int result = ADCL | (ADCH << 8); analogPin += 1; if (analogPin > A5) < analogPin = A0; >; // Устанавливаем флаг смены входного пина trueValue = false ; > else < // Первый раз пропускаем считывание и устанавливаем флаг на чтение в следующий раз trueValue = true ; >>)Рассмотрим пример использования режима АЦП Free Runing Mode на следующем примере. Подключим к двум аналоговым входам потенциометр и датчик освещенности, и в зависимости от их значений будем регулировать яркость светодиодов. Схема:
12
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
(1 << ADPS1) | (1 << ADPS0); //Битам ADPS1 и ADPS0 присваиваем нули // Устанавливаем предделитель - 32 (ADPS[2:0]=101) ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //Биту ADPS2 присваиваем единицу ADCSRA &=
(1 << ADPS1); //Битам ADPS1 и ADPS0 присваиваем нули ADCSRA |= (1 << ADATE); // Включаем автоматическое преобразование ADCSRA |= (1 << ADIE); // Разрешаем прерывания по завершении преобразования ADCSRA |= (1 << ADEN); // Включаем АЦП ADCSRA |= (1 << ADSC); // Запускаем преобразование > volatile int currentSensorValue1 = 0; volatile int currentSensorValue2 = 0; long oldTime = 0; void loop () < if ( millis () - 10 > oldTime) < analogWrite (pinLed1, map (currentSensorValue1, 0, 1023, 0 , 255)); analogWrite (pinLed2, map (currentSensorValue2, 0, 1023, 0 , 255)); oldTime = millis (); >> volatile int analogPin = A0; volatile bool trueValue = false ; ISR(ADC_vect) < if (trueValue) < int result = ADCL | (ADCH << 8); // Получаем 10-битный результат if (analogPin == A0) < // Если актуальный входной пин A0, то присваиваем значение соответствующей переменной currentSensorValue1 = result; >else < currentSensorValue2 = result; >analogPin += 1; // Перебираем входные пины по кругу (А0. А1 - их может быть больше) if (analogPin > A1) < // Все нужные перебрали. analogPin = A0; // . возвращаемся к первому >; int pin = analogPin; // Приводим пин вида A0 (14) к удобному для регистра ADMUX - 0. A0=14, A1=15, . if (pin >= 14) pin -= 14; ADMUX = analog_ref | (pin & 0x07); // Устанавливаем новый вход для преобразования trueValue = false ; // Устанавливаем флаг смены входного пина - следующее прерывание пропускаем > else < trueValue = true ; // Первый раз пропускаем считывание и устанавливаем флаг на чтение в следующий раз >>
Для пренебрежения точностью, а с использованием в analogWrite() большая точность и не нужна, код можно модифицировать следующим образом:
12
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 int pinLed1 = 6; // Потенциометр int pinLed2 = 11; // Фоторезистор uint8_t analog_ref = DEFAULT; void setup () < pinMode (pinLed1, OUTPUT ); pinMode (pinLed2, OUTPUT ); ADC_init(); // Все настройки АЦП вынесены в отдельную процедуру >void ADC_init() < ADCSRA = 0; // Сбрасываем регистр ADCSRA ADCSRB = 0; // Сбрасываем регистр ADCSRB ADMUX |= (1 << REFS0); // Задаем ИОН ADMUX |= (1 << ADLAR); // Меняем порядок записи бит, чтобы можно было читать только 8 бит регистра ADCH analog_ref = ADMUX; // Запоминаем состояние регистра - из него мы будем формировать маску для смены входного пина ADMUX |= (0 & 0x07); // Выбираем пин A0 для преобразования // Устанавливаем предделитель - 32 (ADPS[2:0]=101) ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //Биту ADPS2 присваиваем единицу ADCSRA &=
(1 << ADPS1); //Битам ADPS1 и ADPS0 присваиваем нули ADCSRA |= (1 << ADATE); // Включаем автоматическое преобразование ADCSRA |= (1 << ADIE); // Разрешаем прерывания по завершении преобразования ADCSRA |= (1 << ADEN); // Включаем АЦП ADCSRA |= (1 << ADSC); // Запускаем преобразование > volatile int currentSensorValue1 = 0; volatile int currentSensorValue2 = 0; long oldTime = 0; void loop () < if ( millis () - 10 > oldTime) oldTime = millis (); > > volatile int analogPin = A0; volatile bool trueValue = false ; ISR(ADC_vect) < if (trueValue) < if (analogPin == A0) < // Если актуальный входной пин A0, то присваиваем значение соответствующей переменной currentSensorValue1 = result; >else < currentSensorValue2 = result; >analogPin += 1; // Перебираем входные пины по кругу (А0. А1 - их может быть больше) if (analogPin > A1) < // Все нужные перебрали. analogPin = A0; // . возвращаемся к первому >; int pin = analogPin; // Приводим пин вида A0 (14) к удобному для регистра ADMUX - 0. A0=14, A1=15, . if (pin >= 14) pin -= 14; ADMUX = analog_ref | (pin & 0x07); // Устанавливаем новый вход для преобразования trueValue = false ; // Устанавливаем флаг смены входного пина - следующее прерывание пропускаем > else < trueValue = true ; // Первый раз пропускаем считывание и устанавливаем флаг на чтение в следующий раз >>
В описанном выше примере функция analogRead() фактически ни разу не вызывается, но в процедуре loop() можно делать все что захочется. При этом производительность от использования АЦП не проседает.
В приведенном ниже коде показано, как можно сделать подсветку, плавно подстраивающуюся под изменение внешних условий:
12
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93 int pinLed1 = 6; // Потенциометр int pinLed2 = 11; // Фоторезистор uint8_t analog_ref = DEFAULT; void setup () < pinMode (pinLed1, OUTPUT ); pinMode (pinLed2, OUTPUT ); ADC_init(); // Все настройки АЦП вынесены в отдельную процедуру >void ADC_init() < ADCSRA = 0; // Сбрасываем регистр ADCSRA ADCSRB = 0; // Сбрасываем регистр ADCSRB ADMUX |= (1 << REFS0); // Задаем ИОН //ADMUX |= (1 << ADLAR); // Меняем порядок записи бит, чтобы можно было читать только 8 бит регистра ADCH analog_ref = ADMUX; // Запоминаем состояние регистра - из него мы будем формировать маску для смены входного пина ADMUX |= (0 & 0x07); // Выбираем пин A0 для преобразования // Устанавливаем предделитель - 32 (ADPS[2:0]=101) ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //Битам ADPS2 и ADPS0 присваиваем единицу ADCSRA &=
АЦП Arduino UNO имеет разрешение 10 бит, т.е. позволяет выводить значения в десятичном виде от 0 до 1023.
В относительных единицах деление шклалы 5/1024 = 4.9 мВ;
analogRead(pin) -- Функция считывает значение с указанного аналогового входа. Возвращает: int (0 to 1023).
Считывание значение с аналогового входа занимает примерно 100 микросекунд (0.0001 сек), т.е. максимальная частота считывания приблизительно 10,000 раз в секунду.
analogReference(type) -- определяет опорное напряжение относительно которого происходят аналоговые измерения. Type принимает одно из следующих значений:
DEFAULT: стандартное опорное напряжение 5 В (на платформах с напряжением питания 5 В) или 3.3 В (на платформах с напряжением питания 3.3 В).
INTERNAL: встроенное опорное напряжение 1.1 В на микроконтроллерах ATmega168 и ATmega328, и 2.56 В на ATmega8.
EXTERNAL: внешний источник опорного напряжения, подключенный к выводу AREF (рекомендуется подключать к выводу AREF через резистор 5 кОм).
Примеч.: Опорное напряжение можно установить, используя функцию analogReference или при помощи битов REFT[1:0] в регистре ADMUX.
Используйте внутреннее опорное напряжение 1.1 В для точных измерений внешних напряжений:
analogReference(INTERNAL1V1); // выбираем внутреннее опорное напряжение 1.1В
Опорное напряжение 1.1 В более стабильно и не зависит от изменения напряжения питания или температуры. Таким образом, можно производить измерения абсолютных значений. В Arduino Mega также возможен вариант опорного напряжения 2.56 В.
Режимы работы
1) Разовая выборка - это на самом деле то, что Arduino делает при вызове функции analogRead.
Из-за шумов 2 младших бита обычно отбрасывают:
int val = analogRead(A0)>>2;
-- в итоге получаем значения от 0 до 255, т.е. точность 5/255=19.6мВ.
2) Непрерывная выборка:
Хорошей идеей при непрерывной выборке сигнала является использование прерываний.
Микроконтроллеры ATMega328 и ATMega2560 могут быть переведены в режим непрерывной выборки (free running mode). В этом режиме АЦП запускается автоматически после завершения предыдущей обработки.
Для включения режима непрерывной выборки необходимо установить три регистра: ADMUX, ADCSRA и ADCSRB.
В этой статье мы рассмотрим различные аспекты использования аналого-цифрового преобразования (АЦП, в англ. ADC - Analog to Digital Conversion) в Arduino Uno.
Плата Arduino имеет 6 каналов АЦП, как показано на следующем рисунке.
Любые из этих каналов (или даже все сразу) можно использовать для подачи на них аналогового напряжения. АЦП в Arduino Uno имеет разрешение 10 бит, то есть получаем диапазон целых чисел, соответствующих этому разрешению, от 0 до 2^10-1 (до 1023). Это означает, что значение входного аналогового напряжения от 0 до 5 В преобразуется в целое число от 0 до 1023. То есть получаем шаг АЦП равный 5/1024= 4.9 мВ.
В нашем проекте мы будем подключать потенциометр к каналу ‘A0’, а результат аналого-цифрового преобразования на этом канале показывать на жидкокристаллическом (ЖК) дисплее. В радиолюбительской практике наиболее распространены жидкокристаллические (ЖК) дисплеи 16x1 и 16x2. ЖК дисплей 16x1 может отображать 16 символов, расположенных на одной строке. ЖК дисплей 16x2 может в сумме отображать 32 символа на двух строках – 16 символов на первой строке и 16 символов на второй. Здесь необходимо принимать во внимание тот факт, что каждый символ в подобных дисплеях состоит из 5x10=50 пикселов (точек). То есть чтобы отобразить 1 символ все эти 50 пикселов должны работать вместе. Но мы можем об этом не беспокоиться, потому что за их совместную работу отвечает контроллер HD44780 – его визуально можно увидеть на обратной стороне ЖК дисплея.
Необходимые компоненты
Плата Arduino UNO
Источник питаний 5 В
ЖК дисплей 16х2 (JHD_162ALCD)
Конденсатор 100 пФ
Конденсатор 100 нФ
Потенциометр 100 кОм
Работа схемы
Схема устройства представлена на следующем рисунке.
В ЖК дисплее 16x2 если мы хотим задействовать черный цвет, то нам будут нужны все его 16 контактов, в противном случае нам будет достаточно 14 контактов. Эти 2 контакта, отвечающие за черный цвет, можно оставить неиспользованными. Среди оставшихся 14 контактов мы имеем 8 контактов данных (7-14 или D0-D7), 2 контакта для подачи питания (1&2 или VSS&VDD или GND&+5v), 3-й контакт для управления контрастностью (определяет насколько "жирными" будут выглядеть символы на экране дисплея) и 3 управляющих контакта (RS&RW&E).
На представленной схеме можно увидеть, что мы использовали только 2 управляющих контакта – это обеспечивает гибкость в управлении. Бит контраста и READ/WRITE используются редко, поэтому в нашем случае их можно замкнуть на землю – это обеспечивает ЖК дисплею максимальную контрастность и режим чтения. Таким образом, нам необходимо будет контролировать только контакты ENABLE и RS чтобы передавать на ЖК дисплей символы и данные.
В схеме необходимо будет сделать следующие соединения с ЖК дисплеем:
PIN1 или VSS на землю
PIN2 или VDD или VCC к источнику питания +5В
PIN3 или VEE на землю (обеспечивает максимальную контрастность – хорошо для начинающих)
PIN4 или RS (Register Selection) к контакту PIN0 ARDUINO UNO
PIN5 или RW (Read/Write) на землю (переводит ЖК дисплей в режим чтения, что упрощает взаимодействие с ним для начинающих)
PIN6 или E (Enable) к контакту PIN1 of ARDUINO UNO
PIN11 или D4 к контакту PIN8 of ARDUINO UNO
PIN12 или D5 к контакту PIN9 of ARDUINO UNO
PIN13 или D6 к контакту PIN10 of ARDUINO UNO
PIN14 или D7 к контакту PIN11 of ARDUINO UNO
Программная среда ARDUINO IDE позволяет пользователю использовать ЖК дисплей в 4-битном режиме. Этот тип взаимодействия с ЖК дисплеем позволяет сократить использование контактов ARDUINO, к тому же этот режим взаимодействия (4-битный) по умолчанию заложен в ARDUINO. На представленной схеме мы использовали 4-битный режим взаимодействия (контакты D4-D7).
То есть в сумме мы подсоединили 6 контактов ЖК дисплея к нашей плате Arduino, из которых 4 контакта будут использоваться для передачи данных и 2 контакта для целей управления.
Объяснение работы программы
Для того, чтобы полноценно использовать АЦП в Arduino Uno, необходимо сделать следующие вещи:
analogRead(pin);
analogReference();
analogReadResolution(bits);
Прежде всего необходимо отметить что каналы АЦП Arduino Uno имеют по умолчанию опорное значение 5 В (опорное напряжение). Это означает, что максимальное входное значение напряжения для каждого канала АЦП Arduino составляет 5 В. Но некоторые датчики имеют выходное напряжение в диапазоне 0-2,5 В, поэтому если мы будем использовать опорное напряжение по умолчанию (5 В), то мы потеряем в точности измерений. В связи с этим полезно иметь возможность изменения значения опорного напряжения, для Arduino Uno это делается с помощью команды “ analogReference(); ”.
По умолчанию мы имеем разрешающую способность АЦП, равную 10 бит, разрешение АЦП мы также можем изменить используя команду “ analogReadResolution(bits); ”. Это может быть полезно в ряде случаев.
Теперь, если все установки параметров работы АЦП нами сделаны, мы можем считать значение АЦП с канала ‘0’ просто используя инструкцию “analogRead(pin);”, где “pin” означает контакт (вывод), на который мы подаем аналоговый сигнал, в нашем случае это будет контакт “A0”. Значение с выхода АЦП может быть преобразовано в число типа integer, например, с помощью инструкции “ int ADCVALUE = analogRead(A0); ”, в результате выполнения этой инструкции значение с используемого канала АЦП после проведения преобразования (то есть АЦП) сохраняется в переменной целого типа (integer) под названием “ADCVALUE”.
Далее мы должны указать какой именно тип ЖК дисплея мы будем использовать. Существуют различные типы ЖК дисплеев, например, 20x4, 16x2, 16x1 и т.д. Мы в нашем проекте будем использовать ЖК дисплей 16x2, поэтому мы должны будем записать команду ‘ lcd.begin(16, 2); ’. А если бы у нас был дисплей 16x1, то нам бы пришлось использовать команду ‘lcd.begin(16, 1);’.
Далее мы Arduino Uno должны указать, к каким ее контактам мы подключили ЖК дисплей. В нашем случае мы к Arduino Uno подключили следующие выводы ЖК дисплея: “RS, En, D4, D5, D6, D7”. Мы подключили их к контактам 0, 1, 8, 9, 10, 11 Arduino Uno, поэтому в нашем случае соответствующая команда будет иметь следующий вид: “LiquidCrystal lcd(0, 1, 8, 9, 10, 11);”.
После всего этого мы можем приступит к передаче данных на ЖК дисплей. Сделать это можно, к примеру, с помощью следующей команды: “ lcd.print("hello, world!"); ”. В результате выполнения этой команды на экран ЖК дисплея будет выведена строка ‘hello, world!’.
Исходный код программы
В этом разделе статьи будет представлен полный код программы для обработки данных с АЦП Arduino Uno и последующего их вывода на ЖК дисплей. Если у вас возникнут вопросы, то вы можете задать их в комментариях к данной статье.
ADCVALUE.toCharArray(ADCSHOW, 5); // преобразуем эту строку в символьный массив
lcd.print(ADCSHOW); // выводим значение этого символьного массива на экран ЖК дисплея
lcd.print(" ");
lcd.setCursor(0, 0); // устанавливаем курсор в нулевой столбец 1-й строки
>
Видео, демонстрирующее работу схемы
Также можете посмотреть еще одно видео про то, как использовать АЦП в Arduino Uno. Оно на английском языке, но зато очень подробное и доходчивое.
Для обработки аналогового сигнала можно использовать, например, аналоговый вывод A0:
Ввод значения напряжения на этом выводе реализуется так:
Перевод считанного значения в уровень напряжения реализуется так:
В качестве делителя в некоторых источниках рекомендуется и 1023.
Но в даташите на ATMega328P указано именно число 1024:
В вышеуказанном выражении vref - опорное напряжение (voltage reference).
В режиме по умолчанию (DEFAULT) опорное напряжение равно напряжению питания (5 В для моей платы Arduino).
В режиме INTERNAL используется внутренний источник опорного напряжения (1,1 В для моей платы Arduino).
В режиме EXTERNAL на вывод AREF подается внешнее опорное напряжение (от 0 до 5 В), причем входное сопротивление составляет 32 кОм. В этом случае удобно использовать внешний источник опорного напряжения - например, LM4040, LM385Z, REF-4096.
Источник REF-4096 основан на чипе MCP1541 и имеет три вывода:
Он преобразует напряжение около 5 В (4,3 . 5,5 В) в стабильное напряжение 4,096 В (4,055 . 4,137 В) (макс. выходной ток 2 мА):
Схема включения диода LM4040 следующая:
Диоды LM4040 обеспечивает различные значения напряжения:
LM4040-N-2.0 - 2,0 В;
LM4040-N-2.5 - 2,5 В;
LM4040-N-3.0 - 3,0 В;
LM4040-N-4.1 - 4,1 В;
LM4040-N-5.0 - 5,0 В.
Диод LM4040 обеспечивает стабильное опорное напряжение при токах 60 мкА . 15 мА.
Также можно использовать опорный диод из серии LMx85, например, LM385Z-1.2 на напряжение 1,235 В с погрешностью 2 %, работающий при токах 10 мкА . 20 мА.
Схема включения такого диода аналогична схеме включения LM4040, при этом рекомендуемое значение сопротивления резистора R для входного напряжения 9 В - 510 кОм, 1,5 В - 3 кОм.
Символ "Z" в обозначении диода означает тип корпуса TO-92:
Внутренняя схема такого опорного источника весьма сложна:
Для переключения режима опорного напряжения используется команда:
Следует отметить, что в используемой схеме напряжение на катушке при включенном MOSFET будет отрицательным, что отобразится нулевым значением в результатах измерений АЦП Arduino.
Для успешного детектирования сигнала необходимо ускорить аналого-цифровое преобразование, изменив множитель (prescaler) путем управления битами ADPSx в регистре ADCSRA:
ADPS2 | ADPS1 | ADPS0 | Множитель |
0 | 0 | 0 | 2 |
0 | 0 | 1 | 2 |
0 | 1 | 0 | 4 |
0 | 1 | 1 | 8 |
1 | 0 | 0 | 16 |
1 | 0 | 1 | 32 |
1 | 1 | 0 | 64 |
1 | 1 | 1 | 128 |
Этот множитель показывает, во сколько раз тактовая частота АЦП меньше системной тактовой частоты (16 МГц).
Установка множителя, равного 64 (частота дискретизации около 19 кГц) -
Установка множителя, равного 32 (частота дискретизации около 38 кГц) -
Установка множителя, равного 16 (частота дискретизации около 76 кГц) -
В этом случае тактовая частота АЦП равна 1 МГц. С учетом того, что преобразование занимает 13 тактов, оно будет длиться 13 мкс (частота 1000/13 = 76,92 мкс). Но это в идеальном случае! Тесты показали, что без изменения множителя (128 по умолчанию) одно аналого-цифровое преобразование (analogRead) в цикле занимает
Читайте также: