Skocz do zawartości

Waga wibracyjna multigłowicowa problem z kolejkowaniem zadań


kellyq

Pomocna odpowiedź

Siema

Mam problemik z kolejkowaniem zadań na esp32 i arduino ide. Mam 5 wag, każdą zarządza odrębny esp32 (slave) który komunikuje się z masterem też esp32 dwoma pinami. Pierwszy pin na slave komunikuje do mastera że porcja jest nasypana (output), drugim pinem (input) przychodzi z mastera komenda wysyp naważony towar. Wiem prymitywne ale działa. Master zarządza wszystkimi slave czyli kiedy mają wysypać (wysypanie automatycznie obliguje slave do nasypania kolejnej porcji)

Wymyśliłem sobie że kolejkowanie będzie za pomocą metody fifo. Problem jest taki że fifo nie działa czasem się gubi, czasem wysypują się dwie porcje. Podsunie ktoś pomysł jak to sensownie zrobić? Mam szkic do mastera taki ale wolałbym to na nowo napisać bo już się bajzel zrobił 😉 

#define czujnik 32     //NO zrobić, kiedy cebula się pojawia zwiera
#define przekaznik 33    // jest NC, na start zamyka obwód

// Definicje pinów
const int inputPins[5] = {19, 21, 22, 23, 25}; // Wejścia cyfrowe dla porcji, pinStatus     PINSTATUS
const int outputPins[5] = {13, 14, 16, 17, 18}; // Wyjścia cyfrowe tożsame z wejściami     PRZYCISK
const int footSwitchPin = 26; // Pin przycisku nożnego

// Kolejka FIFO do przechowywania indeksów gotowych porcji
const int queueSize = 5;
int queue[queueSize];
int front = 0; // Początek kolejki
int rear = 0;  // Koniec kolejki
int count = 0; // Liczba elementów w kolejce

volatile bool buttonPressed = false; // Flaga do obsługi przerwania
int activeOutput = -1; // Indeks aktualnie aktywnego wyjścia (-1 oznacza brak aktywnego)

unsigned long czasOczekiwania = 5000; // Czas oczekiwania po wyłączeniu przekaźnika (5 sekund)
unsigned long poprzedniCzas = 0;  // Czas ostatniego wyłączenia przekaźnika
unsigned long lastButtonPress = 0;  // Czas ostatniego naciśnięcia przycisku

bool przekaźnikDziała = true;

// Funkcja obsługi przerwania z debouncingiem
void IRAM_ATTR onFootSwitchPress() {
  if (millis() - lastButtonPress > 200) {  // Zabezpieczenie przed wieloma kliknięciami w krótkim czasie (debouncing)
    buttonPressed = true; // Ustaw flagę
    lastButtonPress = millis();  // Zaktualizuj czas ostatniego naciśnięcia
  }
}

// Dodaj do kolejki
bool enqueue(int value) {
  if (count == queueSize) return false; // Kolejka pełna
  queue[rear] = value;
  rear = (rear + 1) % queueSize;
  count++;
  return true;
}

// Usuń z kolejki
int dequeue() {
  if (count == 0) return -1; // Kolejka pusta
  int value = queue[front];
  front = (front + 1) % queueSize;
  count--;
  return value;
}

// Funkcja sprawdzająca wejścia i aktualizująca kolejkę z debouncingiem
void checkInputs() {
  static unsigned long lastInputCheckTime = 0;
  if (millis() - lastInputCheckTime > 200) {  // Debouncing 200 ms dla wejść
    for (int i = 0; i < 5; i++) {
      if (digitalRead(inputPins[i]) == HIGH) { // Jeśli porcja gotowa
        bool success = enqueue(i);
      }
    }
    lastInputCheckTime = millis();
  }
}

