• Witaj na Forum Arduino Polska! Zapraszamy do rejestracji!
  • Znajdziesz tutaj wiele informacji na temat hardware / software.
Witaj! Logowanie Rejestracja


Ocena wątku:
  • 0 głosów - średnia: 0
  • 1
  • 2
  • 3
  • 4
  • 5
Sterownik do rotora 360 stopni
#1
Witam koledzy , potrzebuję pomocy : posiadam napisany program Arduino uno r3 . Jest w nim zastosowany hallotron do zliczania impulsów , którego to chcę zastąpić kontaktronem . Potrzebuję by kontaktron przy załączeniu i rozłączeniu dawał 1 stopień . Czyli jeden magnes dawał 2 stopnie . Mam przekładnie 1;60 i 3 magnesy na silniku co w sumie dawało by 360 stopni. W tym programie jest jeszcze dużo fajnych funkcji które działają , jednak z braku wiedzy nie wiem jak w nim to powyższe  zmienić . Proszę o pomoc najlepiej poprawę całego programu.


.txt   program arduino.txt (Rozmiar: 8.24 KB / Pobrań: 13)
 
Odpowiedź
#2
Też robię rotor antenowy, ale bez sugerowania się rozwiązaniami z sieci, więc rozwiązania jakie zastosowałem są kompletnie inne.
To co mi się rzuciło w oczy to "EEPROM.write" w każdej pętli. Zastąp to chociaż "EEPROM.update" bo bardzo szybko wykończysz pamięć.

kolejna sprawa to :
eAz = EEPROM.read(0);
AZin = 255 * eAz;
przeliczanie azymutu (0-360) na (0-255) i odwrotnie wiąże się z zaokrąglaniem wyników do pełnych stopni co możne wprowadzać błędy 1 stopnia przy każdej zmianie pozycji rotora. Po kilkuset zmianach pozycja faktyczna będzie zupełnie inna niż wyświetlana (i kabelek możne ukręcić).
Do zapamiętywania pozycji wykorzystuj 2 komórki pamięci.
fragment mojego kodu:
pozAkt = pozDocel = (EEPROM.read (0) * 255 + EEPROM.read (1)); //odczyt
EEPROM.update (0, pozAkt / 255); EEPROM.update (1, pozAkt % 255); //zapis

Pozdrawiam
 
Odpowiedź
#3
Nie chciałbym kraść wątku, ale dostałem kilka pytań na priv, więc napiszę trochę o mojej "wizji" rotora Wink

Założenia:
zielony - zrealizowano
niebieski - w trakcie realizacji
czerwony - czeka na realizację

kolorowy wyświetlacz
obsługa dotyku
możliwość zmiany parametrów przy pomocy pokrętła (enkoder obrotu)
wykorzystanie silnika krokowego z przekładnią (dzięki temu wystarczy mi 1 impuls kontaktronu/halotronu np na północy do kalibracji kroków silnika i kierunku co jakiś czas).
pamiętanie (po resecie) i możliwość zmiany nastaw:
- azymutu anteny
- azymutu operatora (jak siądę twarzą na południe to chcę mieć południe u góry ekranu)
- prędkości rotora 
- przełożenia rotora
- pozycji geograficznej operatora (mnie)
- ulubionych azymutów wraz z nazwami
czytanie z pliku CSV pozycji geograficznej przemienników, porządkowanie ich według odległości od pozycji operatora, obliczanie azymutów i wyświetlanie jako pól wyboru wg. odległości.

W przyszłości zaimplementowanie któregoś z protokołów obsługiwanych przez Ham Radio Deluxe ( ale na razie nie mam takiej potrzeby)


Potrzebowałem do tego obsługi wyświetlacza z dotykiem, czytnika kart SD, enkodera obrotu, sterownika silnika krokowego.
Arduino Mega nie miałem a wyświetlacz miałem tylko w postaci shielda do uno (zajmował mi prawie wszystkie wyjścia), za to miałem oprócz UNO również NANO.
Połączyłem to do kupy transmisją szeregową.

Kody są w trakcie ciągłego przerabiania, więc mogą być trochę nieczytelne Wink

część fizyczna - arduino nano, enkoder obrotu, sterownik silnika krokowego:

Kod:
/*
 -komunikaty wysyłane po Serial.print:
 - 1 [x] - pozycja enkodera [1/-1]
 - 2 [xxx] - aktualna pozycja rotora [0-360]

*/
#include <EEPROM.h>
#include <Stepper.h>
int    pozDocel = 0, //DOCELOWA POZYCJA ROTORA (w stopniach)
      pozAkt = 0, // AKTUALNA POZYCJA ROTORA (w stopniach)
      pozDKr,    //DOCELOWA POZYCJA ROTORA (w krokach)
      pozAKr,    // AKTUALNA POZYCJA ROTORA (w krokach)
      pozAktOld = 0, // POPRZEDNIA POZYCJA ROTORA
      nr,      // numer zmiennej (transmisja szeregowa)
      w,      // wartosc zmiennej (transmisja szeregowa)
      a,
      pozN;
//int pozDocelOld = 0,  //        -/-

/*encoder*/
// piny enkodera
const int pinA = 12;
const int pinB = 11;
int rotSpeed;
//
int reading = 0;
int lowest = -11112;
int highest = 11112;
int changeamnt = 1;
int przelicznik = 2160; //dla małego=2160
// typ danych enkodera
boolean encA;
boolean encB;
boolean lastA = false;
unsigned long currentTime;
unsigned long lastTime;
/*stepper*/
const int stepsPerRevolution = 360;
// ustawienia pinow silnika:
Stepper myStepper(stepsPerRevolution, 2, 4, 3, 5);
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void setup() {
 rotSpeed = (EEPROM.read (2) * 255 + EEPROM.read (3));
 myStepper.setSpeed (rotSpeed);
 //
 Serial.begin(9600);
 Serial.setTimeout (20);
 //
 pinMode(pinA, INPUT_PULLUP);
 pinMode(pinB, INPUT_PULLUP);
 // ustawienia czasu i przerwan
 currentTime = millis();
 lastTime = currentTime;
 attachInterrupt(0, updateEncoder, CHANGE);
 attachInterrupt(1, updateEncoder, CHANGE);
 //odczytanie i zmapowanie aktualnej pozycji rotora po restarcie
 pozAkt = pozDocel = (EEPROM.read (0) * 255 + EEPROM.read (1));
 pozAKr = map (pozAkt, 0, 360, 0, przelicznik);
 Serial.print(2); Serial.print(' '); Serial.println(pozAkt);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void loop() {
 {
   serialek();
 }
 {
   updateEncoder();
 }
 //  {
 //    serialEvent();
 //  }
 pozDKr = map (pozDocel, 0, 360, 0, przelicznik);
 if (pozAKr != pozDKr) {
   if (pozAKr < pozDKr) {
     myStepper.step(1);
     pozAKr++;
     pozAkt = map (pozAKr, 0, przelicznik, 0, 360);
   }
   if (pozAKr > pozDKr) {
     myStepper.step(-1);
     pozAKr--;
     pozAkt = map (pozAKr, 0, przelicznik, 0, 360);
   }
   if (pozAktOld != pozAkt) {
     pozAktOld = pozAkt;
     if (pozAkt % 4 == 0) {
       Serial.print(2); Serial.print(' '); Serial.println(pozAkt);
     }
   }
   a = 0;
 }
 if (a == 0 && pozAKr == pozDKr) {
   Serial.print(2); Serial.print(' '); Serial.println(pozDocel);
   pozAkt = pozDocel;
   EEPROM.update (0, pozAkt / 255);    EEPROM.update (1, pozAkt % 255);
   a = 1;
 }
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void updateEncoder() {
 currentTime = millis();
 // Check if it's time to read
 if (currentTime >= (lastTime + 5))
 {
   // read the two pins
   encA = digitalRead(pinA);
   encB = digitalRead(pinB);
   // check if A has gone from high to low
   if ((!encA) && (lastA))
   {
     // check if B is high
     if (encB)
     {
       // clockwise
       if (reading - changeamnt <= highest)
       {
         reading = reading - changeamnt;
       }
     }
     else
     {
       // anti-clockwise
       if (reading + changeamnt >= lowest)
       {
         reading = reading + changeamnt;
       }
     }
     // Output reading for debugging

     Serial.print(1); Serial.print('a'); Serial.println(reading);
     reading = 0;
   }   // zerowanie A i czasu
   lastA = encA;
   lastTime = currentTime;
 }
}

/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void serialek() {
 while (Serial.available()) {
   nr = Serial.parseInt();
   w = Serial.parseInt();
   switch (nr) {
     case 1: {
         pozDocel = w;
       } break;
     case 2: {
         rotSpeed = w;
         EEPROM.update (2, w / 255); EEPROM.update (3, w % 255);
         myStepper.setSpeed(w);
         Serial.print(3); Serial.print('s'); Serial.println(rotSpeed);
       } break;
     case 3: {
         switch (w) {
           case 3: {
               Serial.print(3); Serial.print('s'); Serial.println(rotSpeed);
             } break;
           case 5: {
               Serial.print(2); Serial.print('a'); Serial.println(pozAkt);
             } break;
         }
       }
   }
 }
}

część graficzno/dotykowa i karta SD (UNO):


Kod:
/*
 -komunikaty wysyłane po Serial.print:
 - 1 [xxx] - pozycja docelowa [0-360]
 - 2 [xx] - prędkość obrotu rotora
 - 3 [x] - Żądanie zwrotu ....
   - 3 3  - ...prędkości opbrotu rotora
   - 3 5  - ...aktualnej pozycji rotora

*/
#include <Adafruit_GFX.h>    // biblioteka graficzna
#include <Adafruit_TFTLCD.h> // biblioteka wyswietlacza
#include <TouchScreen.h>  // biblioteka panelu dotykowego
#include <EEPROM.h>
#define LCD_CS A3 // Chip Select goes to Analog 3
#define LCD_CD A2 // Command/Data goes to Analog 2
#define LCD_WR A1 // LCD Write goes to Analog 1
#define LCD_RD A0 // LCD Read goes to Analog 0

#define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin
#define  BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
/*piny i ustawienia dotyku*/
#define YP A3  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 9   // can be a digital pin
#define XP 8   // can be a digital pin
#define TS_MINX 207
#define TS_MINY 180 //200
#define TS_MAXX 893
#define TS_MAXY 951
#define MINPRESSURE 20
#define MAXPRESSURE 1000
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
// Assign human-readable names to some common 16-bit color values:
/*zmienne*/

int pozDocel = 0;     //cocelowa pozycja rotora
int pozDocelOld = 0,  //        -/-
   pozAkt = 0,       //aktualna pozycja rotora
   pozAktOld = 0,    //        -/-

   /*
     menuX=0 - menu1 dolne
     menuX=1 - busola
     menuX=2 - menu pozycji rotora (domyślne)
     menuX=3 - WEJŚCIE DO OPCJI
     menuX=31 - menu aZymutu operatora
     menuX=32 - menu wyboru przemiennika
   */
   /*ADRESY EEPROM:
       [0-1] - przechowywanie początkowej komurki adresowania EEPROM (eeMem)
       [eeMem]+[0-1] - azymut operatora (mAz)

   */
   eeMem = 2,       // początkowa komurka EEPROM
   menuX = 1,
   oldmenuX = 0,
   x1,
   px,              // przeliczona pozycja x dotyku
   py,              // przeliczona pozycja y dotyku
   x, y,           // dane do obliczeń azymutu
   pres,           // informacja dla "void'ów" że ekran został naciśnięty
   kompas,
   gamma,
   nr, w,           // numer zmiennej i jej wartość w komunikacji szeregowej
   enc,             // odczyt danych z enkodera
   rotSpeed,
   pd = 0;           // strefa dotyku ekranu
int mAz = 0,         // moj azymut (przekręca busolę względem góry ekranu)
   n_mAz;           // moj Nowy azymut (wykorzystany w menu 31)
int a, b = 1;
Adafruit_TFTLCD tft(LCD_CS, LCD_CD, LCD_WR, LCD_RD, LCD_RESET);
unsigned long currentTime;
unsigned long lastTime;
// If using the shield, all control and data lines are fixed, and
// a simpler declaration can optionally be used:
// Adafruit_TFTLCD tft;
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void setup(void) {
 Serial.begin(9600);
 Serial.setTimeout (20);
 tft.begin(0x9341);
 Serial.println ("3 3");
 Serial.println ("3 5");
 mAz = (EEPROM.read (eeMem) * 255 + EEPROM.read (eeMem + 1)); // odczytanie azymutu operatora po restarcie
 delay (300);
 while (Serial.available()) {
   serialDane();
 }
 /*========================================
   tft.drawRoundRect (1, 1, 238, 35, 5, GREEN);
   tft.setTextSize(3);
   tft.setCursor(5, 5);
   tft.setTextColor(GREEN); tft.println("ROTOR "); tft.setTextColor(RED); tft.print("by SQ4KDG");
   delay (2000);
   ===============*/
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void loop() {
 //  {
 //    serialek();
 //  }
 {
   dotyk();
 }
 {
   menu();
 }
 switch (menuX) {
   case 1: {
       busola();
     } break;
   case 2: {
       rotor();
     } break;
   case 3: {
       opcje();
     } break;
   case 31: {
       azymutOp();
     } break;
 }
 //Serial.print("x:");  Serial.print(px); Serial.print("  y:");  Serial.print(py); Serial.print("menu");  Serial.println(menuX);
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void serialEvent() {
 if (Serial.available()) {
   serialDane();
 }
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void serialDane() {
 nr = Serial.parseInt();
 w = Serial.parseInt();
 switch (nr) {
   case 1: {
       enc = w;
     } break;
   case 2: {
       pozAkt = w;
     } break;
   case 3: {
       rotSpeed = w;
     } break;
 }
}

void dotyk() {
 digitalWrite(13, HIGH);
 TSPoint p = ts.getPoint();
 digitalWrite(13, LOW);
 // if sharing pins, you'll need to fix the directions of the touchscreen pins
 pinMode(XP, OUTPUT);
 pinMode(XM, OUTPUT);
 pinMode(YP, OUTPUT);
 // skalowanie dotyku na TFT

 if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
   px = map(p.x, TS_MINX, TS_MAXX, tft.width(), 0) ;
   px = constrain (px, 0, tft.width() ) ;
   py = map(p.y, TS_MINY, TS_MAXY, tft.height(), 0);
   py = constrain (py, 0, tft.height()) ;
   pres = 1;
   //  Serial.println ("dotyk");
 }
 if (pres) {
   if (menuX == 2 || menuX == 31) {
     if (py > 45 && py < 280) {
       x = -py + 150;
       y = px - 120;
       gamma = (atan2 (y, x) * 180 / PI);
       kompas = 1;
       pres = 0;
     }
   }
   else if (menuX == 3)  {
     if (py < 40) {
       pd = 31;
     }
   }
   if (py >= 282) {
     if (px > 180) {
       pd = 3;
     }
     else if (px > 80) {
       pd = 2;
     }
     else {
       pd = 1;
     }
   }
   //  Serial.println ("press");
 }
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void menu() {       //(menuX=0)
 if (oldmenuX != menuX) {
   tft.fillRect (0, 280, 240, 60, BLACK);
   /*rysowanie PRZYCISKU ENTER=================================*/
   tft.drawRoundRect (170, 280, 67, 35, 5, GREEN);
   tft.setTextColor(GREEN);
   tft.setTextSize(2);
   tft.setCursor(174, 290);
   tft.println("ENTER");
   /*rysowanie PRZYCISKU MENU=================================*/
   tft.drawRoundRect (80, 280, 80, 35, 5, YELLOW);
   tft.setTextColor(YELLOW);
   tft.setTextSize(2);
   tft.setCursor(95, 290);
   tft.println("MENU");
   /*rysowanie PRZYCISKU MENU=================================*/
   tft.drawRoundRect (1, 280, 67, 35, 5, RED);
   tft.setTextColor(RED);
   tft.setTextSize(2);
   tft.setCursor(5, 290);
   tft.println(" <-- ");
   //Serial.print (kompas); Serial.print ("  menu  "); Serial.println (gamma + mAz);
   //  Serial.println ("menu");
 }
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void busola() {     /*rysowanie busoli*/ // (menuX=1)
 tft.fillScreen(BLACK);

 tft.fillRoundRect (1, 245, 80, 30, 5, WHITE); tft.fillRoundRect (160, 245, 80, 30, 5, WHITE);
 tft.setTextColor(BLACK);
 tft.setTextSize(2);
 tft.setCursor(3, 247);
 tft.println(rotSpeed); tft.setTextSize(1); tft.println(" Rotor Speed");
 tft.fillCircle(120, 150, 121, BLACK);
 tft.drawCircle(120, 150, 110, YELLOW);
 tft.drawCircle(120, 150, 119, WHITE);

 for (uint8_t i = 0; i < 24; i++) {
   tft.drawLine(120 + ( sin ((i * 15 - mAz)* PI / 180 ) * 105), 150 - ( cos ((i * 15 - mAz)  * PI / 180 ) * 105),
                120 + ( sin ((i * 15 - mAz) * PI / 180 ) * 119), 150 - ( cos ((i * 15 - mAz)  * PI / 180 ) * 119), WHITE);
 }
 char kierunki[8][3] = {"N", "NE", "E", "SE", "S", "SW", "W", "NW"};
 uint16_t color[] = {BLUE, 0xC618, YELLOW, 0xC618, RED, 0xC618, YELLOW, 0xC618};
 int siz[] = {2, 1, 2, 1, 2, 1, 2, 1};
 for (uint8_t i = 0; i < 8; i++) {
   tft.setTextColor(color[i]);
   tft.setTextSize(siz[i]);
   tft.setCursor(120 + ( sin ((i * 45 - mAz) * PI / 180 ) * 95) - 5,
                 150 - ( cos ((i * 45 - mAz)  * PI / 180 ) * 95) - 5);
   tft.print(kierunki[i]);
 }
 // Serial.println ("busola");
 menuX = 2;
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void rotor() {        //(menuX=2)
 /*przyjmij koordynaty z dotyku*/
 if (kompas) {
   pozDocel = gamma + mAz;   // przeliczenie ze wspolzednych prostokatnych na biegunowe https://pl.wikipedia.org/wiki/Uk%C5%82ad_wsp%C3%B3%C5%82rz%C4%99dnych_biegunowych
   kompas = 0;
   //   Serial.println ("rotor-kompas");
 }
 else if (enc) {
   pozDocel = pozDocel + enc;
   enc = 0;
   //   Serial.println ("rotor-enc");
 }
 //  else {
 //    pozDocel = pozDocelOld;
 //  }
 /*zamknij pozycję docelową rotora w 360 stopniach*/
 if (pozDocel < 0) {
   pozDocel = 360 + pozDocel;
 }
 if (pozDocel > 359) {
   pozDocel = pozDocel % 360;
 }
 if (oldmenuX != menuX) { // rysowanie 1 raz aktualnych pozycji przy starcie programu lub powrocie z menu
   if (pozAkt != pozDocel) {
     tft.drawLine(120, 150, 120 + ( sin ((pozDocel - mAz) * PI / 180 ) * 80), 150 - ( cos ((pozDocel - mAz) * PI  / 180 ) * 80), YELLOW);
     tft.drawLine(120, 150,  120 + ( sin ((pozAkt - mAz) * PI / 180 ) * 80), 150 - ( cos ((pozAkt - mAz) * PI / 180 ) * 80), RED);
     tft.fillRoundRect (0, 0, 170, 28, 5, YELLOW);
     tft.setTextColor(BLACK);
     tft.setTextSize(3);
     tft.setCursor(5, 5);
     tft.print("Cel: "); tft.println(pozDocel);
     tft.fillRoundRect  (175, 0, 64, 35, 5, YELLOW);
     tft.setTextColor(BLACK);
     tft.setTextSize(2); tft.setCursor(180, 5); tft.println(pozAkt);
     tft.setTextSize(1);  tft.setCursor(180, 25); tft.println("ANTENA");
   }
   if (pozAkt == pozDocel) {
     tft.drawLine(120, 150,  120 + ( sin ((pozAkt - mAz) * PI / 180 ) * 80), 150 - ( cos ((pozAkt - mAz) * PI / 180 ) * 80), GREEN);
     tft.fillRoundRect (0, 0, 170, 28, 5, GREEN);
     tft.setTextColor(BLACK);
     tft.setTextSize(3);
     tft.setCursor(5, 5);
     tft.print("Cel: "); tft.println(pozDocel);
     tft.fillRoundRect  (175, 0, 64, 35, 5, GREEN);
     tft.setTextColor(BLACK);
     tft.setTextSize(2); tft.setCursor(180, 5); tft.println(pozAkt);
     tft.setTextSize(1);  tft.setCursor(180, 25); tft.println("ANTENA");
   }
   //  b = 0;
   oldmenuX = menuX;
   //   Serial.println ("rotor-a");
 }
 else {        //jeżeli nastąpiła zmiana pozycji docelowej

   if (pozDocelOld != pozDocel ) {  //rysowanie nowej DOCELOWEJ pozycji rotora
     tft.drawLine(120, 150, 120 + ( sin ((pozDocelOld - mAz) * PI / 180 ) * 80), 150 - ( cos ((pozDocelOld - mAz)*PI / 180 ) * 80), BLACK);
     tft.drawLine(120, 150, 120 + ( sin ((pozDocel - mAz) * PI / 180 ) * 80), 150 - ( cos ((pozDocel - mAz) * PI  / 180 ) * 80), YELLOW);
     tft.drawLine(120, 150,  120 + ( sin ((pozAkt - mAz) * PI / 180 ) * 80), 150 - ( cos ((pozAkt - mAz) * PI / 180 ) * 80), RED);
     pozDocelOld = pozDocel;
     tft.fillRoundRect (0, 0, 170, 28, 5, YELLOW);
     tft.setTextColor(BLACK);
     tft.setTextSize(3);
     tft.setCursor(3, 3);
     tft.print("Cel: "); tft.println(pozDocel);
     //Serial.print(4); Serial.print(' '); Serial.println(pozDocel);
     a = 1;
     //     Serial.println ("rotor-b");
   }

   if (pozAktOld != pozAkt ) {     //jeżeli nastąpiła zmiana pozycji aktualnej
     //rysowanie nowej AKTUALNEJ pozycji rotora
     tft.drawLine(120, 150, 120 + ( sin ((pozAktOld - mAz) * PI / 180 ) * 80), 150 - ( cos ((pozAktOld - mAz) * PI / 180 ) * 80), BLACK);
     tft.drawLine(120, 150,  120 + ( sin ((pozAkt - mAz) * PI / 180 ) * 80), 150 - ( cos ((pozAkt - mAz) * PI / 180 ) * 80), RED);
     pozAktOld = pozAkt;
     tft.fillRoundRect  (175, 0, 64, 35, 5, YELLOW);
     tft.setTextColor(BLACK);
     tft.setTextSize(2); tft.setCursor(180, 5); tft.println(pozAkt);
     tft.setTextSize(1);  tft.setCursor(180, 25); tft.println("ANTENA");
     a = 0;

     //    Serial.println ("rotor-c");
   }
   if (pozAktOld == pozAkt && pozAkt != pozDocel && a) {
     tft.fillRoundRect  (175, 0, 64, 35, 5, RED);
     tft.setTextColor(BLACK);
     tft.setTextSize(2); tft.setCursor(180, 5); tft.println(pozAkt);
     tft.setTextSize(1);  tft.setCursor(180, 25); tft.println("ANTENA");
     tft.drawLine(120, 150,  120 + ( sin ((pozAkt - mAz) * PI / 180 ) * 80), 150 - ( cos ((pozAkt - mAz) * PI / 180 ) * 80), RED);
     a = 0;
     //     Serial.println ("rotor-d");
   }
   if (pozAkt == pozDocel && !a) {      //jeżeli pozycja aktualna osiągnęła pozycję docelową
     //rysowanie nowej AKTUALNEJ pozycji rotora
     tft.drawLine(120, 150, 120 + ( sin ((pozAktOld - mAz) * PI / 180 ) * 80), 150 - ( cos ((pozAktOld - mAz) * PI / 180 ) * 80), BLACK);
     tft.drawLine(120, 150,  120 + ( sin ((pozAkt - mAz) * PI / 180 ) * 80), 150 - ( cos ((pozAkt - mAz) * PI / 180 ) * 80), GREEN);
     tft.fillRoundRect (0, 0, 170, 28, 5, GREEN);
     tft.setTextColor(BLACK);
     tft.setTextSize(3);
     tft.setCursor(5, 5);
     tft.print("Cel: "); tft.println(pozDocel);
     tft.fillRoundRect  (175, 0, 64, 35, 5, GREEN);
     tft.setTextColor(BLACK);
     tft.setTextSize(2); tft.setCursor(180, 5); tft.println(pozAkt);
     tft.setTextSize(1);  tft.setCursor(180, 25); tft.println("ANTENA");
     a = 1;
     //    Serial.println ("rotor-e");
   }
 }
 if (pres) {
   if (pd == 3) { //wysłanie nowej pozycji do rotora (nakazanie obrotu)
     Serial.print (1); Serial.print (" "); Serial.println (pozDocel);
     pd = 0;
     delay (400);
   }
   if (pd == 2) { // przejście do opcji
     menuX = 3;
     pd = 0;
   }
   pres = 0;
   //   Serial.println ("rotor-pres");
 }
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void opcje() {      //(menuX=3)
 if (oldmenuX != menuX) {
   pd = 0;
   tft.fillRect (0, 0, 240, 279, BLACK);
   tft.setTextSize(2);
   int space = 6,
       wys = 40;
   char* label[] = {"AZYMUT Operatora", "POZYCJA Operatora", "PRZEMIENNIKI", "ULUBIONE", "DODAJ do ulubionych", "SERWIS"};
   uint16_t color[] = {YELLOW, 0xC618, 0xC618, 0xC618, 0xC618, RED};
   for (uint8_t i = 0; i < 6; i++) {
     tft.drawRoundRect (1, (wys + space)*i, 238, wys, 12, color[i]);
     tft.setTextColor(color[i]);
     tft.setCursor(8, (wys + space)*i + 12);
     tft.print(label[i]);
   }
   oldmenuX = menuX;
 }
 if (pres == 1) {
   if (pd == 1) {
     b = 1;
     menuX = 1;
     pres = 0;
     Serial.println ("3 3");
   }
   if (pd == 31) {
     b = 1;
     menuX = 31;
   }
   // Serial.print (pres); Serial.print (" "); Serial.println (pd);
   pres = 0;
 }
}
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
void azymutOp() { // (menuX=31) - menu aZymutu operatora
 if (oldmenuX != menuX) {
   tft.fillRect (0, 0, 240, 279, BLACK);
   n_mAz = mAz;
   pd = 0;
   for (uint8_t i = 0; i < 24; i++) {
     tft.drawLine(120 + ( sin (i * 15 * PI / 180 ) * 107), 150 - ( cos (i * 15  * PI / 180 ) * 107),
                  120 + ( sin (i * 15 * PI / 180 ) * 119), 150 - ( cos (i * 15  * PI / 180 ) * 119), WHITE);
   }
   tft.drawCircle(120, 150, 110, YELLOW);
   tft.drawCircle(120, 150, 119, WHITE);
   char kierunki[8][6] = {"0", "315", "270", "225", "180", "135", "90", "45"};
   uint16_t color[] = {GREEN, BLUE, YELLOW, BLUE, RED, BLUE, YELLOW, BLUE};
   int siz[] = {2, 1, 1, 1, 1, 1, 1, 1};
   for (uint8_t i = 0; i < 8; i++) {
     tft.setTextColor(color[i]);
     tft.setTextSize(siz[i]);
     tft.setCursor(120 + ( sin ((i * 45 ) * PI / 180 ) * 95) - 5,
                   150 - ( cos ((i * 45 )  * PI / 180 ) * 95) - 5);
     tft.print(kierunki[i]);
   }
   b = 0;
   oldmenuX = menuX;
 }
 int old_n_mAz = n_mAz;
 if (kompas == 1) {
   n_mAz = 360 - gamma;
   b = 0;
   kompas = 0;
 }

 if (enc != 0) {
   n_mAz = n_mAz - enc;
   enc = 0;
   b = 0;
 }
 if (n_mAz < 0) {
   n_mAz = 360 + n_mAz;
 }
 if (n_mAz > 359) {
   n_mAz = n_mAz % 360;
 }
 if (oldmenuX != menuX) {
   n_mAz = mAz;
 }
 if (b == 0) {
   tft.drawLine(120, 150, 120 + ( sin (-old_n_mAz * PI / 180 ) * 80), 150 - ( cos (-old_n_mAz * PI  / 180 ) * 80), BLACK);
   tft.drawLine(120, 150, 120,  80, GREEN);
   tft.drawLine(120, 150, 120 + ( sin (-n_mAz * PI / 180 ) * 80), 150 - ( cos (-n_mAz * PI  / 180 ) * 80), BLUE);
   tft.fillRoundRect (0, 0, 239, 28, 5, WHITE);
   tft.setTextColor(BLACK);
   tft.setTextSize(3);
   tft.setCursor(3, 3);
   tft.print("Azymut: "); tft.println(n_mAz);
   b = 1;
 }
 if (pres == 1) {
   if (pd == 1) {
     menuX = 1;
     pd = 0;
   }
   if (pd == 2) { // przejście do opcji
     menuX = 3;
     pd = 0;
   }
   if (pd == 3) {
     mAz = n_mAz;
     EEPROM.update (eeMem, mAz / 255);    EEPROM.update (eeMem + 1, mAz % 255);
     menuX = 1;
     pd = 0;
   }
   pres = 0;
 }
}

Na filmie używam do testów standartowego silniczka krokowego, ale na dużych silnikach i sterowniku L298 też działa.


Przepraszam za złą jakość kręcone i przesyłane na gorąco.
 
Odpowiedź
#4
Cześć , bardzo dziękuję za wskazówki . Co prawda dla mnie to nadal za skomplikowane ale coś popróbuję . Mam jeszcze wskazówki od tego kolegi ( wykonawcę tego programu ) jak podłączyć kontaktron do tej wersji programowej . Na razie brak czasu ale może tym tygodniu . Podziwiam kolegi projekt super , moja zabawa to na razie tyle : https://www.youtube.com/watch?v=LK-hwzW0Rzg&t=44s https://www.youtube.com/watch?v=J5Z_BpdvsUM Do tego rotora chcę sterownik by był kompatybilny z HRD ROTOR. Wszystko działa tylko te impulsy .
 
Odpowiedź
#5
Mam na zbyciu ARDUINO Mega 2560 . Jeśli by ktoś z kolegów poprawił ten program i po sprawdzeniu by to działało to z miłą chęcią oddam .
 
Odpowiedź
#6
Podpowiem tylko panowie bo mam na co dzień do czynienia z trackerem antenowym , magiczne hasło brzmi kompas , 1 sztuka dla anteny 2 dla operatora i macie o 90% problemów z pisaniem kodu pozycjonowania mniej , ponieważ nic nie musicie obliczać . Antena zawsze się ustawi tam gdzie ma zadane .
Ważne aby robić co się lubi albo lubić co się robi .
Arduino UNO, TINY, PRO MINI
Pomoc nagradzamy punktami reputacji Wink
 
Odpowiedź
#7
Pytanko :
Czy "magiczne hasło kompas" nie zacznie mi szaleć w silnym polu elektromagnetycznym podczas nadawania z dużą mocą ?
Wolał bym się nie zdziwić gdy przy każdym nadawaniu zacznę przy okazji obracać antenę w losowym kierunku Wink

Jeżeli testowałeś to przy antenach nadawczych i działało, to sprawa faktycznie warta przemyślenia.
(Przy łączności z wykorzystaniem odbicia od ruchomych obiektów np. księżyca, może być konieczność zmiany nastaw również podczas nadawania)

Pozdrawiam
 
Odpowiedź
#8
Zapewne będziesz do tego stosował anteny silnie kierunkowe , musiałbyś porobić pomiary . Niestety jestem tylko modelarzem i z odległości 2-3 m 7W nie robiło na kompasie większego wrażenia ( antena dipol w nadajniku RC ) ale obiecać nie mogę . Ostatecznie można zrobić kalibrację startową z kompasu a resztę z enkodera i odpadło by ustawianie początkowe jak i zwiększyła by się precyzja ustawienia . Nie wiem czy jest to sprzęt przenośny czy stacjonarny na wysokim maszcie czy kawałku rurki na kominie .
Ważne aby robić co się lubi albo lubić co się robi .
Arduino UNO, TINY, PRO MINI
Pomoc nagradzamy punktami reputacji Wink
 
Odpowiedź
#9
(04-01-2017, 10:37)JasQ napisał(a): ...Ostatecznie można zrobić kalibrację startową z kompasu...

Przekonałeś mnie Smile
Sprzęt stacjonarno-wyprawowy około 50W UHF/VHF (ale w przyszłości będę chciał z tego zestawu sterować anteną HF 500+ W i tu może już być problem z czujnikiem).
W każdym razie zamawiam i dopinam kompas, na razie jako "obwód zapasowy / kalibracyjny".

Pozdrawiam
 
Odpowiedź
#10
Wszystko OK tylko mam już zrobione 2 rotory dokładnie te z filmiku . Musiałbym poprzerabiać , jednak dziś użyłem małego schemaciku jak podłączyć kontaktron od właśnie tego kolegi który napisał program . Po testach ma to jakiś sens , muszę jeszcze dorobić zasilanie na 24V do rotora i będę testował . Magiczne AZYM=AZin/15.555; zastąpiłem AZYM=AZin/2; ze względu że impuls jest naliczany przy narastaniu i opadaniu . Jednak jeszcze nie jestem pewien tej 2 po testach opowiem . Do masy z wyjścia na impulsy 10-100uF dalej wyjścia dławik 10k zanim 1k do zasilania 5V , a zatym wszystkim kontaktron i masa . Licznik stoi i faktycznie po zwarciu i rozwarci zaczyna liczyć . Robię rotor koledze taki sam więc przetestuję na nim ( może jakiś filmik nagram) . Tylko ten czas i brak jego !!
 
Odpowiedź
  


Skocz do:


Przeglądający: 1 gości