Программа Arduino внезапно перестала обновляться

Я пишу программу спидометра/одометра, которая прекрасно работала, пока я не добавил ЖК-экран и код для ЖК-дисплея.

Экран работает при включении питания, отображает расстояние, записанное на SD-карте, переключается с миль на км при нажатии кнопки, но больше не запускает мой метод расчета при вызове. Метод перестал работать, или, по крайней мере, он больше не обновляется последней информацией, когда метод это требует. Любая помощь будет высоко оценена.

Если это имеет значение, я питаю проект от HTC one M8. Может быть, проблема в недостатке питания или просто в плохом программировании?

Мой код:

#include <Arduino.h>
#include <SPI.h>
#include <SD.h>;
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>

int InterruptPin = 2;
//int PowerPin = 3;
int ButtonPin = 4;
int SDPin = 7;





volatile long km = 0; // СОХРАНИТЬ
volatile float kmTemp = 0; // СОХРАНИТЬ
volatile int kmrevs = 0; // СОХРАНИТЬ
volatile long miles = 0; // СОХРАНИТЬ
volatile float milesTemp = 0; // СОХРАНИТЬ
volatile int milesrevs = 0; // СОХРАНИТЬ

volatile int kph = 0;
volatile int mph = 0;
volatile unsigned long start = 0;
volatile unsigned long stop = 0;
volatile float secs = 0;
volatile float speed = 0;
volatile float temp = 0;

volatile int buttonState = 0;
volatile int lastButtonState = 0;
volatile boolean riding = false;

File myFile;

LiquidCrystal_I2C lcd(0x27, 16, 2); 




void calculate(){
    riding = true;

    // КАЛЬКУЛЯТОР СКОРОСТИ В КМ/Ч
    stop = millis() - start;
    start = millis();
    temp = (float)stop;
    secs = temp / 1000;
    speed = 1.854 / secs;
    speed = speed * 3.6;
    kph = speed;


    // КОНВЕРТОР СКОРОСТИ МИЛЬ В ЧАС
    float x = kph * 0.6214;
    mph = x;


    // КАЛЬКУЛЯТОР РАССТОЯНИЯ В КМ
    kmrevs++;
    if (kmrevs == 540){
        km++;
        kmrevs = 0;
        kmTemp = kmTemp + 0.00116;
    }
    if (kmTemp >= 1.0){
        km++;
        kmTemp = kmTemp - 1.0;
    }


    // КАЛЬКУЛЯТОР РАССТОЯНИЯ В МИЛЬАХ
    milesrevs++;
    if (milesrevs == 868){
        miles++;
        milesrevs = 0;
        milesTemp = milesTemp +0.072;
    }
    if (milesTemp >= 1.0){
        miles++;
        milesTemp = milesTemp - 1.0;
    }


    // ПЕЧАТЬ ДАННЫХ НА ЖК-ДИСПЛЕЕ И ПОСЛЕДОВАТЕЛЬНОМ ПОРТУ
    buttonState = digitalRead(ButtonPin);
    if (buttonState == HIGH){
        lastButtonState = buttonState; 
        Serial.print(kph);
        Serial.print("kph  ");

        Serial.print(km);
        Serial.print("km  (");
        Serial.print(kmTemp, 6);
        Serial.println(")  ");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(kph);
        lcd.print("kph");
        lcd.setCursor(0,1);
        lcd.print(km);
        lcd.print("km");
    }
    if (buttonState == LOW){
       lastButtonState = buttonState; 
        Serial.print(mph);
        Serial.print("mph  ");

        Serial.print(miles);
        Serial.print("miles  (");
        Serial.print(milesTemp, 6);
        Serial.println(")");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(mph);
        lcd.print("mph");
        lcd.setCursor(0,1);
        lcd.print(miles);
        lcd.print("miles");
    }


    // СОХРАНИТЬ ДАННЫЕ НА SD-КАРТУ
    SD.remove("test.txt");
myFile = SD.open("test.txt", FILE_WRITE);
    if (myFile) {
        myFile.print(km);
        myFile.print(" ");//
        myFile.print(kmTemp, 6);
        myFile.print(" ");//
        myFile.print(kmrevs);
        myFile.print(" ");//
        myFile.print(miles);
        myFile.print(" ");//
        myFile.print(milesTemp, 6);
        myFile.print(" ");//
        myFile.print(milesrevs);
        myFile.close();
    }
    else {
        // ОШИБКА СОХРАНЕНИЯ SD
        Serial.println("Save Error");
    }
}