// Funkcja obsługi aktywnego wyjścia
void manageActiveOutput() {
  if (activeOutput != -1) { // Jeśli jakieś wyjście jest aktywne
    if (digitalRead(inputPins[activeOutput]) == LOW) { // Jeśli odpowiadające wejście zmieni się na niski stan
      digitalWrite(outputPins[activeOutput], LOW); // Wyłącz wyjście
      activeOutput = -1; // Brak aktywnego wyjścia
    }
  }
}

// Funkcja obsługi kolejki po naciśnięciu przycisku
void processQueue() {
  if (buttonPressed && count > 0 && activeOutput == -1) {
    buttonPressed = false; // Zresetuj flagę przerwania

    int index = dequeue(); // Pobierz pierwszy element z kolejki
    if (index != -1) {
      digitalWrite(outputPins[index], HIGH); // Włącz wyjście
      delay(10);
      activeOutput = index; // Zapisz indeks aktywnego wyjścia
    }
  }
}

void setup() {

  // Ustawienie pinów wejściowych
  for (int i = 0; i < 5; i++) {
    pinMode(inputPins[i], INPUT);
    pinMode(outputPins[i], OUTPUT);
    digitalWrite(outputPins[i], LOW); // Wyjścia na niskim stanie
  }
  pinMode(czujnik, INPUT);
  pinMode(przekaznik, OUTPUT);
  digitalWrite(przekaznik, LOW);          //przekażnik działa

  pinMode(footSwitchPin, INPUT_PULLUP); // Przycisk nożny z podciągnięciem

  // Ustawienie przerwania na opadające zbocze (LOW)
  attachInterrupt(digitalPinToInterrupt(footSwitchPin), onFootSwitchPress, FALLING);

  // Sekwencja startowa nasypywanie po kolei każdego kosza wagowego
  for (int i = 0; i < 5; i++) {
    digitalWrite(outputPins[i], HIGH);  // Ustawienie stanu wysokiego na aktualnym pinie wyjściowym
    delay(5000);
    digitalWrite(outputPins[i], LOW);
    
    // Oczekiwanie na stan wysoki na odpowiednim pinie wejściowym
    while (digitalRead(inputPins[i]) == LOW) {
      // Czekaj, aż stan na pinie wejściowym będzie wysoki
    }

    enqueue(i); //dodanie porcji do kolejki
  }
}

void loop() {

  int stanCzujnika = digitalRead(czujnik); // Odczyt stanu czujnika
  
  // Sprawdzamy, czy czujnik wykrywa materiał (stan wysoki)
  if (stanCzujnika == HIGH && przekaźnikDziała) {
    // Jeśli materiału jest dość (stan HIGH) i przekaźnik działa
    digitalWrite(przekaznik, HIGH); // Wyłączamy przekaźnik (stan HIGH)
    poprzedniCzas = millis(); // Zapisujemy czas wyłączenia przekaźnika
    przekaźnikDziała = false; // Zmieniamy stan flagi na false, przekaźnik jest wyłączony
  } 
  // Sprawdzamy, czy czujnik przestał wykrywać materiał (stan niski)
  else if (stanCzujnika == LOW && !przekaźnikDziała) {
    // Jeśli materiału brak (stan LOW) i przekaźnik jest wyłączony
    // Czekamy określony czas po wyłączeniu przekaźnika
    if (millis() - poprzedniCzas >= czasOczekiwania) {
      digitalWrite(przekaznik, LOW); // Włączamy przekaźnik (stan LOW)
      przekaźnikDziała = true; // Ustawiamy flagę na true, przekaźnik działa
    }
  }

  checkInputs();       // Sprawdź wejścia i aktualizuj kolejkę
  processQueue();      // Obsłuż kolejkę
  manageActiveOutput(); // Zarządzaj aktywnym wyjściem
}

 

 

  • Lubię! 1
Link do komentarza
Share on other sites

Bądź aktywny - zaloguj się lub utwórz konto!

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto w ~20 sekund!

Zarejestruj nowe konto, to proste!

Zarejestruj się »

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się »
×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.