Skocz do zawartości

Wielozadaniowośćna Arduino - pozbądź się delay


Gość es2

Pomocna odpowiedź

Gość es2

W wielozadaniowym delay nie kręci się w kółko, tylko "zwalnia czas procesora" dla innych zadań na określony czas. Podobnie czekanie na zdarzenie, task "wisi" bo są wykonywane inne taski. Zdarzenie "uruchamia" task dalej. Pisałem system wielozadaniowy na Z-80 więc wiem jak to działa.

A mnie np. drażni gdy ktoś Wie Wszystko , a głosząc prawdy objawione pokazuje wszem i wobec, iż w rzeczywistości wie niewiele (tak, do kolegi wątkotwórcy piję,).

Jak na razie, to w tej dyskusji, to poza wątkotwórcą, konkretnego rozwiązania problemu delay, równoczesnego realizowania kilku zadań nikt nie przedstawił.

Można użyć RTOS. ok, proszę więc pomóc koledze z linku który podałem. Są inne rozwiązania? Proszę pokazać jakie bo jak na razie to czytam, że można inaczej ale rozwiązania nie widzę, tak jak żony Colombo .

Dużo pisania efekt żaden.

Link do komentarza
Share on other sites

Bardzo częstym błędem w programach na uC, nie ważne czy to AVR, czy ARM czy 8080, jest używanie delay.

...można zrealizować pseudo wielozadaniowość. Podstawowe informacje można znaleźć pod adresem https://forbot.pl/blog/kurs-arduino-ii-wielozadaniowosc-opoznienia-z-millis-id18418

Problemem tego wątku jest to, że autor tego wątku ma problem z tym, że ludzie posługują się opóźnieniami.

es2, żeby było jeszcze gorzej przedstawiłeś problem i jego rozwiązanie już w pierwszym poście (ja oczywiście dalej utrzymuję, że dział arduino tyczy arduino ... ).

es2, z cały szacunkiem, jeśli cię to tak drażni, że ludzie źle programują Arduino to może stwórz kurs, który wyjaśni w końcu początkującym jak TO się robi porządnie (czyli taki kurs, którego początkujący nie rzuci w diabły po pierwszym tutku 🙂 )

Link do komentarza
Share on other sites

Gość es2
jeśli cię to tak drażni, że ludzie źle programują Arduino

Ja sobie miga dioda to niech używa delay, nie ma problemu. Jak chce migać diodą, emulowac terminal i w tym czasie wyświetlać animacje na wyświetlaczu o delay trzeba zapomieć.

to może stwórz kurs, który wyjaśni w końcu początkującym jak TO się robi porządnie (czyli taki kurs, którego początkujący nie rzuci w diabły po pierwszym tutku 🙂 )

To jest raczej trudne a wręcz niemożliwe. Aby było łatwo to faktycznie najlepiej użyć RTOS. Ilu poczatkujacych to zrobi? Jak nawet zrobi, to za chwile okaże się, ze w UNO brakuje ram.

Przerwania też nie rozwiążą problemu. Zaczną się schody z volatile i atomic_block.

Większość problemów rozwiąże millis i maszyna stanów. Jest to dośćproste do zrozumienia, wystarczy zacząć od prostych zadań jak np równoczesne miganie diodą i cykliczne wyświetlanie tekstu na lcd. Podstawy millis są opisane w linku z pierwszego postu. Nie widzę sensu tego przepisywać. Tu czekam na konkretne problemy. Naturalnie, nie sposób szybko pomóc gdy kod ma 1000linii. Pisząc kod najlepiej od razu pisać bez delay. Wtedy dodanie kolejnych opcji będzie łatwe.

Pierwsza lekcja "no delay", pisane w HAL (Arduino dla zaawansowanych), no nie do końca bo po rejestrach też piszę:

while (1)
 {
 /* USER CODE END WHILE */

 /* USER CODE BEGIN 3 */

//	NVIC_SystemLPConfig(NVIC_LP_SEVONPEND, DISABLE);	// Glebokie uspienie
//		__WFI();                // Uspienie do przerwania          
	IWDG->KR = 0xaaaa;			//przeladowanie IWDG
	HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);



	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);		
	Delay_us(1); // Pomiar poprawności delay
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);	

	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);		
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);	
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);		
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);	

   GPIOA->BSRR = GPIO_PIN_0;
  GPIOA->BSRR = GPIO_PIN_0;
  GPIOA->BSRR = GPIO_PIN_0;
   GPIOA->BSRR = (uint32_t)GPIO_PIN_0 << 16U;
   GPIOA->BSRR = (uint32_t)GPIO_PIN_0 << 16U;
//  GPIOA->BSRR = (uint32_t)GPIO_PIN_0 << 16U;
  GPIOA->BSRR = GPIO_PIN_0;
   GPIOA->BSRR = GPIO_PIN_0;
//   GPIOA->BSRR = GPIO_PIN_0;
   GPIOA->BSRR = (uint32_t)GPIO_PIN_0 << 16U;
   GPIOA->BSRR = (uint32_t)GPIO_PIN_0 << 16U;
//   GPIOA->BSRR = (uint32_t)GPIO_PIN_0 << 16U;
  GPIOA->BSRR = GPIO_PIN_0;
  GPIOA->BSRR = GPIO_PIN_0;
//   GPIOA->BSRR = GPIO_PIN_0;
   GPIOA->BSRR = (uint32_t)GPIO_PIN_0 << 16U;

	Delay_us(5);	// Przerwa pomiędzy pomiarami delay


//przerwania od przycisku popra
 if( !TimLedPWM )
{
	TimLedPWM = 2;
//zrobic funkcje i przeniesc wywolanie do przerwania od timera 1ms	
unsigned short static jasnosc=0;
//long static jasnosc=0;
char static fazaPwm=0;
#define PWM_MAX	20000 //49999
#define PWM_MIN	0
#define PWM_MNOZNIK_R	0.7
#define PWM_MNOZNIK_G	0.6

	switch( fazaPwm )
	{
		case 0:		// Czerwona
			if( jasnosc < PWM_MAX*PWM_MNOZNIK_R )jasnosc +=50; else { jasnosc= PWM_MAX*PWM_MNOZNIK_R; fazaPwm++; }
			__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, jasnosc);
			break;
		case 1:
			if( jasnosc > PWM_MIN )jasnosc -=50; else { jasnosc=PWM_MIN; fazaPwm++; }
			__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, jasnosc);
			break;
		case 2:		// Zielona	
			if( jasnosc < PWM_MAX*PWM_MNOZNIK_G )jasnosc +=50; else { jasnosc= PWM_MAX*PWM_MNOZNIK_G; fazaPwm++; }
			__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, jasnosc);
			break;
		case 3:
			if( jasnosc > PWM_MIN )jasnosc -=50; else { jasnosc=PWM_MIN; fazaPwm++; }
			__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, jasnosc);
			break;
		case 4:		// Niebieska
			if( jasnosc < PWM_MAX )jasnosc +=50; else { jasnosc= PWM_MAX; fazaPwm++; }
			__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, jasnosc);
			break;
		case 5:
			if( jasnosc > PWM_MIN )jasnosc -=50; else { jasnosc=PWM_MIN; fazaPwm++; }
			__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, jasnosc);
			break;
		default: fazaPwm=0;
	}



}


