Sterownik do rotora 360 stopni - Sławek19761976 - 01-01-2017
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.
[attachment=264]
RE: Sterownik do rotora 360 stopni - SQ4KDG - 02-01-2017
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
RE: Sterownik do rotora 360 stopni - SQ4KDG - 02-01-2017
Nie chciałbym kraść wątku, ale dostałem kilka pytań na priv, więc napiszę trochę o mojej "wizji" rotora
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
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.
RE: Sterownik do rotora 360 stopni - Sławek19761976 - 03-01-2017
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 .
RE: Sterownik do rotora 360 stopni - Sławek19761976 - 03-01-2017
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 .
RE: Sterownik do rotora 360 stopni - JasQ - 04-01-2017
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 .
RE: Sterownik do rotora 360 stopni - SQ4KDG - 04-01-2017
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
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
RE: Sterownik do rotora 360 stopni - JasQ - 04-01-2017
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 .
RE: Sterownik do rotora 360 stopni - SQ4KDG - 04-01-2017
(04-01-2017, 10:37)JasQ napisał(a): ...Ostatecznie można zrobić kalibrację startową z kompasu...
Przekonałeś mnie
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
RE: Sterownik do rotora 360 stopni - Sławek19761976 - 04-01-2017
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 !!
|