Arduino Polska Forum

Pełna wersja: Arduino i LCD Nokia 5110
Aktualnie przeglądasz uproszczoną wersję forum. Kliknij tutaj, by zobaczyć wersję z pełnym formatowaniem.
Stron: 1 2 3
Panowie .. i Panie (kto wie),
Zbudowałem obrotowy stół sterowany Arduino z programowaniem ustawien i menu wyświetlanym na takim własnie LCD.
Wszystko fajnie ale dodałem opcję centrowania czyli załączam program który kręci stolikiem kilka obrotów w celu prawidłowego ustawienia przedmiotu możliwie jak najbardziej w centrum no i dla "bajeru" chciałem dodać na ekranie podczas wykonywania tego procesu albo coś w rodzaju "radaru" czyli kółeczko z biegającą kreską albo częściowo zaczernione kółeczko. I tu pojawił się problem, o ile narysować samo kółeczko nie ma problemu to już animowanie ... trochę gorzej.

Macie jakiś pomysł jak to zrobić ?
Skopałem Googla ale nie trafiłem na nic co mogło by pomóc ...

I jeszcze dodatkowe pytanie za 100 punktów, podczas gdy uruchamia się kolejna linia programu wykonująca obroty stolika oczywiście ruch na ekranie zamiera, czy jest jakaś możliwość w Arduino, żeby wykonywać w tym samym czasie dwa zadania czyli animacja swoje i silnik swoje ?
Czy w przypadku Arduino jest to niemożliwe ?
Podaj kod.
Hej,
Oto kod (proszę się nie nabijać, dopiero zaczynam) Tongue
Trochę zagmatwany ...
Kod:
#include <SPI.h>
#include <Adafruit_GFX.h>
#include <Adafruit_PCD8544.h>
#include <Stepper.h>
#define STEPS_PER_MOTOR_REVOLUTION 600  
#define STEPS_PER_OUTPUT_REVOLUTION 7000