void setup(){
    pinMode(ButtonPin, INPUT_PULLUP);
    pinMode(InterruptPin, INPUT);


    // ПИТАНИЕ ЖК-ЭКРАН
    //lcd.begin(16,2);
    lcd.init();
    lcd.backlight();


    // ЗАПУСК ПОСЛЕДОВАТЕЛЬНОГО СОЕДИНЕНИЯ
    Serial.begin(9600);


    // ЗАГРУЗИТЬ ДАННЫЕ С SD-КАРТЫ
    SD.begin(7);
    myFile = SD.open("test.txt", FILE_READ);
    if (myFile) {
       while (myFile.available()) {

       km = myFile.parseInt();
       kmTemp = myFile.parseFloat();
       kmrevs = myFile.parseInt();
       miles = myFile.parseInt();
       milesTemp=myFile.parseFloat();
       milesrevs = myFile.parseInt();

       }
    myFile.close();
    }
    else {
        Serial.println("Read Error");
    }


    // ПРИСОЕДИНИТЬ ПРЕРЫВАНИЯ
     attachInterrupt(digitalPinToInterrupt(2), calculate, RISING);


    // ЗАГРУЗИТЬ НАЧАЛЬНЫЙ ПОСЛЕДОВАТЕЛЬНЫЙ ПОРТ И СКОРОСТЬ ЖК-ДИСПЛЕЯ
    buttonState = digitalRead(ButtonPin);
    if (buttonState == LOW){
        // ОТОБРАЖАЕМЫЕ МИЛЬ/Ч
        lastButtonState = buttonState;
        Serial.print("0mph  ");

        Serial.print(miles);
        Serial.print("miles  (");
        Serial.print(milesTemp, 6);
        Serial.println(")");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(mph);
        lcd.print("mph");
        lcd.setCursor(0,1);
        lcd.print(miles);
        lcd.print("miles");
    }
    if (buttonState == HIGH){
        // ОТОБРАЖЕНО КМЧ
        lastButtonState = buttonState;
        Serial.print("0kph  ");

        Serial.print(km);
        Serial.print("km  (");
        Serial.print(kmTemp, 6);
        Serial.println(")  ");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(kph);
        lcd.print("kph");
        lcd.setCursor(0,1);
        lcd.print(km);
        lcd.print("km");
    }
}





