Использовать один и тот же пин для двух целей

softwareserial pinmode

У меня есть только один доступный контакт, и мне нужно использовать его как для цифрового чтения, так и для отправки последовательных сообщений (назначив ему роль Tx в SoftwareSerial). Я могу чередовать эти две операции, но, похоже, у меня ничего не получается. Меня могли бы заинтересовать и другие пары (digitalRead+Rx, digitalWrite+Tx и digitalWrite+Rx), и я надеюсь, что понимание одной из них решит их все, но пока я был бы рад заставить работать первую. Моя первая наивная попытка была бы примерно такой:

 #include <SoftwareSerial.h>

SoftwareSerial swSerial(7,6);
int val;

void setup() {

  pinMode(6, INPUT_PULLUP);
  
}

void loop() {

  val = digitalRead(6);

  delay(2000);

  swSerial.begin(19200);
  swSerial.print("myData");
  swSerial.end();

  delay(2000);
  
}

Но я провел и другие эксперименты, например, с digitalWrite, надеясь, что объединение двух форм вывода будет возможно, но опять же нет. Я знаю, что могу чередовать роль вывода между выводом и вводом, если задействованы обычные цифровые операции чтения/записи, но SoftwareSerial кажется менее гибким. Мне кажется, он отказывается работать, как только выход объявляется/используется для обычных цифровых целей. Есть ли способ достичь моей цели?

Я предполагаю, что аналогичные требования и исправления (сделать роль контакта более гибкой) привели к Software Serial with Half Duplex, но я бы воздержался от ее принятия, потому что считаю ее чрезмерно сложной и кажется излишней для моей цели, более того, она не кажутся активно поддерживаемыми.

Чтобы избежать проблем с XY, моей первой потребностью (у меня могут быть и другие, требующие других пар, упомянутых в начале) было бы проверить, является ли этот вывод плавающим или подключен к чему-либо (я могу выбрать между Vcc или Gnd). , настроить подтягивание или внешнее подтягивание соответственно) и отправить обратно какую-то информацию (очевидно, это полезно, если пин действительно подключен, но у меня все равно нет причин не отправлять данные), чередуя задачи несколько раз не менее чем в секунду.

, 👍-1

Обсуждение

почему у тебя только один пин?, @jsotola

Проверьте мой ответ на ваш предыдущий пост этого вопроса., @Gil

@jsotola это аппаратное требование, @lesath82

Прежде чем пытаться написать программное обеспечение, придумайте способ, с помощью которого внешнее оборудование может различать обе цели. Например, если вы хотите прочитать цифровое значение, внешнее оборудование управляет проводом. Как вы управляете им, чтобы освободить провод, чтобы Arduino мог управлять проводом? И как вы управляете аппаратным обеспечением, управляемым TX, которое только во время отправки должно считывать значение по проводу, а не в то время, когда Arduino считывает другое устройство? Пожалуйста [отредактируйте] свой вопрос и добавьте эту важную информацию., @the busybee

@Gil О чем ты говоришь? Я предполагаю, что есть похожий вопрос, который я не мог найти при публикации своего (было бы неплохо иметь ссылку на него), и вы предположили, что я дважды просил скрыть свою личность, что несколько неуважительно (учитывая, что у меня есть приличный профиль на другом SE), @lesath82

@thebusybee Предположим, у меня есть контакт с включенным подтягиванием. Моя идея состоит в том, чтобы внешнее оборудование имело более сильное вытягивание вниз, чтобы я мог распознать, что оно подключено, обнаружив, что мой контакт переведен в НИЗКИЙ уровень. Тем не менее, внешнее оборудование остается готовым к подготовке моих данных., @lesath82

ХОРОШО. Но этот LOW будет интерпретироваться как начальный бит (и, в зависимости от продолжительности LOW и используемой скорости передачи данных, как дополнительные биты данных) на линии TX. Как предотвратить это?, @the busybee

Если бы я сделал наоборот? Мой пин ожидает НИЗКИЙ, внешний переводит его в ВЫСОКИЙ, затем я переключаю свой пин на последовательный и начинаю передачу Или, может быть, я мог бы настроить SoftwareSerial для работы с inverse_logic (я не уверен, означает ли это также низкий холостой ход), @lesath82

Из ваших комментариев мне кажется, что у вас есть только одно внешнее оборудование, подключенное к пину, но вы хотите сначала проверить его наличие, прежде чем отправлять на него данные. Это правильно, или у вас есть несколько разных аппаратных средств, подключенных к этому контакту?, @chrisl

