Протокол Inter-Integrated Circuit (I2C)
Обеспечивает обмен данными между устройствами или датчиками, подключёнными через шину Two Wire Interface.
Авторы: Nicholas Zambetti, Karl Söderby, Jacob Hylén
Последняя редакция: 30.09.2025
Введение
Хороший способ добавить сложность функций в ваши проекты, не усложняя при этом схему подключения, — это использование протокола Inter-Integrated Circuit (I2C). Протокол I2C поддерживается на всех платах Arduino. Он позволяет подключить несколько периферийных устройств — датчики, дисплеи, драйверы двигателей и прочее — всего с помощью нескольких проводов. Это даёт большую гибкость и ускоряет прототипирование без избыточного количества проводов. Продолжайте читать, чтобы узнать, как это работает, как реализуется в разных стандартах, а также как использовать библиотеку Wire для создания собственных устройств I2C.
Что такое I2C?
Протокол I2C предполагает использование двух линий для отправки и приёма данных: контакт тактового сигнала (SCL), который плата-контроллер Arduino тактирует с постоянным интервалом, и контакт данных (SDA), по которому данные передаются между двумя устройствами.
В I2C существует одно устройство-контроллер и одно или несколько периферийных устройств, подключённых к линиям SCL и SDA контроллера.
По мере того как тактовый сигнал меняется с низкого уровня на высокий (так называемый передний фронт тактового импульса), один бит информации передаётся от платы к устройству I2C по линии SDA. По мере продолжения тактирования передаётся всё больше и больше битов, пока не формируется последовательность из 7- или 8-битного адреса и команды или данных. Когда эта информация передаётся — бит за битом — вызываемое устройство выполняет запрос и передаёт свои данные обратно — если это требуется — плате по той же линии, используя тактовый сигнал, всё ещё генерируемый контроллером по линии SCL в качестве синхронизации.
Каждое устройство на шине I2C функционально независимо от контроллера, но будет отвечать с информацией по запросу контроллера.
Поскольку протокол I2C позволяет каждому подключённому устройству иметь собственный уникальный адрес, а и устройства-контроллеры, и периферийные устройства поочерёдно передают данные по одной линии, ваша плата Arduino может общаться (по очереди) со многими устройствами или другими платами, используя всего два контакта микроконтроллера.
Сообщение I2C на уровне отдельных битов выглядит примерно следующим образом:
Сообщение I2C
Контроллер отправляет инструкции через шину I2C по контакту данных (SDA), и инструкции предваряются адресом, чтобы только правильное устройство их слушало.
Затем идёт бит, обозначающий, хочет ли контроллер читать или писать.
Каждое сообщение должно быть подтверждено во избежание неожиданных результатов — как только получатель подтвердил предыдущую информацию, он сообщает об этом контроллеру, чтобы тот мог перейти к следующему набору битов.
8 бит данных
Ещё один бит подтверждения
8 бит данных
Ещё один бит подтверждения
Но как контроллер и периферийные устройства знают, где начинается и заканчивается адрес, сообщения и прочее? Для этого и служит провод SCL. Он синхронизирует тактовый сигнал контроллера с устройствами, гарантируя, что все они переходят к следующей инструкции одновременно.
Однако вам практически никогда не придётся _фактически_ задумываться об этом: в экосистеме Arduino есть библиотека Wire, которая всё делает за вас.
Контакты I2C на Arduino
Ниже приведена таблица с различными форм-факторами плат и соответствующими контактами I2C.
Форм-фактор |
SDA |
SCL |
SDA1 |
SCL1 |
SDA2 |
SCL2 |
|---|---|---|---|---|---|---|
UNO |
SDA/A4 |
SCL/A5 |
||||
Nano |
A4 |
A5 |
||||
MKR |
D11 |
D12 |
||||
GIGA |
D20 |
D21 |
D102 |
D101 |
D9 |
D8 |
Mega & Due |
D20 |
D21 |
Подключение по I2C
Ниже вы найдёте несколько способов подключения модулей-переходников I2C. Оптимальный вариант зависит от конкретного модуля и ваших потребностей.
Платы-переходники (Breakout Boards)
Некоторые модули-переходники позволяют подключить их напрямую, с помощью проводов на макетной плате. Чтобы подключить такой модуль к плате Arduino, соедините их следующим образом:
VCC* — контакт 5V/3V3 (в зависимости от модуля-переходника)
GND* — GND
SDA — SDA
SCL — SCL
*Название контакта может варьироваться в зависимости от модуля: VCC может называться «VIN», «+» и т.д. GND может называться «-».
Вот пример того, как можно подключить датчик к UNO R4 WiFi:
Простое подключение I2C к UNO R4 WiFi
Qwiic и STEMMA QT
Исследуя рынок модулей-переходников и датчиков, вы обнаружите, что существуют целые экосистемы, где стандарты строятся вокруг протокола I2C. Примеры таких стандартов — Qwiic, разработанный SparkFun, и STEMMA QT, разработанный Adafruit®. Оба стандарта — Qwiic и STEMMA QT — используют 4-контактный разъём JST SH для устройств I2C, что упрощает разработку оборудования третьими сторонами с широкой совместимостью. Наличие стандартизированного разъёма означает, что если вы видите слова Qwiic или STEMMA QT рядом с каким-либо устройством, оно будет работать вместе с платой Arduino, имеющей разъём Qwiic или STEMMA QT, — например, с UNO R4 WiFi.
Оба стандарта — Qwiic и STEMMA QT — объединяют провода питания, земли, а также провода SDA и SCL для I2C, образуя полный комплект: один кабель, в котором всё собрано воедино.
I2C через разъём Qwiic/STEMMA QT с UNO R4 WiFi
В чём же разница между ними?
Оба стандарта — Qwiic и STEMMA QT — используют I2C, и даже при детальном осмотре модулей, работающих по этим двум стандартам, может быть сложно понять, чем они отличаются. Но разница есть! И она имеет некоторые последствия для того, как и для чего вы их можете использовать.
Qwiic имеет согласование уровней и стабилизацию напряжения на стороне контроллера (но не на стороне периферийных устройств). Это означает, что Qwiic работает только с логикой 3,3 В. Это делает его более простым в использовании, поскольку для конечного пользователя исключается один из возможных источников проблем при проектировании и сборке схемы.
STEMMA QT, напротив, не имеет такого ограничения. Это позволяет использовать логику и 3,3 В, и 5 В для модулей. Это также означает, что при создании схемы вам, возможно, придётся учитывать ещё один момент, однако это обеспечивает большую гибкость в требованиях к питанию и логике.
Порядок контактов STEMMA QT совпадает с порядком контактов Qwiic, что обеспечивает кросс-совместимость между двумя стандартами.
Grove
Grove — ещё один стандарт разъёмов, на этот раз разработанный компанией Seeed Studio. Вы можете найти множество модулей с разъёмом Grove, однако только некоторые из них используют I2C. Ни одна плата Arduino не имеет встроенного разъёма Grove, однако вы можете использовать такие изделия, как MKR Connector Carrier, Nano Grove Shield или Base Shield из комплекта Arduino Sensor Kit, чтобы подключить датчики Grove к вашей плате Arduino.
Библиотека Wire
Библиотека Wire — это то, что Arduino использует для взаимодействия с устройствами I2C. Она включена во все пакеты плат, поэтому устанавливать её вручную не нужно.
Полную документацию по API библиотеки Wire смотрите на её странице документации.
begin()— инициализирует шину I2Cend()— закрывает шину I2CrequestFrom()— запрашивает байты от периферийного устройстваbeginTransmission()— начинает постановку передачи в очередьendTransmission()— передаёт поставленные в очередь байты и завершает передачуwrite()— записывает данные от периферийного устройства к контроллеру или наоборотavailable()— возвращает количество байтов, доступных для чтенияread()— читает байт, переданный от периферийного устройства к контроллеруsetClock()— изменяет тактовую частотуonReceive()— регистрирует функцию, вызываемую при получении передачи периферийным устройствомonRequest()— регистрирует функцию, вызываемую при запросе данных контроллеромsetWireTimeout()— устанавливает тайм-аут для передач в режиме контроллераclearWireTimeoutFlag()— сбрасывает флаг тайм-аутаgetWireTimeoutFlag()— проверяет, произошёл ли тайм-аут с момента последнего сброса флага
Производные библиотеки
Когда вы покупаете практически любой модуль-переходник, использующий протокол I2C, вместе с ним, как правило, поставляется библиотека, которая помогает работать с датчиком. Такая библиотека чаще всего строится поверх библиотеки Wire и использует её внутри. Она добавляет функциональность, чтобы, например, упростить считывание температуры.
Пример: если вы хотите использовать модуль датчика MCP9808 от Adafruit, вы скачиваете библиотеку Adafruit_MCP9808 из менеджера библиотек IDE, которая позволяет использовать такие функции, как:
tempsensor.readTempC()
чтобы считать температурные данные датчика, запрашивая правильный адрес и читая возвращаемую информацию всего одной строкой кода, вместо того чтобы самостоятельно писать код на Wire.
Чтобы узнать, как устанавливать библиотеки, ознакомьтесь с нашим руководством по установке библиотек.
Примеры
Оставшаяся часть этой статьи представляет собой подборку примеров, которые помогут вам быстро начать работу с I2C.
Controller Reader (Контроллер-читатель)
Платы Arduino, соединённые по I2C
В некоторых ситуациях бывает полезно настроить две (или более!) платы Arduino для обмена информацией друг с другом. В этом примере две платы запрограммированы для взаимодействия друг с другом в конфигурации «Контроллер-читатель / Периферийное устройство-отправитель» через синхронный последовательный протокол I2C. Для этого используется несколько функций библиотеки Wire Arduino. Arduino 1 (контроллер) запрограммирован для запроса и последующего чтения 6 байтов данных, отправленных от периферийного Arduino с уникальным адресом. После получения сообщения его можно просмотреть в окне монитора последовательного порта Arduino Software (IDE).
Скетч Controller Reader
// Wire Controller Reader
// by Nicholas Zambetti http://www.zambetti.com
// Demonstrates use of the Wire library
// Reads data from an I2C/TWI peripheral device
// Refer to the "Wire Peripheral Sender" example for use with this
// Created 29 March 2006
// This example code is in the public domain.
#include <Wire.h>
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
Serial.begin(9600); // start serial for output
}
void loop() {
Wire.requestFrom(8, 6); // request 6 bytes from peripheral device #8
while (Wire.available()) { // peripheral may send less than requested
char c = Wire.read(); // receive a byte as character
Serial.print(c); // print the character
}
delay(500);
}
Скетч Peripheral Sender
// Wire Peripheral Sender
// by Nicholas Zambetti http://www.zambetti.com
// Demonstrates use of the Wire library
// Sends data as an I2C/TWI peripheral device
// Refer to the "Wire Master Reader" example for use with this
// Created 29 March 2006
// This example code is in the public domain.
#include <Wire.h>
void setup() {
Wire.begin(8); // join i2c bus with address #8
Wire.onRequest(requestEvent); // register event
}
void loop() {
delay(100);
}
// function that executes whenever data is requested by master
// this function is registered as an event, see setup()
void requestEvent() {
Wire.write("hello "); // respond with message of 6 bytes
// as expected by master
}
Controller Writer (Контроллер-отправитель)
Платы Arduino, соединённые по I2C
В некоторых ситуациях бывает полезно настроить две (или более!) платы Arduino для обмена информацией друг с другом. В этом примере две платы запрограммированы для взаимодействия друг с другом в конфигурации «Контроллер-отправитель / Периферийное устройство-приёмник» через синхронный последовательный протокол I2C. Для этого используется несколько функций библиотеки Wire Arduino. Arduino 1 (контроллер) запрограммирован для отправки 6 байтов данных каждые полсекунды на периферийное устройство с уникальным адресом. После получения сообщения его можно просмотреть в окне монитора последовательного порта периферийной платы, открытого на компьютере, подключённом по USB и запускающем Arduino Software (IDE).
Скетч Controller Writer
// Wire Master Writer
// by Nicholas Zambetti http://www.zambetti.com
// Demonstrates use of the Wire library
// Writes data to an I2C/TWI Peripheral device
// Refer to the "Wire Peripheral Receiver" example for use with this
// Created 29 March 2006
// This example code is in the public domain.
#include <Wire.h>
void setup()
{
Wire.begin(); // join i2c bus (address optional for master)
}
byte x = 0;
void loop()
{
Wire.beginTransmission(4); // transmit to device #4
Wire.write("x is "); // sends five bytes
Wire.write(x); // sends one byte
Wire.endTransmission(); // stop transmitting
x++;
delay(500);
}
Скетч Peripheral Receiver
// Wire Peripheral Receiver
// by Nicholas Zambetti http://www.zambetti.com
// Demonstrates use of the Wire library
// Receives data as an I2C/TWI Peripheral device
// Refer to the "Wire Master Writer" example for use with this
// Created 29 March 2006
// This example code is in the public domain.
#include <Wire.h>
void setup()
{
Wire.begin(4); // join i2c bus with address #4
Wire.onReceive(receiveEvent); // register event
Serial.begin(9600); // start serial for output
}
void loop()
{
delay(100);
}
// function that executes whenever data is received from master
// this function is registered as an event, see setup()
void receiveEvent(int howMany)
{
while(1 < Wire.available()) // loop through all but the last
{
char c = Wire.read(); // receive byte as a character
Serial.print(c); // print the character
}
int x = Wire.read(); // receive byte as an integer
Serial.println(x); // print the integer
}
Акселерометр
Grove IMU по I2C
Этот код позволяет считывать данные акселерометра с модуля Grove 6-Axis Accelerometer с использованием библиотеки seeed arduino LSM6DS3.
#include "LSM6DS3.h"
#include "Wire.h"
//Create instance of Accelerometer class
LSM6DS3 accelerometer(I2C_MODE, 0x6A);
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
while (!Serial);
if (accelerometer.begin() != 0) {
Serial.println("LSM6DS3 not found, check your wiring.");
} else {
Serial.println("LSM6DS3 found!");
}
}
void loop() {
//Gyroscope
Serial.print("\nGyroscope:\n");
Serial.print(" X1 = ");
Serial.println(accelerometer.readFloatGyroX(), 4);
Serial.print(" Y1 = ");
Serial.println(accelerometer.readFloatGyroY(), 4);
Serial.print(" Z1 = ");
Serial.println(accelerometer.readFloatGyroZ(), 4);
//Accelerometer
Serial.print("\nAccelerometer:\n");
Serial.print(" X1 = ");
Serial.println(accelerometer.readFloatAccelX(), 4);
Serial.print(" Y1 = ");
Serial.println(accelerometer.readFloatAccelY(), 4);
Serial.print(" Z1 = ");
Serial.println(accelerometer.readFloatAccelZ(), 4);
delay(1000);
}
I2C BMP280
Модуль Qwiic BMP280
Этот пример кода позволяет считывать температуру по I2C с модуля BMP280 от Adafruit®:
#include <Wire.h>
#include <Adafruit_BMP280.h>
//Create an instance of the BMP280 sensor
Adafruit_BMP280 bmp;
void setup() {
Serial.begin(9600);
// Start the sensor, and verify that it was found
if (!bmp.begin()) {
Serial.println("Sensor not found");
while (1){}
}
}
void loop() {
// Read the values
float temperature = bmp.readTemperature();
// Print to the Serial Monitor
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" C");
Serial.println();
delay(2000);
}
I2C OLED
Grove OLED по I2C
Этот пример кода рисует версию логотипа Arduino на 128x64 I2C Grove OLED:
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
Adafruit_SSD1306 display(128, 64, &Wire, -1);
// The Arduino Logo in a bitmap format
const uint8_t arduinoLogo[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xe0, 0x00, 0x30, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x3f, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xfc, 0x00, 0x70, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0x80, 0x50, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xe0, 0x40, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf0, 0x20, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xff, 0xfc, 0x0f, 0xff, 0xe0, 0x07, 0xff, 0xf0, 0x3f, 0xff, 0x80, 0x00, 0x00,
0x00, 0x00, 0x01, 0xff, 0xc0, 0x00, 0xff, 0xf0, 0x0f, 0xff, 0x00, 0x07, 0xff, 0x80, 0x00, 0x00,
0x00, 0x00, 0x03, 0xff, 0x80, 0x00, 0x7f, 0xf8, 0x1f, 0xfc, 0x00, 0x01, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x1f, 0xfc, 0x3f, 0xf8, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x0f, 0xfe, 0x7f, 0xf0, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x07, 0xff, 0x7f, 0xe0, 0x00, 0x00, 0x1f, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x01, 0xff, 0xff, 0x80, 0x0f, 0x00, 0x0f, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x80, 0x07, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x0f, 0x80, 0x07, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x0f, 0x80, 0x07, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x0f, 0x80, 0x03, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xc0, 0x1f, 0xff, 0x00, 0x1f, 0xf8, 0x00, 0xff, 0xf8, 0x03, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xc0, 0x3f, 0xff, 0x00, 0x1f, 0xf8, 0x00, 0xff, 0xf8, 0x03, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xc0, 0x3f, 0xff, 0x00, 0x1f, 0xf0, 0x00, 0xff, 0xf8, 0x03, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xc0, 0x1f, 0xff, 0x00, 0x1f, 0xf8, 0x00, 0xff, 0xf8, 0x03, 0xfc, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x0f, 0x80, 0x03, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x3f, 0xfc, 0x00, 0x0f, 0x80, 0x07, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x0f, 0x80, 0x07, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x0f, 0x80, 0x07, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x1f, 0xf0, 0x00, 0x00, 0x01, 0xff, 0xff, 0x80, 0x0f, 0x00, 0x0f, 0xf8, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x03, 0xff, 0xff, 0x80, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x0f, 0xf8, 0x00, 0x00, 0x07, 0xff, 0xff, 0xc0, 0x00, 0x00, 0x1f, 0xf0, 0x00, 0x00,
0x00, 0x00, 0x07, 0xfc, 0x00, 0x00, 0x0f, 0xfe, 0x7f, 0xf0, 0x00, 0x00, 0x3f, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x07, 0xfe, 0x00, 0x00, 0x1f, 0xfc, 0x3f, 0xf8, 0x00, 0x00, 0x7f, 0xe0, 0x00, 0x00,
0x00, 0x00, 0x03, 0xff, 0x00, 0x00, 0x7f, 0xf8, 0x1f, 0xfc, 0x00, 0x00, 0xff, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x01, 0xff, 0xc0, 0x01, 0xff, 0xf0, 0x0f, 0xff, 0x00, 0x03, 0xff, 0x80, 0x00, 0x00,
0x00, 0x00, 0x01, 0xff, 0xf8, 0x07, 0xff, 0xf0, 0x07, 0xff, 0xe0, 0x1f, 0xff, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x03, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0xff, 0xfc, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0f, 0xff, 0xff, 0xfe, 0x00, 0x00, 0x7f, 0xff, 0xff, 0xf0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x07, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x1f, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0xe0, 0x00, 0x00, 0x07, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0x80, 0x00, 0x00, 0x01, 0xff, 0xfc, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x07, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0c, 0x07, 0x80, 0xf0, 0x04, 0x18, 0xff, 0x88, 0x18, 0x1c, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1e, 0x0f, 0xf8, 0xff, 0x1e, 0x1c, 0xff, 0x9e, 0x1c, 0x7f, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x1f, 0x0f, 0xfc, 0xff, 0x9e, 0x1c, 0xff, 0x9f, 0x1c, 0xff, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0x0e, 0x3c, 0xe3, 0xce, 0x1c, 0x1c, 0x1f, 0x1d, 0xe3, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x3f, 0x0e, 0x1c, 0xe1, 0xce, 0x1c, 0x1c, 0x1f, 0x99, 0xc3, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0x33, 0x8e, 0x1c, 0xe1, 0xce, 0x1c, 0x1c, 0x1f, 0x99, 0xc3, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x73, 0x8f, 0x3c, 0xe1, 0xce, 0x1c, 0x1c, 0x1d, 0xd9, 0xc3, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x73, 0x8f, 0xf8, 0xe1, 0xce, 0x1c, 0x1c, 0x1d, 0xf9, 0xc3, 0xc0, 0x00, 0x00,
0x00, 0x00, 0x00, 0x7f, 0x8f, 0xf0, 0xe1, 0xce, 0x1c, 0x1c, 0x1c, 0xf9, 0xc3, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xce, 0x70, 0xe3, 0xce, 0x1c, 0x1c, 0x1c, 0xf9, 0xc3, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0xff, 0xce, 0x78, 0xe7, 0x8e, 0x3c, 0x3c, 0x1c, 0x7d, 0xe7, 0x80, 0x00, 0x00,
0x00, 0x00, 0x00, 0xe1, 0xce, 0x3c, 0xff, 0x8f, 0xf8, 0xff, 0x9c, 0x7c, 0xff, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0xe1, 0xee, 0x3c, 0xff, 0x07, 0xf0, 0xff, 0x9c, 0x3c, 0x7e, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
void setup() {
Serial.begin(9600);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 not found"));
while(1){}
}
display.clearDisplay();
display.drawBitmap(0, 0, arduinoLogo, 128, 64, SSD1306_WHITE);
display.display();
}
void loop() {
}