Соединение АЦП при создании миди-контроллера (множество потенциометров)
Я делаю миди-контроллер с помощью Arduino Uno. Он содержит около 50 аналоговых входов с потенциометрами. У меня достаточно АЦП MCP3008, но я понятия не имею, как подключить 2 или более АЦП к Arduino, чтобы я мог прочитать 50. Как сложить АЦП?
@codGmer, 👍0
Обсуждение2 ответа
Эти АЦП используют протокол SPI. К счастью, в Arduino есть такой модуль.
С каждым АЦП вы получаете 8 каналов (таким образом, входов). Поскольку вам нужно более одного устройства SPI (в вашем случае АЦП).
С помощью SPI вы можете подключить несколько устройств SPI к порту SPI Arduino. Чтобы выбрать, какой из них активен, вы используете сигнал выбора чипа/ведомого устройства. Это отдельный GPIO, который вы можете определить самостоятельно. Узнайте больше о SPI, чтобы узнать подробности.
Для 50 входов необходимо 50/8, округляя вверх, получается 7 АЦП. Это означает также 7 контактов CS. Таким образом, всего вам понадобится 3 (для SPI) + 7 = 10 контактов. Надеюсь, у вас осталось столько же.
Что касается «стекирования», просто поместите АЦП на макетную плату и подключите их в соответствии с протоколом SPI.
См. также Справочный SPI Arduino
Обратите внимание, что при таком большом количестве устройств на шине SPI вам может потребоваться снизить скорость связи или включить драйвер линии, чтобы преодолеть повышенную емкость шины., @Majenko
Пониженная скорость будет встроена из-за максимальной тактовой частоты 3,6 МГц для MCP3008 — таким образом, тактовая частота SPI составит 2 МГц для Arduino с частотой 16 МГц., @CrossRoads
При использовании SPI SCK, MISO, MOSI подключаются параллельно ко всем устройствам. Устройство с активным низким выводом Chip Select — это то, которое получает команду, а затем отправляет данные, остальные игнорируют происходящее. Вы также можете загрузить данные в сдвиговый регистр для создания выбора микросхемы, поэтому для всех устройств необходимы только 4 контакта: SCK (13), MISO (12), MOSI (11) и использовать D10, контакт SS. поскольку штифт защелки (SRCK) в 74HC595 для чипа 7 переключается на MCP3008.
Код для цикла может быть довольно простым.
for (pin = 0; pin <7; pin = pin +1){
digitalWrite (csPin[pin], LOW); // select a device
SPI.transfer(startByte); // send out start byte
upperBits[pin + address] = SPI.transfer(addressByte [address]); // send out address, read in D9, D8
lowerBits[pin + address] = SPI.transfer(0); // send out don't care read in D7-D0
digitalWrite (csPin [pin), HIGH); // deselect a device
digitalWrite (csPin[pin], LOW); // select a device
SPI.transfer(startByte); // send out start byte
upperBits[pin + address+1] = SPI.transfer(addressByte [address+1]); // send out address, read in D9, D8
lowerBits[pin + address+1] = SPI.transfer(0); // send out don't care read in D7-D0
digitalWrite (csPin [pin), HIGH); // deselect a device
digitalWrite (csPin[pin], LOW); // select a device
SPI.transfer(startByte); // send out start byte
upperBits[pin + address+2] = SPI.transfer(addressByte [address+2]); // send out address, read in D9, D8
lowerBits[pin + address+2] = SPI.transfer(0); // send out don't care read in D7-D0
digitalWrite (csPin [pin), HIGH); // deselect a device
digitalWrite (csPin[pin], LOW); // select a device
SPI.transfer(startByte); // send out start byte
upperBits[pin + address+3] = SPI.transfer(addressByte [address+3]); // send out address, read in D9, D8
lowerBits[pin + address+3] = SPI.transfer(0); // send out don't care read in D7-D0
digitalWrite (csPin [pin), HIGH); // deselect a device
digitalWrite (csPin[pin], LOW); // select a device
SPI.transfer(startByte); // send out start byte
upperBits[pin + address+4] = SPI.transfer(addressByte [address+4]); // send out address, read in D9, D8
lowerBits[pin + address+4] = SPI.transfer(0); // send out don't care read in D7-D0
digitalWrite (csPin [pin), HIGH); // deselect a device
digitalWrite (csPin[pin], LOW); // select a device
SPI.transfer(startByte); // send out start byte
upperBits[pin + address+5] = SPI.transfer(addressByte [address+5]); // send out address, read in D9, D8
lowerBits[pin + address+5] = SPI.transfer(0); // send out don't care read in D7-D0
digitalWrite (csPin [pin), HIGH); // deselect a device
digitalWrite (csPin[pin], LOW); // select a device
SPI.transfer(startByte); // send out start byte
upperBits[pin + address+6] = SPI.transfer(addressByte [address+6]); // send out address, read in D9, D8
lowerBits[pin + address+6] = SPI.transfer(0); // send out don't care read in D7-D0
digitalWrite (csPin [pin), HIGH); // deselect a device
digitalWrite (csPin[pin], LOW); // select a device
SPI.transfer(startByte); // send out start byte
upperBits[pin + address+7] = SPI.transfer(addressByte [address+7]); // send out address, read in D9, D8
lowerBits[pin + address+7] = SPI.transfer(0); // send out don't care read in D7-D0
digitalWrite (csPin [pin), HIGH); // deselect a device
}
Конечным результатом являются два 56-байтовых массива, UpperBits[] и LowerBits[], объединяющие по байту каждого для чтения на канал.
У меня там много дублированного кода, который, вероятно, можно было бы свести к циклу внутри цикла, чтобы устранить избыточность.
Адрес также может быть получен из массива, так как данные должны быть 0b10000000, 0b10010000, 0b10100000, 0b10110000, 0b11000000, 0b11010000, 0b11100000, 0b11110000
или начните с адреса = 0x80 и добавьте 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70
Этот код должен интегрироваться для управления сдвиговым регистром, о котором я забыл, поэтому вместо
digitalWrite (csPin[pin], LOW);
and
digitalWrite (csPin[pin], HIGH);
у вас было бы
digitalWrite (shiftRegisterLatch, LOW); // первый низкий уровень CS MCP3008
SPI.transfer(0b11111110);
digitalWrite (shiftRegisterLatch, HIGH); //первый низкий уровень CS MCP3008
// читаем из ADC0 на первом MCP3008, используя SPI.transfers выше
digitalWrite (shiftRegisterLatch, LOW); // первый высокий уровень CS MCP3008
SPI.transfer(0b11111111);
digitalWrite (shiftRegisterLatch, HIGH); //первый высокий уровень CS MCP3008
Повторите действия для каналов от ADC1 до ADC7
Затем перейдите к следующему устройству:
digitalWrite (shiftRegisterLatch, LOW); // 2-й низкий уровень CS MCP3008
SPI.transfer(0b11111101);
digitalWrite (shiftRegisterLatch, HIGH); //2-й MCP3008 CS низкий
// читаем из ADC0 на втором MCP3008, используя SPI.transfers выше
digitalWrite (shiftRegisterLatch, LOW); // 2-й высокий уровень CS MCP3008
SPI.transfer(0b11111111);
digitalWrite (shiftRegisterLatch, HIGH); //2-й MCP3008 CS высокий
Таким образом, данные также могут быть в массиве: 0b11111110, 0b11111101, 0b11111011, 0b11110111, 0b11101111, 0b11011111, 0b10111111, с 0b11111111 для отключения CS
Я бы также использовал прямое манипулирование портом вместо digitalWrite(), чтобы ускорить фиксацию данных в сдвиговом регистре.
- Ускорение двигателя постоянного тока с помощью ШИМ
- Проблема с увеличением ШИМ с течением времени
- Регистр ADCH Arduino Uno завис на значении 255 при чтении из ISR
- Как прочитать значение АЦП без общего заземления? (Возможно или нет!)
- Потенциометр отображает только аналоговое значение напряжения 1023 в proteus
- Если я использую схему смещения для сигнала, поступающего на аналоговый вход, повлияет ли это на работу АЦП?
- Умеренно точный осциллограф на Arduino Uno R3
- Как эмулировать аналоговый потенциометр с помощью ШИМ
Также вопрос: http://forum.arduino.cc/index.php?topic=569402. Если вы собираетесь это сделать, пожалуйста, будьте достаточно внимательны и добавьте ссылки на другие места, где вы размещаете перекрестные сообщения. Это позволит нам избежать траты времени из-за дублирования усилий, а также поможет другим, у кого возникнут такие же вопросы и кто найдет ваше сообщение, найти всю необходимую информацию., @per1234
зачем вам использовать потенциометры? ..... цифровые кодеры имели бы гораздо больше смысла, @jsotola