Почему эта программа работает на R3, но не работает на R4 Wifi?

rtc arduino-uno-r4-wifi

Я работаю над этой программой уже несколько недель и наконец-то почти завершил её. Она загружается и, кажется, работает так, как мне нужно, на плате R3, но не запускается на моей плате R4 Wifi, хотя и сообщает об успешной загрузке.

Последовательный монитор ничего не показывает.

Думаю, дело в библиотеке DS1307, поскольку я пробовал заменить её на DS3232, что улучшило ситуацию, и программа запустилась. Но мне не удалось заставить плату считывать данные с часов реального времени (RTC). Я использую DS3231. Что может быть причиной проблемы?

    #include <SolarPosition.h>
    #include <DS1307RTC.h>
    
    #define MOTOR_ON LOW
    #define MOTOR_OFF HIGH
    
    const uint8_t digits = 3;
    
    
    //SolarPosition Home(134.898551, -25.539774); // Дом//КОД RTC
    SolarPosition Home(32.898551, -2.539774);  // Дом//КОД RTC
    
    
    const int azEncoder_a = 2;  // Зеленый - контакт 2 - цифровой
    const int azEncoder_b = 4;  // Белый - контакт 4 - цифровой
    long azEncoder = 0;
    
    const int elEncoder_a = 3;  // Зеленый - контакт 3 - цифровой
    const int elEncoder_b = 5;  // Белый - контакт 5 - цифровой
    long elEncoder = 0;
    
    
    const int azLimitSwitchPin = A0;  // ОПРЕДЕЛИТЬ ПИН ДЛЯ ИСПОЛЬЗОВАНИЯ В КАЧЕСТВЕ ОГРАНИЧИТЕЛЯ АЗИМУТА
    const int elLimitSwitchPin = A1;  // ОПРЕДЕЛИТЬ ПИН ДЛЯ ИСПОЛЬЗОВАНИЯ В КАЧЕСТВЕ ОГРАНИЧИТЕЛЯ АЗИМУТА
    const int azMotorPinPositive = 12;
    const int azMotorPinNegative = 11;
    const int elMotorPinPositive = 10;
    const int elMotorPinNegative = 9;
    
    bool nightime;
    bool daytime;
    bool trackerAzimuthRunning = false;
    bool trackerElevationRunning = false;
    bool sunRising = false;
    
    int azLimitSwitch = 0;  // ПЕРЕМЕННАЯ ДЛЯ ХРАНЕНИЯ ВЫШЕУКАЗАННОГО ЗНАЧЕНИЯ
    int elLimitSwitch = 0;
    int hours;
    int minutes;
    int seconds;
    int trackerAzimuthAngle;
    int trackerElevationAngle;
    int start = 0;
    int azimuthSun_position;
    float sunElevation;
    float newPosition;
    float oldPosition;
    
    
    void setup() {
      Serial.begin(9600);
    
      pinMode(azEncoder_a, INPUT_PULLUP);
      pinMode(azEncoder_b, INPUT_PULLUP);
    
      pinMode(elEncoder_a, INPUT_PULLUP);
      pinMode(elEncoder_b, INPUT_PULLUP);
    
      attachInterrupt(0, azEncoderPinChangeA, RISING);
      attachInterrupt(1, elEncoderPinChangeB, RISING);
    
      pinMode(azLimitSwitchPin, INPUT);  // КОНЦЕВОЙ ВЫКЛЮЧАТЕЛЬ
      pinMode(elLimitSwitchPin, INPUT);  // КОНЦЕВОЙ ВЫКЛЮЧАТЕЛЬ
    
      pinMode(azMotorPinPositive, OUTPUT);
      pinMode(azMotorPinNegative, OUTPUT);
      pinMode(elMotorPinPositive, OUTPUT);
      pinMode(elMotorPinNegative, OUTPUT);
    
    
      SolarPosition::setTimeProvider(RTC.get);
    }
    
    void loop() {
    
      rtcCode();
    
      trackerAzimuthAngle = azEncoder / 1.67;    //Это изменение в градусах
      trackerElevationAngle = elEncoder / 1.67;  // Это изменится на градусы
      azLimitSwitch = digitalRead(azLimitSwitchPin);
      elLimitSwitch = digitalRead(elLimitSwitchPin);
    
      if (newPosition > oldPosition) {
        Serial.print("Going Up");
        Serial.print('\n');
        sunRising = true;
      }
    
      else if (newPosition < oldPosition) {
        Serial.print("Going Down");
        Serial.print('\n');
        sunRising = false;
      }
      oldPosition = newPosition;
      newPosition = sunElevation;
    
    
      Serial.print("AZIMUTH LIMIT SWITCH STATUS =.....");  //0 = Закрыто
      Serial.print(azLimitSwitch);
      Serial.print('\n');
      Serial.print("ELEVATION LIMIT SWITCH STATUS =.....");  // 0 = Закрыто
      Serial.print(elLimitSwitch);
      Serial.print('\n');
    
      if (start < 1) {
        Serial.print("start ");
        Serial.print(start);
        Serial.print('\n');
        homing();  // Этот оператор проверяет, была ли программа только что запущена.
      }
    
      Serial.print("TRACKER AZIMUTH ANGLE IS   ");
      Serial.print(trackerAzimuthAngle);
      Serial.print('\n');
    
      Serial.print("TRACKER ELEVATION ANGLE IS   ");
      Serial.print(trackerElevationAngle);
      Serial.print('\n');
    
      //КОРРЕКТИРУЙТЕ ЭТИ ВРЕМЕНА ДЛЯ ТЕСТИРОВАНИЯ
      if (hours >= 2 && hours <= 21 && minutes <= 59 && seconds <= 59) {
        daytime = true;
        nightime = false;
      } else {
        nightime = true;
        daytime = false;
      }
      Serial.print("DAYTIME  ");
      Serial.print(daytime);
      Serial.print('\n');
      Serial.print("NIGHTIME  ");
      Serial.print(nightime);
      Serial.print('\n');
    
    
      // ИЗМЕНИТЕ НИЖЕ ДЛЯ ТЕСТИРОВАНИЯ
      if (daytime == true) {
        azimuthRunning();
      } else {
        Serial.print("PAUSED NOT MOVING UNTIL 6AM");
        Serial.print('\n');
        digitalWrite(azMotorPinPositive, HIGH);
      }
      // ПРОВЕРЬТЕ, ПОРА ЛИ ВЕРНУТЬСЯ НА МЕСТО
      if (hours == 9 && minutes == 18 && seconds == 0) {
        homing();
      }
    
      delay(1000);
    }
    
    void homing() {
      digitalWrite(azMotorPinNegative, MOTOR_OFF);
      digitalWrite(azMotorPinPositive, MOTOR_OFF);
      digitalWrite(elMotorPinNegative, MOTOR_OFF);
      digitalWrite(elMotorPinPositive, MOTOR_OFF);
    
      //АЗИМУТ НАВЕДЕНИЯ
    
      while (digitalRead(azLimitSwitchPin) == LOW) {
        Serial.print("HOMING AZIMUTH");
        Serial.print('\n');
        digitalWrite(azMotorPinNegative, MOTOR_ON);
      }
    
      digitalWrite(azMotorPinNegative, MOTOR_OFF);
    
      while (digitalRead(azLimitSwitchPin) == HIGH) {
        Serial.print("BACKING OFF AZIMUTH");  //Измените это, чтобы переместить двигатель
        Serial.print('\n');
        digitalWrite(azMotorPinPositive, MOTOR_ON);
        azEncoder = 0;  // Возвращает кодер в 0 после возврата в исходное положение
      }
      digitalWrite(azMotorPinPositive, MOTOR_OFF);
      start++;
    
      //УРОВЕНЬ НАВЕДЕНИЯ
    
      while (digitalRead(elLimitSwitchPin) == LOW) {
        Serial.print("HOMING ELEVATION");
        Serial.print('\n');
        digitalWrite(elMotorPinNegative, MOTOR_ON);
      }
      digitalWrite(elMotorPinNegative, MOTOR_OFF);
    
      while (digitalRead(elLimitSwitchPin) == HIGH) {
        Serial.print("BACKING OFF ELEVATION");  //Измените это, чтобы переместить двигатель
        Serial.print('\n');
        digitalWrite(elMotorPinPositive, MOTOR_ON);
        elEncoder = 0;  // Возвращает энкодер в 0 после возврата в исходное положение
      }
      digitalWrite(elMotorPinPositive, MOTOR_OFF);
      start++;
    }
    
    
    void azimuthRunning() {
    
      if (azimuthSun_position > trackerAzimuthAngle && daytime == true && trackerElevationRunning == false) {
        trackerAzimuthRunning = true;
        digitalWrite(azMotorPinPositive, MOTOR_ON);
        Serial.print("AZ RUNNING ");
        Serial.print('\n');
      } else {
        trackerAzimuthRunning = false;
        digitalWrite(azMotorPinPositive, MOTOR_OFF);
        Serial.print("AZ Waiting ");
        Serial.print('\n');
      }
      if (trackerAzimuthRunning == false) {
        elevationRunning();  //Elevation Running вызывается только если азимут не работает
      }
    }
    
    void elevationRunning() {
    
      if (sunRising == true) {
        elevationUp();
      } else if (sunRising == false) {
        elevationDown();
      }
    }
    
    void elevationUp() {
      if (sunElevation > trackerElevationAngle && daytime == true) {
        trackerElevationRunning = true;
        digitalWrite(elMotorPinPositive, MOTOR_ON);
        Serial.print("EL RUNNING GOING UP ");
        Serial.print('\n');
      }
    
      else {
        trackerElevationRunning = false;
        digitalWrite(elMotorPinPositive, MOTOR_OFF);
        Serial.print("EL GOING UP WAITING");
        Serial.print('\n');
      }
    }
    
    void elevationDown() {
      if (sunElevation < trackerElevationAngle && daytime == true) {
        trackerElevationRunning = true;
        digitalWrite(elMotorPinNegative, MOTOR_ON);
        Serial.print("EL RUNNING GOING DOWN ");
        Serial.print('\n');
      }
    
      else {
        trackerElevationRunning = false;
        digitalWrite(elMotorPinNegative, MOTOR_OFF);
        Serial.print("EL GOING DOWN WAITING");
        Serial.print('\n');
      }
    }
    
    
    void rtcCode() {
      printTime(RTC.get());
      Serial.print(F("Home:\t"));
      printSolarPosition(Home.getSolarPosition(), digits);
      Serial.println();
      Serial.print('\n');
    }
    
    void azEncoderPinChangeA() {
      azEncoder += digitalRead(azEncoder_a) == digitalRead(azEncoder_b) ? -1 : 1;
    }
    void elEncoderPinChangeB() {
      elEncoder += digitalRead(elEncoder_a) == digitalRead(elEncoder_b) ? 1 : -1;
    }
    
    
    void printSolarPosition(SolarPosition_t pos, int numDigits) {
      Serial.print(F("el: "));
      Serial.print(pos.elevation, numDigits);
      Serial.print(F(" deg\t"));
    
      Serial.print(F("az: "));
      Serial.print(pos.azimuth, numDigits);
      Serial.println(F(" deg"));
      azimuthSun_position = (pos.azimuth);
      sunElevation = (pos.elevation);
    }
    
    void printTime(time_t t) {
      tmElements_t someTime;
      breakTime(t, someTime);
    
      Serial.print(someTime.Hour);
      Serial.print(F(":"));
      Serial.print(someTime.Minute);
      Serial.print(F(":"));
      Serial.print(someTime.Second);
      Serial.print(F(" UTC on "));
      Serial.print(dayStr(someTime.Wday));
      Serial.print(F(", "));
      Serial.print(monthStr(someTime.Month));
      Serial.print(F(" "));
      Serial.print(someTime.Day);
      Serial.print(F(", "));
      Serial.println(tmYearToCalendar(someTime.Year));
    
      hours = someTime.Hour;
      minutes = someTime.Minute;
      seconds = someTime.Second;
    }

