Разница в распиновке (типы?) Uno/Mega

Как человек, который разбирается в Arduino, я начал свой первый проект Arduino 5 часов назад, не имея никаких предварительных знаний об Arduino (хотя у меня есть опыт программирования, я включил это на случай, если я упустил что-то очевидное для ветеранов здесь). Пока что мне удалось подключить 3 SSD1306 SPI OLED-дисплея к моему Uno и создать скрипт, который позволяет мне управлять каждым дисплеем отдельно. Поскольку моя цель — заставить 5 дисплеев работать от одного Arduino, я решил прикрепить все к моему Mega, так как у него больше выходов (пока не уверен в различиях между ЦИФРОВЫМ ШИМ на Uno и 53 дополнительными ЦИФРОВЫМИ контактами на Mega).

Первая проблема, с которой я столкнулся, заключается в том, что я не смог найти, где в демонстрационном скрипте был указан тактовый импульс. Он закреплен на Uno на выводе 13, но в этом скрипте это нигде не указано, и я думаю, что как только я пойму разницу в выводах обеих плат, я смогу помочь себе сделать еще несколько шагов в будущее.

Итак, подведем итог моим вопросам.

  1. Как или где указывается ClockPulse.
  2. Могу ли я использовать 53 ЦИФРОВЫХ контакта на Mega вместо 13 ЦИФРОВЫХ PMW, которые есть на моем Uno, и если да, нужно ли мне менять некоторые настройки?

Вот мой текущий скрипт, который работает на моем Uno, но не на моем Mega, даже если я использую те же самые контакты DIGITAL PMW на моем Mega.

#include "HCuOLED.h"
#include "SPI.h"

//#define CS_DI 10
//#define DC_DI 9
//#define RST_DI 8

//HCuOLED HCuOLED_1(SSD1307, CS_DI, DC_DI, RST_DI); // For SSD1307 displays (HCMODU0050 & HCMODU0052)
HCuOLED HCuOLED_1(SSD1307, 10, 9, 8); // For SSD1307 displays (HCMODU0050 & HCMODU0052)
HCuOLED HCuOLED_2(SSD1307, 7, 6, 5); // For SSD1307 displays (HCMODU0050 & HCMODU0052)
HCuOLED HCuOLED_3(SSD1307, 4, 3, 2); // For SSD1307 displays (HCMODU0050 & HCMODU0052)


void setup()
{
  HCuOLED_1.Reset();
  HCuOLED_2.Reset();
  HCuOLED_3.Reset();
}

void loop()
{
  //display 1
  HCuOLED_1.SetFont(Terminal_8pt);
  HCuOLED_1.Cursor(44,0);
  HCuOLED_1.Print("Cpt");
  HCuOLED_1.Cursor(20,10);
  HCuOLED_1.Print("Fastlane");

  HCuOLED_1.Cursor(14,24);
  HCuOLED_1.SetFont(LCDLarge_24pt);
  HCuOLED_1.Print("KM/H");
  HCuOLED_1.Refresh();

  HCuOLED_1.ClearBuffer();

  //display 2
  HCuOLED_2.SetFont(Terminal_8pt);
  HCuOLED_2.Cursor(44,0);
  HCuOLED_2.Print("Cpt");
  HCuOLED_2.Cursor(20,10);
  HCuOLED_2.Print("Fastlane");

  HCuOLED_2.Cursor(14,24);
  HCuOLED_2.SetFont(LCDLarge_24pt);
  HCuOLED_2.Print("RPM");
  HCuOLED_2.Refresh();

  HCuOLED_2.ClearBuffer();

  //display 3
  HCuOLED_3.SetFont(Terminal_8pt);
  HCuOLED_3.Cursor(44,0);
  HCuOLED_3.Print("Cpt");
  HCuOLED_3.Cursor(20,10);
  HCuOLED_3.Print("Fastlane");

  HCuOLED_3.Cursor(14,24);
  HCuOLED_3.SetFont(LCDLarge_24pt);
  HCuOLED_3.Print("Info");
  HCuOLED_3.Refresh();

  HCuOLED_3.ClearBuffer();
}

А вот и оригинальный сценарий:

#include "HCuOLED.h"
#include "SPI.h"

