Запутанная распиновка на MH-ET ATTiny88
Я немного озадачен аналоговыми контактами на Arduino ATTiny88.
Во-первых, правильно ли я понимаю, что функции analogRead()
и analogWrite()
могут использовать либо строку A0 - A7, либо десятичное число в качестве входов? Поскольку мне нужно использовать выводы A7, A0, A1, A2m A3 и A4 - в таком порядке - как аналоговые входы и A6 как аналоговый выход, было бы гораздо удобнее использовать десятичные цифры вместо вышеупомянутых строк.
Если так, то у меня также есть небольшой вопрос по поводу самих чисел. Мне кажется, что номера выводов начинаются с 0, а не с 1, поэтому правые выводы начинаются с 15, а аналоговые выводы начинаются с 17 (A6) по 24 (A5). Так что могу ли я просто сканировать аналоговые выводы, начиная с analogRead(18)
, и увеличивать каждый вывод на единицу через analogRead(23)
и использовать analogWrite(17)
, или мне нужно построить таблицу строк и перебирать ее?
Я просмотрел документацию по разным платам, и она мне не совсем ясна. Цифровые выводы немного более согласованы, хотя и не полностью. D0, D1 и D2 находятся на тех местах, где обычно находятся выводы 30–32, а цифровые выводы 3–25 смещены на 1 от обычной схемы нумерации. Некоторые другие платы Arduino имеют еще более странные схемы нумерации. (И да, я понимаю, почему распиновка на плате не совпадает в точности с распиновкой на микроконтроллере.)
Пока что мне не удалось заставить аналоговые входы работать, как я ни старался. Я пробовал:
Value = analogRead(A0);
Value = analogRead(A7);
Value = analogRead(17);
for (uint8_t x=17; x < 24; X++)
{
Value = analogRead(x);
}
Очевидно, я предварил все эти вызовы, определив порты с помощью pinMode(xx, INPUT)
, используя идентичные целевые значения. Ни один из них, похоже, не вернул подходящее значение, учитывая напряжения на входах. (Примерно 3 вольта на каждом выводе, что должно было вернуть значение около 600.)
@LesRhorer, 👍1
3 ответа
Лучший ответ:
Это все еще кажется мне странным, но я получил ответ, который работает. В попытке обнаружить правильные порты для использования функций analogRead() и analogWrite я создал этот тестовый скетч:
#include <Arduino.h>
#include <TM1637Display.h>
// Создаем объект отображения типа TM1637Display
TM1637Display display(4, 3);
int BatteryValue = 0;
void setup()
{
// Примечание: настройка аналоговых контактов в качестве входов не требуется.
display.setBrightness(0x0f); // Инициализация дисплея
display.clear(); // Очистить дисплей
}
void loop()
{
// Перемещение по ячейкам батареи
for (int x = 1; x < 26; x++)
{
display.showNumberDec(x, false); // Использование TM1637 для отображения номера контакта
delay(1500);
BatteryValue = analogRead(x); // Считать значение номера контакта
display.showNumberDec(BatteryValue, false); // Отображение аналогового значения пина
delay(2000);
}
}
Сначала я попытался инициализировать выводы как входы, но оказалось, что это не нужно и, как оказалось, может вызвать проблемы. Вывод скетча совершенно ясно показал, какие выводы являются аналоговыми входами. Эта плата использует выводы 11 - 16 в коде для считывания выводов, обозначенных на плате как A7 и A0 - A4 соответственно, и вывод 10 для записи на A6 на плате. Это имеет смысл в некотором роде извращенным образом, если мы возьмем числа как шестнадцатеричные значения, а не десятичные. В любом случае, этот код теперь работает идеально:
#include <Arduino.h>
int BatteryValue = 0;
void setup()
{
analogWrite(10, 128); // Отправляем ШИМ на аналоговый вывод 10
}
void loop()
{
// Перемещение по ячейкам батареи
for (int x = 11; x < 17; x++)
{
BatteryValue = analogRead(x);
}
}
Все попытки использовать A0, 17 и т. д. не увенчались успехом.
Мне нужно использовать контакты A7, A0, A1, A2, A3 и A4 — именно в таком порядке
Если вы хотите считывать данные АЦП с каналов в нужном вам порядке, все, что вам нужно сделать, это создать массив, содержащий контакты в последовательности, соответствующей вашему порядку, и получить доступ к каждому из них с помощью индекса.
int adcChannels[]{A7, A0, A1, A2, A3, A4};
for (int i=0; i<sizeof(adcChannles; i++) {
int adcValue = analogRead(adcChannel[i]);
}
Кстати, основываясь на вашем комментарии, я нашел Arduino Core (он же Arduino framework), который вы используете в интернете. Основываясь на определении платы для MH-ET LIVE Tiny88, определение аналоговых выводов можно найти здесь. Они частично в последовательности с выводами 19-24 для A1-A5 и выводами 17-18 для A6-A7.
Еще один момент, наименование пина A0
не является строкой. Это просто наименование переменной, как
static const uint8_t A0 = 19;
Ожидания
Прежде всего, правильно ли я понимаю, что функции
analogRead()
иanalogWrite()
могут использовать в качестве входных данных либо строку A0 - A7, либо десятичное число?
Это требует разбора, чтобы объяснить, что правильно (или, скорее, должно было быть правильным), а что нет. A0
, A1
являются «идентификаторами», а не строками, и обычно оцениваются как некоторое значение типа int
. Эти выводы связаны с использованием analogRead()
. analogWrite()
не имеет строгой связи с этими выводами. В некоторых случаях ни один из выводов A0
, A1
и т. д. не поддерживает выход ШИМ или ЦАП.
Для analogRead()
вы более или менее правы. Нормой является то, что используемые числа A0
, A1
и т. д. больше, чем наибольший номер канала АЦП. И это позволяет записать analogRead()
таким образом, чтобы принять либо номер канала АЦП, либо один из идентификаторов, начинающихся с A
.
Основная ошибка
Однако код ядра MHEtLiveArduino, который позволяет это сделать, неисправен. И если вам интересно, как это сделать:
#elif defined(__AVR_ATtiny88__)
if (17 <= pin <= 18) pin -= 11; // allow for channel or pin numbers
else if (19 <= pin <= 24) pin -= 19;
#else
if (pin >= 14) pin -= 14; // allow for channel or pin numbers
#endif
В разделе #else
вы можете увидеть код, который используется для более распространенных UNO R3 (и некоторых других), которые имеют чипы ATmega8/168/328 с 14 (от 0 до 13 включительно) «цифровыми», но не «аналоговыми» контактами. Аналоговые контакты отображаются на номера от 14 и выше. Они вычитают 14, чтобы преобразовать номер контакта в номер канала АЦП, который позже попадает в аппаратный регистр ADMUX
.
Код, который MHET прикрутил к исходному коду ядра AVR (в разделе #elif defined(__AVR_ATtiny88__)
), содержит несколько операторов if с условиями, которые принимают форму A <= B <= C
. Это обычная математическая нотация, которая будет работать в Python, но для C (или C++) ее необходимо переписать как A <= B && B < lt;= C
. C (и C++) трактуют A < lt;= B <= C
более буквально как (A < lt;= B) < lt;= C
; они проверяют, является ли истинностное значение A <= B
(0 или 1) меньшим, чем C
, что редко кому-то нужно.
Итак, MHET имеет if (17 < lt;= pin < lt;= 18)
, что всегда истинно независимо от значения pin
. 17 < lt;= pin
равно либо 0, либо 1. Оба значения 0 и 1 равны <= 18
. Поэтому, какое бы число вы ни указали для pin
, оно будет равно pin -= 11
. pin
имеет тип uint8_t
. Поэтому они вычитают из него 11 и позволяют уменьшить по модулю 0x100. Позже берут младшие четыре бита для номера канала АЦП.
Исправление ядра
Если хотите, вы можете найти и исправить wiring_analog.c установленного ядра MHET, исправив условия if
:
if (17 <= pin && pin <= 18) pin -= 11;
else if (19 <= pin && pin <= 24) pin -= 19;
ATtinycore
Вероятно, лучше перейти на ATTinyCore. Кажется, они поддерживают отображение выводов MHtiny.
- NodeMCU - Vin контакт как выход 5V?
- Использовать все контакты как цифровые входы/выходы
- При использовании Arduino Uno в качестве ISP: "Yikes! Invalid device signature" - плохое соединение, неверную конфигурацию или неверную версию avrdude?
- Что такое ICSP pin (разъём)?
- Сколько датчиков может поддерживать один модуль Arduino?
- NodeMCU - использовать кнопку flash в качестве входного сигнала в loop()
- Связь ATtiny85 с компьютером через USB
- Какой тип разъема использует система GROVE?