"Вы читаете о роботах и программировании и думаете: «Было бы здорово сделать что-то подобное самому!» Теми, кем эта идея овладевает чуть больше просто мыслей смотрят кто и как делал своего робота. Читают статьи, смотрят видео. На картинках все понятно. В видеороликах тоже обычно показываются уже готовые продукты, а также сжато показываются технологии их изготовления. И вроде бы то же всё понятно: отпилил, прикрутил, припаял, соединил, запрограммировал вон на той программе вот этим кодом."
понедельник, 10 февраля 2020 г.
четверг, 6 февраля 2020 г.
Занятие кружка от 04.02.20
Сегодня мы рассмотрим способность АЦП генерировать прерывания и выполнять обработку аналоговых сигналов независимо от работы ядра микроконтроллера то есть паралельно выполнению основной программы (Прерывание это команда процессору по которой он останавливает выполнение основной программы и переходит к выполнению подпрограммы - обработчику прерывания, после выполнения которой снова переходит в точку останова основной программы и продолжает ее выполнение с момента останова). Все дело в том том, что АЦП это отдельный независимый узел(блок) микроконтроллера, со своими настройками и возможностью автономной работы. Регистр ADSRB микроконтроллера, как раз и отвечает за работу АЦП в различных режимах, в том числе и в автоматическом непрерывном режиме.
Регистр ADCSRB (ADC Control and Status Register B)
У регистра ADCSRB всего одна группа битов — ADTS[2:0] - биты номер 5, 6, 7.
Источник автоматического запуска задается битами ADTS[2:0] регистра ADCSRB. Возможны следующие варианты:
АЦП прерыванием информирует МК о завершенном преобразовании. Пока осуществляется преобразование, Arduino занимается своими делами — исполняет заданную программу.
Настройка АЦП сводится к следующим действиям:
====Источник автоматического запуска задается битами ADTS[2:0] регистра ADCSRB. Возможны следующие варианты:
| 2:0] | Источник запуска преобразования ADC |
| 000 | Постоянное преобразование (Free Running mode) |
| 001 | Аналоговый компаратор |
| 010 | Внешний запрос на прерывание 0 |
| 011 | Timer/Counter0 Compare Match |
| 100 | Timer/Counter0 Overflow |
| 101 | Timer/Counter1 Compare Match B |
| 110 | Timer/Counter1 Overflow |
| 111 | Timer/Counter1 Capture Event |
АЦП прерыванием информирует МК о завершенном преобразовании. Пока осуществляется преобразование, Arduino занимается своими делами — исполняет заданную программу.
Настройка АЦП сводится к следующим действиям:
- Обнуляем ADCSRB
- Устанавливаем источник опорного напряжения
- Выбираем пин для преобразования
- Запускаем преобразования
- Устанавливаем пределитель частоты
- Включаем автоматическое преобразование
- Разрешаем прерывание после окончания преобразования
- Включаем АЦП
- Запускаем преобразование
ADCSRB = 0x00;
ADMUX = 0b01100000;//A0
ADCSRA = 0b11101111;//делитель 128
=====
volatile int result;
int main()
{
...
//краткая настройка АЦП
ADCSRB = 0;
ADMUX = 96;//A0
ADCSRA = 239;//делитель 128
...
}
//функция для работы с АЦП по прерыванию
volatile bool trueValue = false; ISR(ADC_vect) { if (trueValue) { result = ADCH;
trueValue = false; } else { trueValue = true; } }
воскресенье, 2 февраля 2020 г.
Занятие кружка 31.01.20
Для нашего занятия усложним предыдущее устройство. Добавим к устройству управления возможность регулировать задержку между включением и выключением следующего светодиода с помощью потенциометра. Наши бегущие огни можно замедлить или на оборот увеличить скорость и другим способом, но сначала рассмотрим способ с потенциометром.
Сигнал снимаемый с потенциометра аналоговый, значит подключать его нужно к аналоговом входу микроконтроллера. Для обработки таких сигналов в ардуино предлагается функция analogRead(Ax), где х номер вывода для аналоговых сигналов. Время работы функции 100 -110 мкс. Диапазон оцифрованного сигнала от 0 до 1023. Если использовать штатные функции обработки аналогового сигнала иэ задержки. Примерно так:
//================
t_data = analogRead(A3);
delay(t_data);
//================
На занятии от 28.01.2020 мы рассмотрели способ ускорения работы analogRead() и хотя нам такое ускорение и не требуется напишем программу, которая учтет опыт прошлого занятия.
Итак для работы с аналоговыми сигналами на вход требуется настроить АЦП
| потенциометр |
| схема подключения |
Сигнал снимаемый с потенциометра аналоговый, значит подключать его нужно к аналоговом входу микроконтроллера. Для обработки таких сигналов в ардуино предлагается функция analogRead(Ax), где х номер вывода для аналоговых сигналов. Время работы функции 100 -110 мкс. Диапазон оцифрованного сигнала от 0 до 1023. Если использовать штатные функции обработки аналогового сигнала иэ задержки. Примерно так:
//================
t_data = analogRead(A3);
delay(t_data);
//================
На занятии от 28.01.2020 мы рассмотрели способ ускорения работы analogRead() и хотя нам такое ускорение и не требуется напишем программу, которая учтет опыт прошлого занятия.
Итак для работы с аналоговыми сигналами на вход требуется настроить АЦП
Настройка АЦП сводится к следующим действиям:
1. Необходимо настроить регистр ADMUX (Регистр настройки мультиплексора АЦП).
2. Настройки регистра ADCSRA (Регистр статуса и контроля А)
3. При необходимости, настройки DCSRB (Регистр статуса и контроля B)
3. Чтение результата преобразования
А теперь приступим к самому интересному:
И начинаем запуск преобразования. В регистре ADCSRA, битом ADSC необходимо запустить преобразование и выполнять его,
пока не будет выставлен бит о свидетельствующий о том, что преобразование завершено (бит ADIF).
Данной строчкой (ADCSRA & (1 << ADIF) == 0 происходит проверка и одновременное сбрасывание флага об окончании преобразования.
Далее считываем полученное значение, как видно использовать АЦП не так уж и сложно!
unsigned int data;
int main()
Serial.begin(9600);
DDRC = 0x00; // назначает выводы с 14 по 19 входными
PORTC = 0x00;
ADCSRA |= (1 << ADEN)|(1 << ADPS2)|(1 << ADPS1)|(1 << ADPS0);
ADMUX |= (0 << REFS1)|(1 << REFS0)|(0 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3);
L0:;
ADCSRA |= (1 << ADSC); // Начинаем преобразование
L1:;
if((ADCSRA & (1 << ADIF)) == 0) goto L1; // пока не будет выставлен флаг об окончании преобразования
data = (ADCL|ADCH << 8); // Считываем полученное значение
Serial.println(data);
goto L9;
}
Как заменить функцию delay()? А попробуйте разработать алгоритм самостоятельно. На занятии клуба 04.02.20 мы обсудим ваши алгоритмы и займемся написанием программы и созданием нашего устройства.
вторник, 28 января 2020 г.
Занятие кружка 28.01.20
По техническим причинам заседание клуба не состоялось, однако тема для разговора есть и она очень важна в контексте того,что мы с Вами обсуждали на прошлом заседании. Тогда мы рассмотрели программирование микроконтроллера на основе создание устройства "Бегущий огонь" и хоть оно не проявляет особой требовательности к процессору и программе, однако на её примере мы рассмотрели написание программы используя внутренние устройство микроконтроллера. Теперь, когда мы убедились что стандартные функции для работы с дискретными сигналами работают в разы медленнее, а размер программы на порядок меньше, имеет смысл рассмотреть и другие способы управления сигналами на выводах микроконтроллера, используя регистры нашего микроконтроллера. Однако надо отдавать себе отчёт, что у этого способа есть плюсы и минусы. Основных плюсов два, скорость реакции программы её размер. К основным минусам можно отнести, то что рассматривая регистры конкретного микроконтроллера, мы неизбежно столкнётся, с тем что на других МК структура регистров и их количество будет различаться, и как следствие программа становиться не переносимой. Другим значительным минусом становиться трудоемкость написания программы, что требует большей квалификации от программиста разработчика.
Тем не менее, мы знаем, что функции ввода-вывода цифровых сигналов digitalWriter() и digitalRead() можно заменить на непосредственные операции с регистрами портов D,В,C. Теперь пора перейти к рассмотрению аналоговых сигналов, которые может обрабатывать микроконтроллер.
В отличие от остальных функций, ускорение функции analogRead() достигается не модификацией её исходного кода, а настройкой режима работы АЦП. Но обо всем по порядку и начнем с описания работы АЦП микроконтроллера Atmega 328P.
Тем не менее, мы знаем, что функции ввода-вывода цифровых сигналов digitalWriter() и digitalRead() можно заменить на непосредственные операции с регистрами портов D,В,C. Теперь пора перейти к рассмотрению аналоговых сигналов, которые может обрабатывать микроконтроллер.
В отличие от остальных функций, ускорение функции analogRead() достигается не модификацией её исходного кода, а настройкой режима работы АЦП. Но обо всем по порядку и начнем с описания работы АЦП микроконтроллера Atmega 328P.
Микроконтроллер Atmega 328P, на котором построен Arduino Uno содержит встроенный 10-битный аналого-цифровой преобразователь (далее АЦП, англ. ADC — Analog to Digital Converter) последовательного приближения. Именно он, как видно из названия, отвечает за оцифровку входящего аналогового сигнала.
|
По умолчанию, у Arduino в качестве ИОН
выступает напряжение пиитания МК — 5 В. Для использования в качестве ИОН
других источников референсного внешнего напряжения у микроконтроллера
есть дополнительный вход AREF. Перед преобразованием аналогового
сигнала, при использовании внешнего ИОН необходимо вызвать функцию analogReference().
|
Сигнал, поданный на вход АЦП должен быть в границах заданного диапазона 0 (GND)...ИОН. 10-битный означает, что заданный диапазон будет разбит на 210=1024 значения, и входной сигнал будет оцифрован в соответствующее цифровое значение из диапазона 0...1023:
|
Запуск преобразования может осуществляться несколькими способами:
|
Для управления АЦП существует 5 основных восьмибитных регистров:
|
Регистр ADCSRA (ADC Control and Status Register A)
Назначение битов регистра ADCSRA (ADC Control and Status Register A, регистр управления и состояния):
- ADEN (ADC Enable, включение АЦП) — флаг, разрешающий использование АЦП, при сбросе флага во время преобразования процесс останавливается;
- ADATE (ADC Auto Trigger Enable) — выбор режима работы АЦП. 0 – разовое преобразование (Single Conversion Mode); 1 – включение автоматического преобразования по срабатыванию триггера (заданного сигнала). Источник автоматического запуска задается битами ADTS[2:0] регистра ADCSRB. Возможны следующие варианты:
- ADSC (ADC Start Conversion, запуск преобразования) — флаг установленный в 1 запускает процесс преобразования.
В режиме Single Conversion (ADATE=0) для запуска каждого нового преобразования этот флаг должен быть установлен в единицу. После завершения преобразования, флаг ADSC сбрасывается в 0.
В режиме Free Running Mode (ADATE=1, ADTS[2:0]=000) этот флаг должен быть установлен в единицу один раз — для запуска первого преобразования, следующие происходят автоматически.
Если установка флага ADSC происходит во время или после разрешения АЦП (ADEN), то перед запрашиваемым преобразованием происходит дополнительное (extended) преобразование, во время которого происходит инициализация АЦП. Сброс флага во время преобразования не оказывает никакого влияния на процесс. - ADIF (ADC Interrupt Flag) — флаг прерывания от компаратора
- ADIE (ADC Interrupt Enable) — разрешение прерывания от компаратора
- ADPS[2:0] (ADC Prescaler Select) — комбинацией битов задается частота преобразования АЦП по отношению к частоте МК. Выбранная частота влияет на точность — чем выше частота, тем ниже точность. АЦП тактируется через выбранный делитель от частоты ядра микроконтроллера. Значения битов:
int pinIn = A0; // Пин аналогового входа
void setup()
{
pinMode(pinIn, INPUT);
ADCSRA |= (1 << ADPS2); //Биту ADPS2 присваиваем единицу - коэффициент деления 16
ADCSRA &= ~ ((1 << ADPS1) | (1 << ADPS0)); //Битам ADPS1 и ADPS0 присваиваем нули
}
void loop()
{
Serial.println(analogRead(pinIn));
delay(1000);
}
Замеры производительности показывают время выполнения функции — 16 мкс (вместо первоначальных 112 мкс):
Вспомним какие биты содержатся в регистре ADMUX:
Замеры производительности показывают время выполнения функции — 16 мкс (вместо первоначальных 112 мкс):
Регистр ADMUX (ADC Multiplexer Selection Register)
Назначение битов регистра ADMUX:
- REFS[1:0](Reference Selection Bit) — биты определяют источник опорного напряжения. Возможные значения:
- ADLAR(ADC Left Adjust Result) — бит отвечающий за порядок записи битов результата в регистры ADCL и ADCH. В зависимости от того значения, которое присвоено биту ADLAR возможны 2 варианта:
- MUX[3:0] (Multiplexer Selection Input) — биты выбора аналогового входа. Значения:
Продолжение следует
Использованы материалы :
https://codius.ru/articles/Arduino_%D1%83%D1%81%D0%BA%D0%BE%D1%80%D1%8F%D0%B5%D0%BC_%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D1%83_%D0%BF%D0%BB%D0%B0%D1%82%D1%8B_%D0%A7%D0%B0%D1%81%D1%82%D1%8C_2_%D0%90%D0%BD%D0%B0%D0%BB%D0%BE%D0%B3%D0%BE_%D1%86%D0%B8%D1%84%D1%80%D0%BE%D0%B2%D0%BE%D0%B9_%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D0%B5%D0%BB%D1%8C_%D0%90%D0%A6%D0%9F_%D0%B8_analogRead
Подписаться на:
Сообщения (Atom)