Нужна небольшая помощь по тестированию скетча I2C.
У меня есть код, полученный на YouTube, для связи между двумя Arduino. Набрав «R» вручную на последовательном мониторе «ведущего» Arduino, «ведомый» напечатает «Успех». Я пробую все это для основы проекта, который начинаю.
После успеха с кодом я теперь пытаюсь сделать его автоматическим. Я хочу, чтобы «главный» Arduino сам напечатал «R», а «ведомый» прочитал это и напечатал «Успех». println
здесь не работает, может быть, сработает, если сменить подчиненный код? Оба исходных кода приведены ниже. Есть идеи, как сделать то, что мне нужно?
Мастер:
#include <Wire.h>
char incomingByte;
int x = 0;
void setup() {
Serial.begin(9600);
Wire.begin();
}
void loop()
{
Wire.beginTransmission(9);
if (Serial.available()) {
while (Serial.available() > 0) {
incomingByte = Serial.read();
Wire.write(incomingByte);
Serial.println(incomingByte);
Wire.endTransmission();
}
}
}
Раб:
#include <Wire.h>
int x = 0;
void setup() {
Wire.begin(9);
Wire.onReceive(recieveEvent);
Serial.begin(9600);
}
void recieveEvent(int bytes) {
x = Wire.read();
}
void loop() {
if (x == 'R'){
Serial.println("Success");
delay(100);
}
}
@Josh, 👍4
Обсуждение2 ответа
Вот мое предложение по решению вашей проблемы:
- Используйте вторую линию последовательной связи ведущего устройства, соединив контакты Rx и Tx Serial2 (это делается только на ведущем устройстве, практически ярлык между Rx и Tx на ведущем устройстве)
- Настройте Serial2, если необходимо:
HardwareSerial Serial2(2);
(вот как необходимо/сделано для моего M5Stack) - Определите скорость передачи данных для Serial2:
Serial2.begin(9600);
- Запустите автоматизацию с помощью
Serial2.write("R\n");
в соответствующем месте вашего кода - Измените условия
if(..)
иwhile(..)
в исходном коде сSerial.available()
наSerial2.available()
- Измените
incomingByte = Serial.read();
наincomingByte = Serial2.read();
Благодаря этому решению вы по-прежнему сможете видеть распечатанный сигнал запуска на последовательном мониторе через первую последовательную линию связи. Связь с ведомым устройством по-прежнему осуществляется через IC2, Serial2 — это только предложение для решения автоматизации на ведущем устройстве. Выглядит сложно, но я так понял вопрос, конечно, вы также можете напрямую использовать incomingByte="R\n";
, чтобы запустить автоматизацию и пропустить все эти вещи с помощью Serial2 :-)
Общение I2C — это непростая задача, и есть много вещей, которые могут пойти не так. Две платы Arduino вместо одной часто используются по неправильной причине.
Использовать последовательный порт проще. Arduino Leonardo имеет дополнительный аппаратный последовательный порт, который можно использовать для связи между двумя платами Arduino. Arduino Mega 2560 имеет три дополнительных последовательных порта.
Иногда используются две платы Arduino, поскольку необходимо выполнять несколько задач одновременно.
Когда вы используете пример Blink Without Delay с millis
, Arduino может выполнять множество вещи одновременно.
Иногда используются две платы Arduino, поскольку между платами Arduino имеется некоторое расстояние.
Шина I2C — это «шина», но это не значит, что можно использовать длинный кабель. Вы можете подняться до 20 дюймов (50 см).
Когда две платы Arduino Uno подключены к шине I2C, то необходимо три провода:
- Земля к земле
- SDA на SDA (плюс подтягивающий резистор)
- SCL на SCL (плюс подтягивающий резистор)
Для небольшого теста с короткими перемычками можно обойтись и без подтягивающих резисторов. В окончательном проекте следует использовать подтягивающие резисторы для SDA и SCL, например 4 к7 или 10 кОм.
В примере ниже используется флаг в ведомом Arduino. Эта дополнительная переменная упрощает задачу.
В подчиненной функции receiveEvent
имеется дополнительная проверка, проверяющая, получен ли ровно один байт. Эта дополнительная проверка не требуется, но может быть полезна.
Я привожу этот пример как начало, потому что существует слишком много плохих примеров для I2C между главным и подчиненным устройствами.
Мастер
#include <Wire.h>
byte dataTransmit;
void setup() {
Wire.begin();
}
void loop() {
Wire.beginTransmission(9); // отправляем подчиненному устройству с адресом i2c 9
Wire.write(dataTransmit); // данные для отправки
Wire.endTransmission();
dataTransmit++; // все числа от 0 до 255
delay(250); // Задержка 250 мс для отправки 4 раза в секунду
}
Раб
#include <Wire.h>
volatile byte dataReceive;
volatile bool newData; // флаг, указывающий, что поступили новые данные
void setup() {
Wire.begin(9); // создаем подчиненное устройство i2c по адресу i2c 9
Wire.onReceive(receiveEvent);
Serial.begin(9600);
}
void loop() {
if(newData) { // есть ли новые данные?
Serial.print("Received: ");
Serial.println(int(dataReceive)); // конвертируем в целое число, чтобы напечатать число
newData = false; // флаг сброса
}
}
void receiveEvent(int howMany) {
if(howMany == 1) { // дополнительная проверка, чтобы проверить, получен ли один байт
dataReceive = Wire.read();
newData = true; // устанавливаем флаг, есть новые данные
}
}
- Отправка и получение различных типов данных через I2C в Arduino
- Как работают функции вне цикла void?
- Как отображать переменные на 0,96-дюймовом OLED-дисплее с библиотекой u8glib?
- OVF в последовательном мониторе вместо данных
- ЖК-дисплей I2C отображает странные символы
- Соединение I2C зависает Ведущий если ведомый отключается
- Экран LCD 16*02 I2C показывает только первый напечатанный символ
- Ведомое устройство Arduino с двумя мастерами, использующими одну и ту же шину I2C?
Предполагается, что ваш Мастер должен послать «R». Где это происходит в коде?, @smajli
Посмотрите, что делает мастер. Он читает сериал и записывает то, что читает, в Wire. Как вы думаете, как заставить его отправлять R, а не то, что он читает из серийного номера?, @Mark Smith
сделать x нестабильным.
летучий int x = 0;
, @Juraj@MarkSmith Вот в чем я не уверен. Я новичок в этом, поэтому не знаю, что изменить в любом коде., @Josh
@smajli Мне нужно вручную ввести «R» в последовательный монитор., @Josh
Джош, какой у тебя проект? Какую проблему вы пытаетесь решить, используя две платы Arduino?, @Jot
@ Джош. Вы получаете такие комментарии, потому что StackExchange требует, чтобы вы приложили усилия для понимания вопроса, который вы задаете. Если вы не можете ответить, как изменить Master, где полученная переменная отправляется на устройство I2C, вы просто скопируете и вставите чужой код, который вы не понимаете, как это происходит в случае с код, который вам уже удалось заставить работать., @linhartr22