/* Example bitmap */
const PROGMEM byte Tiny_Logo_Resistor[] =
{
  0xC0, 0xE0, 0x30, 0x30, 0xF0, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x38, 0x0E, 0x07, 0x1E, 0x78, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x70, 0x1C, 0x07, 0x0F, 0x3C, 0xF0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0x3C, 0x0F, 0x07, 0x1C, 0x70, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x78, 0x1E, 0x07, 0x0E, 0x38, 0xE0, 0x80, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xF0, 0x30, 0x30, 0xE0, 0xC0,
  0x00, 0x01, 0x03, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x3C, 0x38, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1E, 0x38, 0x1C, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x38, 0x38, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x1C, 0x38, 0x1E, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0E, 0x38, 0x3C, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x01, 0x00,
};


/* Digital pin number for the displays chip select pin */
#define CS_DI 10
/* Digital pin number for the displays data/command pin */
#define DC_DI 9
/* Digital pin number for the displays reset pin */
#define RST_DI 8

/* Array indexes for the X and Y coordinates */
#define X1 0
#define Y1 1
#define X2 2
#define Y2 3

/* Arrays to store coordinates and direction for the line, rectangle and bitmap */
byte Box[4] = {1,1,20,20};
byte BoxDir[4] = {1,1,1,1};
byte Line[4] = {100,25,120,55};
byte LineDir[4] = {-1,-1,-1,-1};
byte Bitmap[2] = {40,40};
byte BitmapDir[2] = {-1,-1};



/* Create an instance of the library (uncomment one of the lines below) */
//HCuOLED HCuOLED(SSD1307, SS_DI, DC_DI, RST_DI); // For SSD1307 displays (HCMODU0050 & HCMODU0052)
HCuOLED HCuOLED(SH1106, CS_DI, DC_DI, RST_DI); // For SH1106 displays (HCMODU0058 & HCMODU0059)


void setup()
{

  /* Reset the display */
  HCuOLED.Reset();
}

void loop()
{
  /* Display some text using a small 8x8 fixed width font */
  HCuOLED.SetFont(Terminal_8pt);
  HCuOLED.Cursor(44,0);
  HCuOLED.Print("HOBBY");
  HCuOLED.Cursor(20,10);
  HCuOLED.Print("COMPONENTS");

  /* Display a number using a large 4 line LCD style font */
  HCuOLED.Cursor(20,24);
  HCuOLED.SetFont(LCDLarge_24pt);
  HCuOLED.Print("HCuOLED");

  /* Change the draw mode from NORMAL to INVERT */
  HCuOLED.DrawMode(INVERT);
  while(1)
  {
    /* Move the positions of the 3 objects */
    MoveRect();
    MoveLine();
    MoveBitmap();

    /* Draw the objects to the display buffer */
    HCuOLED.Rect(Box[X1],Box[Y1],Box[X2],Box[Y2], SOLID);
    HCuOLED.Line(Line[X1],Line[Y1],Line[X2],Line[Y2]);

    HCuOLED.Cursor(Bitmap[X1],Bitmap[Y1]);
    HCuOLED.Bitmap(84, 2, Tiny_Logo_Resistor);

    /* Write the display buffer to the screen */
    HCuOLED.Refresh();

    /* Draw the objects again. As we are in INVERT mode this will remove them */
    HCuOLED.Rect(Box[X1],Box[Y1],Box[X2],Box[Y2], SOLID);
    HCuOLED.Line(Line[X1],Line[Y1],Line[X2],Line[Y2]);

    HCuOLED.Cursor(Bitmap[X1],Bitmap[Y1]);
    HCuOLED.Bitmap(84, 2, Tiny_Logo_Resistor);
  }
}


/* Update the X and Y coordinates for the box */
void MoveRect(void)
{
  if(Box[X1] == 0 || Box[X1] == 127)
    BoxDir[X1] *= -1;
  Box[X1] += BoxDir[X1];

  if(Box[Y1] == 0 || Box[Y1] == 63)
    BoxDir[Y1] *= -1;
  Box[Y1] += BoxDir[Y1];

  if(Box[X2] == 0 || Box[X2] == 127)
    BoxDir[X2] *= -1;
  Box[X2] += BoxDir[X2];

  if(Box[Y2] == 0 || Box[Y2] == 63)
    BoxDir[Y2] *= -1;
  Box[Y2] += BoxDir[Y2];   
}

/* Update the X and Y coordinates for the Line */
void MoveLine(void)
{
  if(Line[X1] == 0 || Line[X1] == 127)
    LineDir[X1] *= -1;
  Line[X1] += LineDir[X1];

  if(Line[Y1] == 0 || Line[Y1] == 63)
    LineDir[Y1] *= -1;
  Line[Y1] += LineDir[Y1];

  if(Line[X2] == 0 || Line[X2] == 127)
    LineDir[X2] *= -1;
  Line[X2] += LineDir[X2];

  if(Line[Y2] == 0 || Line[Y2] == 63)
    LineDir[Y2] *= -1;
  Line[Y2] += LineDir[Y2];   
}

