Sterowanie elektrozaworami ,według kolejności załączenia w czasie

Witam!
Mam do wykonania sterowanie elektrozaworami (9szt). Elektrozawory mogą załączać się po 3 szt (załączają się na 30s ). Sygnały na załączenie (BOOL) dostaję z zewnątrz. Sygnał (czyli logiczne 1) trwa 25s. Tak jak w temacie zawory mają się załączać w takiej kolejności jak dostaję sygnały z zewnątrz.

Teraz mój problem:
Przyjmijmy jak symbol elektrozaworów
EZ_1(elektrozawór 1) ,
EZ_2(elektrozawór 2) itp.

EZ_1(załącz)
EZ_2(załącz)
EZ_3(załącz)
(zawory załączone na 30s)
np. po 10 s dostaję sygnał z EZ_4(załącz) i po 15s z EZ_5(załącz) i po 20s z EZ_6(załącz) .

Jak to ująć w programie by wiadomo było że jeśli WYŁĄCZY się np EZ_1 (Czyli zwolni się 1 z 3 miejsc) załączył się kolejny (czyli EZ_4) a nie EZ_6.
Macie jakiś pomysł ?

Stwórz tablice na więcej niż potrzeba pól, czyli 9+.
Tablica jest wypełniona numerami zaworów lub 0, wrzucaj na następne puste miejsce nowy zawór do otwarcia, a otwieraj tylko te z pozycji 0…2.

Tzn.
Tablica: 0,0,0,0,0,0,0,0,0
Czyli wszystko wyłączone, dostajemy informacje o otwarciu zaworów więc dodajemy ich numery
Tablica: 1,2,0,0,0,0,0,0,0
Otwieramy zawory 1 i 2, w między czasie przychodzi rozkaz na następny zawór
Tablica: 1,2,5,0,0,0,0,0,0
Otwieramy zawory 1,2 i 5.
Czas otwarcia zaworów 1 i 2 mija, więc przesuwanymi wartości “w dół”
Tablica: 5,0,0,0,0,0,0,0,0.

Warunki otwarcia zaworu to sprawdzenie czy na jednej z trzech pierwszych pozycji tabeli jest numer danego zaworu.

Kolejkowanie odbywa się poprzez pętle for, gdzie sprawdzamy najbliższe wolne miejsce (wartość 0).
Usuwanie zaworu z tablicy poprzez zbocze opadające timera odpowiadającego za otwarcie lub zbocze opadające cewki zaworu. (usuwanie czyli ustawienie wartości w tabeli na 0 z numeru zaworu).
Przesuwanie wartości w tablicy sprawdzane w każdym cyklu, tam gdzie jest 0 to przesuwamy z góry na dół (tablica[n] = tablica[n+1]).

Powinno działać :slight_smile:

2lajki

Po prostu kolejka FIFO z którego czytasz 3 pierwsze elementy.

2lajki

Rafał, myślę że to można prościej niż na tablicach załatwić.
Stwórz słowo gdzie będziesz przechowywać ilość aktywnych zaworów, każdy załączający się zawór zwiększa licznik, kończy pracę odejmuje wartość. Zewnętrzny sygnał ustawia status “zawór do załączenia”, jeśli ilość pracujący zaworów jest mniejsza niż 3 to załącza. Załączający się zawór daje info który zawór będzie następny do załączenia po spełnieniu warunku ilości pracujących zaworów. To dość duże uproszczenie ale powinno działać.

Jacek,robiłem tak niestety wtedy załączają się na raz 4 zawory zamiast 3.
Poza tym to o czym napisałem to jest mała część całego programu w którym jest więcej komplikacji.
Ale dziękuję za pomysł !:slight_smile:

Powiesz mi jak zrobić taką kolejkę FIFO w języku ST ?

Przemek , piszę program w języku ST .Powiem szczerze że myślałem prawie identycznie.Niestety dopiero zaczynam przygodę z programowaniem i nie do końca wiem jak zapisać to w kodzie programu . Byłbyś w stanie chociaż trochę mi to zarysować?
Jak wpisywać do kolejnych wolnych wierszy tablicy te zawory ?
Jak przesuwać ta kolejkę w dół ?

