Как правильно читать АЦП на ATtiny85?

Что я хочу сделать: подключить шесть кнопок к одному входу. Каждая кнопка запускает отдельное действие.

Как я хочу это сделать: использовать AD-преобразование и добавить к каждой кнопке резистор с разными номиналами, чтобы можно было различать разные входные сигналы
Я использую следующие значения: 1 к, 4,7 к, 18 к, 22 к, 55 к, 300 к

Vcc стабильно 3,3 В, но я пробовал и на 5 В. Я использую Vcc в качестве опорного значения для АЦП.

У меня проблема: что бы я ни делал, я всегда считываю одно и то же значение на АЦП. При подключении к GND он показывает 0, а при Vcc — значение, которое всегда одинаково, независимо от того, какой резистор я на самом деле использую.

Я перепробовал многое, что нашел в Интернете, но мне ничего не помогло. Я явно делаю что-то не так

Это метод, который я вызываю в setup() для инициализации преобразователя на ADC2(pb4)

void initADC()
{
  // 8-битное разрешение
  // устанавливаем ADLAR в 1, чтобы активировать результат сдвига влево (доступны только биты ADC9..ADC2)
  // тогда для 8-битных результатов (256 значений) достаточно только чтения ADCH

  ADMUX =
            (1 << ADLAR) |     // результат сдвига влево
            (0 << REFS1) |     // Устанавливает ссылку. напряжение до VCC, бит 1
            (0 << REFS0) |     // Устанавливает ссылку. напряжение до VCC, бит 0
            (0 << MUX3)  |     // используем АЦП2 для входа (PB4), бит 3 мультиплексора
            (0 << MUX2)  |     // используем ADC2 для входа (PB4), бит MUX 2
            (1 << MUX1)  |     // используем АЦП2 для входа (PB4), бит мультиплексора 1
            (0 << MUX0);       // используем АЦП2 для ввода (PB4), бит мультиплексора 0

  ADCSRA = 
            (1 << ADEN)  |     // Включаем АЦП
            (1 << ADPS2) |     // устанавливаем прескалер на 64, бит 2
            (1 << ADPS1) |     // устанавливаем прескалер на 64, бит 1
            (0 << ADPS0);      // устанавливаем прескалер на 64, бит 0
}

Код взят отсюда https://www.marcelpost.com/wiki/index.php/ATtiny85_ADC

Похоже, что страница в данный момент недоступна, поэтому вот ее архивная версия. https://web.archive.org/web/ 20230128091128/https://www.marcelpost.com/wiki/index.php/ATtiny85_ADC

В методе loop() я делаю в основном следующее: считываю АЦП, а затем мигаю светодиодом n раз в зависимости от считанного значения.

ADCSRA |= (1 << ADSC);         // начинаем измерение АЦП
while (ADCSRA & (1 << ADSC) ); // ждем завершения преобразования

uint8_t adcValue = ADCH;

if (adcValue >= 0 && adcValue < 32) {
  blink(1);
} else if (adcValue >= 32 && adcValue < 126) {
  blink(2);
} else if (adcValue >= 126 && adcValue < 193) {
  blink(3);
} else if (adcValue >= 193 && adcValue < 227) {
  blink(4);
} else if (adcValue >= 227 && adcValue < 245) {
  blink(5);
} else if (adcValue >= 245 && adcValue <= 255) {
  blink(6);
}
delay(60000);

На моей макетной плате резисторы идут от Vcc к пустой строке, и я подключаю перемычку от PB4 к одному из этих резисторов и выполняю внешний сброс микроконтроллера, чтобы проверить свою настройку. Они имеют общий GND/Vcc

Что я делаю не так? Что я могу сделать, чтобы отладить это?

Спасибо

, 👍0

Обсуждение

вы забыли подключить резистор между аналоговым входом и землей...исследуйте делитель напряжения, @jsotola

Используете ли вы ядро Arduino, которое не поддерживает AnalogRead(), или есть другая причина, по которой вы напрямую считываете регистры АЦП? АЦП имеет разрядность 10 бит, поэтому может считывать аналоговые значения до 1023. Позволяет ли ваше приложение одновременно нажимать две или более кнопок? Если у вас есть мультиметр, вы можете проверить напряжение между аналоговым контактом и землей при нажатии кнопки., @6v6gt

