Проблема с реализацией двухканального АЦП-ШИМ ATTINY13
- Войдите на сайт для отправки комментариев
Уважаемые знатоки, помогите с изучением проблемы: реализую на ATTINY13 два канала А и Б.
два потенциометра( переменные резисторы) - для входа ( ножка 2 и 3)
на выходах - ножка 5 и 6 - светодиоды
пробую управлять яркостью в каждом канале : к примеру ножка 2 вход АЦП- ножка 6 выход ШИМ и аналогично 3 и 5
но одновременно работает 1 канал ( второй, чтоб не мешал , я закоментил),
пробовал в прерывании, по окончанию преобразования, инвертировать бит ( биты) для настройки АЦП ( определение входа) и ШИМ ( определение выхода) ,
пробовал заводить переменную, которая по прерыванию инвертируется каждый раз " HIGH-LOW-HIGH-LOW..." и далее в основном цикле выбирал по условию if (x==HIGH) { АЦП с входа А на ШИМ выход А) в противном случае else{ АЦП с входа Б на ШИМ выход Б}
не сработало - что делаю не так?
ниже код ( полурабочий - только один канал на выбор)
//работает одновременно только один канал - или PB3-OCR0B, или PB4-OCR0A. пока код использует 130 байт (12%) в ATTINY13// #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> // завел но не использовал int n=HIGH; unsigned int u; //пока не использовал unsigned int w; //не придумал как в прерывании последовальельно "разносить" по выходам результат АЦП-ШИМ SIGNAL(ADC_vect) //SIGNAL(SIG_ADC) на выбор два - один рабочий для attiny13, другой для attiny2313 { OCR0A = ADCH; //OCR0B = ADCH для второго канала; PORTB ^=0b00000100; //PORTB ^=0b00000100 для второго канала ;подтягивающий резистор на входе } //void setup() { // ничего не писал - проверил однократные установки входов - и выходов - НЕ РАБОТАЮТ, функционируют только в теле основной программы //} int main(void) { DDRB |= (0 << 4); // вход PB4 DDRB |= (0 << 3); // вход PB3 DDRB |= (1 << 0); // выход PB0 DDRB |= (1 << 1); // выход PB1 ADMUX = 0b00100010; //АЦП на входе PB4 ADCSRA = 0b11101111;//запускаем АЦП, разрешаем прерывания DIDR0 = 0b00010000; //запрет на цифровой вход TCCR0A = 0b11000001; //настройка выхода ШИМ OCR0A TCCR0B = 0b00000011; // выбор делителя //ADMUX = 0b00100011; //АЦП на входе PB3 //ADCSRA = 0b11101111;//запускаем АЦП, разрешаем прерывания //DIDR0 = 0b00001000; //запрет на цифровой вход //TCCR0A = 0b00110001; //настройка выхода ШИМ OCR0B //TCCR0B = 0b00000011; // выбор делителя sei(); while (1) {} }
Круто! Только не все строчки делают то, что Вы им приписываете. Не проще поставить ядро https://github.com/MCUdude/MicroCore и сделать всё средствами ардуино? Или хотя бы посмотреть в файлах ядра как правильно инициализировать периферию под Вашу задачу?
А что именно не так? скажите - если не сложно - я проверю ( возможно менял строки и комментарии оставил старые - код менял неоднократно) а по поводу средств ардуино IDE - можно , но я начитался даташита и примеров - так вроде даже проще - в нужном регистре биты выствил и работает ( магия!)
Если (магия) работает - вопросов бы не возникло. Значит не работает магия.
А вообще в коде (лично я, со своим скудоумием) только дичь вижу. Почему? Потому что сишный код, какие то действия делает, но... Но что вы хотите увидеть в действии от программы (с регуляторами всякмими там), которая просто висит в вечном цикле ничего при этом не делая?
так то конечно не наглядно выходит при чтении, но функционирует
, в ардуине например , я иногда в цикле делал дополнительную функцию - мигалку какую нибудь , чтоб определять, что цикл проходит, а тут просто по факту - меняется яркость свечения и даже осциллограф использовал - полюбоваться ШИМ сигналом - ну посмотрел форму, хотя и по светодиоду понятно, что он есть. Мне сейчас нужно алгоритм правильный найти , чтоб по прерыванию ( в данном случае - когда АЦП закончит преобразование, а возможно по таймеру) в программе "перекидывались бы каналы: последовательно "принял на входе -преобразовал - выдан ШИМ в нагрузку одноименного канала ....И переключился на второй канал"
Я конечно же новичек на форуме. Но не понимаю вообще ничего из вышеописанного. Как может работать код с миганиями разными, если в коде написано - «сделай что то один раз и крутись в вечном цикле»? Прерывания могут работать. Но их работу тут я тоже не вижу (код) или не умею так глубоко его читать (поясните).
К примеру в строке 26 и 27 два регистра, по даташиту смотрим - какой бит за что отвечает.
TCCR0A - "1" в определенном бите : в 1100 0000 - выход на OCR0A - это ножка 5 dip8, а 00110000 - ножка 6 dip8 - если инвертировать эти биты - то "перекидываем" выход с OCR0A на OCR0B.
Круто. Но это один раз до вечного цикла. А далее либо прерывание по таймеру должно быть и менять состояния или в цикле. Ни того ни другого не вижу. Поясните.
Вот тут и проблема: работает один канал - прерывание ниже - в нем на выход OCR0A записываем результат из регистра хранящего данные после обработки АЦП - это регистр ADCL|ADCH - нам интересен младший байт ADCH - запись результата происходит по прерыванию "окончание цикла преобразования" , чтоб получить не промежуточный результат на выходе, а финальное значение.
08
SIGNAL(ADC_vect)
09
//SIGNAL(SIG_ADC) на выбор два - один рабочий для attiny13, другой для attiny2313
10
{ OCR0A = ADCH;
//OCR0B = ADCH для второго канала;
11
PORTB ^=0b00000100;
//PORTB ^=0b00000100 для второго канала ;подтягивающий резистор на входе
12
}
в строках 30-34 натроен втрой канал - он у меня работает - если закоментить строки 23-27 , но нужно еще местами променять команду и комментарии в строках 10 и 11
В результате мы будем принимать сигнал с другого входа и управлять нагрузкой на другом выходе : был канал вход PB3 и выход OCR0A, а перекидываем на вход PB4 - выход OCR0B.
как прерывание по таймеру реализовать, чтоб не прервать цикл обработки , по окончании которого я записываю результат на выход - в нагрузку?
Мне кажется по прерываниям такое реализовать маловероятно. Нельзя прерыванием прервать прерывание (или выполнить что то ещё во время прерывания). Или я не до конца понял вопрос.
Прерывания можно прерывать прерываниями и логику работы можно (в некоторых случаях) полностью реализовать внутри прерываний. Но работа с прерываниями требует более глубокого понимания работы микроконтроллера и двумя строчками кода, как надеется ТС, тут не обойдешься.
Хорошо, пусть не двумя строками, а какой алгоритм можете рекомендовать .По главному прерыванию понятно - закончился процесс в АЦП - передали данные в регистр, далее повторяется цикл, вот как мне его перенастроить на второй канал?
Павел74, как-то так:
Вы волшебник, нет правильнее так ВОЛШЕБНИК. В прерывании так изящно расписано
ISR(ADC_vect) { ADMUX&1 ? (OCR0A = ADCH) : (OCR0B = ADCH); ADMUX^=1<<0; }
- когда я такое самостоятельно осилю - главное, что читается все понято!
видно , как вход поменяли, я пробовал - но просто проводил инверсию бита в прерывании - не сработало.
спасибо!
Мда..... красиво, но мне ардуиновый код понять для начала )
Ардуиновский почти как бейсик в школе : слова и команды почти на "человесеском языке", а тут вроде одни цифры - но это проще , выставил код в регистре и получил нужную настройку функций процессора.
Код, который мне DIMAX предоставил, за что ему огромная благодарность, позволяет внутри цикла прерывания добавить дополнительное преобразование сигнала, что я и сделал для эксперимента
Понятно, что чем код «ближе процессору» тем он компактнее и более производительный. Жалко, что с развитием многие об этом забывают. У меня браузер файрфокс жрет почти гиг памяти при 10 вкладках. Когда то на 256мб озу и ос крутилась и браузер столько не жрал. (Может я и ошибаюсь)
Мда..... красиво, но мне ардуиновый код понять для начала )
Ну кстати "ардуиновским" его сложно назвать, я даже писал этот код не в arduino ide, а в атмел студии :)
У меня корректно только IDE ардуиновкая установлена, поставил AVR Studio 4 - пока не разобрался с программой, в окружении рядом никого нет, что б подсмотреть работу и освоить.
DIMAX, добрый вечер!
я продолжаю эксперименты с Attiny13 - делал разные примеры для прерываниям по различным событиям , намигался всякими светодиодами, проверял код, а точнее значение переменной по количеству вспышек .
И вот в очередном эксперименте вернулся к нашей старой теме, которую вы помогли мне освоить: двухканальный шим, в тюни13 из можно реализовать 4!!!, это здорово, но мне пока хватает двух, а вот выходов на управление уже недостает. Задачи реализовать задуманное любой ценой не стоиит - это больше вопрос освоения новых знаний- задействовать процессор с ограниченным колич выводов - так интереснее ( иначе бы продолжал на ардуинке) .
На сей момент задумал задействовать два входа АЦП : по одному контролирую параметр, а вторым вношу корректировку порога сравнения этого параметра.
решил использовать Вашу подсказку со сменой входа ацп в прерывании по окончанию преобразования:
ранее в своей программке я добавил небольшую обработку значения ADCH и она работает, корректируя выходное значение:
Тогда была задача вывести эти значения на стрелочный индикатор, а сейчас выходы ШИМ мне не нужен.
Как можно хранить промежуточные значения преобразований каждого канала АЦП, чтоб по сравнению с пороговым значением выставлять "1" или "0" на выходах PB1 или PB0?
Ниже полностью Ваш код - только схему обвязки поменял - есть 1 аналоговый датчик и 1 потенциометр, задающий значение:
Компиляция без ошибок, код залился , работает следующим образом:
контролируемый параметр могу принудительно менять в некотором диапазоне, это видно на выходе PB0 - ШИМ светодиода ( можно задать прямой или инверсный), ручной регулятора потенциометра смещаю точку задания сравнения и изменение наблюдаю на втором канале - PB1 ШИМ светодиода.
Напрашивалось редактирование строки :
в
но так параметр не работает.
Как обойтись без OCR0A или OCR0B ?
В этом и увяз - как мне высвободить PB1 или PB0 под управление исполнительным элементом, а один ШИМ в принципе для индикации можно оставить.
Или единственная возможность - запись во флеш память?
Павел74, два раза прочитал, но так и не понял, что вам нужно.
Для упрощения действия с каналами можно развернуть в обычный if/else
Павел74, два раза прочитал, но так и не понял, что вам нужно.
Для упрощения действия с каналами можно развернуть в обычный if/else
высвободить ноги по видимому хотел )))
Краткая запись тоже очень удобна - но я попробую развернутую версию обязательно попробую прописать нужными командами.
Сейчас проблема исключительно для 8pin корпуса - мало ножек и заняв OCR0A и OCR0B свободных не остается а у меня есть задача не занимая этих выводов PB0 и PB1 под ШИМ, сохранять ГДЕ-ТО временные значения ADCH для некоторых арифметических операция и последующего сравнения, по результатам которого выдавать управляющий сигнал на PB1 или PB0
а в коде я обращаюсь к OCR0A и OCR0B
вот тут я остановился
именно - освободить ноги, не выводя ADCH на эти выводы , а сигналы обрабатывать программно
может я не совсем прав - но разве у тини13 не ОДИН АЦП? который просто можно 2 ноги по очереди читать?... тоетсь одновременно без перенастройки МК не получится ведь считывать аналоговый сигнал....
может я не совсем прав - но разве у тини13 не ОДИН АЦП? который просто можно 2 ноги по очереди читать?... тоетсь одновременно без перенастройки МК не получится ведь считывать аналоговый сигнал....
Да практически у всех атмелов и многих других микроконтроллерах АЦП один. Плюс аналоговый коммутатор который позволяет считывать сигнал с разных ножек, но, естественно, не одновременно.
Именно так и делается : срабатывает прерывание настроенное на окончание преобразования, результат преобразования из АЦП заносится в рег сравнения OCR0A ( или OCR0B) а далее переключается вход, соответственно меняется регистр хранения результата преобразования
Именно так и делается : срабатывает прерывание настроенное на окончание преобразования, результат преобразования из АЦП заносится в рег сравнения OCR0A ( или OCR0B) а далее переключается вход, соответственно меняется регистр хранения результата преобразования
Все смешалось в доме обломских :) . ОСR0A/B это регистры совпадения для таймера. К АЦП они никаким боком не отностятся.
именно для того и использовал - в верхней части темы было , это данные для управления шщим на выходах
Да, я просто #28 не так понял.
А в чем проблема с "сохранить ГДЕ-ТО временные значения ADCH для некоторых арифметических операция и последующего сравнения" ? Памяти не хватает?