void loop(){
    buttonState = digitalRead(ButtonPin);

    // НУЛЕВАЯ СКОРОСТЬ ПРИ МЕДЛЕННОМ ВРАЩЕНИИ
    if (riding == true){
    long period = millis() - start;
    if (period == 4150){
    if (buttonState == LOW){
        // ОТОБРАЖАЕМЫЕ МИЛЬ/Ч
        lastButtonState = buttonState;
        Serial.print("0mph  ");

        Serial.print(miles);
        Serial.print("miles  (");
        Serial.print(milesTemp, 6);
        Serial.println(")");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(mph);
        lcd.print("mph");
        lcd.setCursor(0,1);
        lcd.print(miles);
        lcd.print("miles");
    }
    if (buttonState == HIGH){
        // ОТОБРАЖЕНО КМЧ
        lastButtonState = buttonState;
        Serial.print("0kph  ");

        Serial.print(km);
        Serial.print("km  (");
        Serial.print(kmTemp, 6);
        Serial.println(")  ");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(kph);
        lcd.print("kph");
        lcd.setCursor(0,1);
        lcd.print(km);
        lcd.print("km");
    }
    }
    }


    // ИЗМЕНИТЬ ПОКАЗАНИЯ ПРИ НАЖАТИИ
    if (buttonState != lastButtonState){
        long period = millis() - start; 
        if (buttonState == HIGH && period < 4150){
        // ОТОБРАЖЕНО КМЧ
        lastButtonState = buttonState;
        Serial.print(kph);
        Serial.print("kph  ");

        Serial.print(km);
        Serial.print("km  (");
        Serial.print(kmTemp, 6);
        Serial.println(")  ");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(kph);
        lcd.print("kph");
        lcd.setCursor(0,1);
        lcd.print(km);
        lcd.print("km");
        }
        if (buttonState == HIGH && period > 4150){
        // ОТОБРАЖЕНО КМЧ
        lastButtonState = buttonState;
        Serial.print("0kph  ");

        Serial.print(km);
        Serial.print("km  (");
        Serial.print(kmTemp, 6);
        Serial.println(")  ");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(kph);
        lcd.print("kph");
        lcd.setCursor(0,1);
        lcd.print(km);
        lcd.print("km");
    }
    if (buttonState == LOW && period < 4150){
        // ОТОБРАЖАЕМЫЕ МИЛЬ/Ч
        lastButtonState = buttonState;
        Serial.print(mph);
        Serial.print("mph  ");

        Serial.print(miles);
        Serial.print("miles  (");
        Serial.print(milesTemp, 6);
        Serial.println(")");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(mph);
        lcd.print("mph");
        lcd.setCursor(0,1);
        lcd.print(miles);
        lcd.print("miles");
    }
    if (buttonState == LOW && period > 4150){
        // ОТОБРАЖАЕМЫЕ МИЛЬ/Ч
        lastButtonState = buttonState;
        Serial.print("0mph  ");

        Serial.print(miles);
        Serial.print("miles  (");
        Serial.print(milesTemp, 6);
        Serial.println(")");

        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print(mph);
        lcd.print("mph");
        lcd.setCursor(0,1);
        lcd.print(miles);
        lcd.print("miles");
    }
    }
}

, 👍1

Обсуждение

Обычно это плохая идея делать так много в ISR (обработчик прерываний). Те другие функции, которые вы вызываете там, могут нуждаться в прерываниях, чтобы быть включенными для правильной работы. Вы должны делать там как можно меньше (возможно, просто обновить счетчик тиков), а затем выполнять всю остальную обработку в другой функции, вызываемой из основного цикла., @Chad G

Используя текущую конфигурацию, вы можете пропустить некоторые тики, даже если бы они работали, так как обновление ЖК-дисплея, печать всей этой информации и сохранение ее на SD-карту, вероятно, займет больше времени, чем время между тиками. Было бы гораздо лучше записывать на SD-карту более крупные «куски» данных, чтобы исключить накладные расходы на открытие и закрытие файла каждый раз., @Chad G

Вы используете millis, делаете последовательные отпечатки и передачи SPI внутри ISR, все это красные флаги. Я бы перепрограммировал его так, чтобы он просто переключал булеву переменную и помещал необходимые данные в глобальные переменные; затем обрабатывал значения и сохранял их в loop. Смотрите https://arduinoprosto.ru/q/22212/using-millis-and-micros-inside-an-interrupt-routine/22237#22237 и https://arduinoprosto.ru/q/30968/how-do-interrupts-work-on-the-arduino-uno-and-similar-boards/30969#30969, @Maximilian Gerhardt

Очевидно, похоже, что все согласны, что проблема, вероятно, кроется в длинном ISR... Я помню, что читал это когда-то давно. Думаю, я могу перепрограммировать его в соответствии с тем, что вы сказали. Я бы в любом случае удалил все операторы print(), поскольку это только для тестирования, но, похоже, у меня все равно возникнут проблемы. Кроме того, вы сказали сохранять на SD большими порциями... вы имеете в виду что-то вроде того, чтобы сбить все значения в одну переменную и сохранить ее, а не делать 6 задач?, @user4163554


1 ответ


1

Спасибо, ребята, удаление работы из ISR решило проблему идеально. К сожалению, совет не был дан как ответ, поэтому я не могу отдать вам должное за это, но ценю предоставленные решения. Спасибо.

,

Похоже, я тоже не могу принять свой ответ! ...может кто-нибудь написать несколько слов в ответе, чтобы я мог его принять. Ура., @user4163554