boolean backlight = false;
int contrast=1;
int frame = 1;
int frames = 12;
int menuitem = 1;
int page = 1;
Stepper small_stepper(STEPS_PER_MOTOR_REVOLUTION, 8, 10, 9, 11);
int  Steps2Take;
const byte logo[] PROGMEM = {84,48,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011100,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111110,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01100011,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01100011,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B01100011,B00000000,B00000000,B00000000,B00000000,
B00000011,B11111000,B00000011,B11111100,B00000011,B11111100,B01110111,B00000000,B00000000,B00000000,B00000000,
B00001111,B11111110,B00000111,B11111110,B00000111,B11111110,B00111110,B00000000,B00000000,B00000000,B00000000,
B00001111,B11111111,B00001111,B11111111,B00001111,B11111111,B00001000,B00000000,B00000000,B00000000,B00000000,
B00011111,B00011111,B00001111,B00001111,B00001111,B10011111,B00000000,B00000000,B00000000,B00000000,B00000000,
B00011110,B00011111,B00011111,B00001111,B10011111,B00001111,B10000000,B00000000,B00000000,B00000000,B00000000,
B10000000,B00011111,B00011111,B00000000,B00011111,B00001111,B10011100,B00000000,B00000000,B00000000,B00000011,
B10000000,B00011110,B00011110,B01111000,B00011111,B00001111,B10011111,B00000000,B00000000,B00000000,B00011111,
B10000000,B11111100,B00011111,B11111110,B00011111,B00001111,B10011111,B11100000,B00000000,B00000000,B01111111,
B10000000,B11111110,B00011111,B11111111,B00011111,B00001111,B10011111,B11111000,B00000000,B00000001,B11111111,
B10000000,B01111111,B00011111,B00001111,B10011111,B00001111,B10011111,B11111100,B00000000,B00000111,B11111111,
B00000000,B00001111,B00011111,B00001111,B10011111,B00001111,B10011111,B11111111,B00000000,B00001111,B11111111,
B00000000,B00001111,B10011110,B00001111,B10011111,B00001111,B10000111,B11111111,B10000000,B00011111,B11111110,
B00011110,B00001111,B10011111,B00001111,B10011111,B00001111,B10000111,B11111111,B10000000,B00111111,B11111100,
B00011111,B00111111,B00001111,B10011111,B00001111,B10011111,B00000011,B11111111,B11000000,B01111111,B11111000,
B00011111,B11111111,B00001111,B11111111,B00001111,B11111111,B00000011,B11111111,B11000000,B01111111,B11111000,
B00001111,B11111110,B00000111,B11111110,B00000111,B11111110,B00000011,B11111111,B11100000,B01111111,B11111000,
B00000011,B11111000,B00000001,B11111000,B00000001,B11111000,B00000011,B11111111,B11100000,B01111111,B11111000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000011,B11111111,B11000000,B01111111,B11111100,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000111,B11111111,B11000000,B01111111,B11111110,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00011111,B11111111,B10000000,B00111111,B11111111,
B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00111111,B11111111,B10000000,B00011111,B11111111,
B11110000,B00000000,B00000000,B00000000,B00000000,B00000000,B11111111,B11111111,B00000000,B00001111,B11111111,
B11111100,B00000000,B11000000,B00000000,B00000000,B00000111,B11111111,B11111110,B00000000,B00000111,B11111111,
B11111111,B11000000,B11111000,B00000000,B00000000,B01111111,B11111111,B11111000,B00000000,B00000011,B11111111,
B11111111,B11111110,B11111111,B10000000,B00011111,B11111111,B11111111,B11100000,B00000000,B00000000,B11111111,
B11111111,B11111111,B11111111,B11110000,B00111111,B11111111,B11111111,B10000000,B00000000,B00000000,B00111111,
B11111111,B11111111,B11111111,B11111111,B00000000,B11111111,B11111110,B00000000,B00000000,B00000000,B00000111,
B11111111,B11111111,B11111111,B11111111,B11100000,B11111111,B11110000,B00000000,B00000000,B00000000,B00000000,
B00001111,B11111111,B11111111,B11111111,B11000011,B11111111,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B01111111,B11111111,B11111100,B00011111,B11100000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B11111111,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B11111100,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B11000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00111100,B00111000,B01111100,B01111100,B00111000,B01111000,B00000000,B00000000,B00000000,B00000000,B00000000,
B01000000,B01000100,B01000000,B00010000,B01000100,B01000100,B00000000,B00000000,B00000000,B00000000,B00000000,
B00111000,B01000100,B01110000,B00010000,B01000100,B01000100,B00000000,B00000000,B00000000,B00000000,B00000000,
B00000100,B01000100,B01000000,B00010000,B01111100,B01111000,B00000000,B00000000,B00000000,B00000000,B00000000,
B01000100,B01000100,B01000000,B00010000,B01000100,B01010000,B00000000,B00000000,B00000000,B00000000,B00000000,
B00111000,B00111000,B01000000,B00010000,B01000100,B01001100,B00000000,B00000000,B00000000,B00000000,B00000000,
};
volatile boolean up = false;
volatile boolean down = false;
volatile boolean middle = false;
volatile boolean run = false;

int speakerPin = A0;
int length = 50; // the number of notes
char notes[] = "cccde e defg ccc ggg eee ccc g fe dc "; // a space represents a rest
int beats[] = { 2,2,2,1,2,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1 };
int tempo = 100;  

int downButtonState = 0;
int upButtonState = 0;  
int selectButtonState = 0;          
int runButtonState = 0;

int lastDownButtonState = 0;
int lastSelectButtonState = 0;
int lastUpButtonState = 0;
int lastRunButtonState = 0;

