======= Arduino Nano RP2040 Connect: инструкция, примеры использования и документация ====== Используйте платформу [[amp>product/arduino-nano-rp2040-connect?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Nano RP2040 Connect]] для создания электронных гаджетов, метеостанций, роботов и других изобретений. Плата программируется на языке C++ или MicroPython и отлично подойдёт как начинающим мейкерам, так и опытным разработчикам. {{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect.1.jpg?nolink |}} ===== Программирование на C++ ===== {{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-software-arduino.1.png?nolink |}} Рассмотрим программирование Nano RP2040 Connect на языке C++ в среде Arduino IDE на компьютере под управлением Windows. ==== Подключение и настройка ==== - [[#запись_загрузчика|Запишите загрузчик Arduino в плату Nano RP2040]]. Если вы только купили плату или использовали её только в Arduino IDE, загрузчик записывать не нужно. - [[:articles:arduino-ide-install|Скачайте и установите Arduino IDE.]] - По умолчанию среда программирования настроена только на AVR-платы. Для работы с платформой Nano RP2040 Connect добавьте в менеджере плат поддержку [[articles:arduino-boards-manager#платформы_arduino_mbed_os_nano_boards|платформ Mbed OS Nano Boards]]. - Выберите плату Nano RP2040 Connect в IDE: Инструменты Плата Arduino Mbed OS Nano Boards Arduino Nano RP2040 Connect{{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-software-arduino.2.png?nolink |}} - Выберите COM-порт в IDE: Инструменты Порт COMx, где x — номер текущего порта.{{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-software-arduino.3.png?nolink |}} - Это значит, всё получилось и можно смело переходить к [[#примеры_работы1|примерам работы]]. [[https://docs.arduino.cc/hardware/nano-rp2040-connect|Документация на плату Arduino Nano RP2040 Connect.]] ==== Примеры работы ==== Рассмотрим несколько примеров программирования Nano RP2040 Connect на C++ через Arduino IDE. Библиотеки, которые используют в своём коде программируемый ввод-вывод PIO, используют нумерацию GPIO микроконтроллера RP2040 вместо Arduino. Подробности по нумерацию читайте в разделе [[#распиновка|Распиновка]]. Для стабильной работы примеров обновите все сторонние библиотеки до последней версии в менеджере библиотек. === Маячок === Для начала мигнём встроенным светодиодом LED на 13 пине. == Код для Arduino == // Даём имя встроенному светодиоду на 13 пине constexpr uint8_t LED_ARDUINO_PIN = 13; void setup() { // Настраиваем пин со светодиодом в режим выхода pinMode(LED_PIN, OUTPUT); } void loop() { // Зажигаем светодиод digitalWrite(LED_PIN, HIGH); // Ждём 1 секунду delay(1000); // Гасим светодиод digitalWrite(LED_PIN, LOW); // Ждём 1 секунду delay(1000); } После прошивки скетча светодиод начнёт мигать раз в секунду. {{ :products:arduino-nano-rp2040-connect:example-arduino-blink.gif?nolink |}} === Гирлянда === Главная фишка Nano RP2040 — это микроконтроллер, который поддерживает возможность программируемого ввода-вывода через блоки PIO, на которых можно реализовать произвольный интерфейс. В следующем примере заставим Arduino рулить светодиодами WS2812. == Что понадобится == * [[amp>product/arduino-nano-rp2040-connect?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Arduino Nano RP2040 Connect]] * [[amp>product/usb-cable-micro?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Кабель USB (A — Micro USB)]] * [[amp>product/breadboard-half?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Breadboard Half]] * [[amp>product/troyka-rgb-led-4x4?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Светодиодная матрица WS2812B 4×4]] * [[amp>product/wire-mm?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Соединительные провода «папа-папа»]] == Схема устройства == {{ :products:arduino-nano-rp2040-connect:example-ws2812-rainbow.1.png?nolink |}} == Код для Arduino == Для работы примера скачайте и установите библиотеку [[https://github.com/adafruit/Adafruit_NeoPixel/|Adafruit NeoPixel]]. // Библиотека для работы со светодиодами WS2812 #include // Номер пина, к которому подключена матрица WS2812 // Библиотека использует блок PIO, // который в свою очередь использует нумерацию // микроконтроллера RP2040, а не Arduino. constexpr uint8_t PIN_GPIO_WS2812 = 25; // Количество светодиодов в матрице constexpr uint8_t LED_COUNT = 16; // Создаём объект для работы со светодиодной матрицей Adafruit_NeoPixel matrix = Adafruit_NeoPixel(LED_COUNT, PIN_GPIO_WS2812, NEO_GRB + NEO_KHZ800); void setup() { // Инициализация матрицы matrix.begin(); // Устанавливаем яркость светодиодов // Диапазон значений от 0 до 255 matrix.setBrightness(40); } void loop() { // Заполняем матрицу по сегментам «бегущий огонь» красного цвета colorWipe(matrix.Color(255, 0, 0), 100); // Заполняем матрицу по сегментам «бегущий огонь» зелёного цвета colorWipe(matrix.Color(0, 255, 0), 100); // Заполняем матрицу по сегментам «бегущий огонь» синего цвета colorWipe(matrix.Color(0, 0, 255), 100); // Гасим матрицу по сегментам «бегущая тень» colorWipe(matrix.Color(0, 0, 0), 100); } // Функция заполнения каждого сегмента void colorWipe(uint32_t c, uint8_t wait) { for (uint16_t i = 0; i < matrix.numPixels(); i++) { // Заполняем текущий сегмент выбранным цветом matrix.setPixelColor(i, c); matrix.show(); // Ждём delay(wait); } } После прошивки управляющей платформы вы увидите заполнение по очереди каждого светодиода матрицы из красного, зелёного и синего цветов. {{ :products:arduino-nano-rp2040-connect:example-ws2812-rainbow.2.gif?nolink |}} === Вывод информации на дисплей === А теперь попробуем подружить плату с дисплеем и отобразить простой текст. == Что понадобится == * [[amp>product/arduino-nano-rp2040-connect?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Arduino Nano RP2040 Connect]] * [[amp>product/usb-cable-micro?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Кабель USB (A — Micro USB)]] * [[amp>product/breadboard-half?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Breadboard Full]] * [[amp>product/troyka-display-lcd-text-16x2?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Текстовый дисплей 16×2 (Troyka-модуль)]] * [[amp>product/wire-mm?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Соединительные провода «папа-папа»]] == Схема устройства== {{ :products:arduino-nano-rp2040-connect:example-print-text-lcd.1.png?nolink |}} == Код для Arduino == Для работы примера скачайте и установите библиотеку [[https://github.com/amperka/TroykaTextLCD|TroykaTextLCD]]. // Библиотека для работы с дисплеем #include // Номер пина, к которому подключена подсветка дисплея constexpr uint8_t PIN_ARDUINO_LCD_BACKLIGHT = A3; // I²C-адрес дисплея constexpr uint8_t LCD_SLAVE_ADDRESS = 0x3E; // Создаём объект для работы с дисплеем // передаём ему объект I²C, I²C-адрес и пин подсветки TroykaTextLCD lcd(&Wire, LCD_SLAVE_ADDRESS, PIN_ARDUINO_LCD_BACKLIGHT); void setup() { // Устанавливаем количество столбцов и строк экрана lcd.begin(16, 2); // Устанавливаем контрастность в диапазоне от 0 до 63 lcd.setContrast(45); // Устанавливаем яркость в диапазоне от 0 до 255 lcd.setBrightness(255); // Устанавливаем курсор в колонку 0, строку 0 lcd.setCursor(0, 0); // Печатаем первую строку lcd.print("Hello, world!"); // Устанавливаем курсор в колонку 0, строку 1 lcd.setCursor(0, 1); // Печатаем вторую строку lcd.print("Arduino RP2040"); } void loop() { } После прошивки управляющей платформы на дисплее отобразится приветствующий текст.{{ :products:arduino-nano-rp2040-connect:example-print-text-lcd.2.png?nolink |}} === Звуковая волна === Пришло время пошуметь, будем считывать звук со встроенного микрофона и выводить полученные данные в Serial Plotter. == Код для Arduino == Для работы примера скачайте и установите библиотеку [[https://www.arduino.cc/en/Reference/PDM|PDM]]. // Библиотека для работы с микрофоном #include // Количество аудио каналов constexpr uint8_t channels = 1; // Частота дискретизации constexpr uint32_t frequency = 16000; // Буфер для хранения семплов short sampleBuffer[512]; // Счётчик пришедших семплов volatile int samplesRead; // Границы верхнего и нижнего диапазона выводимого семпла // Для наглядной визуализации звуковой волны в Serial Plotter constexpr int32_t sampleLimitUpper = 3000; constexpr int32_t sampleLimitLower = -3000; void setup() { // Открываем Serial-порт Serial.begin(115200); while (!Serial); // Выполняем конфигурацию PDM.onReceive(onPDMdata); // Устанавливаем усиление сигнала PDM.setGain(1); // Инициализируем PDM if (!PDM.begin(channels, frequency)) { Serial.println("Failed to start PDM!"); while (1); } } void loop() { // Ожидаем семплы для считывания if (samplesRead) { // Печатаем семплы в Serial-порт for (int i = 0; i < samplesRead; i++) { Serial.print(sampleLimitLower); Serial.print("\t"); Serial.print(sampleBuffer[i]); Serial.print("\t"); Serial.println(sampleLimitUpper); } // сбрасываем счётчик семплов samplesRead = 0; } } // Функция для обработки данных с микрофона void onPDMdata() { // Запрашиваем количество пришедших байтов int bytesAvailable = PDM.available(); // Считываем данные в буфер PDM.read(sampleBuffer, bytesAvailable); // 16 бит, 2 байта на семпл samplesRead = bytesAvailable / 2; } После прошивки скетча запустите Serial Plotter. А затем попробуйте пошуметь — например, хлопнуть в ладоши или включить музыку.{{ :products:arduino-nano-rp2040-connect:example-microphone-serialplotter.png?nolink |}} === Визуализация объекта в пространстве === В продолжение приведём пример отображения платы в пространстве в виде самолёта, а для этого нам поможет встроенный IMU-сенсор. Для запуска примера необходимо прошить платформу Nano RP2040 кодом ниже и настроить графическую среду Processing. == Код для Arduino == Для работы примера скачайте и установите библиотеку [[https://www.arduino.cc/en/Reference/ArduinoLSM6DSOX|LSM6DSOX]]. // Библиотека для работы фильтра Madgwick #include // Библиотека для работы IMU-сенсора LSM6DSOXTR #include // Создаём объект для фильтра Madgwick Madgwick filter; // Переменные для данных с гироскопа и акселерометра float gx, gy, gz, ax, ay, az; // Переменные для хранения самолётных углов ориентации float yaw, pitch, roll; // Переменная для хранения частоты выборок фильтра float sampleRate = 100; void setup() { // Открываем последовательный порт Serial.begin(9600); // Выводим сообщение об неудачной инициализации IMU if (!IMU.begin()) { Serial.println("Failed to initialize IMU!"); } // Выводим сообщение об удачной инициализации IMU Serial.println("Success to initialize IMU"); // Инициализируем фильтр filter.begin(); } void loop() { // Запоминаем текущее время unsigned long startMillis = millis(); // Считываем данные с акселерометра в единицах G if (IMU.accelerationAvailable()) { IMU.readAcceleration(ax, ay, az); } // Считываем данные с гироскопа в градусах if (IMU.gyroscopeAvailable()) { IMU.readGyroscope(gx, gy, gz); } // Переводим показания гироскопа изградусов в радианы в секунду gx *= DEG_TO_RAD; gy *= DEG_TO_RAD; gz *= DEG_TO_RAD; // Устанавливаем частоту фильтра filter.setFrequency(sampleRate); // Обновляем входные данные в фильтр filter.update(gx, gy, gz, ax, ay, az); if (Serial.available() > 0) { int val = Serial.read(); // Если пришёл символ 's' if (val == 's') { float q0, q1, q2, q3; filter.readQuaternion(q0, q1, q2, q3); // Выводим кватернион в serial-порт Serial.print(q0); Serial.print(","); Serial.print(q1); Serial.print(","); Serial.print(q2); Serial.print(","); Serial.println(q3); } } // Вычисляем затраченное время на обработку данных unsigned long deltaMillis = millis() - startMillis; // Вычисляем частоту обработки фильтра sampleRate = 1000 / deltaMillis; } == Настройка Processing == - [[https://processing.org/|Скачайте и установите графическую среду Processing.]] - {{ :products:troyka-imu-10-dof-v2:toxiclibs.zip |Скачайте библиотеки для Processing}} и распакуйте их в директорию хранения модулей для Processing: userdir Processing libraries - [[#код_для_processing|Запустите на Processing программный код, расположенный ниже.]] == Код для Processing == import processing.serial.*; import toxi.geom.*; import toxi.processing.*; // NOTE: requires ToxicLibs to be installed in order to run properly. // 1. Download from http://toxiclibs.org/downloads // 2. Extract into [userdir]/Processing/libraries // (location may be different on Mac/Linux) // 3. Run and bask in awesomeness // The serial port Serial port; String message; float[] q = new float[4]; Quaternion quat = new Quaternion(1, 0, 0, 0); // New line character in ASCII final char newLine = '\n'; String [] massQ = new String [4]; float[] ypr = new float[3]; void setup() { // Size form 400x400 size(400, 400, P3D); // Open serial port // Replace "COM7" with the COM port on which your arduino is connected port = new Serial(this, "COM7", 9600); } void draw() { // Read and parse incoming serial message serialEvent(); // Set background to black background(0); printQuaternions(); printYawPitchRoll(); // Set position to centre translate(width / 2, height / 2); // Begin object pushMatrix(); float[] axis = quat.toAxisAngle(); rotate(axis[0], axis[2], axis[3], axis[1]); // Draw main body in red drawBody(); // Draw front-facing tip in blue drawCylinder(); // Draw Triangles drawTriangles(); // Draw Quads drawQuads(); // End of object popMatrix(); // Send character 's' to Arduino port.write('s'); } void serialEvent() { // Read from port until new line (ASCII code 13) message = port.readStringUntil(newLine); if (message != null) { // Split message by commas and store in String array massQ = split(message, ","); q[0] = float(massQ[0]); q[1] = float(massQ[1]); q[2] = float(massQ[2]); q[3] = float(massQ[3]); } // Print values to console print(q[0]); print("\t"); print(q[1]); print("\t"); print(q[2]); print("\t"); print(q[3]); println("\t"); // Set our toxilibs quaternion to new data quat.set(q[0], q[1], q[2], q[3]); } void drawCylinder() { float topRadius = 0; float bottomRadius = 20; float tall = 20; int sides = 8; // Begin object pushMatrix(); translate(0, 0, -120); rotateX(PI/2); fill(0, 0, 255, 200); float angle = 0; float angleIncrement = TWO_PI / sides; beginShape(QUAD_STRIP); for (int i = 0; i < sides + 1; ++i) { vertex(topRadius * cos(angle), 0, topRadius * sin(angle)); vertex(bottomRadius * cos(angle), tall, bottomRadius * sin(angle)); angle += angleIncrement; } endShape(); // if it is not a cone, draw the circular top cap if (topRadius != 0) { angle = 0; beginShape(TRIANGLE_FAN); // Center point vertex(0, 0, 0); for (int i = 0; i < sides + 1; i++) { vertex(topRadius * cos(angle), 0, topRadius * sin(angle)); angle += angleIncrement; } endShape(); } // If it is not a cone, draw the circular bottom cap if (bottomRadius != 0) { angle = 0; beginShape(TRIANGLE_FAN); // Center point vertex(0, tall, 0); for (int i = 0; i < sides + 1; i++) { vertex(bottomRadius * cos(angle), tall, bottomRadius * sin(angle)); angle += angleIncrement; } endShape(); } popMatrix(); } void drawBody() { fill(255, 0, 0, 200); box(10, 10, 200); } void drawTriangles() { // Draw wings and tail fin in green fill(0, 255, 0, 200); beginShape(TRIANGLES); // Wing top layer vertex(-100, 2, 30); vertex(0, 2, -80); vertex(100, 2, 30); // Wing bottom layer vertex(-100, -2, 30); vertex(0, -2, -80); vertex(100, -2, 30); // Tail left layer vertex(-2, 0, 98); vertex(-2, -30, 98); vertex(-2, 0, 70); // Tail right layer vertex( 2, 0, 98); vertex( 2, -30, 98); vertex( 2, 0, 70); endShape(); } void drawQuads() { beginShape(QUADS); vertex(-100, 2, 30); vertex(-100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80); vertex( 100, 2, 30); vertex( 100, -2, 30); vertex( 0, -2, -80); vertex( 0, 2, -80); vertex(-100, 2, 30); vertex(-100, -2, 30); vertex(100, -2, 30); vertex(100, 2, 30); vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, -30, 98); vertex(-2, -30, 98); vertex(-2, 0, 98); vertex(2, 0, 98); vertex(2, 0, 70); vertex(-2, 0, 70); vertex(-2, -30, 98); vertex(2, -30, 98); vertex(2, 0, 70); vertex(-2, 0, 70); endShape(); } void printQuaternions() { // Set text mode to shape textMode(SHAPE); textSize(13); fill(255, 255, 255); text("Quaternions:", 20, 20, 10); text(q[0], 20, 40, 10); text(q[1], 20, 60, 10); text(q[2], 20, 80, 10); text(q[3], 20, 100, 10); } void printYawPitchRoll() { // Calculate yaw/pitch/roll angles ypr[0] = atan2(2*q[1]*q[2] - 2*q[0]*q[3], 2*q[0]*q[0] + 2*q[1]*q[1] - 1) * 57.2; ypr[1] = atan2(2 * q[2] * q[3] - 2 * q[0] * q[1], 2 * q[0] * q[0] + 2 * q[3] * q[3] - 1) * 57.2; ypr[2] = -atan2(2 * (q[0] * q[2] - q[1] * q[3]), 1 - 2 * (q[2] * q[2] + q[1] *q[1])) * 57.2; text("Yaw:", 150, 20, 10); text(ypr[0], 150, 40, 10); text("Pitch:", 220, 20, 10); text(ypr[1], 220, 40, 10); text("Roll:", 290, 20, 10); text(ypr[2], 290, 40, 10); } При запуске визуализации на Processing откроется окно с графическим отображением платы в виде самолёта. Самолёт на экране будет повторять перемещения IMU-сенсора в пространстве. {{ :products:arduino-nano-rp2040-connect:example-imu-visualization-6dof-processing.png?nolink |}} === Соединение двух плат === Приведём пример, как соединить две платы по беспроводной сети. == Что понадобится == * 2× [[amp>product/arduino-nano-rp2040-connect?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Arduino Nano RP2040 Connect]] * 2× [[amp>product/usb-cable-micro?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Кабель USB (A — Micro USB)]] * 2× [[amp>product/breadboard-half?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Breadboard Half]] * 1× [[amp>product/troyka-rgb-led-4x4?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Кнопка (Troyka-модуль)]] * 1× [[amp>product/troyka-rgb-led-4x4?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Светодиод 5 мм / красный (Troyka-модуль)]] * 1× [[amp>product/wire-mm?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Соединительные провода «папа-папа» (65 шт.)]] == Схема Peripheral Device == {{ :products:arduino-nano-rp2040-connect:example-peripheral-device.1.png?nolink |}} == Схема Central Device == {{ :products:arduino-nano-rp2040-connect:example-central-device.1.png?nolink |}} == Код для Peripheral Device == // Библиотека для общения устройств по BLE #include // Номер пина, к которому подключена кнопка constexpr uint8_t PIN_ARDUINO_BUTTON = 19; // Переменная, для хранения состояния светодиода boolean ledSwitch; // BLE LED Service BLEService LEDService("19B10000-E8F2-537E-4F6C-D104768A1214"); // BLE LED Switch Characteristic - custom 128-bit UUID, read and writable by central BLEByteCharacteristic LEDCharacteristic("19B10001-E8F2-537E-4F6C-D104768A1214", BLERead | BLENotify | BLEWrite); void setup() { // Открываем Serial-порт Serial.begin(9600); // Ожидаем подключение по USB // Если не используете отладку, удалите строку while (!Serial); // Кнопку в режим входа pinMode(PIN_ARDUINO_BUTTON, INPUT); // Инициализируем BLE if (!BLE.begin()) { Serial.println("Starting BLE failed!"); } // Устанавливаем локальное имя BLE.setLocalName("Button Device LED"); // Устанавливаем службу UUID BLE.setAdvertisedService(LEDService); // Добавляем характеристику LEDService.addCharacteristic(LEDCharacteristic); // Добавляем сервис BLE.addService(LEDService); // Запускаем BLE.advertise(); Serial.println("BLE LED Peripheral, waiting for connections…"); } void loop() { // Слушаем все устройства BLE BLEDevice central = BLE.central(); // Если Central Device подключилось if (central) { Serial.print("Connected to central: "); // Выводим MAC-адрес подключенного устройства Serial.println(central.address()); // Пока Central Device подключено к переферийному while (central.connected()) { // Считываем состояние кнопки bool buttonState = digitalRead(PIN_ARDUINO_BUTTON); // Если кнопка нажата if (buttonState == LOW) { ledSwitch = !ledSwitch; delay(500); // Если светодиод не горит, включаем его // Если светодиод горит, выключаем его if (ledSwitch) { Serial.println("ON"); LEDCharacteristic.writeValue((byte)0x01); } else { LEDCharacteristic.writeValue((byte)0x00); Serial.println("OFF"); } } } // Если Central Device отключилось // Выводим сообщение в Serial-порт Serial.print(F("Disconnected from central: ")); Serial.println(central.address()); } } == Код для Central Device == // Библиотека для общения устройств по BLE #include // Номер пина, к которому подключен светодиод constexpr uint8_t PIN_ARDUINO_LED = 14; void setup() { // Открываем Serial-порт Serial.begin(9600); // Ожидаем подключение по USB // Если не используете отладку, удалите строку while (!Serial); // Светодиод в режим выхода pinMode(PIN_ARDUINO_LED, OUTPUT); // Инициализируем BLE BLE.begin(); Serial.println("BLE Central - LED control"); // Сканируем все устройства LED BLE peripherals BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214"); } void loop() { // Проверяем было ли найдено Peripheral Device BLEDevice peripheral = BLE.available(); // Если Peripheral Device найдено, выводим информацию в Serial-порт if (peripheral) { Serial.print("Found "); Serial.print(peripheral.address()); Serial.print(" '"); Serial.print(peripheral.localName()); Serial.print("' "); Serial.print(peripheral.advertisedServiceUuid()); Serial.println(); // Если имя Peripheral Device не содержит фразу «LED» // Выходим из функции if (peripheral.localName().indexOf("LED") < 0) { Serial.println("No 'LED' in name"); return; } // Останавливаем сканирование BLE.stopScan(); controlLed(peripheral); // Если Peripheral Device отключено, продолжаем сканирование BLE.scanForUuid("19b10000-e8f2-537e-4f6c-d104768a1214"); } } void controlLed(BLEDevice peripheral) { // Подключаемся к Peripheral Device Serial.println("Connecting ..."); if (peripheral.connect()) { Serial.println("Connected"); } else { Serial.println("Failed to connect!"); return; } // Сканируем свойства Peripheral Device Serial.println("Discovering attributes ..."); if (peripheral.discoverAttributes()) { Serial.println("Attributes discovered"); } else { Serial.println("Attribute discovery failed!"); peripheral.disconnect(); return; } // Получаем текущее состояние светодиода BLECharacteristic LEDCharacteristic = peripheral.characteristic( "19b10001-e8f2-537e-4f6c-d104768a1214"); if (!LEDCharacteristic) { Serial.println("Peripheral does not have LED characteristic!"); peripheral.disconnect(); return; } while (peripheral.connected()) { if (LEDCharacteristic.canRead()) { byte value = LEDCharacteristic.read(); LEDCharacteristic.readValue(value); if (value == 0x01) { Serial.println("ON"); digitalWrite(PIN_ARDUINO_LED, HIGH); } else if (value == 0x00) { digitalWrite(PIN_ARDUINO_LED, LOW); Serial.println("OFF"); } } delay(500); } Serial.println("Peripheral disconnected"); } == Запуск эксперимента == - Соберите схему двух устройств: [[#схема_peripheral_device|Peripheral Device]] и [[#схема_central_device|Central Device]] - Прошейте оба устройства соответствующим кодом ниже: [[#код_для_peripheral_device|Peripheral Device]] и [[#код_для_central_device|Central Device]] - Подключите Peripheral Device и Central Device к питанию. Для отладки советуем подключить Peripheral Device к одному ПК по USB, Central Device к другому ПК по USB. - При нажатии на кнопку на Peripheral Device, светодиод на Central Device должен менять своё состояния.{{ :products:arduino-nano-rp2040-connect:example-bluetooth-device-to-device.gif?nolink |}} ===== Программирование на MicroPython ===== {{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-software-micropython.1.png?nolink |}} Рассмотрим программирование Nano RP2040 Connect на языке MycroPython на компьютере под управлением Windows. ==== Подключение и настройка ==== - [[#запись_загрузчика|Запишите загрузчик MycroPython в плату Nano RP2040 Connect]]. - [[articles:thonny-python-ide|Скачайте и настройте Thonny Python IDE.]] - На этом всё, можно смело переходить к [[#примеры_работы1|примерам работы]]. ==== Примеры работы ==== Рассмотрим несколько примеров программирования Nano RP2040 Connect на MicroPython. Интерпретатор Python используют нумерацию GPIO микроконтроллера RP2040 вместо Arduino. Подробности про нумерацию читайте в разделе [[#распиновка|Распиновка]]. === Маячок === Для начала мигнём встроенным светодиодом LED на плате Nano RP2040. В коде используем нумерацию GPIO. == Код для MicroPython == # Библиотека для работы с пинами ввода-вывода from machine import Pin # Библиотека для работы с временем import time # Даём имя встроенному светодиоду # на 6 пине нумерации GPIO LED_GPIO_PIN = 6 # Светодиод в режим выхода на 6 пине led = Pin(6, Pin.OUT) while True: # Зажигаем светодиод led.value(1) # Ждём 1 секунду time.sleep(1) # Гасим светодиод led.value(0) # Ждём 1 секунду time.sleep(1) После прошивки скетча, светодиод начнёт мигать раз в секунду. {{ :products:arduino-nano-rp2040-connect:example-arduino-blink.gif?nolink |}} ===== Запись загрузчика ===== - [[#режим_загрузчика|Включите плату в режиме загрузчика.]] - Перетяните файл с прошивкой методом Drag-and-drop в устройство Flash-накопителя с именем RPI-RP2. - {{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-arduino-blink.zip |Загрузчик для Arduino IDE}} - [[https://micropython.org/download/rp2-pico/|Загрузчик для MycroPython.]] - Перезагрузите плату, нажав на кнопку RESET. ===== Режимы загрузки ===== Arduino Nano RP2040 Connect поддерживает два метода загрузки: [[#штатный_режим|штатный режим]] и [[#режим_загрузчика|режим загрузчика]]. ==== Штатный режим ==== Платформа загружается с [[#flash-память_at25sf128a-mhb-t|внешней Flash-памяти]], распаянной на плате Arduino Nano RP2040 Connect. В диспетчере устройств OS Windows плата отображается как виртуальный COM-порт с именем Устройство с последовательным интерфейсом USB. Режим служит для загрузки пользовательских программ через Arduino IDE, Thonny Python и друг сред разработки.{{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-bootsel-normal-mode.1.png?nolink |}} Активация режима происходит простым подключением платы по USB.{{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-bootsel-normal-mode.2.png?nolink |}} ==== Режим загрузчика ==== Платформа загружается с внутренней памяти микроконтроллера RP2040. В диспетчере устройств OS Windows плата отображается как съёмный накопитель с именем RPI-RP2. Режим служит для загрузки прошивки в формате UF2 простым перемещением файла с одного носителя на другой.{{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-bootsel-boot-mode.1.png?nolink |}} Активация режима: - Замкните между собой контакты REC и GND. В качестве перемычки используйте [[amp>product/jumper_pins_x10?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|джампер]] или [[amp>product/wire-mm?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|провод «папа-папа»]]. - Подключите плату к компьютеру по USB. - Разомкните между собой контакты REC и GND.{{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-bootsel-boot-mode.2.gif?nolink |}} ===== Элементы платы ===== {{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-annotation.png?nolink |}} ==== Микроконтроллер RP2040 ==== Платформа Arduino Nano RP2040 Connect выполнена на одноименном чипе {{ :products:arduino-nano-rp2040-connect:rp2040-datasheet.pdf |RP2040}} от компании Raspberry Pi Foundation. Кристалл содержит двухъядерный процессор на архитектуре ARM Cortex M0+ с тактовой частотой до 133 МГц. На RP2040 также расположились часы реального времени, датчик температуры и SRAM-память на 264 КБ. А [[#flash-память_at25sf128a-mhb-t|Flash-память на 16 МБ]] расположилась на плате отдельной микросхемой. ==== Flash-память AT25SF128A-MHB-T ==== Для хранения программ и сопутствующих статичных ресурсов на плате распаяна внешняя Flash-память {{ :products:arduino-nano-rp2040-connect:at25sf128a-mhb-t-datasheet.pdf |AT25SF128A-MHB-T}} объёмом 16 МБ. ==== Беспроводной модуль NINA-W102 ==== За беспроводную передачу данных отвечает чип {{ :products:arduino-nano-rp2040-connect:nina-w102-datasheet.pdf |U-blox NINA-W102}} со встроенным чипом ESP32 для обмена данными по воздуху в диапазоне 2,4 ГГц по Wi-Fi и Bluetooth. Для работы с модулем используйте библиотеку [[https://www.arduino.cc/en/Reference/WiFiNINA|WiFiNINA]]. ==== IMU-сенсор LSM6DSOXTR ==== Инерционный модуль на чипе {{ :products:arduino-nano-rp2040-connect:lsm6dsox-datasheet.pdf |LSM6DSOXTR}} трёхосевой акселерометр и трёхосевой гироскоп для распознавания движений и моушен-функций с жестами. Для работы с модулем используйте библиотеку [[https://www.arduino.cc/en/Reference/ArduinoLSM6DSOX|ArduinoLSM6DSOX]]. ==== Микрофон MP34DT05 ==== Встроенный цифровой микрофон {{ :products:arduino-nano-rp2040-connect:mp34dt05-a-datasheet.pdf |MP34DT05}} пригодится для распознавания коротких голосовых команд или записи звука. Для работы с модулем используйте библиотеку [[https://www.arduino.cc/en/Reference/PDM|PDM]]. ==== Крипточип ATECC608A ==== Криптографический сопроцессор Microchip {{ :products:arduino-nano-rp2040-connect:atecc608a-datasheet.pdf |ATECC608A}} интегрирует протокол безопасности ECDH (Elliptic Curve Diffie Hellman) в сверхзащищённый метод, обеспечивающий согласование ключей для шифрования / дешифрования, наряду с ECDSA (алгоритм цифровой подписи эллиптической кривой) для проверки подлинности с подписью для Интернета вещей (IoT), включая домашнюю автоматизацию, промышленные сети, медицинские услуги, аутентификацию аксессуаров и расходных материалов. ==== Преобразователь питания MP2332 ==== Понижающий DC-DC преобразователь {{ :products:arduino-nano-rp2040-connect:mp2322-datasheet.pdf |MP2322}} обеспечивает питание [[#микроконтроллер_rp2040|микроконтроллера RP2040]] и другой логики на плате. Диапазон входного напряжения от 5 до 18 вольт. Выходное напряжение 3,3 В с максимальным выходным током 1 А. ==== Светодиодная индикация ==== ^ Имя светодиода ^ Назначение ^ | ON |Индикатор питания платформы. | | L | Пользовательский светодиод, подключенный к пину GPIO6 микроконтроллера RP2040. При задании значения высокого уровня светодиод включается, при низком – выключается. Для управления светодиодом в Arduino IDE используйте нумерацию Arduino — пин 13 или определение LED_BUILTIN. А в среде Thonny Python используйте нумерацию портов микроконтроллера PR2040 — пин 6.| | RGB | Пользовательский RGB-светодиод с общим анодом. Катоды красного, зелёного и синего цвета выведены на пины GPIO27, GPIO25 и GPIO26 беспроводного модуля NINA-W102. При задании значения высокого уровня светодиоды выключаются, при низком – включаются. Для управления RGB-светодиодом в Arduino IDE используйте библиотеку [[https://www.arduino.cc/en/Reference/WiFiNINA|WiFiNINA]] и встроенные определения LEDR, LEDG и LEDB. | ==== Порт micro-USB ==== Разъём USB Micro предназначен для прошивки и питания платформы. Для подключения к ПК понадобится [[amp>product/usb-cable-micro?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|кабель USB (A — Micro USB)]]. ==== Кнопка сброса ==== Кнопка предназначена для ручного сброса прошивки — аналог кнопки RESET обычного компьютера. ===== Распиновка ===== [[this>_media/products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-pinout.pdf|{{:products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-pinout.png}}]] ===== Принципиальная схема ===== [[this>_media/products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-schematic.pdf|{{:products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-schematic.png}}]] ===== Габаритный чертеж ===== [[this>_media/products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-dimensions.pdf|{{:products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-dimensions.png}}]] ===== Характеристики ===== * Модель: Arduino Nano RP2040 Connect (SKU ABX00053) * Чипы и периферийные устройства: * Микроконтроллер RP2040 * Внешняя Flash-память AT25SF128A-MHB-T * Беспроводной модуль NINA-W102 * Инерциальный датчик LSM6DSOXTR * МЭМС-микрофон MP34DT05 * Крипто чип ATECC608A * RGB-светодиод * Входное напряжение питания: * Через USB: 5 В * Через пин Vin: 5–18 В * Напряжение логических уровней: 3,3 В * Контакты ввода-вывода: 22 * Контакты с АЦП: 8 * Разрядность АЦП: 12 бит * Контакты с ШИМ: 20 * Каналы DMA: 12 * Аппаратные интерфейсы: * 1× UART * 1× I²C * 1× SPI * Программируемый интерфейс PIO: * До 8 подпрограмм одновременно * До 26 контактов одновременно * Размеры: 44,3×17,7×14,2 мм ==== Микроконтроллер RP2040 ==== * Модель: Raspberry Pi RP2040 * Количество ядер: 2× ARM Cortex-M0+ (32 бита) * Тактовая частота: 133 МГц * Оперативная память: 264 КБ ==== Внешняя Flash-память AT25SF128A-MHB-T ==== * Модель: Adesto Technologies AT25SF128A-MHB-T * Объём памяти в чипе: 16 МБ * Интерфейс: QSPI * Скорость передачи: до 532 Мбит/с * Циклы перезаписи: 100000 ==== Беспроводной модуль NINA-W102 ==== * Модель: U-blox NINA-W102 * Количество ядер: 2× Tensilica Xtensa LX6 (32 бита) * Тактовая частота: до 240 МГц * Flash-память: 2 МБ * ROM-память: 448 КБ * SRAM-память: 520 КБ * Частотный диапазон связи: 2,4 ГГц * Стандарт Wi-Fi: 802.11b/g/n * Стандарт Bluetooth: BLE v4.2 BR/EDR * Встроенная антенна: планарная F-образная (PIFA) ==== IMU-сенсор LSM6DSOXTR ==== * Модель: ST LSM6DSOXTR * Частота обновления 3-осевого акселерометра: 1,6–6664 Гц * Диапазон измерения ускорения: ±2/±4/±8/±16g * Частота обновления 3-осевого гироскопа: 12,5–6664 Гц * Диапазон измерения поворота: ±125/±250/±500/±1000/±2000 град./с * Дополнительные аппаратные возможности: * Активация сценариев при наклоне устройства * Режим шагомера — продвинутое определение и подсчёт шагов * Конечные автоматы (FSM) и ядро машинного обучения для распознавания жестов и сценариев ==== Микрофон MP34DT05 ==== * Модель: ST MP34DT05 * Тип: микроэлектромеханический (MEMS), всенаправленный * Точка акустической перегрузки (AOP): 122,5 дБ * Чувствительность: -26 дБ * Отношение сигнал/шум: 64 дБ ==== Крипточип ATECC608A ==== * Модель: криптографический сопроцессор Microchip ATECC608A * Защищённое хранилище для криптографических ключей * Аппаратная поддержка симметричных алгоритмов шифрования: * SHA-256 / HMAC * AES-128 * Встроенный генератор случайных чисел: NIST SP 800-90A/B/C * Безопасная загрузка с цифровой подписью ECDSA ===== Ресурсы ===== * [[amp>product/arduino-nano-rp2040-connect?utm_source=man&utm_campaign=arduino-nano-rp2040-connect&utm_medium=wiki|Arduino Nano RP2040 Connect]] в магазине. * [[https://github.com/amperka/hardware-drawings/blob/master/arduino-nano-rp2040-connect.svg|Векторное изображение Nano RP2040 Connect]] * {{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-3d.zip |3D-файлы Nano RP2040 Connect}} ==== Полезные статьи ==== * [[articles:arduino-ide-install|Подключение и настройка Arduino IDE]] * [[articles:thonny-python-ide|Подключение и настройка Thonny Pyhon IDE]] ==== Документация ==== * [[https://docs.arduino.cc/hardware/nano-rp2040-connect|Документация на плату Arduino Nano RP2040 Connect]] * {{ :products:arduino-nano-rp2040-connect:arduino-nano-rp2040-connect-datasheet.pdf |Datasheet на Nano RP2040 Connect}} * {{ :products:arduino-nano-rp2040-connect:rp2040-datasheet.pdf |Datasheet на микроконтроллер RP2040}} * {{ :products:arduino-nano-rp2040-connect:at25sf128a-mhb-t-datasheet.pdf |Datasheet на внешнюю Flash-память AT25SF128A-MHB-T}} * {{ :products:arduino-nano-rp2040-connect:nina-w102-datasheet.pdf |Datasheet на беспроводной модуль NINA-W102}} * {{ :products:arduino-nano-rp2040-connect:lsm6dsox-datasheet.pdf |Datasheet на IMU-сенсор LSM6DSOX}} * {{ :products:arduino-nano-rp2040-connect:mp34dt05-a-datasheet.pdf |Datasheet на микрофон MP34DT05}} * {{ :products:arduino-nano-rp2040-connect:atecc608a-datasheet.pdf |Datasheet на крипточип ATECC608A}} * {{ :products:arduino-nano-rp2040-connect:mp2322-datasheet.pdf |Datasheet на преобразователь питания MP2322}} ==== Библиотеки ==== * [[https://www.arduino.cc/en/Reference/WiFiNINA|Библиотека для беспроводного модуля NINA-W102]] * [[https://www.arduino.cc/en/Reference/ArduinoLSM6DSOX|Библиотека для IMU-сенсора LSM6DSOXTR]] * [[https://www.arduino.cc/en/Reference/PDM|Библиотека для микрофона MP34DT05]]