Настройка опорного напряжения АЦП ATtiny88
Я пишу простое приложение, которое считывает напряжение с аналогового входа 0. Вот код:
#define OUT 5
#define ADC 0
void setup() {
ADMUX &= (0<<REFS0); //Установка внутреннего опорного напряжения 1,1 В
}
// процедура цикла выполняется снова и снова вечно:
void loop() {
// считываем входной сигнал на аналоговом выводе 0:
int sensorValue = analogRead(0);
float voltage = sensorValue * (1.1 / 1023.0);
if (voltage>0.5) {
digitalWrite(OUT,HIGH);
} else {
digitalWrite(OUT,LOW);
}
}
Когда я подаю 1 В на ADC0, вывод OUT низкий. Похоже, что опорное напряжение установлено неправильно. Когда я устанавливаю VREF на VCC (5 В), все работает нормально.
Я не могу найти ошибку. Буду признателен за любую помощь:)
Редактировать:
Ссылка на техническое описание: http://www.atmel.com/images/doc8008.pdf
@Em Ka, 👍3
Обсуждение2 ответа
В разделе настроек вам нужно установить или очистить все соответствующие биты в admux.
Это вопрос?, @Em Ka
Заявление
ADMUX &= (0<<REFS0);
Выполняет операцию И между текущим значением ADMUX и нулем, в результате чего получается нулевое значение, и оно сохраняется в ADMUX.
Чтобы очистить бит REFS0 в ADMUX, не затрагивая остальную его часть, обычно вместо этого говорят
ADMUX &= ~(1<<REFS0);
который выполнит операцию AND своего значения с дополнением 1<<REFS0.
Однако вам следует использовать утверждение
analogReference(INTERNAL);
вместо настройки ADMUX напрямую. Один из первых операторов, выполняемых в исходном коде analogRead(), это
ADMUX = (analog_reference << 6) | (pin & 0x07);
что переопределяет выбор ссылок, сделанный путем простого изменения ADMUX.
Параметры INTERNAL и DEFAULT для analogReference() выбирают либо внутренний опорный сигнал запрещенной зоны 1,1 В, либо аналоговый опорный сигнал по умолчанию, Vcc.
Правка 1: Если вы заменили ADMUX &= (0<<REFS0) на analogReference(INTERNAL) в настройке, и это все еще не работает, вам нужно будет применить более мощные средства отладки. Например, проверьте, что вы правильно скомпилировали скетч и что вы правильно его загрузили. Проверьте, что AVCC подключен к Vcc, желательно через фильтр нижних частот , как указано в разделах §1.1.2 и §17.9 «Методы аналогового шумоподавления» в техническом описании. Затем попробуйте несколько входных напряжений, чтобы увидеть, на каком уровне загорается светодиод. Если он никогда не загорается, поищите проблемы со светодиодом, используя простой скетч, например Blink. Если он загорается постоянно при каком-то входном напряжении, выясните, какой опорный сигнал применяется.
Правка 2: По-видимому, исходный код analogRead() отличается для деталей ATtiny по сравнению с другими. Код, который я вижу для него в ... /arduino/avr/cores/arduino/wiring_analog.c [ваш путь может отличаться], выглядит следующим образом (я опустил некоторые комментарии и пустые строки).
uint8_t analog_reference = DEFAULT;
void analogReference(uint8_t mode) {
analog_reference = mode;
}
int analogRead(uint8_t pin) {
#if defined( CORE_ANALOG_FIRST )
if ( pin >= CORE_ANALOG_FIRST ) pin -= CORE_ANALOG_FIRST; // разрешить номера каналов или контактов
#endif
ADC_SetVoltageReference( analog_reference );
ADC_SetInputChannel( pin );
ADC_StartConversion();
while( ADC_ConversionInProgress() );
return( ADC_GetDataRegister() );
}
Некоторые функции и константы ADC_... определены в ... avr/cores/tiny/core_adc.h; и то, какое определение ADC_SetVoltageReference() используется, зависит от условной компиляции. Для окончательной проверки того, как analogReference() определен для вашей части, найдите analogReference() в листинге сборки вашей программы. Получите этот листинг, как объяснено в нескольких ответах Arduino SE, например, в параграфе «Создание листингов сборки» в конце моего ответа на вопрос № 33033. Кроме того, в ветке forum.arduino.cc от конца апреля 2016 года есть обсуждение чтения входов АЦП на микроконтроллерах; не знаю, относится ли это к делу.
@EmKa, а это работает?, @James Waldby - jwpat7
Хорошо, я добавил analogReference(INTERNAL) вместо ADMUX &= (0<<REFS0) в разделе настроек, но это все равно не работает :( @jwpat7, @Em Ka
@EmKa, см. пункт 1. Какое у вас есть испытательное оборудование? Цифровой вольтметр? Осциллограф? Частотомер?, @James Waldby - jwpat7
У меня есть осциллограф. При использовании VCC он работает, более-менее нормально. Но мне нужны более точные измерения, поэтому я использую внутреннее опорное напряжение 1,1 В. @jwpat7, @Em Ka
При использовании "analogReference(INTERNAL)" выходной контакт всегда в состоянии низкого уровня. Однако с VCC (5 В) всё работает более-менее нормально. Есть небольшая ошибка, но она может быть связана с тем, что я питаю микроконтроллер от программатора, а он выдаёт напряжение ниже 5 В. В расчётах я использую 5 В @jwpat7, @Em Ka
И скетч успешно загружается и компилируется каждый раз. Может быть, это связано с тем, что я использую ATTINY 88? То есть, для этого конкретного микроконтроллера функция analogRead может работать по-другому? @jwpat7, @Em Ka
@EmKa, см. редактирование 2. И, пожалуйста, не стесняйтесь отметить этот ответ (нажмите зеленую стрелку), @James Waldby - jwpat7
- Измерить Vcc на ATtiny13a
- Микроконтроллер зависает при срабатывании затвора N-канального МОП-транзистора.
- При использовании Arduino Uno в качестве ISP: "Yikes! Invalid device signature" - плохое соединение, неверную конфигурацию или неверную версию avrdude?
- Связь ATtiny85 с компьютером через USB
- Получить доступ к EEPROM ATtiny с помощью кода Arduino?
- Постоянный выход тактовой частоты Arduino
- avrdude: ошибка проверки, первое несоответствие в байте 0x0000 : 0x00 != 0x16 с использованием USBasp
- Радиочастотное дистанционное управление с использованием VirtualWire на ATtiny85, работающем на частоте 8 МГц на внутреннем генераторе
Конечно, вот ссылка на техническое описание: http://www.atmel.com/images/doc8008.pdf, @Em Ka
@Rohat Kılıç Я считаю, что в ATTINY 88 нет такого понятия, как REFS1., @Em Ka