Adafruit_PCD8544 display = Adafruit_PCD8544( 6, 5, 4);
//////////// VOID SETUP ////////////
void setup() {
 pinMode(speakerPin, OUTPUT);
 pinMode(3, INPUT_PULLUP);
 pinMode(2, INPUT_PULLUP);
 pinMode(1, INPUT_PULLUP);
 pinMode(0, INPUT_PULLUP);
 pinMode(7,OUTPUT);
 digitalWrite(7,HIGH); //Turn Backlight ON
 Serial.begin(9600);
 display.begin();      
 display.setContrast(contrast); //Set contrast to 1
 display.clearDisplay();
 display.drawBitmap(0, -1,  logo, 84, 48, 1);
 display.display();
 music();
 delay(1000);
}
//////////// MAIN LOOP ////////////
void loop() {
 
 drawMenu();
 runButtonState = digitalRead(3);  
 downButtonState = digitalRead(2);
 selectButtonState = digitalRead(1);
 upButtonState =   digitalRead(0);

 checkIfRunButtonIsPressed();
 checkIfDownButtonIsPressed();
 checkIfUpButtonIsPressed();
 checkIfSelectButtonIsPressed();

 if (up && page == 1 ) {
   up = false;
   menuitem--;
   if (menuitem==0)
   {
     menuitem=4;
   }      
 }
 else if (up && page == 2 ) {
   up = false;
   if(contrast <=1){
     contrast = 1;
   }else{
   contrast--;
   setContrast();      
   }
 }

 if (down && page == 1) {
   down = false;
   menuitem++;
   if (menuitem==5)
   {
     menuitem=1;
   }      
 }else if (down && page == 2 ) {
   down = false;
   contrast++;
   setContrast();
 }

 if (middle) {
   middle = false;
   if (page == 1 && menuitem==2)
   {
     if (backlight)
     {
       backlight = false;
       turnBacklightOff();
       }
     else
     {
       backlight = true;
       turnBacklightOn();
      }
   }

   if(page == 1 && menuitem ==3)
   {
     resetDefaults();
   }

else if (page == 1 && menuitem==1) {
     page=2;
    }
else if (page == 2) {
     page=1;
    }
     if(page == 1 && menuitem ==4)
   {
     display.clearDisplay();
     display.setTextColor(BLACK, WHITE);
       display.setTextSize(1);
       display.setCursor(0, 4);
       display.print("Centering");
       display.setTextSize(3);
       display.setCursor(4, 15);
       display.print("Wait");
       
       display.drawCircle(display.width()/2, display.height()/2, 8, BLACK);
       delay(300);display.display();
       display.drawCircle(display.width()/2, display.height()/2, 12, BLACK);
       delay(300);display.display();
       display.drawCircle(display.width()/2, display.height()/2, 16, BLACK);
       delay(300);display.display();
       display.drawCircle(display.width()/2, display.height()/2, 20, BLACK);
       delay(300);display.display();
       display.drawCircle(display.width()/2, display.height()/2, 24, BLACK);
       delay(300);display.display();
       Steps2Take  =  STEPS_PER_OUTPUT_REVOLUTION;          
       small_stepper.setSpeed(37);  
       small_stepper.step(Steps2Take);
       display.drawCircle(display.width()/2, display.height()/2, 8, WHITE);
       delay(300);display.display();
       display.drawCircle(display.width()/2, display.height()/2, 12, WHITE);
       delay(300);display.display();
       display.drawCircle(display.width()/2, display.height()/2, 16, WHITE);
       delay(300);display.display();
       display.drawCircle(display.width()/2, display.height()/2, 20, WHITE);
       delay(300);display.display();
       display.drawCircle(display.width()/2, display.height()/2, 24, WHITE);
       delay(300);display.display();
       music();
       delay(1000);
   }
   
  }
}
 
//////////// FUNCTIONS ////////////
void runProgram(int prog = contrast)
 {
   frames = prog * 12;
   display.setTextSize(1);
   display.clearDisplay();
   display.setTextColor(BLACK, WHITE);
   display.setCursor(0, 0);
   display.print("Program: ");
   display.print(prog);
   display.drawFastHLine(0,8,83,BLACK);
   display.setCursor(0, 12);
   display.print("frame");
   display.setTextColor(BLACK, WHITE);
   display.setTextSize(1);
   display.setCursor(35, 40);
   display.print(" RUNNING ");
   for(int i=1; i <= frames; i++){
     display.setTextSize(3);
     display.setCursor(0, 22);
     display.print(i);
     display.setTextSize(1);
     display.print("/");
     display.print(frames);
     display.display();
     Steps2Take  =  STEPS_PER_OUTPUT_REVOLUTION / frames;          
     small_stepper.setSpeed(75);  
     small_stepper.step(Steps2Take);
     delay(1000);
     if(i>=frames){
       display.clearDisplay();
       display.setTextSize(1);
       display.setCursor(0, 4);
       display.print("WELL");
       display.setTextSize(3);
       display.setCursor(4, 15);
       display.print("DONE");
       display.display();
       music();
       delay(1000);
     }
   }
   delay(2000);
 }  
 
 void checkIfRunButtonIsPressed()
 {
   if (runButtonState != lastRunButtonState)
 {
   if (runButtonState == 0)
   {
     run=true;
     runProgram(contrast);
   }
   delay(50);
 }
  lastRunButtonState = runButtonState;
 }

 void checkIfDownButtonIsPressed()
 {
   if (downButtonState != lastDownButtonState)
 {
   if (downButtonState == 0)
   {
     down=true;
   }
   delay(50);
 }
  lastDownButtonState = downButtonState;
 }