Код загружается и запускается с Wire.h в этой позиции, но не считывает данные из RTC.

    #include <Wire.h>
    #include <DS1307RTC.h>
    #include <SolarPosition.h>  

Если Wire.h находится в указанной ниже позиции, код загружается, но не запускается и не отображает ничего на последовательном мониторе.

    #include <DS1307RTC.h>
    #include <SolarPosition.h>
    #include <Wire.h>

В любом случае добавление Wire.begin() не оказывает никакого влияния на вывод.

, 👍2

Обсуждение

Какая часть кода вызывает проблему?, @jsotola

attachInterrupt(0, azEncoderPinChangeA, RISING); Не используйте здесь магические числа, вместо этого используйте digitalPinToInterrupt() для лучшей совместимости по типам плат. Какой вывод здесь вообще имеется в виду? То же самое относится и к другому оператору attachInterrupt()., @6v6gt

Прерывания находятся на контактах 2 и 4. Я попробовал attachInterrupt(2 , azEncoderPinChangeA, RISING);, но энкодеры не заработали., @user115219

Я понятия не имею, какая часть программы вызывает проблему. На мониторе ничего не отображается., @user115219

Прерывания находятся на контактах 2 и 4. Я пробовал attachInterrupt(2 , azEncoderPinChangeA, RISING); 2 — это не номер контакта, а номер прерывания. Попробуйте вместо этого attachInterrupt(digitalPinToInterrupt(2) , azEncoderPinChangeA, RISING);. То же самое для контакта 4., @6v6gt

