Как установить 60-минутный звуковой сигнал?

Я пытаюсь создать устройство, которое будет регистрировать латентность и количество ударов для пассивного избегающего поведения у дрозофилы. У моего устройства есть две кнопки-зеленая и красная. Я нажимаю зеленый, когда сажаю плодовую мушку в пробирку. Когда дрозофила входит в шоковый отсек, я нажимаю красную кнопку, чтобы дать электрический удар через Травяной стимулятор. Мой Arduino регистрирует задержки или прошедшее время от нажатия зеленой кнопки и последующих нажатий красной кнопки, а также количество ударов (нажатий красной кнопки). Эта часть работает просто отлично, однако я хочу иметь 60-секундный звуковой сигнал, так как тест проходит всего 1 минуту. Эта часть не работает. Звуковой сигнал отсчитывает 60 секунд с момента запуска устройства, а не с момента нажатия зеленой кнопки. Я не уверен, что делаю неправильно.

Вот этот код:


#include <LiquidCrystal.h>

/*
  Супер-базовый секундомер с использованием millis();
*/

unsigned long start, finished, elapsed;
unsigned long startTime;
unsigned long endTime;
unsigned long duration;
byte timerRunning;
int switchPin = 3;              // переключатель подключен к контакту 3
int val;                        // переменная для чтения статуса пин
int buttonState;                // переменная для хранения состояния кнопки 
int buttonPresses = 0;          // Сколько раз кнопка была нажата
const int buz = 13;
unsigned long delayStart = 0; // Время задержки начала
//bool timerRunning = false; // истина, если все еще ждут задержки, чтобы закончить
// include the library code:
#include <LiquidCrystal.h>


// initialize the library with the numbers of the interface pins
LiquidCrystal lcd (9, 8, 7, 6, 5, 4);

void setup()
{
  lcd.begin(16, 2);
  //lcd.setCursor (0,0);
  //lcd.print("resetting");
  lcd.setCursor (3,1);
  lcd.print("resseting");
  delay(3000);
  lcd.clear();
  lcd.setCursor (0,0);
  lcd.print ("Latency= ");
lcd.setCursor (0,1);
lcd.print ("Shocks= ");
  Serial.begin(9600);
  pinMode(2, INPUT); // start button
  pinMode (2, INPUT_PULLUP);
  pinMode (buz,OUTPUT);
  pinMode(switchPin, INPUT);    // Set the switch pin as input
  digitalWrite(buz, LOW); // turn buz off
  delayStart = millis();   // start delay
  //delayRunning = true; // not finished yet
  buttonState = digitalRead(switchPin);   // read the initial state
  Serial.println("Press 'Green' for Start/Reset, 'Red' for Shocks");
}

void displayResult()
{
  float h,m,s,ms;
  unsigned long over;
  elapsed=finished-start;
  h=int(elapsed/3600000);
  over=elapsed%3600000;
  m=int(over/60000);
  over=over%60000;
  s=int(over/1000);
  ms=over%1000;
  Serial.print("Elapsed time: ");
  Serial.println(elapsed);
  Serial.print("Latency: ");
  Serial.print(m,0);
  Serial.print("m ");
  Serial.print(s,0);
  Serial.print("s ");
  Serial.print(ms,0);
  Serial.println("ms");
  Serial.print("Shocks: ");
  Serial.print(buttonPresses);
  Serial.println(" time(s)");
  lcd.setCursor (8,0); 
  lcd.print(m,0);
  lcd.print("m");
  lcd.print(s,0);
  lcd.print("s");
  lcd.print(ms,0);
  lcd.setCursor (7,1); 
  lcd.print(buttonPresses);

}

void loop()

    
    
    {float h,m,s,ms;
  
  if (digitalRead(2) == HIGH);{ // кнопка нажата и таймер уже не работает
  start=millis();
  lcd.setCursor (7,1);
  lcd.print("           "); 
  buttonPresses=0;
  lcd.print(buttonPresses);
    Serial.println("Started");
    lcd.setCursor (8,0); 
    lcd.print("           ");
    lcd.print("Start..."); 
  lcd.print(buttonPresses);
  lcd.setCursor (8,0);
    lcd.noBlink();

  delay(300);

  // Turn on the blinking cursor:

  lcd.blink();
    delay(200); // for debounce
     
  }
  
  if (digitalRead(3)==HIGH)
  { lcd.noBlink();
  lcd.setCursor (9,0);
   lcd.print("        ");
    finished=millis();
    delay(200); // for debounce
    buttonPresses++;
    displayResult();
    delay(200);}
    
    if (timerRunning && ((millis() - delayStart) >= 60000)) {
    //timerRunning = false; // // запретить выполнение этого кода более одного раза
    digitalWrite(buz, HIGH); // включить buz on
   // tone(buz, 1000); // Send 1KHz sound signal...
  delay(1000);        // ...for 1 sec
  noTone(buz);     // Stop sound...
  delay(1000);        // ...for 1sec
    Serial.println("Turned buz on");
    lcd.setCursor (10,1);
    lcd.print("1min");
  }}

, 👍1

Обсуждение

Проверьте пример мигания без задержки. Установите переменную при запуске теста и сверьтесь с текущим временем (минус 60 секунд), чтобы запустить звуковой сигнал., @Michel Keijzers

ваш код действительно плохо отформатирован, что может легко привести к ошибкам ... например, у вас не должно быть двух фигурных скобок"}} " рядом друг с другом, @jsotola


1 ответ


1

Лучше всего начать с примера BlinkWithoutDelay в IDE.

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

Затем вы можете создать универсальную функцию, которая поможет уменьшить "спагетти-код".

Я бы предпочел ООП-подход.

// Sketch uses 910 bytes (2%) of program storage space.
// Global variables use 18 bytes (0%) of dynamic memory.
// Arduino Uno, IDE 1.8.9
class MillisTimer{

  private:

    unsigned long m_timeInMilliSeconds;
    unsigned long m_previousMillis;
    byte m_timerActive;

  public:

    MillisTimer(unsigned long timeInMilliSeconds):
      m_timeInMilliSeconds(timeInMilliSeconds){
      m_timerActive = 0;
      m_previousMillis = 0;
    }

    bool Update(){
      if(m_timerActive && (millis() - m_previousMillis >= m_timeInMilliSeconds)){
        m_previousMillis += m_timeInMilliSeconds;
        return 1;
      }
      else{
        return 0;
      }
    }

    void Start(){
      m_timerActive = 1;
    }

    void Stop(){
      m_timerActive = 0;
    }

    void ReStart(){
      m_timerActive = 1;
      m_previousMillis = millis();
    }

};

// Сделаем копию объекта для работы.
MillisTimer SixtySecondTimer(60000);

void setup(){

  // Вызовите эту функцию одним нажатием кнопки
  // для запуска 60-секундного таймера.
  SixtySecondTimer.Start();

  // Индикатор завершения таймера.
  pinMode(LED_BUILTIN, OUTPUT);

}

void loop(){

  // Вызовите функцию обновления как можно быстрее.
  if(SixtySecondTimer.Update()){
    digitalWrite(LED_BUILTIN, HIGH);
    SixtySecondTimer.Stop();
  }

}

,