/* Update the X and Y coordinates for the bitmap */
void MoveBitmap(void)
{
  if(Bitmap[X1] == 0 || Bitmap[X1] == 43)
    BitmapDir[X1] *= -1;
  Bitmap[X1] += BitmapDir[X1];

  if(Bitmap[Y1] == 0 || Bitmap[Y1] == 47)
    BitmapDir[Y1] *= -1;
  Bitmap[Y1] += BitmapDir[Y1];
}

, 👍1


1 ответ


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

2

Вы взаимодействуете со своими OLED-дисплеями с помощью SPI - последовательного периферийного интерфейса. Это специальное аппаратное периферийное устройство, встроенное в микроконтроллер, и его выходы физически подключены внутри микроконтроллера к тому, что становится контактами 11-13 на Arduino UNO.

Это и другие вещи, такие как UART, ШИМ и аналоговые входы, известны как альтернативные функции контактов.

В небольших микроконтроллерах, таких как Arduino, эти функции зафиксированы на аппаратном уровне (более продвинутые микроконтроллеры используют систему, позволяющую сопоставлять функции с различными контактами).

Когда вы используете SPI на UNO, он всегда использует контакты 11-13 (MOSI, MISO и SCK в этом порядке). Когда вы используете SPI на Mega, он всегда использует контакты 51, 50 и 52 (в этом порядке для тех же функций). Вы не можете это изменить. Контакт 10 на UNO — это контакт выбора ведомого устройства, и это снова альтернативная функция, которая жестко запрограммирована. На Mega эта функция — контакт 53.

Чтобы SPI работал как мастер (что вам и нужно), то контакт 10 на UNO или контакт 53 на Mega должны быть установлены на ВЫХОД. Неважно, используете ли вы его на самом деле, но он должен быть установлен на ВЫХОД, поскольку это определяет направление работы периферийного устройства SPI.

Таким образом, для Mega вам нужно будет подключить OLED-дисплеи к контактам 51, 50 и 52 вместо контактов 11, 12 и 13. Вы можете использовать контакт 53 как один из контактов выбора микросхемы (хотя вам это не обязательно, главное, чтобы вы установили его на ВЫХОД).

Кстати, вы можете сохранить пины в своей настройке, поделившись некоторыми из них. Единственный пин, который должен быть уникальным для каждого OLED, — это пин выбора чипа. Это пин, который сообщает OLED, что с ним разговаривают. Только когда этот пин активен, OLED будет слушать любой из других пинов.

Единственное, что вам может понадобиться подключить отдельно, это контакты сброса, поскольку вы сбрасываете дисплеи по очереди — сброс второго приведет к сбросу первого и отмене конфигурации. TBH Я бы подключил контакты сброса OLED к одному выводу и указал другой (неиспользуемый или несуществующий) вывод в конструкторах для сброса — затем вручную сбросил бы все OLED вместе с помощью одного НИЗКОГО импульса контакта сброса, а затем вызвал бы функции сброса для каждого дисплея, что должно настроить их все.

Таким образом, вы используете только (приведены примеры номеров выводов UNO):

  • МОСИ (11)
  • МИСО (12)
  • ССК (13)
  • DC (7)
  • СБРОС (6)
  • CS1 (10)
  • CS2 (9)
  • CS3 (8)
,

Удивительная вещь! Мне, вероятно, придется прочитать ее пару раз, прежде чем я смогу полностью ее понять. Я не до конца понимаю часть RESET, потому что, как я ее вижу, мне кажется, что я не могу обойтись без использования одного контакта на плате на дисплей, будь то обычным способом или вручную. Не могли бы вы пояснить? Разделяя контакты постоянного тока, я освобождаю еще 3 контакта, что позволяет мне добавить 2 экрана, и у меня есть еще один контакт, который в конечном итоге будет управлять моей полосой оборотов (еще не разобрался с этим, но это будет полоса светодиодов, которая будет принимать данные об оборотах)., @sdieters

Кроме того, если я подключил контакты 50 и 52 (теперь не использую контакт 10 на UNO), могу ли я назначить DC, RESET и CS любому из остальных 49 цифровых контактов на MEGA? (пост стал слишком длинным), @sdieters

