Не работает программный рестарт ардуины

Тема в разделе "Arduino & Shields", создана пользователем Константин_Ли, 12 апр 2018.

Метки:
  1. для перезапуска использую такую вот функцию :
    Код (C++):
    void(* resetFunc) (void) = 0;  
    после в коде через некоторое время ее вызываю:
    Код (C++):
    resetFunc();
    и после того как я вызываю эту функцию все виснет.. вообще ничего не делает, очухивается только после ручного перезапуска

    Вот весь мой код, на всякий случай:
    Код (C++):
    #include "SIM900.h"
    #include <MsTimer2.h>

    void(* resetFunc) (void) = 0;

    int relay1 = 12;
    int relay2 = 13;
    char smsbuffer[5];
    char balancebuffer[30];
    float voltage, amperage, WhTotal = 0;
    float Wh = 0.03;
    float UMin = 11;
    float UMax = 14.8;
    float US = 2.49;
    #define V_in 7
    #define TPause 1000
    #define Cycle 60000
    #define PHONE_NUMBER "+7913xxxxxxx"

    void setup()
    {
      //Serial.begin(9600);
      pinMode(relay1, OUTPUT);
      pinMode(relay2, OUTPUT);

      digitalWrite(relay1, LOW);
      digitalWrite(relay2, LOW);

      if (gsm.begin(2400)) {
        gsm.readBalance(balancebuffer, 30);
      }

      //Serial.println("; Balance: " + String(balancebuffer));

      MsTimer2::set(Cycle, timerInterupt);
      MsTimer2::start();
      //Serial.println(String(true) + String(true) + String(true));
    }

    bool ch3_pr = true;
    bool ch2_pr = true;
    int ch1_pr = 0;
    bool ch1 = true, ch2 = true, ch3 = true;

    void loop()
    {
      voltage = analogRead(V_in) * 0.0049 * 10.6;
      amperage = ((analogRead(6) * 0.0049) - US) / 0.066;
      WhTotal += voltage * amperage / 3600;
      //Serial.println("voltage: " + String(voltage) + "; amperage: " + String(amperage) + "; WH: " + String(WhTotal));
      //Serial.println(String(ch1) + String(ch2) + String(ch3));

      if ((voltage >= UMax) && ch1  && ch1_pr < 3) {
        //Serial.println("; UMaxBalance: " + String(balancebuffer));
        //Serial.println((String("The charge is over; Voltage: " + String(voltage) + "; UMax:" + String(UMax))));
        digitalWrite(relay1, LOW);
        gsm.mySendSms(String("The charge is over; Voltage: " + String(voltage) + "; Balance: " + String(balancebuffer)), String(PHONE_NUMBER));
        ch1 = false;
        ch2 = true;
        ch3 = true;
        ch1_pr += 1;

      }
      else if ((voltage <= UMin or WhTotal >= Wh)  && ch2 && ch2_pr) {
        //Serial.println("; UMinBalance: " + String(balancebuffer));
        //Serial.println("voltage <= UMin or WhTotal >= Wh:  " + String(voltage) + " " + String(UMin) + " " + String(WhTotal) + " " + String(Wh));

        digitalWrite(relay2, HIGH);
        delay(TPause);
        digitalWrite(relay1, HIGH);

        gsm.mySendSms(String("Discharge finished; Voltage: " + String(voltage) + "; Amperage: " + String(amperage) + "; Energy: " + String(WhTotal) + "; Balance: " + String(balancebuffer)), String(PHONE_NUMBER)); //отправить напряжение РІ СЃРјСЃ Рё силу тока Рё энергию
        ch1 = true;
        ch2 = false;
        ch3 = true;
        ch2_pr = false;
        ch3_pr = false;
      }
      else if ((voltage < UMax) && (voltage > UMin) && (WhTotal < Wh) && ch3 && ch3_pr) {
        //Serial.println("ELSE:  " + String(voltage) + " " + String(UMin) + " " + String(UMax) + " " + String(WhTotal) + " " + String(Wh));
        digitalWrite(relay1, LOW);
        digitalWrite(relay2, LOW);
        ch1 = true;
        ch2 = true;
        ch3 = false;
      }
      delay(1000);
    }

    void  timerInterupt() {
      resetFunc();
    }

     
     
    Последнее редактирование: 12 апр 2018
  2. ostrov

    ostrov Гуру

    Это не перезапуск, а старт с нулевого адреса. Переменные и регистры могут содержать старые данные.
     
  3. ОК, это понятно, но почему тогда все виснет?
     
  4. DIYMan

    DIYMan Guest

    Подозреваю, что некошерно вызывать старт с нулевого адреса из прерывания. В timerInterrupt просто ставьте флаг, что надо перезапуститься, а в loop - проверяйте и перезапускайтесь при необходимости.
     
  5. parovoZZ

    parovoZZ Гуру

    Это не ресет. Это перевод программного счетчика в начало программы.
     
  6. parovoZZ

    parovoZZ Гуру

  7. ostrov

    ostrov Гуру

    А вот интересно, сам МК может себя за ногу "резет" дернуть? Теоретически почему бы нет, надо попробовать.
     
  8. По задаче.. необходимо чтоб весь программный цикл длился определенное время, после которого начинался заново
     
  9. ostrov

    ostrov Гуру

    Так для этого луп и существует.
     
  10. В принципе источник проблемы я установил:
    Код (C++):
      MsTimer2::set(Cycle, timerInterupt);
      MsTimer2::start();
    заменил на
    Код (C++):
    void softReset() {
      asm volatile ("jmp 0");
    }
    ...
    void loop(){
    if(millis()>=Cycle){
        softReset();
      }
    }
    теперь работает
     
  11. ostrov

    ostrov Гуру

    По уму так не делается.
     
  12. DIYMan

    DIYMan Guest

    Как я и говорил - из прерывания переходить в начало - не гуд, в регистрах мусор всякий.
    Чего бы нет бы? Соединил резет с пином, подтянул куда надо, когда надо - хлоп, и перезагрузка, причём честная ;) Но лучше использовать внешний ватчдог, имхо: тот же один пин, периодически на нём смена уровня. Если смены уровня нет - внешний ватчдог передёргивает питание.
     
    ostrov нравится это.
  13. parovoZZ

    parovoZZ Гуру

    Вачдог на что?
     
  14. ostrov

    ostrov Гуру

    Не на то.
     
  15. ostrov

    ostrov Гуру

    Я не про борьбу с зависанием.
     
  16. parovoZZ

    parovoZZ Гуру

    Взвел, выставил самый короткий промежуток и вуаля.
     
  17. ostrov

    ostrov Гуру

    И напихал во все функции которые длятся короче таймаута взводов. А забыл где и вуаля.
     
  18. parovoZZ

    parovoZZ Гуру

    Если честно, то не понимаю, что должно зачесаться, чтобы так почесать. Решается же просто - оформляется код в отдельные функции, каждая из которых вызывается по мере необходимости.
     
  19. parovoZZ

    parovoZZ Гуру

    В самом начале кода выключаешь вачдог. Где надо - включаешь. Но это выстрел в ногу =)
     
  20. ostrov

    ostrov Гуру

    Я тоже за правильную программу, а не за итерацию путем резета.