if( !TimLedRGB )
{
	TimLedRGB=1000;
	signed char static StanLedRGB=0;

	LcdSetCursorPosition(0,1);
	sprintf(buffer, "Liczba=% 4d", nrlcd++); LcdPrintString(buffer);



	uint8_t data[4]={0xAA,0xAA,0x55,0x55};
	uint8_t static krok=0;
	data[0] = data[2] = (1<<(krok&7));
	krok++;

	LcdSetCursorPosition(0,0);		//0123456789abcdef												 0123456789abcdef
	if( nrlcd & 1 )
		{
		LcdPrintString("ARM STM32F411CE ");
	//----- Sterowanie PCA9555 IIC
		HAL_I2C_Mem_Write(&hi2c1, 0x26<<1, 0x02, 1, data, 2, 5);	
		}
	else
		{
		LcdPrintString("Alphanumeric LCD");	
	//----- Sterowanie PCA9555 IIC
			HAL_I2C_Mem_Write(&hi2c1, 0x26<<1, 0x02, 1, data+2, 2, 5);	
		}
	uint8_t odczyt[2];	
	HAL_I2C_Mem_Read(&hi2c1, 0x26<<1, 0, 1, odczyt, 2, 2);		// Odczyt obu wejsc expandera
	sprintf(buffer, "\n\rPIO=%x", odczyt[1] );	uart_write(&huart2, buffer);


	switch( StanLedRGB )
{
	case 0:
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);			// Wyzwalanie

	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_RESET);			// Czerwona RGB
		break;
	case 1:
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET);			// Wyzwalanie


	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_14, GPIO_PIN_SET);			// Czerwona RGB

		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_RESET);			// Zielona RGB


MessageLength = sprintf((char *)DataToSend, "Wiadomosc nr %d\n\r", MessageCounter);
CDC_Transmit_FS(DataToSend, MessageLength);	


//uart_write(&huart2, "\n\rWprowadz tekst: ");
//uart_read_line(&huart2, buffer, 1024);
//		uart_write(&huart2, "Odebrano: ");
//		uart_write_line(&huart2, buffer);


 uint32_t static liczba=1;
liczba++;

uart_write(&huart2, "\n\rZmienna int="); sprintf(buffer, "%d", liczba); uart_write(&huart2, buffer);

uart_write(&huart2, "\n\rZmienna float="); sprintf(buffer, "%f", zmienna); uart_write(&huart2, buffer);


     break;
	case 2:
		HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_RESET);			// Wyzwalanie

	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_15, GPIO_PIN_SET);			// Zielona RGB

	HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_RESET);		// Niebieska RGB
		break;
	case 3:
		HAL_GPIO_WritePin(GPIOB, GPIO_PIN_13, GPIO_PIN_SET);// Niebieska RGB

		zmienna = zmienna + 10.123;

		StanLedRGB=-1;
	break;
	default:
		StanLedRGB=-1;
	}	
StanLedRGB++;
}


 }
 /* USER CODE END 3 */

Zestaw "Arduino" z wcześniejszych fotografii. W tym samym czasie płynnie zmienia kolor dioda RGB, wysyłane sa komunikaty na USB, USARTA, LCD, obsługiwany jest ekspander na I2C. Nie ma delay, nie ma przerwań.

Delay, które sa (5 i 1 us) służą, właściwie służyły do sprawdzenia poprawności realizowania funkcji opóźniające oraz do sprawdzenia czasu reakcji na przerwanie zewnętrzne. STM32F411 96MHz reaguje na przerwanie zewnętrzne w czasie ponad 200ns (czas liczony od wystawienia poziomu aktywnego na GPIO do czasu wykonania operacji na GPIO w przerwaniu więc faktycznie jest kródszy, bo HAL swoje dokłada). W AVR 16MHz dla procków bez rejestru RAMPZ, czas ten wynosi 700ns (łącznie z odłożeniem rejestrów na stosie więc można go skrócić).

Link do komentarza
Share on other sites

A ja mam takie niedyskretne pytanie...

Po kiego grzyba założyłeś ten wątek? Chcesz pokazać że jesteś mądrzejszy od 20% userów tego forum? Wierzymy Ci na słowo...

Na razie nic konkretnego nie powiedziałeś oprócz jakichś smętnych dywagacji na temat różnych procesorów na których się oczywiście znasz...

Pokaż coś konkretnego, kawałek przykładowego kodu z wyjaśnieniem dlaczego tak.

Potrafisz?

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Nie wiem czy dobrze zrozumiałem zamysł es2, ale w tym wątku chyba chciał przekonać początkujących do nie używania delay. Jako, że jestem początkujący i już wiem, że delay nie powinno się używać, chciałem coś wynieść z tej "dyskusji", ale nic nie rozumiem, co to freeRTOS, HAL i inne takie. Ten wątek na pewno nie jest dla zielonych 😉