@chrisl Правильно, только одно внешнее оборудование! Arduino должен знать, когда он подключен, в то время как он (при подключении) должен получать данные от Arduino. У меня нет проблем с отправкой данных в любом случае (очевидно, они будут получены только при наличии соединения), но Arduino должен знать, когда присутствует внешнее оборудование. Проверка правильности получения информации не повредит, но это не обязательно., @lesath82

Это аппаратное обеспечение, которое вы создаете/программируете сами, или аппаратное обеспечение, которое даст ответ, если вы отправите ему подходящие данные? Обычно можно просто использовать простое рукопожатие , означающее, что ваш Arduino отправляет простую команду и ожидает ответа. Если ответ не получен, ничего не подключено, и вы можете повторить попытку позже. Это подойдет для вас?, @chrisl

Определенно да! Это даже больше, чем нужно! Вероятно, у меня будет возможность погонять с выбором внешнего железа, это может быть другая Arduino. Это была идея возможного решения Serial with Half Duplex. Возможно, мне придется повторить один и тот же принцип более одного раза (n контактов, расположенных в разных местах, каждый из которых должен определять, подключено ли ITS-оборудование). И я бы чувствовал себя более комфортно с надежным решением, а не с почти экспериментальной библиотекой, которую я вряд ли смогу отлаживать..., @lesath82

Я до сих пор не понимаю, почему вопрос заминусован..., @lesath82


1 ответ


Лучший ответ:

2

Прежде всего, для использования прогрмаммного последовательного порта вам необходимо установить контакты tx и rx в положение OUTPUT, это то, что библиотека делает под капотом.

Что вы можете попробовать сделать, так это установить миллисекундный таймер (забудьте о delay(), никогда не используйте его) и изменить режим вывода на INPUT, скажем, каждые 200 мс. И после ваших измерений верните его в режим вывода, как только сможете.

Задержка в 200 мс обычно подходит для некоторых показаний, таких как нажатие кнопки. Если вы можете прочитать значение реже, сделайте это (например, вы можете прочитать значение какого-либо датчика только один раз в час). Вот пример:

    #include <SoftwareSerial.h>

SoftwareSerial swSerial(7,6);
int val;

byte timer = 200; // Чтение значения каждые 200 мс
uint32_t prevTime = 0;

void setup() {

    // Не меняйте здесь режим вывода
    swSerial.begin(19200);
  
}

void loop() {

    if (millis() - prevTime > timer) {
        // можно попробовать swSerial.flush(); здесь...
        prevTime = millis(); // сброс таймера
        pinMode(6, INPUT_PULLUP); // изменение режима вывода и значения чтения
        val = digitalRead(6);
        pinMode(6, OUTPUT); // меняем режим вывода обратно
    }

    swSerial.print("myData");
    // swSerial.end(); // Я не думаю, что вам нужна эта строка;

}

Это может быть решением с точки зрения программирования. Но другая задача - организовать электрическое мультиплексирование 2-х разных устройств на одном пине, о чем говорил @the busybee

,

Я попробую это прямо сейчас!, @lesath82

Оно работает! Благодарю вас! Позвольте мне спросить вас: вы уверены, что для tx и rx нужны контакты, установленные для вывода? Мне кажется, что метод setRX (строка 282 здесь: https://github.com/arduino/ArduinoCore-avr/blob/master/libraries/SoftwareSerial/src/SoftwareSerial.cpp), вызываемый конструктором, устанавливает вывод rx как ввод, как можно догадаться. Если бы я хотел чередовать цифровое чтение и чтение swSerial, могу ли я оставить режим вывода нетронутым? (кроме подтягиваний). У меня не получилось с первой попытки, но у меня оставалось всего несколько минут, и я мог ошибиться в чем-то другом., @lesath82

Как я и думал, мне просто нужно было отладить код, теперь он работает также с чередованием цифровых и последовательных показаний, не нужно менять назначение вывода: должен быть ввод rx. Благодарю вас!, @lesath82

Вы правы, Rx (приемник) - это ВХОД, а Tx (трансивер) - это ВЫХОД. Вы можете оставить контакт Rx нетронутым и изменить только режим контакта Tx. НО!!! Вы должны быть уверены, что значение, которое вы читаете, не из Serial. Вам понадобится serial.flush, тайминг или даже какое-то физическое решение на диодах и транзисторах. Это зависит от конкретной задачи и условий., @GZstudio GZstudio