void checkIfUpButtonIsPressed()
{
 if (upButtonState != lastUpButtonState)
 {
   if (upButtonState == 0) {
     up=true;
   }
   delay(50);
 }
  lastUpButtonState = upButtonState;
}

void checkIfSelectButtonIsPressed()
{
  if (selectButtonState != lastSelectButtonState)
 {
   if (selectButtonState == 0) {
     middle=true;
   }
   delay(50);
 }
  lastSelectButtonState = selectButtonState;
}

 void drawMenu()
 {
   
 if (page==1)
 {    
   display.setTextSize(1);
   display.clearDisplay();
   display.setTextColor(BLACK, WHITE);
   display.setCursor(15, 0);
   display.print("MAIN MENU");
   display.drawFastHLine(0,8,83,BLACK);
   display.setCursor(0, 10);
 
   if (menuitem==1)
   {
     display.setTextColor(WHITE, BLACK);
   }
   else
   {
     display.setTextColor(BLACK, WHITE);
   }
   display.print(">Program");
   display.setCursor(0, 20);
 
   if (menuitem==2)
   {
     display.setTextColor(WHITE, BLACK);
   }
   else
   {
     display.setTextColor(BLACK, WHITE);
   }    
   display.print(">Backlight: ");
   
   if (backlight)
   {
     display.print("ON");
   }
   else
   {
     display.print("OFF");
   }
   display.display();
   
   if (menuitem==3)
   {
     display.setTextColor(WHITE, BLACK);
   }
   else
   {
     display.setTextColor(BLACK, WHITE);
   }  
   display.setCursor(0, 30);
   display.print(">Reset");
   display.display();
   
   if (menuitem==4)
   {
     display.setTextColor(WHITE, BLACK);
   }
   else
   {
     display.setTextColor(BLACK, WHITE);
   }  
   display.setCursor(0, 40);
   display.print(">Centering");
   display.display();    
 }

 else if (page==2)
 {
   
   display.setTextSize(1);
   display.clearDisplay();
   display.setTextColor(BLACK, WHITE);
   display.setCursor(0, 0);
   display.print("SELECT program");
   display.drawFastHLine(0,10,83,BLACK);
   display.setCursor(5, 15);
   display.print("program");
   display.setTextSize(3);
   display.setCursor(5, 25);
   display.print(contrast);
   display.setTextColor(WHITE, BLACK);
   display.setTextSize(1);
   display.setCursor(54, 40);
   display.print(" RUN ");
   display.display();
 }
 
}

 void resetDefaults()
 {
   contrast = 1;
   setContrast();
   backlight = true;
   turnBacklightOn();
 }

 void setContrast()
 {
   display.setContrast(contrast);
   display.display();
 }

 void turnBacklightOn()
 {
   digitalWrite(7,HIGH);
 }

   void turnBacklightOff()
 {
   digitalWrite(7,LOW);
 }
////////////////////////////////////////////////////
void playTone(int tone, int duration)
{  
 for (long i = 0; i < duration * 1000L; i += tone * 2)
 {    
     digitalWrite(speakerPin, HIGH);    
     delayMicroseconds(tone);    
     digitalWrite(speakerPin, LOW);    
     delayMicroseconds(tone);  
 }
}  
////////////////////////////////////////////////////
void playNote(char note, int duration)
{  
 char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };  
 int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };     // play the tone corresponding to the note name  
 for (int i = 0; i < 8; i++)
 {    
   if (names[i] == note)
   {      
       playTone(tones[i], duration);    
   }  
 }
}

void music(){
 for (int i = 0; i < length; i++)
 {    
    if (notes[i] == ' ')
    {      
        delay(beats[i] * tempo); // rest    
    }
    else
    {      
       playNote(notes[i], beats[i] * tempo);    
    }       // pause between notes    
    delay(tempo / 2);    
 }
}
(11-04-2018, 23:40)RobUK napisał(a): [ -> ]czy jest jakaś możliwość w Arduino, żeby wykonywać w tym samym czasie dwa zadania czyli animacja swoje i silnik swoje ?
Czy w przypadku Arduino jest to niemożliwe ?