Да, DC, CS и RESET могут быть любыми выводами, которые вам нравятся (даже аналоговыми выводами). Когда вы делитесь выводами (например, DC), все дисплеи получают настройку DC (HIGH или LOW), но только один из них что-то делает с ней — дисплей, у которого в данный момент вывод CS LOW., @Majenko

О, теперь понятно (я думаю, ха-ха). То есть я могу объединить все пины, кроме CS, и вместо выполнения обычной команды .display(), я сначала вручную устанавливаю выход для любого пина CS для дисплея, который я хочу обновить, на LOW, а затем использую функцию .display() (после обновления данных для отображения, то есть)?, @sdieters

Библиотека сделает это за вас. Просто повторите те же числа в конструкторах., @Majenko

Ах, точно. Опять же, это уже ОГРОМНАЯ помощь в понимании того, как работают эти платы. Я по профессии разработчик игр, так что я привык все делать сам, ха-ха., @sdieters

Я возвращаюсь к этому на секунду. Есть ли способ рассчитать, хватит ли у UNO или MEGA мощности процессора/памяти, чтобы справиться с тем, что я хочу? Прямо сейчас я собираюсь использовать 5 OLED-экранов, 4 будут только текстовыми белыми, пятый будет цветным для предупреждающих лампочек растровых изображений. Помимо этого я собираюсь добавить индикатор оборотов примерно с 30 RGB-светодиодами., @sdieters

@sdieters Это практически невозможно узнать. Не так важно, что вы подключаете, как то, что вы с ними делаете. И это во многом зависит от того, как работают используемые вами библиотеки и т. д. У Mega2560 больше памяти (как флэш-памяти, так и ОЗУ), чем у Uno, но все равно ее немного по сравнению с более современными микроконтроллерами. Обязательно прочтите об использовании PROGMEM для экономии ОЗУ — это будет вашей самой важной областью., @Majenko

Будет сделано! Что вы имеете в виду под более современными MCU? Я всегда думал, что Mega — это флагман среди любительских MCU для самостоятельного изготовления., @sdieters

@sdieters Сейчас существует множество гораздо более мощных MCU, чем старые 8-битные. Множество 32-битных, использующих ядра ARM или MIPS. Гораздо быстрее, гораздо больше памяти, гораздо больше флэш-памяти, более мощные периферийные интерфейсы и т. д., @Majenko

Охх, надо будет заняться этим, когда начну проектировать более мощную цифровую панель. Надеюсь, с ними будет так же легко работать, как с Arduino, @sdieters

Ну, в общем, они используют тот же API - часто добавляя больше функций. Иногда даже тот же футпринт. Я работаю почти исключительно с chipKIT. Teensy очень популярен., @Majenko

Хорошо, похоже, я не могу заставить его работать при совместном использовании других контактов. В настоящее время я совместно использую все контакты, кроме контакта CS, и использую следующие контакты: VCC=3.3v, GND=GND, SCK=13, SDA=11, DC=10, RST=9 CS(display1)=8, CS(display2)=7, CS(display3)=6. Странно, что в настоящее время я заставляю работать только дисплей 3, остальные 2 ничего не делают. При добавлении других 2 дисплеев на контакты 5 и 4 без их использования в моем коде они просто мерцают (вроде как и ожидалось, поскольку они не получают данных и не сбрасываются). Я не менял ничего в скрипте, кроме переназначения контактов Defined Vars и CS, @sdieters

Ладно, теперь все работает! Забыл удалить лишние команды RESET. Я подумал, что если вызвать эти RESET 3 раза в течение одного цикла, то теперь, когда они все подключены, работать будет только 3-й дисплей, а 2 других будут постоянно сбрасываться... У меня в настройке только одна команда HCuOLED_1.Reset() вместо 3 для каждого дисплея., @sdieters

Теперь я также могу без усилий добавить еще 2 дисплея, просто подключив их к оставшимся пинам. Еще раз спасибо за всю вашу поддержку! Не уверен, разрешено ли это, но если вы хотите следить за тем, над чем я работаю, ищите мою страницу на FBdotCOMslashCPTfastlane =), @sdieters

После некоторого перерыва в проекте я вернулся к нему, чтобы заставить его работать с моим MEGA. Однако даже без установки вывода 53 на ВЫХОД в функции настройки он все еще работает. Почему так? Подробности того, что я сделал, можно найти здесь: https://arduinoprosto.ru/q/56301/getting-spi-ssd1307-to-work-on-arduino-mega/56314#56314, @sdieters