Как ни странно, кто-то ещё также хотел подключить шесть кнопок к ATtiny85, чтобы «Подключить 6 кнопок с 6 разными резисторами к одному выводу АЦП контроллера». Это удивительное совпадение!, @Nick Gammon

@NickGammon К сожалению, я не могу понять, пытаешься ли ты быть смешным или саркастичным. Это тот же проект, но другой вопрос., @boop

Добавление к вашему вопросу схемы, показывающей хотя бы все, что подключено к выводу A/D, помогло бы!, @JRobert

«К сожалению, я не могу понять, пытаетесь ли вы быть смешным или саркастичным…». Это не помогает. Пожалуйста, сосредоточьте свои усилия на предоставлении ответов на дополнительные вопросы, которые вам задали и на которые пока нет ответа. Кстати, в природе школьных заданий несколько экземпляров одного и того же вопроса могут появляться в разных обличиях., @6v6gt

@6v6gt Я не собирался быть нахальным. Меня просто смутил комментарий ника, поэтому я попытался объяснить., @boop

в вопросе нет принципиальной схемы... невозможно определить, как ОП всё связал... голосование за закрытие за неясностью, @jsotola

Честно говоря, мне действительно было интересно, было ли это задание. Также, возможно, предыдущий вопрос о том же самом мог помочь, так что это был указатель на то, чтобы проверить это., @Nick Gammon

@NickGammon Думаю, это зашло слишком далеко, но оно должно стать игрушкой для моей дочери. Не задание, @boop

Хорошо, извини, что сомневался в тебе., @Nick Gammon


1 ответ


Лучший ответ:

1

К сожалению, @jsotola опубликовал свое решение только в виде комментария. Но это был правильный ответ. Поэтому я просто опубликую свое решение здесь

Теперь я использую делитель напряжения со следующими значениями:

Формула делителя напряжения Vs * R2 / (R1 + R2)

Против: 3,3 В
R2: 100 кОм
R1: 10 к (3,0 В), 27 к (2,8 В), 38 к (2,6 В), 50 к (2,2 В), 65 к (2,0 В)

Используя 8-битный АЦП, я придумал эти операторы if, чтобы различать входные данные. Я дал ему немного места для отклонений

if (adcValue >= 227 && adcValue <= 237)
{
  // 10 кОм (3,0 В -> АЦП 232)
}
else if (adcValue >= 212 && adcValue <= 223)
{
  // 18 кОм (2,8 В -> АЦП 217)
}
else if (adcValue >= 196 && adcValue <= 206)
{
  // 27 кОм (2,6 В -> adc 201)
}
else if (adcValue >= 181 && adcValue <= 191)
{
  // 38 кОм (2,4 В -> АЦП 186)
}
else if (adcValue >= 165 && adcValue <= 175)
{
  // 50 кОм (2,2 В -> 170 АЦП)
}
else if (adcValue >= 150 && adcValue <= 160)
{
  // 65 кОм (2,0 В -> 155 АЦП)
}

Вот изображение моего макета. Я знаю, что это не настоящая схема, но сейчас я не мог этого понять. Но я надеюсь, что это достаточно хорошо

,

комментарий - единственное, что было уместно... можно было высказать только предположение из-за отсутствия информации в вопросе, @jsotola

Я не вижу здесь шести кнопок. Это работа в стадии разработки?, @Nick Gammon

@NickGammon Я просто вставил разные резисторы, чтобы проверить каждый из них один за другим. Это было проще, чем настраивать 6 кнопок, и этого было достаточно. Просто нужно было знать, работает ли это в целом, @boop

Кажется, в ваших диапазонах есть некоторые пробелы. Например, что, если adcValue равно 238? Но, возможно, это намеренно. Вероятно, вы могли бы переписать его так, чтобы оно выполняло только тесты «больше, чем». Например, >= 227, затем, если это не удается, >= 212 и так далее. Тестирование другого предела кажется излишним., @Nick Gammon

Неясно, имеет ли это значение в данном случае использования, но резистор 65 кОм, включенный параллельно с резистором 50 кОм, фактически представляет собой резистор 28,2 кОм. С учетом допусков это очень близко к резистору 27 кОм, который вы также используете, а это означает, что может быть трудно отличить одно нажатие кнопки от, по крайней мере, некоторых комбинаций нескольких нажатий кнопок., @6v6gt