Naturalnie da się. Są dwie metody:
- maszyna stanów w pętli głównej
- przerwania (tu też realizuje się maszynę stanów).
W przypadku silnika i ekranu, silnik obsłużyłbym na przerwaniach, wyświetlacz w pętli głównej.

Naucz sie nie używać delay.
Dzięki za podpowiedzi, może kiedyś na coś sie przydadzą. Narazie to co kolega napisał jak dla mnie (w tej chwili) to magia o której nie mam pojęcia. Nie żeby pojęcia "przerwania" czy "pętla" nic mi nie mówiły ale w przypadku Arduino i programowania w/w moje pojęcie jest .... stosunkowo małe. Więc może wrzuciłby kolega jakiś przykład albo "link" to może szybciej bym załapał .... chyba za wiele wymagam ... Tongue
w kwestii delay():
jeśli nie delay to jak ?
Jeśli chciałbym aby po wykonaniu jakiegoś polecenia poczekał - w tym przypadku po wykonaniu kroku, kamera musi się na nowo sfokusować, ustawić, przygotować do kolejnej klatki - to jak niby miałbym zmusić program, żeby "poczekał" aż kamera będzie gotowa ?
Nie bardzo rozumiem co kolega chciał przez to powiedzieć. Użyłem delay() w sytuacjach kiedy uważałem to za stosowne i potrzebne. Jeśli mam przez chwilę widzieć np jakiś komunikat na ekranie i po chwili przejść dalej .... no to nie wiem jak można to inaczej zrobić.
Pogadamy za kilka tygodni/miesięcy jak się już trochę wciągnę to będę mądry, narazie jednak pytam
z nadzieją, że ktoś mi podpowie coś sensownego.
Tak czy owak ... dziękuję.
(14-04-2018, 22:41)RobUK napisał(a): [ -> ]w kwestii delay():
jeśli nie delay to jak ?
Jeśli chciałbym aby po wykonaniu jakiegoś polecenia  poczekał - w tym przypadku po wykonaniu kroku, kamera musi się na nowo sfokusować, ustawić, przygotować do kolejnej klatki - to jak niby miałbym zmusić program, żeby "poczekał" aż kamera będzie gotowa ?
Nie bardzo rozumiem co kolega chciał przez to powiedzieć. Użyłem delay() w sytuacjach kiedy uważałem to za stosowne i potrzebne. Jeśli mam przez chwilę widzieć np jakiś komunikat na ekranie i po chwili przejść dalej .... no to nie wiem jak można to inaczej zrobić.
Typowy problem początkującego. Proszę poczytać o millis ii wielozadaniowości na Arduino https://forbot.pl/blog/kurs-arduino-ii-w...is-id18418. Poniżej przykład nieużywania delay, do wyświetlenia kilku napisów na LCD w odstępach 3 sekundowych
Kod:
uint8_t static stan_lcd=0;
uint32_t static czas=0;
if( millis()>czas )
{
czas=millis()+3000;

switch( stan_lcd )
  {
  case 0: print_lcd("Ala ma kota"); break;
  case 1: print_lcd("Kot ma Ale"); break;
  case 2: print_lcd("kolejny napis"); break;
  }
  if( stan_lcd<2 )stan_lcd++;
}

Wiele się słyszy o przepełnieniu licznika millis. Arduino to platforma do zabawy, demonstracji a nie pisania użytecznych programów (brak debugera w zasadzie wyklucza Arduino do poważnych zastosowań).

W swoich programach używam wirtualnych timerów w przerwaniu 1ms liczących do zera, deklaracja zmiennej:
Kod:
uint16_t volatile tim1;


 kod w przerwaniu:
Kod:
if( tim1 ) tim1--;


Kod w pętli głównej:
Kod:
uint8_t static stan_lcd=0;
if( !tim1 )
{
tim1=3000;

switch( stan_lcd )
{
case 0: print_lcd("Ala ma kota"); break;
case 1: print_lcd("Kot ma Ale"); break;
case 2: print_lcd("kolejny napis"); break;
}
if( stan_lcd<2 )stan_lcd++;
}