Link do komentarza
Share on other sites

ethanak, czy mógłbyś rozwinąć jak rozumiesz różnice między wielozadaniowością i wielowątkowością - w przypadku mikrokontrolerów oczywiście?

Ja opierałem się na dokumentacji FreeRTOSa:

A Note About Terminology

In FreeRTOS, each thread of execution is called a ‘task’.

There is no consensus on

terminology within the embedded community, but I prefer ‘task’ to ‘thread,’ as thread can have

a more specific meaning in some fields of application.

I stąd stosowanie obu terminów zamiennie.

Link do komentarza
Share on other sites

Gość es2
Nie wiem czy dobrze zrozumiałem zamysł es2, ale w tym wątku chyba chciał przekonać początkujących do nie używania delay.

Dokładnie tak.

Jako, że jestem początkujący i już wiem, że delay nie powinno się używać, chciałem coś wynieść z tej "dyskusji", ale nic nie rozumiem, co to freeRTOS, HAL i inne takie. Ten wątek na pewno nie jest dla zielonych 😉

To pokaz kod jaki masz z delay a chciałbyś aby go nie było. Pokażę jak to zrobić. Oczywiście jak będziesz miał tych delay dziesiątki czy setki, to pokażę jak pozbyć się np dwóch, reszty pozbędziesz się w analogiczny sposób.

freeRTOS to darmowy RTOS. RTOS to system wielozadaniowy, jak Unix (MaxOS) Linux, (Windows świadomie pomijam a 3.11 obowiązkowo) przeznaczony na uC. Ma małe wymagania na zasoby (pamięć ram, flash, mmu).

HAL to biblioteki ułatwiające (czasem utrudniające) pisanie programów na uC STM32. W połączeniu z CubeMX łatwo rozpocząć przygodę a ARM, tak jak Arduino ułatwia start z uC (głównie AVR).

[ Dodano: 16-04-2018, 16:20 ]

Pokaż coś konkretnego, kawałek przykładowego kodu z wyjaśnieniem dlaczego tak.

Pokazałem całą pętle główną i napisałem jak działa.

Link do komentarza
Share on other sites

RTOS... co znaczy system wielozadaniowy na mikro kontrolery? Np. na arduino? Co taki system potrafi, dlaczego piszecie, że nie nadaje się dla zielonych, co ułatwia a co utrudnia, przecież kod i tak trzeba pisać???? chyba 😖

Dwa kody:

void menu_glowne(){
 Serial.println(brama_garaz);
if(sekunddwie.available()){
  kontrola_przekazniki();
  sekunddwie.restart();
}
if(czujniki.available()){
 napiecie_pralka = analogRead(A7);
 term_strych_maxmin_reset();
 term_slonce_maxmin_reset();
 term_grunt_maxmin_reset();
 term_CO_maxmin_reset();
 dht_wew_maxmin_reset();
 bmp_maxmin_reset();
 dht_zew_maxmin_reset();
 Blynk.virtualWrite(5,"    ",temperatura_dht_kuchnia," *C");
 Blynk.virtualWrite(6," ",wilgotnosc_dht_kuchnia," %RH");
 Blynk.virtualWrite(7,"    ",temperatura_dht_zew," *C");
 Blynk.virtualWrite(8," ",wilgotnosc_dht_zew," %RH");
 Blynk.virtualWrite(9,"   ",cisnienie_bmp_strych," hPa");
 Blynk.virtualWrite(10,"    ",temp_grunt," *C");
 Blynk.virtualWrite(11,"    ",temp_slonce," *C");
 Blynk.virtualWrite(12,"    ",temp_strych," *C");
 Blynk.virtualWrite(13,"    ",temp_CO," *C");
 Blynk.virtualWrite(23,"    ",temperatura_bmp_piwnica," *C");
 czujniki.restart();
}
switch(menu_1){
case JEDEN:
   jeden();
   if(alarm_on==false){
   alarm();
   alarm_on=true;
   }
   if(digitalRead(PinP)==LOW){
     delay(30);
       lcd.clear(); 
       pozycja_markera=1;
       licznik=1;
       ping();
       time1=millis();
       menu_opcje();
 }
 if(glowny.available()){
     lcd.clear(); 
    glowny.restart();
    alarm_on=false;
    menu_1=DWA;
   }

break;
case DWA:
   dwa();
   if(digitalRead(PinP)==LOW){
     delay(30);
       lcd.clear(); 
       pozycja_markera=1;
       licznik=1;
       ping();
       time1=millis();
       menu_opcje();
 }
   if(glowny.available()){
  lcd.clear(); 
  glowny.restart();
   menu_1=TRZY;
   }
break;
case TRZY:
   trzy();
   if(digitalRead(PinP)==LOW){
     delay(30);
       lcd.clear(); 
       pozycja_markera=1;
       licznik=1;
       ping();
       time1=millis();
       menu_opcje();
 }
   if(glowny.available()){
  lcd.clear(); 
  glowny.restart();
   menu_1=CZTERY;
   }
break;
case CZTERY:
   cztery();
   if(alarm_on==false){
    alarm();
    alarm_on=true;
   }
   if(digitalRead(PinP)==LOW){
     delay(30);
       lcd.clear(); 
       pozycja_markera=1;
       licznik=1;
       ping();
       time1=millis();
       menu_opcje();
 }
   if(glowny.available()){
  lcd.clear(); 
  glowny.restart();
  alarm_on=false;
   menu_1=PIEC;
   }
break;
case PIEC:
   piec();
   if(digitalRead(PinP)==LOW){
     delay(30);
       lcd.clear(); 
       pozycja_markera=1;
       licznik=1;
       ping();
       time1=millis();
       menu_opcje();
 }
   if(glowny.available()){
  lcd.clear(); 
  glowny.restart();
   menu_1=SZESC;
   }
break;
case SZESC:
   szesc();
   if(digitalRead(PinP)==LOW){
     delay(30);
       lcd.clear(); 
       pozycja_markera=1;
       licznik=1;
       ping();
       time1=millis();
       menu_opcje();
 }
   if(glowny.available()){
  lcd.clear(); 
  glowny.restart();
   menu_1=SIEDEM;
   }
break;
case SIEDEM:
   siedem();
  if(alarm_on==false){
    alarm();
    alarm_on=true;
   }
   if(digitalRead(PinP)==LOW){
     delay(30);
       lcd.clear(); 
       pozycja_markera=1;
       licznik=1;
       ping();
       time1=millis();
       menu_opcje();
 }
   if(glowny.available()){
  lcd.clear(); 
  glowny.restart();
   alarm_on=false;
   menu_1=OSIEM;
   }
break;
case OSIEM:
   osiem();
   if(digitalRead(PinP)==LOW){
     delay(30);
       lcd.clear(); 
       pozycja_markera=1;
       licznik=1;
       ping();
       time1=millis();
       menu_opcje();
 }
   if(glowny.available()){
  lcd.clear(); 
  glowny.restart();
   menu_1=DZIEWIEC;
   }
break;
case DZIEWIEC:
   dziewiec();
   if(digitalRead(PinP)==LOW){
     delay(30);
       lcd.clear(); 
       pozycja_markera=1;
       licznik=1;
       ping();
       time1=millis();;
       menu_opcje();
 }
   if(glowny.available()){
  lcd.clear(); 
  glowny.restart();
   menu_1=JEDEN;
   }
break;
}
}
void led_alarm(){
int i = 0;
 uint32_t kolor = 0;
 for (i = 0; i < 8; i++) {
   if (i < 4) {
     LED.setPixelColor(i, LED.Color(125, 0, 0)); //Dioda nr i świeci na wybrany kolor
   } else {
     LED.setPixelColor(i, LED.Color(0, 0, 125)); //Dioda nr i świeci na wybrany kolor     
   }

   LED.show(); 
   delay(100);
 }
 LED.clear();
 //krotki_ping();
}

małe delay których można się pozbyć za pomocą timerów lub...?

Link do komentarza
Share on other sites

Gość es2
RTOS... co znaczy system wielozadaniowy na mikro kontrolery? Np. na arduino?

