В этой статье мы рассмотрим низкодиапазонный амперметр на микроконтроллере ATmega8 (семейство AVR). Для реализации этой идеи мы задействуем 10 битный аналого-цифровой преобразователь (АЦП) данного микроконтроллера. Для упрощения схемы используем резистивный метод, являющийся самым простым способом определения нужных нам параметров.
В этом методе мы будем пропускать ток, силу которого необходимо измерить, через резистор с маленьким сопротивлением. Измеряя напряжение на этом резисторе с помощью АЦП микроконтроллера мы сможем определить и интересующую нас силу тока. Измеренное значение тока мы будем показывать на жидкокристаллическом (ЖК) дисплее 16х2.
В схеме мы будем использовать делитель напряжения на резисторах. Измеряемый ток будем пропускать через всю цепочку резисторов, а измерять напряжение будем в средней точке делителя. Напряжение в этой точке будет изменяться по линейному закону в зависимости от величины тока, протекающего через делитель напряжения.
При проектировании схем с делителем напряжения следует принимать во внимание то, что входной ток на АЦП микроконтроллера AVR должен быть не менее 50 мкА. Поэтому следует правильно выбирать резисторы делителя напряжения чтобы минимизировать влияние нагрузки (loading effect) резистора на проходящий через делитель ток.
Необходимые компоненты
Аппаратное обеспечение
- Микроконтроллер ATmega8 (купить на AliExpress).
- Программатор AVR-ISP (купить на AliExpress), USBASP (купить на AliExpress) или другой подобный.
- JHD_162ALCD (ЖК дисплей 16x2) (купить на AliExpress).
- Конденсатор 1000 мкФ (купить на AliExpress).
- Конденсатор 100 нФ (4 шт.) (купить на AliExpress).
- Резистор 100 Ом (7 шт.) (купить на AliExpress).
- Резистор 100 кОм (купить на AliExpress).
- Источник питания с напряжением 5 Вольт
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Программное обеспечение
- Atmel Studio версии 6.1 (или выше).
- Progisp или flash magic (необязательно).
Работа схемы
Схема устройства приведена на следующем рисунке.
Принципы взаимодействия микроконтроллера AVR с ЖК дисплеем можно изучить в этой статье (или, если в сокращенной форме, то в этой).
Напряжение на резисторах R2 и R4 (точка, где мы измеряем напряжение) не будет полностью линейным, оно будет зашумлено. Для фильтрации этого шума в схему включен конденсатор C6.
Аналого-цифровой преобразователь (АЦП) микроконтроллера ATmega8 может быть использован на любом из четырех каналов PORTC – мы выберем канал 0 (PIN0) PORTC.
В микроконтроллере ATmega8 АЦП имеет разрешение (разрешающую способность) 10 бит, таким образом микроконтроллер способен реализовать чувствительность равную Vref/2^10, то есть если опорное напряжение (Vref) равно 5В мы получим цифровой инкремент на выходе 5/2^10 = 5мВ. Таким образом, на каждое приращение напряжения на 5 мВ мы будем получать один дополнительный инкремент цифрового выхода АЦП.
Для обеспечения работы схемы мы должны установить значения регистров АЦП следующим образом:
- Сначала мы должны активировать АЦП микроконтроллера.
- Затем необходимо установить максимальное входное напряжение для АЦП равное 5В. Это можно сделать путем установки значения опорного напряжения АЦП равного 5В.
- АЦП микроконтроллера в нашей схеме будет начинать действовать при внешнем воздействии (не от действий пользователя), поэтому нам следует установить его в режим непрерывного преобразования (free running mode): в этом режиме запуск преобразований выполняется непрерывно через определенные интервалы времени.
- В любом АЦП частота преобразования аналогового значения в цифровое и точность цифрового выхода обратно пропорциональны. То есть для лучшей точности цифрового выхода мы должны выбрать меньшую частоту. Для этого мы должны установить коэффициент деления предделителя АЦП в максимальное значение (2). Поскольку мы используем внутреннюю частоту микроконтроллера 1 МГц, то значение частоты преобразования АЦП будет равно 1000000/2.
Четыре основных принципа работы с АЦП микроконтроллера мы рассмотрели, теперь нам нужно установить правильные значения в двух регистрах АЦП.
RED (красный, ADEN): этот бит устанавливается чтобы задействовать функции АЦП в ATmega8.
BLUE (синий, REFS1, REFS0): эти два бита используются для установки опорного напряжения (максимального входного напряжения, которое мы собираемся обрабатывать). Поскольку мы будем использовать опорное напряжение равное 5В, бит REFS0 необходимо выставить в соответствии с приведенной таблицей.
LIGHT GREEN (светло зеленый, ADATE): этот бит должен быть установлен чтобы АЦП работал непрерывно (в режиме непрерывного преобразования).
PINK (розовый, MUX0-MUX4): эти 5 бит используются чтобы задать входной канал. Поскольку мы будем использовать ADC0 (PIN0) то, как следует из ниже приведенной таблицы, нам нет необходимости устанавливать все эти биты.
BROWN (коричневый, ADPS0-ADPS2): эти три бита используются для установки коэффициент деления предделителя АЦП. Поскольку мы используем коэффициент деления предделителя 2, мы должны установить только один из этих битов.
DARK GREEN (темно-зеленый, ADSC): этот бит необходимо установить для того чтобы АЦП начал осуществлять преобразование. Далее в программе мы можем его сбросить (в 0) если нам нужно будет остановить процесс аналого-цифрового преобразования.
Для лучшего понимания этой статьи можно также прочитать статью о цифровом вольтметре на микроконтроллере AVR.
Исходный код программы на языке С (Си) с пояснениями
Программа для рассматриваемой схемы представлена следующим фрагментом кода на языке С (Си). Комментарии к коду программу поясняют принцип работы отдельных команд.
1 2 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 |
#include <avr/io.h> // заголовок чтобы разрешить контроль данных на контактах #define F_CPU 1000000 // задание тактовой частоты микроконтроллера #include <util/delay.h> // заголовок чтобы задействовать функции задержки в программе #include <stdlib.h> #define enable 1 // задействуем контакт PB1 PORTB (“enable”), поскольку он соединен с контактом “enable” ЖК дисплея #define registerselection 0 // задействуем PB0 PORTB (“enable”), поскольку он соединен с контактом RS ЖК дисплея void send_a_command(unsigned char command); void send_a_character(unsigned char character); void send_a_string(char *string_of_characters); int main(void) { DDRD = 0xFF; // установка portD на вывод данных DDRC = 0; // установка PC0/ADC0 (вход АЦП) на ввод данных DDRB= 0xFF; // установка portB на вывод данных ADMUX |=(1<<REFS0); // установка опорного напряжения для АЦП ADCSRA |=(1<<ADEN)|(1<<ADPS0)|(1<<ADFR); // активация АЦП, установка свободного режима, установка шкалы АЦП 2 float i =0; float CURRENT = 0; char CURRENTSHOW [7]; send_a_command(0x01); //очистить экран 0x01 = 00000001 _delay_ms(5); send_a_command(0x38); // сообщаем ЖК дисплею что мы будем использовать 8 битный режим передачи данных/команд _delay_ms(5); send_a_command(0b00001111); //включаем курсор и мигание курсора на ЖК дисплее _delay_ms(5); ADCSRA |=(1<<ADSC); //старт АЦП send_a_string ("CIRCUIT DIGEST "); // отображение строки "CIRCUIT DIGEST " send_a_command(0x80 + 0x40 + 0); // переводим курсор на 1 позицию второй строки send_a_string ("CURRENT="); // отображение строки " CURRENT=" send_a_command(0x80 + 0x40 + 8); // переводим курсор на 10 позицию второй строки while(1) { i=ADC/204.8; CURRENT = (2*i*1000)/2.7; // ADC/18.618; - вычисление значения тока dtostrf(CURRENT, 4, 1, CURRENTSHOW); //преобразуем число в строку send_a_string(CURRENTSHOW); send_a_string("mAmp"); //ADCSRA &=~(1<<ADSC); //ADCSRA |=(1<<ADSC); _delay_ms(50); send_a_command(0x80 + 0x40 + 8); //dtostr(double precision value, width, precision, string that will store the numbers); // Value – число, или переменная , содержащая число //Width – общая длина числа, которое функция dtostrf должна преобразовать в строку, включающая точку и отрицательный знак числа(-). Например, если рассматриваем число -532.87, то его длина будет равна 7 (5 цифр + знак (-) + точка (.)) //Precision – задает точность преобразования, то есть сколько знаков после запятой учитывать } } void send_a_command(unsigned char command) { PORTD = command; PORTB &= ~ (1<<registerselection); // устанавливаем RS в 0 чтобы сообщить ЖК дисплею что мы будем передавать команду PORTB |= 1<<enable; // сообщаем ЖК дисплею чтобы он принял команду/данные _delay_ms(2); PORTB &= ~1<<enable; // сообщаем ЖК дисплею что мы закончили передачу данных PORTD = 0; } void send_a_character(unsigned char character) { PORTD = character; PORTB |= 1<<registerselection; // сообщаем ЖК дисплею что мы будем передавать данные (не команду) PORTB |= 1<<enable; // сообщаем ЖК дисплею чтобы он начал прием данных _delay_ms(2); PORTB &= ~1<<enable; // сообщаем ЖК дисплею что мы закончили передачу данных PORTD = 0; } void send_a_string(char *string_of_characters) { while(*string_of_characters > 0) { send_a_character(*string_of_characters++); } } |
А как вы рассчитали надежность этой схемы и тепловой режим?
Лично я не рассчитывал, статья является переводом с популярного иностранного сайта. Его авторы многие свои схемы моделируют в Proteus и вообще очень талантливые ребята судя по отзывам на их работы в сети. Я думаю, проблем с этой схемой быть не должно
Не пинайте, я в CVAVR.
Да мы не пинаем, у нас образовательный ресурс, а в обучении не бывает глупых вопросов как говорил один из моих преподавателей в институте ))
Добрый день!
Команда (функция) dtostrf () в тексте: "dtostrf(CURRENT, 4, 1, CURRENTSHOW); //преобразуем число в строку"
это - библиотечная ф-ция? Как она работает и что делает?
С уважением, Сергей.
Добрый вечер, это стандартная для языка C++ функция. Она преобразует число вещественного типа в строку (массив символов) с заданной точностью - указывается общее количество знаков числа и после запятой которые нужно преобразовать в строку. В тексте программы есть же подробные комментарии по этому поводу. Дело в том, что на ЖК дисплее вам не удастся простым способом вывести значение числа, поэтому его и преобразуют в строку. Более подробно об этой функции можете прочитать, к примеру, здесь - portal-pk.ru/news/95-funkciya--dtostrf-.html
Спасибо!
С уважением, Сергей.
Да не за что, заходите к нам еще. Нам важна обратная связь от посетителей - это помогает улучшать сайт
Пустой экран в proteus.
Извините, не совсем понял что вы имели ввиду. Можно немного поподробнее?