PS
Pisałem on-line, więc może sa małe błędy ale idea jest widoczna.

PS2
Pewnie padnie pytanie co sie dzieki temu zyskuje?
Jeszcze gwoli ścisłości:
Padło pytanie, jak animować ten "radar", czy kreskę.
Otóż są to zwykłe funkcje trygonometryczne.
Chcemy narysować linię. Znamy jej długość i początek. Jej koniec zależy od kąta jej nachylenia.
I tutaj od razu taka uwaga: chodzi o kąt między linią a pionową osią y, więc jeśli wiemy, że w trójkącie prostokątnym
sinα = y/r, to w naszym przypadku będzie to cosinus kąta między osią y, a linią r.
Czyli:
x = sinα/r
y = cosα/r

[Obrazek: 4L3uyaX.gif]

Dla naszego programu musimy jeszcze przesiąść się ze stopni na radiany,
oraz oczywiście przenieść się z układem współrzędnych gdzieś w głąb ekranu, bo dla x=0 i y=0 będziemy widzieli tylko prawą dolną ćwiartkę radaru.

Kod dla pojedynczej kreski może wyglądać tak: 
Kod:
int kat;
void loop()
{
        int x1=64;//Współrzędne początku linii
        int y1=32;
        int R=15;// Długość linii

        display.drawCircle(64,32,20,WHITE); // a tu mamy takie kółko, tarczę radaru
               
               //************************************************
               //  Policzmy i narysujemy linię czarną
               //  która będzie zamazywać niepotrzebne linie
               //************************************************
        int kat2=kat-1;
                float s2 = (float) (kat2%60)/60*2.0*PI;
        float x2 = x1+(sin(s2)*R);
        float y2 = y1-(cos(s2)*R);
        display.drawLine(x1, y1, x2, y2,BLACK);

               //************************************************
               //  A tutaj kod rysujący linię radaru
               //************************************************
        float s = (float) (kat%60)/60*2.0*PI;
        float x = x1+(sin(s)*R);
        float y = y1-(cos(s)*R);
        display.drawLine(x1, y1, x, y,WHITE);
        display.display();
        kat+=1;    
        
    }

[Obrazek: MvZyM26.gif]

Oczywiście wywołanie tego powinno być na przerwaniach.
Kod umieszczony w innej funkcji.
Te floaty bardzo spowalniają Atmegę.
Modyfikacja tego jest dziecinnie prosta.
Oczywiście można też dopisać kilka linii kodu i mieć to "częściowo zaczernione kółeczko.
 
[Obrazek: wetSnOW.gif]
(15-04-2018, 00:59)Robson Kerman napisał(a): [ -> ]Oczywiście wywołanie tego powinno być na przerwaniach.

Te floaty bardzo spowalniają Atmegę.
Float w przerwaniach na AVR?
AVR to nie ARM z FPU.

Float w przerwaniach może spowodować "zablokowanie" innych przerwań, np od USART i gubienie znaków. AVR nie ma systemu przerwań wielopoziomowych, można się ratować tylko tym, aby przerwaniom, w którym używa sie float ustawić atrybut NO_BLOCK.
- Kolejna sztuczka, po podział operacji z float na kilka części, każdą wykonuje się w kolejnym przerwaniu. Niestety spowoduje to z zmniejszenie częstotliwości odświeżania.
- Najrozsądniejsze byłoby przejście na liczby stałoprzecinkowe. Zmniejszy sie precyzja obliczeń ale wyświetlacz nie ma rozdzielczości 1280x768 tylko 84x84 i mała precyzja nie wpłynie na jakość obrazu a operacje będą wykonywane zdecydowanie szybciej niż zmiennoprzeciskowo.
- Warto też, zmodyfikować
Kod:
display.display();
tak aby używało przerwań. Bez przerwań, to funkcja traci sporo czasu procesora na czekanie, aż kolejny bajt zostanie wysłany. Gdyby, komunikacja ze sterownikiem LCD przebiegała z prędkością 8MHz to używanie przerwań, nie bardzo miałoby sens ale przy1MHz sens jest i to głęboki. Prędkość można spokojnie zmniejszyć 50kb/s. Ekran 84x84 to poniżej 1kb, odświeżanie 20ms zapewni więc 50kb. Niestety, SPI w AVR nie daje takiej możliwości ale USART w trybie SPI już tak.
Jak można się przekonać, czasami, zmniejszenie prędkości transmisji i przerzucenie jej na przerwania, zmniejsza obciążenie mikrokontrolera.
- Nie trzeba wszystkiego liczyć w czasie rzeczywistym. Rozpatrzyłbym też zapamiętanie w flash kilkunastu klatek animacji tego radaru. Wtedy nie trzeba nic liczyć, wskaźnik na kolejną klatkę i wywołać zmodyfikowaną display.display(), która wyświetli obraz z flash a nie ram.