Dobrze jest odpocząć od pisania kodu, żeby… napisać trochę kodu :smile:

Nie będzie to CTRL+C > CTRL+V, ale zarys do przepisania i przetestowania.

        tableSize := .. ; //dlugosc tabeli
	//valveTable[0] .. valveTable[tableSize];
	
	INT nextValve, valveCoil;
	BYTE valveTable[tableSize];
	
	//przyjmowanie rozkazow startu, obsluge zbocza narastajacego musisz dopisac
	nextValve.0 := R_Trig_1.Q
	//(...)
	nextValve.8 := R_Trig_8.Q
	
	
	//kolejkowanie - przyjecie nowych rozkazow
	IF nextValve > 0 THEN
		FOR i:= 0 TO tableSize BY 1 DO
			IF valveTable[i] <> 0 THEN
				FOR j:= 0 TO tableSize BY 1 DO
					IF nextValve.j THEN
						nextValve.j = FALSE;
						valveTable[i] := j+1;
						//nextValve.j oznacza sprawdzenie bitu w zmiennej z indeksem j
						//kwestia jak wykonasz to sprawdzenie to osobna sprawa
						//wpisujemy j+1 zeby przejsc na zakres 1..9
					END_IF;
				END_FOR;
			END_IF;
		END_FOR;
	END_IF;
	
	//przyjmowanie rozkazow startu, obsluge zbocza narastajacego musisz dopisac
	// F_TRIG_0(CLK:= TimerPulse_0.Q)
	// czyli sprawdzenie zamkniecia zaworu po danym czasie, moze byc inny timer
	closedValve.0 := F_TRIG_0.Q
	//(...)
	closedValve.8 := F_Trig_8.Q
	
	IF closedValve > 0 THEN
		FOR i:= 0 TO tableSize BY 1 DO
			IF closedValve.i THEN
				closedValve.i := FALSE;
				FOR j:= i TO tableSize BY 1 DO
					valveTable[j] = valveTable[j+1];
					//nadpisujemy zamkniete zawory wartosciami z wyzszych indeksow
				END_FOR;
				valveTable[8] := 0; 
				//wpisujemy zero na koniec tabeli poniewaz dokonalismy przesuniecia
				//i zostala by tam poprzednio wpisana wartosc
			END_IF;
		END_FOR;
	END_IF;
	
	//zerowanie bitow dla wszystkich zaworow
	FOR i:= 0 TO 8 BY 1 DO
		FOR j:= 0 TO 2 BY 1 DO
			IF valveTable[j] == i+1 THEN //sprawdzamy czy numer zaworu jest w zakresie od 0 do 2 w tabeli
				valveCoil.i := TRUE;
			ELSE
				valveCoil.i := FALSE;
				//tak jak wyzej sprawdzalismy bit zmiennej valveCoil
				//tak tutaj ustawiamy konkretny bit
			END_IF;
		END_FOR;
	END_FOR;
	
	TimerPulse_0.IN := valveCoil.0;
	//(...)
	TimerPulse_8.IN := valveCoil.8;
	
	cewkaZaworu_1 := TimerPulse_0.Q;
	//(...)
	cewkaZaworu_9 := TimerPulse_8.Q;
	//dlaczego wszedzie jest numeracja 0..8, a cewakaZaworu 1..9?
	//latwiej podczas operacji na tablicach operowac w tym samym zakresie
	//i przeniesc sie w jednym polu widzenia na inny zakres

Tak na szybko napisane więc może nie być dokładnie, ale koncept się zgadza.

2lajki

Dziękuję ! Jestem pod wrażeniem .
Pytanie poza tematem , jaki masz staż w programowaniu ?:smiley:

Taki staż, że już mi się nie chce programować :stuck_out_tongue:

2lajki

@Rafal_T Wybacz, że nie odpisywałem dziś. Niestety delegacja. Cieszę się, że problem rozwiązany :slight_smile:

1lajk