Извините, прерывания на 2 и 3. Я пробовал., @user115219

attachInterrupt(digitalPinToInterrupt(2), azEncoderPinChangeA, RISING); attachInterrupt(digitalPinToInterrupt(3), elEncoderPinChangeB, RISING);, @user115219

Попробую на R3 и посмотрю, заработают ли энкодеры., @user115219

Да, это отлично работает с R3. Но этот код не запускается на R4., @user115219

Я уже закомментировал весь код для кодировщиков, чтобы устранить эту проблему, но на R4 он все равно не работает., @user115219

В некоторых библиотеках DS1307 есть функция Wire.begin() в конструкторе, что может вызывать проблемы с некоторыми платами. Перенесите функцию Wire.begin() в setup() и попробуйте ещё раз. Если это не поможет, найдите простой пример кода для DS1307 или DS3231 и попробуйте сначала запустить его отдельно. Также убедитесь, что в IDE включены предупреждения компилятора., @6v6gt

Я изменил библиотеку RTC на DS3232RTC и исправил функцию получения времени из RTC, все загружается и работает отлично., @user115219

Хорошо, что проблема решена. Если вы можете продемонстрировать с помощью простого кода несовместимость конкретной библиотеки DS1307 с Uno R4 (но работающей с Uno R3), было бы неплохо ответить на свой вопрос, указав точную версию библиотеки. Это может помочь и другим., @6v6gt


1 ответ


1

Я обнаружил, что добавление #include <Wire.h> в заголовок и Wire.begin() в файл настройки позволяет загрузить и запустить программу на плате R4 Wifi. Единственная проблема — не работают часы реального времени.

С тех пор я изменил библиотеку RTC на DS3232RTC.h и добавил <DS3232RTC myRTC> в заголовок. Я также изменил функции для получения и вывода RTC.

    #include <DS3232RTC.h>
    #include <SolarPosition.h>

    DS3232RTC myRTC;

    Void setup (){
    SolarPosition::setTimeProvider(myRTC.get);}

    void rtcCode() {
    printTime(myRTC.get());}

Теперь программа работает так, как и ожидалось, и отображает время и дату точно.

,

Поздравляю с нахождением решения, но можно ли изучить вопрос подробнее, чтобы определить причину проблемы? Можете ли вы вернуться к проблеме (если сохранили код), а затем просто добавить строку #include<wire.h> и посмотреть, исправится ли ошибка с помощью include-файла или wire.begin()?, @Code Gorilla

Код загружается и работает с Wire.h в этой позиции, но не считывает данные из RTC., @user115219