Jak napiszesz program

while( 1 )
{
 LedToggle(1); // zmiana stanu led 1
 Delay(5000)
}

To dioda będzie zmieniać stan co 5 sekund, a co gdybyś chciał w tym samym czasie badać stan wejścia i terować inną diodą? Jak zrobisz tak

while( 1 )
{
 LedToggle(1; // zmiana stanu led 1
 Delay(5000)
if( klawisz ) LedToggle(2; // zmiana stanu led 2
}

To zależnie od szczęścia lub jego braku trzeba trzymać przycisk nawet 5 sekund aby zmienił sie stan led 2.

W wielozadaniowym systemie zrobisz tak:

void task1()
{
while( 1 )
{
 LedToggle(1; // zmiana stanu led 1
 Delay(5000)
}
}

void task2()
{
while( 1 )
{
if( klawisz ) LedToggle(2; // zmiana stanu led 2
}
}

Oba programy będa wykonywały się równocześnie, dokładniej co np 10ms będzie wykonywany task1 naprzemiennie z taskiem 2. Pominąłem tu powołanie taksków które trzeba wcześniej zrobić. Niestety RTOS maja ograniczona liczbę tasków, z tego co pamiętam, dla AVR jest to 10 czy 16 tasków.

Link do komentarza
Share on other sites

Gość es2

Krótki kod bierzemy na początek

void led_alarm(){
int i = 0;
 uint32_t kolor = 0;
 for (i = 0; i < 8; i++) {
   if (i < 4) {
     LED.setPixelColor(i, LED.Color(125, 0, 0)); //Dioda nr i świeci na wybrany kolor
   } else {
     LED.setPixelColor(i, LED.Color(0, 0, 125)); //Dioda nr i świeci na wybrany kolor     
   }

   LED.show(); 
   delay(100);
 }
 LED.clear();
 //krotki_ping();
}

małe delay których można się pozbyć za pomocą timerów lub...?

Z użyciem millis zrobiłbym tak:

void led_alarm(){
//int i = 0; // Liczysz do 8 a używasz int???
uint8_t i static=0;
uint32_t static czas=0;
 uint32_t kolor = 0;

 if( !alarm ) return;   // Jeśli nie ma alarmu wyjdź
 if( czas > millis() ) return; // Jeśli nie minął czas wyjdź
 czas = millis()+100; // czas opóźnienia 100ms

   if (i < 4) {
     LED.setPixelColor(i, LED.Color(125, 0, 0)); //Dioda nr i świeci na wybrany kolor
   } else {
     LED.setPixelColor(i, LED.Color(0, 0, 125)); //Dioda nr i świeci na wybrany kolor     
   }    
   LED.show(); 
//    delay(100);

 if( ++i==8 ){ // Zwiększenie licznika i porównanie czy == 8
  LED.clear();
  alarm=false; // Wyłączenie alarmu
  i=0; // wyzerowanie licznika
  } 

}

led_alarm(); wywołujesz w pętli głównej, jak chcesz zamigać ledami to ustawiasz zmienną alarm na true.

Pisałem "z palca" więc mogły wkraść się błędy.

Z timerami jest podobnie, jak chcesz mogę pokazać kod ale musisz zorganizować sobie przerwanie 1ms. Wiesz jak to zrobic?

[ Dodano: 16-04-2018, 17:03 ]

czy też nie chodzi Ci o millis tylko inny sposób...?

Spójrz na kody w moim poprzednim poście... co z nimi zrobić?

W kodzie masz czasochłonną, blokującą LED.show (czasochłonność zależy od liczby led). Gdyby nie to można by całe miganie zrobić w przerwaniu od timera. LED.show mogłoby być nieblokujące, gdyby używało SPI czy USART to transmisji do led. Jeśli jednak jest jak jest to pozostaje millis lub wirtualny timer.

W pierwszym kodzie łatwo pozbyć się delay(30). Użyłeś ich do eliminacji drżenia styków. Wystarczy zamiast digitalRead(PinP) użyc funkcji, która drżenie styków wyeliminuje.

Co chwila edytujesz post (dodając np kod) a ja w tym czasie daję odpowiedź i robi sie bałagan.

[ Dodano: 16-04-2018, 17:13 ]

Używając wirtualnego timera:

void led_alarm(){
uint8_t i static=0;
uint32_t static czas=0;
 uint32_t kolor = 0;

 if( !alarm ) return;   // Jeśli nie ma alarmu wyjdź
 if( timled ) return; // Jeśli nie minął czas wyjdź
 timled =100; // czas opóźnienia 100ms

   if (i < 4) {
     LED.setPixelColor(i, LED.Color(125, 0, 0)); //Dioda nr i świeci na wybrany kolor
   } else {
     LED.setPixelColor(i, LED.Color(0, 0, 125)); //Dioda nr i świeci na wybrany kolor     
   }   
   LED.show();


 if( ++i==8 ){ // Zwiększenie licznika i porównanie czy == 8
  LED.clear();
  alarm=false; // Wyłączenie alarmu
  i=0; // wyzerowanie licznika
  }

deklaracja timera:

uint8_t timled volatile; // czasy do 255ms więc wystarczy bajt

W przerwaniu 1ms:

if( timled ) timled--;

O zaletach metody z wirtualnym timerem już pisałem. Przerwanie nie musi być co 1ms, może byc np 10. Wtedy czasy będa 10 razy dłuższe.

Link do komentarza
Share on other sites

1. czy !alarm to to samo co alarm==false?

2.if( czas > millis() ) return; // Jeśli nie? minął czas wyjdź

3.Wiem co to przerwania, były w kursie forbota, ale nie wiem jak i po co ich używać "jako timerów", czemu 1ms? o co biega?

4.wiem że ta LED.show jest czasochłonna bo trochę mi blokuje przesyłanie danych z aplikacji, kiedy jest włączony alarm...

5."Co chwila edytujesz post (dodając np kod) a ja w tym czasie daję odpowiedź i robi sie bałagan." Bom nie przyzwycajony że kotoś tak szybko odpowiada 😉

Link do komentarza
Share on other sites

Gość es2
1. czy !alarm to to samo co alarm==false?

2.if( czas > millis() ) return; // Jeśli nie? minął czas wyjdź

3.Wiem co to przerwania, były w kursie forbota, ale nie wiem jak i po co ich używać "jako timerów", czemu 1ms? o co biega?

4.wiem że ta LED.show jest czasochłonna bo trochę mi blokuje przesyłanie danych z aplikacji, kiedy jest włączony alarm...

5."Co chwila edytujesz post (dodając np kod) a ja w tym czasie daję odpowiedź i robi sie bałagan." Bom nie przyzwycajony że kotoś tak szybko odpowiada 😉

1. tak

2. nie za bardzo wiem o co pytasz

3. używam 1ms, czas może być inny. 1ms to trochę za dużo na AVR (zależy co sie w tym przerwaniu robi, przy WS2812 wywołuję przerwania co 3,75us obciążenie uC jest wtedy duże), powinno byc 4..5, można dać 10ms. Trzeba tylko pamiętać, że czasy wpisywane do wirtualnego timera nie będą w ms a np dziesiątkach ms.

4. w przypadku AVR jedyna metoda użyć SPI lub usart

5. zależy co robię, czasem odpowiem szybko, czasem za dwa dni

Link do komentarza
Share on other sites

ok, pierwsza rzecz(wybacz moją zieloność), co w ogóle robi ta linijka:

if( czas > millis() ) return; 

i jakim cudem może czas być kiedyś większy od millis skoro od razu po wejściu do procedury ustawiamy

 uint32_t static czas=0; 

, to jak dwie linijki niżej może być czas większy od millis?

Czego nie rozumiem?

druga rzecz, nie wiem co to wirtualne timery..., czym się różnią od "normalnych"? o co chodzi z tym przerwaniem co 1ms(lub inna wartość)? Co robimy co 1ms? Co to za zmienna używna w przerwaniach(volatile) timled?

Co robi ta linijka:

if( timled ) timled--; 
Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • 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.