Skocz do zawartości

Przeszukaj forum

Pokazywanie wyników dla tagów 'ArduinoUNO'.

  • Szukaj wg tagów

    Wpisz tagi, oddzielając przecinkami.
  • Szukaj wg autora

Typ zawartości


Kategorie forum

  • Elektronika i programowanie
    • Elektronika
    • Arduino i ESP
    • Mikrokontrolery
    • Raspberry Pi
    • Inne komputery jednopłytkowe
    • Układy programowalne
    • Programowanie
    • Zasilanie
  • Artykuły, projekty, DIY
    • Artykuły redakcji (blog)
    • Artykuły użytkowników
    • Projekty - DIY
    • Projekty - DIY roboty
    • Projekty - DIY (mini)
    • Projekty - DIY (początkujący)
    • Projekty - DIY w budowie (worklogi)
    • Wiadomości
  • Pozostałe
    • Oprogramowanie CAD
    • Druk 3D
    • Napędy
    • Mechanika
    • Wydarzenia
    • Sprzedam/Kupię/Zamienię/Praca
    • Inne
  • Ogólne
    • Ogłoszenia organizacyjne
    • Dyskusje o FORBOT.pl
    • Na luzie

Kategorie

  • Quizy o elektronice
  • Quizy do kursu elektroniki I
  • Quizy do kursu elektroniki II
  • Quizy do kursów Arduino
  • Quizy do kursu STM32L4
  • Quizy do pozostałych kursów

Szukaj wyników w...

Znajdź wyniki, które zawierają...


Data utworzenia

  • Rozpocznij

    Koniec


Ostatnia aktualizacja

  • Rozpocznij

    Koniec


Filtruj po ilości...

Data dołączenia

  • Rozpocznij

    Koniec


Grupa


Imię


Strona


TempX