Do bajerów jak animacje na LCD lepiej było wybrać ARM. Nie dlatego, że nie da się tego zrobić na AVR, da, można i na 8051 czy 8080 ale trzeba się napocić, w ARM po prostu pisze sie program i nie przejmuje czy to float czy long a może unsigned char.
Generalnie wyświetlacz graficzny i ArduinoUNO to nie najlepszy pomysł. Mega328 ma bardzo mało ram (2kb). Już przy malutkim LCD jak 84x84 bufor zajmuje blisko połowę pamięci. 128x128 CAŁĄ dostępną pamięć, więc program nie ma szansy działać (gdzie umieścić stos). Mowa o wyświetlaczach monochromatycznych o kolorze nie warto pisać. Na ARM bez problemu zbuforuję wyświetlacz 320x240 16-bit. Ekran zajmuje 159kb ale jak przechowam go w postaci 8-bit to tylko 76,8kB a ARM z 128k ram nie są rzadkością.


PS
Nie wiem czemu, wyciska się Arduinowcom wyświetlacze 320x240 16-bit? Jakie jest odświeżanie? Ile trwa czyszczenie ekranu?
Odczyt obrazków z karty SD :-) Ile to trwa?
Do pobawienia sie ok ale użyteczne urządzenie z ekranem odświeżanym przez sekundę? Kto to kupi?
Dlatego napisałem o konieczności modyfikacji programu ze względu na zmienne float.
Można podzielić liczbę zmiennoprzecinkową na część całkowitą i część ułamkową
int x1=PI;
int x2=(PI-x1)*1000;// do trzech miejsc po przecinku.

(15-04-2018, 10:35)es2 napisał(a): [ -> ]- Nie trzeba wszystkiego liczyć w czasie rzeczywistym. Rozpatrzyłbym też zapamiętanie w flash kilkunastu klatek animacji tego radaru.

Ja tak najczęściej robię. Tworzę tabelę w excelu, obliczam poszczególne wartości i tworzę mapę.
Z merytorycznego punktu widzenia, wyjaśniłem zasadę tworzenia tej mapy, a że jest liczona w czasie rzeczywistym to insza inszość.
(15-04-2018, 13:17)Robson Kerman napisał(a): [ -> ]Z merytorycznego punktu widzenia, wyjaśniłem zasadę tworzenia tej mapy, a że jest liczona w czasie rzeczywistym to insza inszość.

Nawet na ARM tablicuję wyniki, nie liczę "w locie" sinusa w generatorze DDS. Podobnie, jeśli nie muszę, nie używam float lecz liczb stałoprzecinkowych. Najczęściej jednak, można tak robić. A jak ARM za wolny, to RasberyPi, OrangePi, itp. Niby tam też jest ARM, ale wąskim gardłem uC jest szybkość pamięci flash. Przy jej odczycie (zegran cpu > 48MHz) wstawiane sa takty oczekiwania. Można część kodu (np obsługi przerwań) umieścić w ram i tam wykonać (w AVR sie nie da, w 8051 przy pewnej sztuczce tak) ale na to jest rezerwowane np 8kb ram. W Rasbery i podobnych, bootloader z flash, ładuje program karty SD do szybkiej pamięci ram. Tam można juz nieźle szaleć ale to rozwiązanie ma tez pewne wady. Ładowanie systemu trwa ok 30 sekund. Kto by to zamontował w poduszce powietrznej lub ABS? System (w 99% Linux) trzyma łapę na sprzęcie. Nie da sie zamigać diodą zapisując coś pod jakiś tam adres. Trzeba owego Linuxa "ogarnąć" a jest to trudniejsze niż biblioteki Arduino.
Stron: 1 2 3