Arduino отключает шину i2c
Я строю самолет. В качестве контроллера я использую Raspberry pi 4. Есть 3 датчика (MPU6050, QMC5883L, BME280) и Arduino Pro Mini, подключенные к Raspberry через i2c. При отправке запросов в Arduino он переводит шину в 0 и выключается(?).
Первый скриншот. При первом поиске всех устройств на шине Arduino отвечает и выключается, но не переводит шину в 0. При втором поиске он реагирует и переводит шину в 0.
Второй скриншот. Перезагружаем ардуино, линия SDA поднимается. Повторные запуски поиска приводят к тому, что показано на первом скриншоте.
Третий скриншот. Arduino генерирует сигнал ШИМ, который прерывается после запроса к i2c.
В качестве тестового запроса я использую команду i2cdetect на Raspberry. Raspberry подключается к шине датчика через преобразователь уровня, поскольку уровень сигналов от Raspberry составляет 3,3В, а датчики принимают 5-вольтовую логику.
Подтягивания шины на верхний уровень нет, он есть на схеме всех используемых датчиков (ей будет достаточно?).
В Arduino есть простой код подчиненного устройства i2c, который записывает в регистры поступившее значение и выводит его на другие элементы (сервоприводы, контроллер двигателя, драйверы шаговых двигателей). Arduino действует как расширитель портов, поскольку у Raspberry всего 2 шины и слишком мало выходов для всех необходимых устройств.
Почему автобус падает и как это исправить?
код Arduino
#include <Wire.h>
#include <Servo.h>
#include <Stepper.h>
uint16_t servoAngle1 = 90;
uint16_t servoAngle2 = 90;
uint16_t servoAngle3 = 90;
uint16_t servoAngle4 = 90;
bool zoomIn = false;
bool zoomOut = false;
bool focusIn = false;
bool focusOut = false;
Servo servo1;
Servo servo2;
Servo servo3;
Servo servo4;
Servo ESC;
Stepper zoomMotor(100, 2, 4, 7, 8);
Stepper focusMotor(100, 10, 11, 12, 13);
void setup() {
Wire.begin(0x23);
Wire.onReceive(receiveEvent);
servo1.attach(3);
servo2.attach(5);
servo3.attach(6);
servo4.attach(9);
ESC.attach(11, 1000, 2000);
}
void loop() {
servo1.write(servoAngle1);
servo2.write(servoAngle2);
servo3.write(servoAngle3);
servo4.write(servoAngle4);
ESC.write(0);
if (zoomIn) {
zoomMotor.step(100);
zoomIn = false;
}
if (zoomOut) {
zoomMotor.step(-100);
zoomOut = false;
}
if (focusIn) {
focusMotor.step(100);
focusIn = false;
}
if (focusOut) {
focusMotor.step(-100);
focusOut = false;
}
}
void receiveEvent(int howMany) {
if (howMany == 2) {
uint8_t action = Wire.read();
uint8_t value = Wire.read();
if (action == 1) { servoAngle1 = value; }
if (action == 2) { servoAngle2 = value; }
if (action == 3) { servoAngle3 = value; }
if (action == 4) { servoAngle4 = value; }
if (action == 10) {
if (value == 1) { zoomIn = true; }
if (value == 2) { zoomOut = true; }
}
if (action == 11) {
if (value == 1) { focusIn = true; }
if (value == 2) { focusOut = true; }
}
} else {
while (true) {
Wire.read();
}
}
}
Скриншот 1
Скриншот 2
Скриншот 3
и схема подключения
@Xrou, 👍0
Обсуждение1 ответ
Лучший ответ:
Для работы I2C где-то должны быть подтяжки на SDA и SCL (не по одному для каждого устройства). Обычно используются резисторы номиналом 4,7 кОм или около того.
Также вам понадобится двунаправленный преобразователь уровня напряжения. Пример схемы:
Изображение предоставлено: Sparkfun: Руководство по подключению двунаправленного преобразователя логических уровней
Это связано с тем, что устройства I2C активно подтягивают SDA и SCL к низкому уровню, однако они полагаются на подтягивающие резисторы, которые подтягивают их к высокому уровню. Кроме того, это не будет работать, если переключатель уровня напряжения не является двунаправленным.
Для получения дополнительной информации см. Примечания по применению Philips AN97055 — двунаправленный преобразователь уровня для шины I²C и других устройств. системы.
Если вы используете преобразователь уровня, вам потребуются подтягивающие резисторы как на части 3,3 В, так и на части 5 В схемы (показаны как Rp ниже).
- Wire.endTransmission() зависает
- Пайка несовмещенных выводов Arduino Pro Mini
- Ошибка при компиляции: 'class TwoWire' has no member named 'setClock'
- Несколько РАЗРЫВОВ I2C с подтягивающими резисторами не работают
- Сбой при записи данных MPU-6050 на SD-карту
- Сбросить соединение I2C с arduino в качестве ведомого
- Преобразование float в байт, от Arduino до Raspberry Pi i2c
- Raspberry Pi, Teensy и Arduino на i2c
пожалуйста, добавьте в свой пост четкий вопрос, на который можно ответить... также добавьте листинг кода, @jsotola
Автобусу нужно подъехать., @Delta_G
Этот переключатель логического уровня должен быть двунаправленным. Если на нем есть маркировка типа TX/RX, то вряд ли он будет двунаправленным. На сторонах низкого и высокого напряжения шины I2C должны быть подтягивающие резисторы (скажем, 4,7 кОм). Если хотя бы по одному модулю с каждой стороны устройства переключения уровня они есть, этого должно быть достаточно. Модуль mpu6050 (и, возможно, другие) имеет логику 3,3 В и должен находиться на стороне Raspberry Pi переключателя уровня., @6v6gt
добавлен листинг кода., @Xrou
BME280, по-видимому, является устройством с напряжением 3,3 В, поэтому я не знаю, почему он у вас установлен на 5-вольтовой части схемы., @Nick Gammon
Pro Mini также может работать при напряжении 3,3 В — вы усложняете себе задачу с помощью преобразователя логических уровней., @Nick Gammon
Из вашего недавно опубликованного кода. Как он собирается вырваться из этого бесконечного цикла?
else { while (true) { Wire.read(); } }
, @6v6gt@NickGammon Как мне подать питание на 3,3 В? У него нет контакта 3,3 В или на контакт VCC можно подать напряжение 3,3 В?, @Xrou
Вам необходимо найти и понять схемы тех модулей, которые вы используете. Вот https://www.waveshare.com/w/upload/4/42/BME280-Environmental-Sensor-Schematic.pdf, например, модуль BME280. Сам чип рассчитан на напряжение 3,3 В, но модуль рассчитан на работу с напряжением 5 В и имеет встроенный переключатель уровня. Если это тот, который вы используете, то в этом случае правильно подключить его к стороне 5 В. А как насчет ошибки кодирования, на которую было указано в моем предыдущем комментарии. Не вызовет ли это симптомы, о которых вы сообщили?, @6v6gt
Вы показываете, что Raspberry Pi имеет напряжение 3,3 В на SDA и SCL — откуда это взялось? Вы показываете свои устройства, такие как BME280, с питанием 3,3 В. Почему вы спрашиваете, откуда берется 3,3В? Если вы не хотите этого делать, посмотрите комментарий 6v6gt. Вам нужен двунаправленный переключатель уровня, иначе I2C не будет работать., @Nick Gammon
Глобальные переменные, которые используются в цикле и обновляются в полученииEvent(), должны быть объявлены как изменчивые, поскольку вызов этой процедуры осуществляется через прерывание. Вы также должны показать код, используемый на ведущем устройстве I2C., @6v6gt