Интерфейс I2C не работает, не понимаю почему (rs 485 тоже)

Тема в разделе "Arduino & Shields", создана пользователем yozhikov.d, 24 мар 2019.

  1. yozhikov.d

    yozhikov.d Нерд

    Добрый день. Решил изучать интерфейсы передачи данных. Вначале пробовал реализовать общение через rs 485, купил три микросхемы max 485, собрал все по схемам, скачал пример кода, прошил - не работает, осциллографа посомтреть, что на шинах данных нет. Подумал, что возможно проблема в том, что rs 485 реализовал без сопротивлений и емкостей, на чистых микросхемах, по этому от греха по дальше заказал готовые модули. Пока идут модули, решил попробовать передать данные через I2C, снова собрал по схеме, скачал пример с англо сайта - не работает. В чем проблема? Arduino Uno - китайские. Ниже код на I2C, и фото макета. Питание 12V от отдельного БП компьютера (Мастер посылает команду слейву на мигание светодиода)
    Код (C++):
    //Мастер
    #include <Wire.h>
    int x = 0;
    void setup() {
      // Start the I2C Bus as Master
      Serial.begin(9600);
      Wire.begin(1);
    }
    void loop() {
      Wire.beginTransmission(9); // transmit to device #9
      Wire.write(x);              // sends x
      Wire.endTransmission();    // stop transmitting
      x++; // Increment x
      if (x > 10) x = 0; // `reset x once it gets 6
      delay(500);
      Serial.print(x);
    }
    Код (C++):
    //Слейв
    #include <Wire.h>
    int LED = 8;
    int x = 0;
    void setup() {
      // Define the LED pin as Output
      pinMode (LED, OUTPUT);
      Serial.begin(9600);
    // Start the I2C Bus as Slave on address 9
      Wire.begin(9);
      // Attach a function to trigger when something is received.
      Wire.onReceive(receiveEvent);
    }
    void receiveEvent(int bytes) {
      x = Wire.read();    // read one character from the I2C
    }
    void loop() {
      //If value received is 0 blink LED for 200 ms
      if (x == '0') {
        digitalWrite(LED, HIGH);
        delay(200);
        digitalWrite(LED, LOW);
        delay(200);
        Serial.print(x);
      }
      //If value received is 3 blink LED for 400 ms
      if (x == '3') {
        digitalWrite(LED, HIGH);
        delay(1000);
        digitalWrite(LED, LOW);
        delay(100);
        Serial.print(x);
      }
     

    Вложения:

    • общая.jpg
      общая.jpg
      Размер файла:
      460,6 КБ
      Просмотров:
      520
    • мастер.jpg
      мастер.jpg
      Размер файла:
      427,2 КБ
      Просмотров:
      564
    • слейв.jpg
      слейв.jpg
      Размер файла:
      428,3 КБ
      Просмотров:
      508
  2. znamen

    znamen Guest

    Интерфейсы названные Вами разные ,в первую очередь по назначению,а не по функциональности. Если между платами на картинке 1 км,то 12С вам не подойдёт,а только RS485. И наоборот ,если обе платы
    находятся на столе,то RS485 использовать можно,но не рационально,так,как необходимо добавлять дорол
    нительную микросхему max485. A с интерфейсом 12С ,без проблем. Так ,что Вы определитесь в первую очередь с задачей,а скопипастить правильный код- не проблема.
     
  3. parovoZZ

    parovoZZ Гуру

    как выясняется - проблема.
     
  4. yozhikov.d

    yozhikov.d Нерд

    Я знаю, что интерфейсы разные, спасибо. Для задачи нужен rs-485, его я делал по видео

    , не получилось, не заработало. Встал вопрос "в чем проблема?", снять сигналы осциллографом на шинах даты и посмотреть идет ли отправка не могу, тк, как его попросту нет. Схема собрана правильно, но на голых микросхемах не обвязанных сопротивлениями и емкостью, я сделал предположение, что мб они не исправны, заказал их. И решил пока сделать передачу команд по i2с (чисто поиграться), собрал схему, "скопипастил код для того, чтобы исключить его неправильность" в итоге - не работает. Я же вроде все описал выше. Так как не заработало на i2c, возникло предположение, что мб ардуинки не исправны. Так я и спрашиваю в чем проблема.
     
  5. AlexU

    AlexU Гуру

    Что бы шина I2C работала, линии надо подтягивать к питанию. Точный номинал надо рассчитывать -- зависит от скорости передачи данных и ёмкости линии. Для Вашего опыта должно хватить сопротивлений 2-4 кОм.
    Код пока не смотрел...
     
  6. AlexU

    AlexU Гуру

    Только подтягивать надо к 5V. А то спалите входы.
     
  7. yozhikov.d

    yozhikov.d Нерд

    Вопрос решен, стер кавычки в условии цикла слейва "1" - все заработало. Всем спасибо
     
  8. znamen

    znamen Guest

    А как Вы определили,что шины не подтянуты и какой номинал у сопротивлений? По видео?
    Так там речь о 12С не идёт. Если мне глаза не врут,то речь о RS485. В программе по 12С тоже
    этого не видно.
     
  9. yozhikov.d

    yozhikov.d Нерд

    Но вот кстати я не понимаю, почему у меня на max485 не заработало. Насколько я смог изучить информацию, то сопротивления для на рс485 нужны для передачи на дальние расстояния, а в лр условиях, все должно работать на микросхемах
     
  10. znamen

    znamen Guest

    Сопротивления нужны для согласования волнового сопротивления при большой длине кабеля. При малой
    длине эти сопротивления и нафик не нужны. Покажите схему.
     
  11. AlexU

    AlexU Гуру

    Я этого не определял, всего лишь указал автору, что должно быть и что он должен проверить. В оригинальных Arduino UNO нет подтяжки. Но у автора не оригинальные -- поэтому надо смотреть на платы, возможно там подтяжка есть. Хотя это очень странно, т.к. будут проблемы с использованием ADC.
    По фоткам из первого поста.
     
  12. znamen

    znamen Guest

    Я теперь очень осторожен с Вами. Одел очки и долго выискивал сопротивления. Особенно трудно было читать номиналы.Наверное это чисто гипотетически предполагаемые сопротивления. И даже,если это так,то то никогда и никто их не расчитывает. Тупо подтягивается шины через сопротивление через 2-10ком. Но если ошибетесь и поставила
    20ком. От этого шина кашлять не начнёт. Проверено.
     
    Последнее редактирование модератором: 24 мар 2019
  13. yozhikov.d

    yozhikov.d Нерд

    Вначале я спаял на макетку, чтобы удобнее было - не заработало, потом вытащил микрухи спаял воздушным монтажом - не заработало, вот такой код использовал
    Код (C++):
    //
    #include <SoftwareSerial.h>

    #define DIR 8 // прием\передача
    SoftwareSerial RS485 (7, 6); // RX, TX

    void setup(){
      Serial.begin(9600);
      RS485.begin(9600); // SoftwareSerial

      pinMode(DIR, OUTPUT);
    }

    void loop(){
         
    digitalWrite(DIR, HIGH);
        RS485.write(2); //  ID
        RS485.write(3); // отправляем второй байт,  
    digitalWrite(DIR, LOW);

        delay(250);
    }
    Код (C++):
    #include <SoftwareSerial.h>

    #define DIR 8

    const byte ID =2 ;
    SoftwareSerial RS485 (7, 6); // RX, TX
    void setup(){
      Serial.begin(9600);
      RS485.begin(9600); // SoftwareSerial
      pinMode(DIR, OUTPUT);
      pinMode(5, OUTPUT);
      digitalWrite(DIR, LOW); // включаем прием
    }

    void loop(){

    if (RS485.available() >= 2) {
       byte id = RS485.read();  
        if (id == ID){
          byte val = RS485.read();
            if (val == 3) digitalWrite(5, HIGH);  //  
            else digitalWrite(13, LOW);
           }
        else RS485.flush(); // если пакет не нам, очищаем буфер
     
      }

    }
    https://drive.google.com/open?id=1_jhyIxXfe1mwd0KLycN_tOKLdDHdCCAJ
     
    Последнее редактирование: 24 мар 2019
  14. znamen

    znamen Guest

    По схеме Вашей оригинальной могу сказать следующее. Ошибок не вижу. Но тщательно обратите внимание не попутайте А с В. Если попутаете работать не будет 100 пудово. По программе сказать
    пока не могу,потому,что неизвестно,что в библиотеках там понаписывано. Я этой библиотекой не пользовался
    и гарантировать её работу не могу.
     
    Daniil нравится это.
  15. Daniil

    Daniil Гуру

    Вы уверены что при переходе от
    RS485.write(3);
    к
    digitalWrite(DIR, LOW);
    Передача 3 завершилась?
     
  16. znamen

    znamen Guest

    Присмотрелся внимательно к программной части. Хоть и не большой специалист в этих ардуиновских
    языках,но заметил следующее. Ваша первая плата посылает 2 байта в шину. Первый байт является
    адресным. Вторая плата,опознав адрес,что то там переключает и выдаёт в шину ответ. Как Вы узнаете,что
    ответ от слейва пришёл. Я не вижу в 1м скетче анализа ответа. Даже если он пришёл, то Вы этого не увидите.
    Т.е не поймёте состоялся диалог или нет.И ещё при передаче первого байта каким то образом контролируйте
    что его передача закончилась. Если ардуиновские программные средства этого сделать не позволяют,то
    хотя бы после передачи 1 байта сделайте небольшую задержку,время которой легко высчитать исходя
    из скорости обмена,которая у Вас 9600 бод.
     
  17. yozhikov.d

    yozhikov.d Нерд

    Я только, что выставил задержки, ничего не изменилось(
     
  18. znamen

    znamen Guest

    Хорошо,а как Вы контролируете, что слейв ответил мастеру?
     
  19. yozhikov.d

    yozhikov.d Нерд

    Ну по сути никак. Сейчас добавил
    Код (C++):
    if (RS485.available() >= 1) {
       byte id = RS485.read();
        if (id > 0){
          Serial.print(id);
          digitalWrite(5, HIGH);
    Ничего не видно в терминале. Да и если бы приходило, светодиод загорался бы. Как в случае с i2c я же там не контролировал и слейв не сообщал мастеру, что пришло сообщение, но светодиод загорался
     
  20. znamen

    znamen Guest

    Все эти гадания на кофейной гуще будут долгими и нудными. Поэтому нужно действовать следующим обра
    дом. Для начала нужно определится, что виновато. Программная или аппаратная часть. Сначала убеждаемся
    в правильности программной части. Для этого 2 пути. Откажитесь от подозрительных библиотек и напишите
    тупо управление rs485 логическими уровнями. Или же найдите заведомо рабочую библиотеку у друзей Андуин
    щиков. Друг при этом должен сказать" У меня это работает" И только после этого искать ошибки в аппаратной части.