В COM-порт приходит "?" и на этом всё встает

Тема в разделе "Arduino & Shields", создана пользователем Лев Николаевич, 16 окт 2018.

  1. Делаю "мобильный" телефон на основе стационарного дискового телефона (надо).
    Почему-то код останавливается на моменте считывания с диска (когда поднимется трубка и геркон размыкается) и в итоге шлет "?".
    Что не так?
    Код (C++):
    #include <SoftwareSerial.h>

    SoftwareSerial Modem(2, 3);
    const int   _ringPin            = 4;
    const int   _headsetPin         = 5;
    const int   _speakerPin         = 6;
    const int   _resetPin           = 11;
    const int   _ledPin             = 9;
    const int   _diskActivePin      = 12;
    const int   _diskContactPin     = 10;

    bool  _diskActive         = 0;
    bool  _diskActiveSwitch   = 0;
    bool  _diskContact        = 0;
    bool  _diskContactSwitch  = 0;
    bool  _speakerEnable      = 0;
    bool  _WaitEnable         = 0;
    long  _WaitTime           = 0;
    int   _diskNumber         = 10;
    int   _Mode               = 0;
    String _Number           = "";
    String _temp              = "";


    void setup() {
      Serial.begin (9600);
      Modem.begin(9600);
      Modem.println("AT");
      pinMode (_headsetPin, INPUT);
      pinMode (_ringPin, INPUT);
      pinMode (_resetPin, INPUT);
      pinMode (_ledPin, OUTPUT);
      pinMode (_diskActivePin, INPUT);
      pinMode (_diskContactPin, INPUT);
      Modem.println("AT+DDET=1");
    }

    String readDisk () {
      Serial.println("readDisk()");
      if (digitalRead(_diskActivePin)) {
        _diskNumber = 0;
        while (1){
          if (!digitalRead(_diskContactPin)) {
            _diskNumber += + 1;
            while (!digitalRead(_diskContactPin)) {}
          }
          delay(10);
       
          if (!digitalRead(_diskActivePin)) {
            if (_diskNumber == 10) _diskNumber = 0;
            _WaitTime = millis();
            _WaitEnable = 1;
            Serial.println("PHN" + String(_diskNumber));
            break;
          }
        }
      } else _diskNumber = 10;
      return _diskNumber;
    }


    void rington () {
      if (! millis()% 1000) {
        if (millis()% 100)
          tone (_speakerPin, 2800, 100);
        else
          tone (_speakerPin, 4186, 100);
      }
    }

    void modemSerial(){
      if (Modem.available()) Serial.write(Modem.read());    // ...и выводим их в Serial
      if (Serial.available()) Modem.write(Serial.read());    // ...и отправляем полученную команду модему
    }

    //bool resetButton()    {if   (digitalRead (_resetPin))     return 1;                      else  return 0;}
    bool headsetGercon ()   {if   (digitalRead (_headsetPin))   return 1;                      else  return 0; Serial.println("PHHG");}
    bool ifRing()           {if   (digitalRead (_ringPin))      return 0;                      else  return 1;}
    void led (bool enable)  {if   (enable)                      digitalWrite (_ledPin, HIGH);  else  digitalWrite (_ledPin, LOW);}

    void loop() {
      again:

      if  (_Mode == 0) { // Режим ожидания
        if (ifRing()){
          _Mode = 1;
        }
        if (!headsetGercon()){
          _Mode = 2;
          delay(500);
        }
        led(0);
      }

      if (_Mode == 1) { //Режим входящего звонка
        if (!ifRing()) _Mode = 0;
        if (!headsetGercon()) {
          delay(100);
          if (!headsetGercon())
            Modem.println ("ATA");
          } else {
            Modem.println ("ATH");
            _Mode = 0;
          }
        led(0);
        rington();
      }

      if (_Mode == 2) {//Режим набора номера
        Serial.println("case: 2");
        _Number = _Number + readDisk();
        Serial.println(_Number);
        if (ifRing()) Modem.println ("ATH");
        if (headsetGercon()) {
          Serial.println("Return to Mode 0");
          delay (500);
          _Mode = 0;
          _Number = "";
          _WaitEnable = 0;
          goto again;
        }
        //if (resetButton()) _Number = "";
        if (_WaitEnable && millis() - _WaitTime >= 5000) {
          _WaitEnable = 0;
          Modem.println("ATD" + _Number + ";");
          _Mode = 3;
        }
        led(1);
      }

      if (_Mode == 3){ //Режим диалога
        readDisk();
        if (_diskNumber != 10) {
          _temp = ("AT+VTS=" + '"' + _diskNumber + '"');
          Modem.println(_temp);
        }
        if (headsetGercon()){
          _Mode = 0;
          Modem.println ("ATH");
        }
        led(0);
      }

      modemSerial();
    }
     

    Вложения:

  2. parovoZZ

    parovoZZ Гуру

    а почему бы не писать так:
    Код (C++):
    mode == wait;
    mode == dialog;
    чем запоминать все эти беспонтовые цифры и числа...

    знак вопроса кто шлет? В коде не вижу. В симуляторе код прогони.

    и это - где реализация устранения дребезга контактов?
     
    Последнее редактирование модератором: 17 окт 2018
  3. ostrov

    ostrov Гуру

    #define вместо const int экономит память и, теоретически, работает быстрее.
     
  4. parovoZZ

    parovoZZ Гуру

    под const память выделяется? В ОЗУ или в РОН?
     
  5. ostrov

    ostrov Гуру

    Ладно, const эквивалентен define, уговорили.
     
    parovoZZ нравится это.
  6. Мне самому интересно, кто это шлет
     
  7. ostrov

    ostrov Гуру

    Помехи шлют вероятно. Осциллограф есть или логический анализатор?
     
  8. DIYMan

    DIYMan Guest

    Схема соединений будет? А то так можно на кофейной гуще долго гадать ;) Пока вангую про дикие помехи по сигнальным линиям в процитированный момент - причина появления мусора в приёмном буфере SoftwareSerial.
     
  9. b707

    b707 Гуру

    это телефон спрашивает "ШО?????"
     
    Лев Николаевич нравится это.
  10. Кто-то схему просил
     

    Вложения:

  11. parovoZZ

    parovoZZ Гуру

    ниче се...почти все красиво нарисовал. Ещё потренироваться и уже станешь конструктором =)
     
  12. DIYMan

    DIYMan Guest

    Вопрос: у вас отдельно впаянный SIM800, или китайская плата? Зачем делитель на RX - модуль, емнип, толерантен к 5В уровням. Стяжка к земле у геркона - не маленький ли номинал? Я бы заменил на 4К7, хотя бы. Вообще - с номиналами всех подтяжек как-то странновато. По остальному - вроде всё ок, значит - надо разбираться, где источник помех. Предлагаю сократить код до минимума, оставив только эхо в Serial от SIM800 - и смотреть, что происходит при срабатывании геркона. Короче - искать источник помех.
     
    DetSimen нравится это.
  13. ostrov

    ostrov Гуру

    А дело, как всегда, в соплях контактов, которых на схеме не нарисовано.
     
    DIYMan и DetSimen нравится это.
  14. Распаянная плата
    нет. http://codius.ru/articles/251#a38
    Ну да. Я просто забыл расписать номиналы
    На геркон идет 1,5 КОм, на SIM800 - 1 КОм, на контакты диска - 10 КОм.
    Собрал из чего было)))
     
  15. DIYMan

    DIYMan Guest

    Да, апшипся, пролистал даташит, там сказано про согласование уровней. Подводит память :)
     
  16. Спустя дофига времени я снова вернулся к телефону.
    Я кажись нашел место, где ARD просто не понимает, что делать и зависает. И это команда
    Код (C++):
    Serial.println("PHN" + String(_diskNumber));
    А именно String(_diskNumber)
    Вот код, где поймал баг
    Код (C++):
    const int _DiskContactPin = 10;
    const int _DiskTickPin = 12;

    int _DiskNumber = 0;

    void setup() {
      pinMode (_DiskContactPin, INPUT);
      pinMode (_DiskTickPin, INPUT);
      Serial.begin (9600);
    }

    String readDisk () {
      if (digitalRead(_DiskContactPin)) {
        _DiskNumber = 0;
        while (1){
          if (digitalRead(_DiskTickPin)) {
            _DiskNumber += + 1;
            while (!digitalRead(_DiskTickPin)) {}
          }
          delay (50);
          if (!digitalRead(_DiskContactPin)) {
            if (_DiskNumber == 10) _DiskNumber = 0;
            Serial.print("PHN");
            //Serial.println(String (_DiskNumber));
            break;
          }
        }
      }
    }

    void loop() {
      readDisk();
    }
    Есть вариант конвертации int в String без использования String()?