Znaleziono 2 wyniki

  1. Napisałem prosty program, którego zadaniem jest wyświetlaniu na ośmioelementowej listwie LED dowolnego wzoru i jego przesuwanie. //Dołączenie biblioteki obsługującej linijkę led #include <Adafruit_NeoPixel.h> //dedklaracja pinów i stałych const int ledPin = A0; const int ledCount = 8; //ilość LED w linijce const int patCount = 3; //ilość elementów wzoru do wyświetlania //deklaracja tablicy wyświetlanego wzoru unsigned long pattern[patCount]; bool start = true; //flaga używana w instrukcji if , start = true dla początkowego wzoru, start = false dla kolejnych wzorów //Konfiguracja linijki Adafruit_NeoPixel linijka = Adafruit_NeoPixel(ledCount, ledPin, NEO_GRB + NEO_KHZ800); void setup() { //Inicjalizacja linijki linijka.begin(); linijka.show(); } void loop() { //definiowanie wyświetlanego wzoru unsigned long red = linijka.Color(30, 0, 0); unsigned long blue = linijka.Color(0, 0, 30); unsigned long green = linijka.Color(0, 30, 0); unsigned long magenta = linijka.Color(30, 0, 30); unsigned long pattern[patCount]; // ponowna deklaracja, bez której program nie działa if (start) { //wypełnienie linijki kolejnymi elementami wzoru unsigned long pattern[] = {blue, blue, red}; for (int id = 0; id < ledCount; id=id+patCount) { for (int m = 0; m < patCount; m++) { linijka.setPixelColor(m+id, pattern[m]); } } //wyświetlenie linijki linijka.show(); delay(150); start = false; } else { //zmiana wzoru - przesunięcie o jeden element w górę, element ostatni staje się pierwszym unsigned long tempVal = pattern[patCount-1]; for (int i=patCount-1; i>0; i--) { pattern[i] = pattern[i-1]; } pattern[0]=tempVal; //wypełnienie linijki kolejnymi elementami wzoru for (int id = 0; id < ledCount; id=id+patCount) { for (int m = 0; m < patCount; m++) { linijka.setPixelColor(m+id, pattern[m]); } } //wyświetlenie linijki linijka.show(); delay(150); } } Program nie jest skomplikowany, wymaga zdefiniowania kolorów: //definiowanie wyświetlanego wzoru unsigned long red = linijka.Color(30, 0, 0); unsigned long blue = linijka.Color(0, 0, 30); unsigned long green = linijka.Color(0, 30, 0); unsigned long magenta = linijka.Color(30, 0, 30); zadeklarowania w tablicy pattern: unsigned long pattern[] = {blue, blue, red}; przypisania kolejnym LED elementów wzoru: for (int id = 0; id < ledCount; id=id+patCount) { for (int m = 0; m < patCount; m++) { linijka.setPixelColor(m+id, pattern[m]); } } wyświetlenia: linijka.show(); delay(150); Funkcję ruchu uzyskałem dzięki zmianie wzoru - przesuwając elementy o jeden tzn.: pierwszy staje się drugim, drugi - trzecim, a ostatni - pierwszym: unsigned long tempVal = pattern[patCount-1]; for (int i=patCount-1; i>0; i--) { pattern[i] = pattern[i-1]; } pattern[0]=tempVal; oraz ponownemu przypisaniu elementom LED kolejnych elementów nowego wzoru i wyświetleniu: //wypełnienie linijki kolejnymi elementami wzoru for (int id = 0; id < ledCount; id=id+patCount) { for (int m = 0; m < patCount; m++) { linijka.setPixelColor(m+id, pattern[m]); } } //wyświetlenie linijki linijka.show(); delay(150); Nic nadzwyczajnego, ale uruchamiając program napotkałem kilka istotnych problemów. Najważniejszy, to deklaracja zmiennych i ich zasięg. Aż się prosi by fragment przypisywania elementom LED elementów wzoru i wyświetlenie wstawić do odrębnej funkcji: //wypełnienie linijki kolejnymi elementami wzoru unsigned long pattern[] = {blue, blue, red}; for (int id = 0; id < ledCount; id=id+patCount) { for (int m = 0; m < patCount; m++) { linijka.setPixelColor(m+id, pattern[m]); } } //wyświetlenie linijki linijka.show(); delay(150); Jednak gdy to zrobiłem, okazało się, że kompilator nie zgłaszał błędu, ale zapisany wzór nie był wyświetlany. Podobnie prosi się, by fragment funkcji void loop(): //definiowanie wyświetlanego wzoru unsigned long red = linijka.Color(30, 0, 0); unsigned long blue = linijka.Color(0, 0, 30); unsigned long green = linijka.Color(0, 30, 0); unsigned long magenta = linijka.Color(30, 0, 30); unsigned long pattern[patCount]; // ponowna deklaracja, bez której program nie działa który właściwie mógłby być wykonywany tylko raz, umieścić w void setup(). Próba umieszczenia tego fragmentu do setup także kończyła się błędami kompilacji. Czy mógłby ktoś bardziej biegły w programowaniu powiedzieć, co jest nie tak i skąd błędy w kompilacji i sygnalizowanie błędów zasięgu zmiennych? Co trzeba zrobić by powtarzające się fragmenty zapisać w funkcji?
  2. Cześć, zapewne wielu z was miało problem z obsługą równolegle w czasie kiklu zadań pisząc program dla Arduino. Często mamy zadania typu zbieranie danych z czujników, wyświetlanie ich na wyświetlaczu LCD, sterowania serwo-mechanizmami itp. Jak było to wyjaśnione w drugiej części kursu Arduino można taką pseudo-równoległą obsługę kilku zadań oprogramować za pomocą funkcji millis() - nie jest to niestety prawdziwa wielozadaniowość. Dla trochę mocniejszych MCU (ESP32 i STM32xx) możemy użyć prawdziwego RTOS'a do obsługi wielozadaniowośći. Dla przykładu w obsłudze "Board" dla ESP32 w ArduinoIDE jest osadzony "Free RTOS". Jednakże dla np. płytki "Arduino UNO R3" "Free RTOS" zajmuje za dużo zasobów, aby można go użyć. Jaki więc jest rozwiązanie dla płytek z małymi MCU AVR (np. Atmega328 lub Atmega 324)? Ostatnio natrafiłem na bardzo fajny projekt o nazwie RIOS - jest to scheduler tasków napisany w języku C i zajmujący tak mało zasobów, że może być używany na małych MCU AVR (np. na płytce Arduino UNO). Tutaj linki do strony domowej projektu i portu RIOS dla AVR: https://www.cs.ucr.edu/~vahid/rios/ https://www.cs.ucr.edu/~vahid/rios/rios_avr.htm A tutaj link do filmu o RIOS na Youtube: Postanowiłem wypróbować jak będzie działał RIOS na płytce Arduino UNO R3. Wypróbowałem kod z drugiego podanego linku (wersja schedulera preemptive). Kod został zmodyfikowany tak aby każdy z trzech użytych tasków migał z osobna diodą LED (zielona LED - okres 0.4s, czerwona 1s, żółta 2 s). Tutaj kod zmodyfikowanego kodu dla Arduino UNO (sketch dla Arduino IDE): #include <avr/io.h> #include <avr/interrupt.h> #include <math.h> #define F_CPU 8000000UL #include <util/delay.h> typedef struct task { unsigned char running; // 1 indicates task is running int state; // Current state of state machine unsigned long period; // Rate at which the task should tick unsigned long elapsedTime; // Time since task's previous tick int (*TickFct)(int); // Function to call for task's tick } task; task tasks[3]; const unsigned char tasksNum = 3; const unsigned long tasksPeriodGCD = 25; const unsigned long period1 = 400; //okres 0.4s const unsigned long period2 = 1000;//okres 1s const unsigned long period3 = 3000;//okres 3s int TickFct_1(int state); int TickFct_2(int state); int TickFct_3(int state); unsigned char runningTasks[4] = {255}; // Track running tasks, [0] always idleTask const unsigned long idleTask = 255; // 0 highest priority, 255 lowest unsigned char currentTask = 0; // Index of highest priority task in runningTasks unsigned schedule_time = 0; ISR(TIMER1_COMPA_vect) { unsigned char i; for (i=0; i < tasksNum; ++i) { // Heart of scheduler code if ( (tasks[i].elapsedTime >= tasks[i].period) // Task ready && (runningTasks[currentTask] > i) // Task priority > current task priority && (!tasks[i].running) // Task not already running (no self-preemption) ) { SREG &= 0x7F; tasks[i].elapsedTime = 0; // Reset time since last tick tasks[i].running = 1; // Mark as running currentTask += 1; runningTasks[currentTask] = i; // Add to runningTasks SREG |= 0x80; tasks[i].state = tasks[i].TickFct(tasks[i].state); // Execute tick SREG &= 0x7F; tasks[i].running = 0; // Mark as not running runningTasks[currentTask] = idleTask; // Remove from runningTasks currentTask -= 1; SREG |= 0x80; } tasks[i].elapsedTime += tasksPeriodGCD; } } void init_processor() { /*Set up SPI*/ PORTB = 0xff; /*Set up timer*/ TCCR1B = (1<<WGM12)|(1<<CS11); // CTC mode (clear timer on compare). Prescaler=8 // AVR output compare register OCR0. OCR1A = 25000; // AVR timer interrupt mask register TIMSK1 = (1<<OCIE1A); //enables compare match interrupt TCNT1 = 0; /* Init GPIO pins PB0, PB1, Pb2 */ DDRB |= _BV(DDB0); //Pin 8 DDRB |= _BV(DDB1); //Pin 9 DDRB |= _BV(DDB2); //Pin 10 /*Enable global interrupts*/ SREG |= 0x80; } int main(void) { init_processor(); // Priority assigned to lower position tasks in array unsigned char i = 0; tasks[i].state = -1; tasks[i].period = period1; tasks[i].elapsedTime = tasks[i].period; tasks[i].running = 0; tasks[i].TickFct = &TickFct_1; ++i; tasks[i].state = -1; tasks[i].period = period2; tasks[i].elapsedTime = tasks[i].period; tasks[i].running = 0; tasks[i].TickFct = &TickFct_2; ++i; tasks[i].state = -1; tasks[i].period = period3; tasks[i].elapsedTime = tasks[i].period; tasks[i].running = 0; tasks[i].TickFct = &TickFct_3; while(1) { } } int TickFct_1(int state) { //_delay_us(1000); PORTB ^= _BV(PB0); return 0; } int TickFct_2(int state) { //_delay_us(5000); PORTB ^= _BV(PB1); return 0; } int TickFct_3(int state) { //_delay_us(25000); PORTB ^= _BV(PB2); return 0; } A tutaj zrzut ekranu z komlipacji w Arduino IDE 2.3.2 Jak widać program binarny po kompilacji zajmuje zaledwie 730 bajtów i 44 bajty RAM (2%) co pozostawia prawie całą pamięć dla obsługi naszej aplikacji. Do Arduino UNO do pinów 8, 9, 10 (PB0, PB1, PB2) zostały podłączone trzy diody LED przez rezystory 240 Ohm. Poniżej krótki film wiedo z działania powyższego programu. Niestety filmu nie zamieszczę bo format mp4 nie jest obsługiwany dla forum. Ja zamierzam w programach dla Arduino UNO R3 używać RIOS 😀 Pozdrawiam BTW: jak zapewne wielu z was zauważy tak prosty RTOS (sam scheduler tasków) nie zawiera implementacji wielu ważnych mechanizmów jak mutexy, semafory i kolejki. Można je spróbować zaimplementować samemu lecz nie zawsze jerst to trywialne ponieważ niektóre operacje muszą być atomowe.
×
×
  • 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.