Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Manufacturing Technology >> Proses manufaktur

Pengontrol Antena Rotator kompatibel dengan perangkat lunak pelacakan

Komponen dan persediaan

Arduino UNO
papan Arduino Uno
× 1
Potensiometer putar (generik)
maks. 1Kohm (500 Ohm bekerja lebih baik)
× 2
Rotary Encoder dengan Tombol Tekan
× 2
Breadboard (generik)
× 1
Modul Relai (Generik)
2 modul x 2 relai NO-Com-NC
× 2
N-Channel MOSFET Daya
modul power mosfet (min 12V/3A)
× 2

Aplikasi dan layanan online

Arduino IDE

Tentang proyek ini

Pembaruan terbaru November 2020

Proyek ini dimulai sebagai hiburan dan menjadi peralatan yang serius.

Kontroler menerima pemosisian antena secara manual, melalui dua enkoder putar, Azimuth dan Elevation. Alat ini dapat melacak satelit secara otomatis, saat terhubung dengan USB ke PC yang menjalankan perangkat lunak pelacakan satelit.

Ini kompatibel dengan semua perangkat lunak pelacakan menggunakan protokol EasyComm2 / 9600 bauds. PstRotator, WXtrack, HRD, MacDoppler... Bahkan WXtoIMG dapat mengontrol rotator.

Ia bekerja langsung dengan Orbitron, dengan plugin DDE dari http://tripsintech.com/orbitron-dde-azimuth-elevation-to-serial/

Kontroler mengeluarkan respons secara serial, agar perangkat lunak pelacakan menampilkan posisi antena sebenarnya di layar. Sejauh ini, hanya PstRotator yang melakukannya.

Kode tidak menggunakan perpustakaan apa pun (kecuali LCD) dan berjalan persis apa adanya, dengan pin sesuai dengan diagram listrik di bawah ini. Jika Anda menekan tombol encoder Azimuth, semua gerakan antena akan segera berhenti, dan perintah azimuth dapat diatur dalam 10 derajat. langkah.

Anda akan menemukan dua versi di sini:Satu untuk motor DC, dan satu untuk motor AC (hanya relay). Yang terakhir dapat dihubungkan dengan rotator antena komersial yang ada.

Versi motor DC memiliki keunggulan menggunakan PWM untuk pergerakan antena yang lebih lembut/halus. Ini menghasilkan respons daya yang proporsional dengan kesalahan sudut (Target<->Antena). Oleh karena itu, ketika antena mulai bergerak, ia berakselerasi secara progresif, dan, ketika mendekati posisi yang diinginkan, ia melambat hingga berhenti sepenuhnya. Ini dikenal sebagai Soft-Start / Soft-Stop . Ada Zona Mati yang dapat disesuaikan, di mana antena tidak bergerak untuk offset target sedikit pun.

Saya memiliki beta versi dengan Soft-Start / Soft-Stop untuk motor AC, memanfaatkan modul AC-Dimmer ini, tetapi saat ini hanya berfungsi untuk azimuth. Jika Anda ingin mencobanya, beri tahu saya melalui email.

Jika Anda memiliki 180 derajat. sistem elevasi, Anda baik, beri saya email. Ada juga versi dengan 0.1deg. presisi, tetapi saya tidak akan merekomendasikannya kecuali jika Anda memiliki pembacaan potensiometer yang kokoh dan desain konstruksi pengontrol paranoiac. Anda akan menemukan lebih banyak versi di halaman web saya.

Setelah menyelesaikan konstruksi, Anda harus menerapkan prosedur kalibrasi .

  • Kalibrasi potensiometer adalah wajib dan memastikan pembacaan yang benar dari 0-359deg. / 0-90 derajat, apa pun jenis potensiometer yang Anda gunakan.
  • Kalibrasi motor hanya untuk menyetel Soft-Start-Stop fitur. Ini diperlukan jika Anda tidak menyukai pengaturan default.

Penjelasan lebih detail di video. Karena kode telah ditingkatkan dari waktu ke waktu, dan video tidak dapat diperbarui lagi, periksa halaman web saya untuk informasi terbaru dan pengalaman pribadi yang hidup dengan pengontrol ini. https://racov.ro/index.php/2020/12/09/arduino-based-antenna-rotator-part3-software-tracking-update/

Beri saya email jika Anda ingin tahu lebih banyak, karena platform ini tidak memberi tahu saya tentang komentar baru, tidak tahu mengapa. Saya akan mencoba memecahkan masalah kecil sebaik mungkin. [email protected]

Terima kasih banyak untuk semua yang mengirimi saya umpan balik, membantu membuat proyek ini lebih dapat diandalkan. Setiap umpan balik sangat dihargai.

Kode

  • semut-busuk-DC-nov2021
  • ant-rot-AC-aug2021
  • Prosedur kalibrasi potensiometer
  • Prosedur kalibrasi motor
ant-rot-DC-nov2021Arduino
Kode ini untuk motor DC, dengan output PWM start-stop yang lembut
/* Pengontrol Rotator Antena AZ/EL untuk Arduino - motor DC * ========================================================* Menggunakan protokol EasyComm untuk komputer - Perangkat Lunak Pelacakan * Perintah manual oleh berarti dua rotary encoders AZ - EL * * Viorel Racoviteannu * https://www.youtube.com/channel/UCiRLZX0bV9rS04BGAyUf-fA * https://racov.ro * [email protected] * * Saya tidak bertanggung jawab atas penyalahgunaan kode ini * atau segala jenis kerusakan yang mungkin terjadi dari penggunaan kode ini. * * Desember 2020 v2 - peningkatan stabilitas komunikasi serial * Januari 2021 - peningkatan dekat target zona mati, di mana antena tidak akan bergerak * April 2021 - peningkatan stabilitas komunikasi serial * Juni 2021 - kesalahan daya proporsional untuk gerakan pelacakan. Soft-Stop Nyata * agustus 2021 - pembaruan USB lebih cepat, pengalihan dingin arah Az/El, pengoptimalan kecil dalam kode * November 2021 - memecahkan rahasia Soft-Start. Itu tidak sulit. Itu dia */ #include  // Library untuk komunikasi I2C#include  // Library untuk LCD// Wiring:pin SDA terhubung ke A4 dan pin SCL ke A5.// Hubungkan ke LCD melalui I2C, alamat default 0x27 (A0-A2 tidak dilompati) LiquidCrystal_I2C lcd (0x27, 16, 2); // alamat, karakter, baris.// mendeklarasikan simbol khusus untuk byte panah atas/bawah DownArrow[8] ={ B00000, B00100, B00100, B00100, B10101, B01110, B00100, B000000}; byte Panah Atas[8] ={ B00000, B00100, B01110, B10101, B00100, B00100, B00100, B00000};/************************* ********** DI SINI ANDA BENAR-BENAR MENGUBAH GERAKAN ANTENA***************/// KALIBRASI potensiometer ANTENA int AzMin =1; //awal potensiometer int AzMax =1023; //akhir potensiometer int ElMin =1; int ElMax =1023;// Kesalahan yang diizinkan di mana antena tidak dapat bergerak int AzErr =8; int ElErr =4;// Selisih sudut di mana soft stop dimulai int Amax =25; //azimuth int Emaks =15; //elevasi// mnt dan daya maksimum untuk motor, persen; int PwAzMin =30; //daya minimum yang membuat motor tidak mati dan mulai di bawah beban int PwAzMax =100; //kekuatan penuh untuk kecepatan tercepat int PwElMin =30; int PwElMax =100; int PwAz =0; // daya yang dihitung untuk ditransmisikan ke motor (persen); int PwEl =0;/****************************************** ************************************************** *****/// Variabel encoder enum AzPinAssignments { AzEncoderPinA =2, // Az encoder kanan AzEncoderPinB =3, // encoder left AzClearButton =4, // encoder push ElEncoderPinA =6, // El encoder right ElEncoderPinB =5 }; // encoder kiri // interupsi service rutin vars unsigned int lastReportedPos =1; // ubah manajemen static boolean rotating =false; // manajemen debounce boolean A_set =false; boolean B_set =salah; int Negara; int aLastState; // variabel lain int AzPotPin =A0; // pilih pin input untuk azim. potensiometer int AzRotPin =12; // pilih pin keluar untuk arah putaran int AzPWMPin =11; // pilih pin keluar untuk perintah PWM azimuth int TruAzim =0; // menghitung nilai azimuth nyata int ComAzim =0; // memerintahkan nilai azimuth int OldTruAzim =0; // untuk menyimpan nilai azimuth sebelumnya int OldComAzim =0; char AzDir; // simbol untuk tampilan azim rot int AzEncBut =1; // variabel untuk beralih dengan tombol tekan encoder int ElPotPin =A1; // pilih pin input untuk ketinggian. potensiometer int ElRotPin =13; // pilih pin keluar untuk arah rotasi elevasi int ElPWMPin =10; // pilih pin keluar untuk rotasi elevasi perintah PWM int TruElev =0; // menghitung nilai elevasi nyata int ComElev =0; // nilai elevasi yang diperintahkan int OldTruElev =0; // untuk menyimpan nilai elevasi sebelumnya int OldComElev =0; char ElDir; // simbol untuk ketinggian. rot display // flag untuk AZ, toleransi EL bool AzStop =false; bool ElStop =salah; int ElUp =1; // 1 - Elevation Dn, 0 - Elevation STOP, 2 - Elevation Up int StaAzim =0; // Mulai sudut Azimuth untuk motor Soft-Start int PwAzStop =0; // menghitung PWM (persen) untuk soft-stop int PwAzStar =0; // menghitung PWM (persen) untuk soft-start int StaElev =0; // Mulai sudut Ketinggian untuk motor Soft-Start int PwElStop =0; // menghitung PWM (persen) untuk soft-stop int PwElStar =0; // menghitung PWM (persen) untuk soft-start //averaging loop const int numReadings =25; int indeks baca =0; // indeks bacaan saat ini int azimuth[numReadings]; // pembacaan dari input analog int elevasi[numReadings]; int totalAz =0; // total int totalEl =0;// variabel untuk komunikasi serial String Azimuth =""; Ketinggian String =""; String KomputerBaca; String KomputerTulis; bool AZser =salah; bool ELser =salah; bool ANTser =false;/*************** END VARIABLE DECLARATION ************/void setup() { Serial.begin(9600); Serial.setTimeout(50); // milidetik untuk menunggu sata USB. Default 1000// Memulai LCD:// lcd.begin(16,2); //pilih yang ini jika panah tidak ditampilkan dengan benar lcd.init(); lcd.backlight();// tulis pada nama tampilan dan versi lcd.setCursor(0, 0); // Atur kursor pada kolom pertama baris pertama.(penghitungan dimulai dari 0!) lcd.print("EasyCom AntRotor"); // tampilkan "..." lcd.setCursor(0, 1); // Atur kursor pada kolom pertama baris kedua lcd.print("*Racov* Nov.2021");//membuat simbol khusus untuk panah atas/bawah lcd.createChar(1, DownArrow); lcd.createChar(2, Panah Atas); // deklarasi pin pinMode(AzRotPin, OUTPUT); //deklarasikan azim. arah putaran Pin sebagai OUTPUT pinMode(AzPWMPin, OUTPUT); // mendeklarasikan pin perintah PWM azimuth sebagai OUTPUT pinMode(ElRotPin, OUTPUT); //deklarasikan ketinggian. arah putaran Pin sebagai OUTPUT pinMode(ElPWMPin, OUTPUT); pinMode(AzPotPin, INPUT); pinMode(ElPotPin, INPUT); pinMode(AzEncoderPinA, INPUT); pinMode(AzEncoderPinB, INPUT); pinMode(AzClearButton, INPUT); pinMode(ElEncoderPinA, INPUT); pinMode(ElEncoderPinB, INPUT);// Pin AzEncoder pada interupsi 0 (pin A) attachInterrupt(0, doEncoderA, CHANGE);// Pin AzEncoder pada interupsi 1 (pin B) attachInterrupt(1, doEncoderB, CHANGE);// Membaca keadaan awal ElEncoderPinA aLastState =digitalRead(ElEncoderPinA);/* inisialisasi loop rata-rata */ TruAzim =(peta(analogRead(AzPotPin), AzMin, AzMax, 0, 359)); // nilai azimuth 0-359 if (TruAzim<0) {TruAzim=0;} if (TruAzim>359) {TruAzim=359;} // simpan nilai di antara batas TruElev =(peta(analogRead(ElPotPin), ElMin, ElMax , 0, 90)); // nilai elev 0-90 if (TruElev<0) {TruElev=0;} if (TruElev>90) {TruElev=90;} // pertahankan nilai di antara batas untuk (int thisReading =0; thisReading 359) {TruAzim=359;} if (TruElev<0) {TruElev=0;} if (TruElev>90) {TruElev =90;} // maju ke posisi berikutnya dalam array:readIndex =readIndex + 1; // jika kita berada di akhir array, bungkus ke awal:if (readIndex>=numReadings) {readIndex =0;} // ini untuk membaca perintah dari encoder ReadAzimEncoder(); ReadElevEncoder(); if (Serial.available()) {SerComm();} // baca data USB// perbarui tampilan posisi antena hanya jika nilai berubah if ((millis()%500)<10){ //tidak mengedipkan tampilan jika (LamaTruAzim!=TruAzim) { DisplAzim(TruAzim,4,0); OldTruAzim =TruAzim; } if (OldTruElev!=TruElev) { DisplElev(TruElev,5,1); OldTruElev =BenarElev; } }// perbarui tampilan posisi target hanya jika nilai berubah if (OldComAzim !=ComAzim) { DisplAzim(ComAzim,12,0); OldComAzim =ComAzim; } if (OldComElev !=ComElev) { DisplElev(ComElev,13,1); OldComElev =ComElev; }// ini untuk memutar dalam azimuth if (TruAzim ==ComAzim) { // jika sama, berhenti bergerak AzStop =true; analogWrite(AzPWMPin, 0); // Daya motor Az =0 StaAzim =TruAzim; // ini akan menjadi azimuth awal untuk soft-start lcd.setCursor(8, 0); lcd.print("="); } else if ((abs(TruAzim - ComAzim)<=AzErr)&&(AzStop ==false)) { // jika dalam toleransi, tetapi tidak sama, putar AzimRotate();} else if (abs(TruAzim - ComAzim)>AzErr){ // jika target melenceng dari toleransi AzStop =false; // tidak sama dengan AzimRotate(); // rotate }// ini untuk memutar di ketinggian if (TruElev ==ComElev) { // jika sama, berhenti bergerak ElStop =true; analogWrite(ElPWMPin, 0); // Daya motor El =0 StaElev =TruElev; // ini akan menjadi elevasi awal untuk soft-start lcd.setCursor(8, 1); lcd.print("="); ElUp =0; // tandai untuk elevasi STOP } else if ((abs(TruElev - ComElev)<=ElErr)&&(ElStop ==false)) { // jika dalam toleransi, tapi tidak sama, putar ElevRotate();} else if (abs(TruElev - ComElev)>ElErr){ // jika target meleset toleransi ElStop =false; // tidak sama dengan ElevRotate(); // rotate } // ini untuk menginterpretasikan perkalian Az encoder x10 while (AzEncBut ==10) { // while toggle ke x10 analogWrite(AzPWMPin, 0); // BERHENTI rotasi antena StaAzim =TruAzim; // ini akan menjadi azimuth awal untuk soft-start analogWrite(ElPWMPin, 0); lcd.setCursor(8, 0); lcd.print("*"); BacaAzimEncoder(); if (OldComAzim !=ComAzim){ // perbarui tampilan hanya jika angka berubah DisplAzim(ComAzim, 12, 0); OldComAzim =ComAzim; } penundaan (100); }}// akhir LOOP utama//______________________________________________________// ___________ definisi prosedur_________void DisplAzim(int x, int y, int z) { char displayString[7] =""; sprintf(displayString, "%03d", x); // menampilkan angka dengan panjang tetap (3 bilangan bulat) lcd.setCursor(y, z); // untuk tidak ada nol di depan "__7" gunakan "%3d" lcd.print(displayString); // ************** UNTUK KALIBRASI **************// Serial.print ("Az ");// Serial.println ( analogRead(AzPotPin));}void DisplElev(int x, int y, int z){ char displayString[7] =""; sprintf(displayString, "%02d", x); // menampilkan angka dengan panjang tetap (2 bilangan bulat) lcd.setCursor(y, z); // tanpa nol di depan "_7" gunakan "%2d" lcd.print(displayString);// ************** UNTUK TUJUAN KALIBRASI ********** ****// Serial.print ("El ");// Serial.println (analogRead(ElPotPin));}void ReadElevEncoder() { aState =digitalRead(ElEncoderPinA); // Membaca status "saat ini" dari ElEncoderPinA // Jika status ElEncoderPinA sebelumnya dan saat ini berbeda, berarti telah terjadi Pulsa jika (aState !=aLastState){ // Jika status ElEncoderPinB berbeda dengan status ElEncoderPinB ElEncoderPinA state, artinya encoder berputar searah jarum jam if (digitalRead(ElEncoderPinB) !=aState) { ComElev ++;} else { ComElev --;} if (ComElev <0) {ComElev =0;} if (ComElev>90 ) {ComElev =90;} } aLastState =aState; // Memperbarui status ElEncoderPinA sebelumnya dengan status saat ini}void ReadAzimEncoder() { rotating =true; // reset debouncer if (lastReportedPos !=ComAzim) { lastReportedPos =ComAzim; } penundaan (10); if (digitalRead(AzClearButton) ==LOW ) { // jika sakelar encoder tertekan penundaan (250); // sakelar debounce if (AzEncBut ==1){ AzEncBut =10; ComAzim =int(ComAzim/10)*10; // ComAzim dalam 10 derajat. langkah } else { AzEncBut =1; } }} //end ReadAzimEncoder()// Interrupt on A mengubah statevoid doEncoderA() { // debounce jika ( berputar ) delay (1); // tunggu sebentar sampai pantulan selesai // Uji transisi, apakah semuanya benar-benar berubah? if ( digitalRead(AzEncoderPinA) !=A_set ) { // debounce sekali lagi A_set =!A_set; // sesuaikan penghitung + jika A mengarah B jika ( A_set &&!B_set ) ComAzim +=AzEncBut; ComAzim =((ComAzim + 360) % 360); // encoderPos antara 0 dan 359 derajat. berputar =salah; // tidak ada lagi debouncing sampai loop() memukul lagi }}// Interrupt pada status perubahan B, sama seperti A di atasvoid doEncoderB() { if ( rotating ) delay (1); if ( digitalRead(AzEncoderPinB) !=B_set ) { B_set =!B_set; // sesuaikan penghitung - 1 jika B mengarah A jika ( B_set &&!A_set ) ComAzim -=AzEncBut; ComAzim =((ComAzim + 360) % 360); // encoderPos antara 0 dan 359 derajat. berputar =salah; } }void AzimRotate() { if (ComAzim> TruAzim) { // ini untuk menentukan arah putaran// cold switching - menghentikan motor sebelum mengubah arah - untuk melindungi bagian mekanik dan elektrik if (AzDir ==char(127)) { // jika sebelumnya berputar berlawanan arah analogWrite(AzPWMPin, 0); // HENTIKAN motor StaAzim =TruAzim; // ini akan menjadi azimuth awal untuk soft-start delay(200); // penundaan pra-pengalihan digitalWrite(AzRotPin, LOW); // nonaktifkan pin rotasi - putar tunda kanan(200); // post-switch delay } else { // arah yang sama, tanpa Stop, tanpa delay digitalWrite(AzRotPin, LOW); // nonaktifkan pin rotasi - putar ke kanan } AzDir =char(126); // "->" } else { if (AzDir ==char(126)) { // jika sebelumnya berputar berlawanan arah analogWrite(AzPWMPin, 0); // HENTIKAN motor StaAzim =TruAzim; // ini akan menjadi azimuth awal untuk soft-start delay(200); // penundaan pra-pengalihan digitalWrite(AzRotPin, HIGH); // aktifkan pin rotasi - putar delay kiri(200); // post-switch delay } else { // arah yang sama, tanpa Stop, tanpa delay digitalWrite(AzRotPin, HIGH); // aktifkan pin rotasi - putar ke kiri } AzDir =char(127); // "<-" } lcd.setCursor(8, 0); lcd.print(String(AzDir)); // ini mengaktifkan pin PWM azim proporsional dengan kesalahan sudut (dihitung dalam persen %) PwAzStop =PwAzMin + round((abs(ComAzim-TruAzim))*(PwAzMax-PwAzMin)/Amax); //rumus yang menghasilkan kekuatan proporsional dengan perbedaan sudut untuk Soft-Stop PwAzStar =PwAzMin + round((abs(StaAzim-TruAzim))*(PwAzMax-PwAzMin)/Amax); //rumus yang menghasilkan daya proporsional dengan perbedaan sudut untuk Soft-Start if (PwAzStar> PwAzStop){ PwAz =PwAzStop; //pilih nilai yang terkecil } else {PwAz =PwAzStar;} if (PwAz> PwAzMax) {PwAz =PwAzMax;} analogWrite(AzPWMPin, round(2,55*PwAz)); // aktifkan pin PWM drive Azim }// end AzimRotate()void ElevRotate() {// ini untuk menentukan arah putaran if (ComElev> TruElev) { if (ElUp ==1) { // jika sebelumnya berputar sebaliknya arah analogWrite(ElPWMPin, 0); // HENTIKAN motor StaElev =TruElev; // ini akan menjadi elevasi awal untuk soft-start delay(200); // penundaan pra-sakelar digitalWrite(ElRotPin, LOW); // nonaktifkan pin rotasi - putar delay UP(200); // post-switch delay } else { // arah yang sama, tanpa Stop, tanpa delay digitalWrite(ElRotPin, LOW); // nonaktifkan pin rotasi - putar UP } lcd.setCursor(8, 1); lcd.tulis(2); // panah ke atas ElUp =2; // flag untuk elevasi NAIK } else { if (ElUp ==2) { // jika sebelumnya berputar ke arah yang berlawanan analogWrite(ElPWMPin, 0); // HENTIKAN motor StaElev =TruElev; // ini akan menjadi elevasi awal untuk soft-start delay(200); // penundaan pra-sakelar digitalWrite(ElRotPin, HIGH); // nonaktifkan pin rotasi - putar delay UP(200); // post-switch delay } else { // arah yang sama, tanpa Stop, tanpa delay digitalWrite(ElRotPin, HIGH); // nonaktifkan pin rotasi - putar UP } lcd.setCursor(8, 1); lcd.tulis(1); // panah bawah ElUp =1; // flag untuk elevasi DN } // ini mengaktifkan pin PWM azim proporsional dengan kesalahan sudut (dihitung dalam persen %) PwElStop =PwElMin + round((abs(ComElev-TruElev)))*(PwElMax-PwElMin)/Emax); //rumus yang menghasilkan kekuatan proporsional dengan perbedaan sudut untuk Soft-Stop PwElStar =PwElMin + round((abs(StaElev-TruElev))*(PwElMax-PwElMin)/Emax); //rumus yang mengeluarkan daya proporsional dengan perbedaan sudut untuk Soft-Start if (PwElStar> PwElStop){ PwEl =PwElStop; //pilih nilai yang terkecil } else {PwEl =PwElStar;} if (PwEl> PwElMax) {PwEl =PwElMax;} analogWrite(ElPWMPin, round(2,55*PwEl)); // aktifkan pin PWM drive Elev}// akhiri ElevRotate()void SerComm() { // inisialisasi pembacaan ComputerRead =""; Azimut =""; Ketinggian =""; while(Serial.available()) { ComputerRead=Serial.readString(); // membaca data yang masuk sebagai string// Serial.println(ComputerRead); // echo penerimaan untuk tujuan pengujian } // mencari perintah  for (int i =0; i <=ComputerRead.length(); i++) { if ((ComputerRead.charAt(i) ==' A')&&(ComputerRead.charAt(i+1) =='Z')){ // jika dibaca AZ untuk (int j =i+2; j <=ComputerRead.length(); j++) { if (isDigit (ComputerRead.charAt(j))) { // jika karakternya adalah angka Azimuth =Azimuth + ComputerRead.charAt(j); } else {break;} } } } // mencari perintah  for (int i =0; i <=(ComputerRead.length()-2); i++) { if ((ComputerRead.charAt(i ) =='E')&&(ComputerRead.charAt(i+1) =='L')){ // jika dibaca EL if ((ComputerRead.charAt(i+2)) =='-') { ComElev =0; // jika elevasi negatif putus; } for (int j =i+2; j <=ComputerRead.length(); j++) { if (isDigit(ComputerRead.charAt(j))) { // jika karakter berupa angka Elevation =Elevation + ComputerRead.charAt( J); } else {break;} } } } // jika  diterima jika (Azimuth !=""){ ComAzim =Azimuth.toInt(); ComAzim =ComAzim%360; // menjaga nilai di antara batas (untuk pelacak dengan rotasi lebih dari 360 derajat) }// jika  diterima jika (Elevation !=""){ ComElev =Elevation.toInt(); if (ComElev>180) { ComElev =0;} if (ComElev>90) { //jika menerima lebih dari 90 derajat. (untuk pelacak dengan ketinggian 180 derajat) ComElev =180-ComElev; // tetap di bawah 90 derajat. ComAzim =(ComAzim+180)%360; //dan putar antena di belakang } }// cari interogasi  untuk posisi antena untuk (int i =0; i <=(ComputerRead.length()-4); i++) { if ((ComputerRead .charAt(i) =='A')&&(ComputerRead.charAt(i+1) =='Z')&&(ComputerRead.charAt(i+3) =='E')&&(ComputerRead.charAt(i +4) =='L')){ // kirim kembali posisi antena <+xxx.x xx.x> ComputerWrite ="+"+String(TruAzim)+".0 "+String(TruElev)+". 0"; Serial.println(ComputerWrite); } }}// end SerComm()
ant-rot-AC-aug2021Arduino
Pastikan Anda menggunakan Diagram Listrik untuk motor AC
Menawarkan kontak kering (ON/OFF). Ini dapat dengan mudah dihubungkan dengan rotator komersial.
/* AZ/EL Antena Rotator controller untuk Arduino - motor AC * ========================================================* Menggunakan protokol EasyComm untuk komputer - Perangkat Lunak Pelacakan * Perintah manual melalui dua encoder putar AZ - EL * * kompatibel dengan rotator kotak sakelar * atau motor AC * kontak kering untuk Kiri-Kanan, Atas-Bawah * * Viorel Racoviteannu / * https://www.youtube.com/channel/UCiRLZX0bV9rS04BGAyUf-fA * https://racov.ro * [email protected] * * Saya tidak bertanggung jawab atas penyalahgunaan kode ini * atau segala jenis kerusakan yang mungkin terjadi karena penggunaan kode ini. * * Desember 2020 v2 - peningkatan stabilitas komunikasi serial * Januari 2021 - AZ tetap, toleransi EL untuk aktivasi motor * apr 2021 - peningkatan stabilitas komunikasi serial * Agustus 2021 - pembaruan USB lebih cepat, pengalihan dingin arah Az/El, optimasi kecil dalam kode */ #include  // Library untuk komunikasi I2C#include  // https://www.arduinolibraries.info/libraries/liquid-crystal-i2-c (Library for LCD)// Pengkabelan:Pin SDA terhubung ke A4 dan pin SCL ke A5.// Hubungkan ke LCD melalui I2C, alamat default 0x27 (A0-A2 tidak dilompati) LCD LiquidCrystal_I2C (0x27, 16, 2); // alamat, karakter, baris.// mendeklarasikan simbol khusus untuk byte panah atas/bawah DownArrow[8] ={ B00000, B00100, B00100, B00100, B10101, B01110, B00100, B000000}; byte Panah Atas[8] ={ B00000, B00100, B01110, B10101, B00100, B00100, B00100, B00000};// KALIBRASI potensiometer ANTENA int AzMin =1; //awal potensiometer int AzMax =1023; //akhir potensiometer int ElMin =1; int ElMax =1023;// Kesalahan yang diizinkan untuk antena yang tidak mau bergerak int AzErr =8; int ElErr =4;// Variabel encoder Azim enum AzPinAssignments { AzEncoderPinA =2, // encoder kanan AzEncoderPinB =3, // encoder left AzClearButton =4}; // encoder mendorong unsigned int lastReportedPos =1; // ubah manajemen static boolean rotating =false; // manajemen debounce // interupsi layanan rutin vars boolean A_set =false; boolean B_set =salah; //Elevasikan variabel encoder enum ElPinAssignments{ ElEncoderPinA =6, // encoder kanan ElEncoderPinB =5, // encoder kiri ElClearButton =7}; // tekan encoder int aState; int aLastState; // variabel lain int AzPotPin =A0; // pilih pin input untuk azim. potensiometer int AzRotPinR =13; // select the out pin for rotation direction int AzRotPinL =12; int TruAzim =0; // calculated real azimuth value int ComAzim =0; // commanded azimuth value int OldTruAzim =0; // to store previous azimuth value int OldComAzim =0; char AzDir; // symbol for azim rot display int AzEncBut =1; // variable to toggle with encoder push button int ElPotPin =A1; // select the input pin for the elev. potentiometer int ElRotPinD =11; // select the out pin for elevation rotation direction int ElRotPinU =10; int TruElev =0; // calculated real elevation value int ComElev =0; // commanded elevation value int OldTruElev =0; // to store previous elevation value int OldComElev =0; char ElDir; // symbol for elev. rot display int ElEncBut =1; // variable to toggle with encoder push button // flags for AZ, EL tolerances bool AzStop =false; bool ElStop =false; int ElUp =0; // 1 =Elevation Dn, 0 =Elevation STOP, 2 =Elevation Up //averaging loop const int numReadings =25; int readIndex =0; // the index of the current reading int azimuth[numReadings]; // the readings from the analog input int elevation[numReadings]; int totalAz =0; // the running total int totalEl =0;// variables for serial comm String Azimuth =""; String Elevation =""; String ComputerRead; String ComputerWrite; bool AZser =false; bool ELser =false; bool ANTser =false;/*************** END VARIABLE DECLARATION ************/ void setup() { Serial.begin(9600); Serial.setTimeout(50); // miliseconds to wait for USB sata. Default 1000// Initiate the LCD:// lcd.begin(16,2); //select this one if the arrows are not displayed correctly lcd.init(); lcd.backlight();// write on display name and version lcd.setCursor(0, 0); // Set the cursor on the first column first row.(counting starts at 0!) lcd.print("EasyCom AntRotor"); lcd.setCursor(0, 1); // Set the cursor on the first column the second row lcd.print("*Racov* Aug.2021 ");//creating custom symbol for up/dwn arrow lcd.createChar(1, DownArrow); lcd.createChar(2, UpArrow); // pin declaration pinMode(AzRotPinR, OUTPUT); //declaring azim. rotation direction Pin as OUTPUT pinMode(AzRotPinL, OUTPUT); pinMode(ElRotPinD, OUTPUT); //declaring elev. rotation direction Pin as OUTPUT pinMode(ElRotPinU, OUTPUT); pinMode(AzPotPin, INPUT); pinMode(ElPotPin, INPUT); pinMode(AzEncoderPinA, INPUT); pinMode(AzEncoderPinB, INPUT); pinMode(AzClearButton, INPUT); pinMode(ElEncoderPinA, INPUT); pinMode(ElEncoderPinB, INPUT); pinMode(ElClearButton, INPUT);// AzEncoder pin on interrupt 0 (pin A) attachInterrupt(0, doEncoderA, CHANGE);// AzEncoder pin on interrupt 1 (pin B) attachInterrupt(1, doEncoderB, CHANGE);// Reads the initial state of the ElEncoderPinA aLastState =digitalRead(ElEncoderPinA);/* initialization of the averaging loop */ TruAzim =(map(analogRead(AzPotPin), AzMin, AzMax, 0, 359)); // azimuth value 0-359 if (TruAzim<0) {TruAzim=0;} if (TruAzim>359) {TruAzim=359;} // keep values between limits TruElev =(map(analogRead(ElPotPin), ElMin, ElMax, 0, 90)); // elev value 0-90 if (TruElev<0) {TruElev=0;} if (TruElev>90) {TruElev=90;} // keep values between limits for (int thisReading =0; thisReading 359) {TruAzim=359;} if (TruElev<0) {TruElev=0;} if (TruElev>90) {TruElev=90;} // advance to the next position in the array:readIndex =readIndex + 1; // if we're at the end of the array, wrap around to the beginning:if (readIndex>=numReadings) {readIndex =0;} // this is to read the command from encoder ReadAzimEncoder(); ReadElevEncoder(); if (Serial.available()) {SerComm();} // read USB data// update antenna position display only if value change if ((millis()%500)<10){ //not to flicker the display if (OldTruAzim!=TruAzim) { DisplAzim(TruAzim,4,0); OldTruAzim =TruAzim; } if (OldTruElev!=TruElev) { DisplElev(TruElev,5,1); OldTruElev =TruElev; } }// update target position display only if value change if (OldComAzim !=ComAzim) { DisplAzim(ComAzim,12,0); OldComAzim =ComAzim; } if (OldComElev !=ComElev) { DisplElev(ComElev,13,1); OldComElev =ComElev; }// this is to rotate in azimuth if (TruAzim ==ComAzim) { // if equal, stop moving AzStop =true; digitalWrite(AzRotPinL, LOW); // deactivate rotation pin digitalWrite(AzRotPinR, LOW); lcd.setCursor(8, 0); lcd.print("="); } else if ((abs(TruAzim - ComAzim)<=AzErr)&&(AzStop ==false)) { // if in tolerance, but it wasn't an equal, rotate AzimRotate();} else if (abs(TruAzim - ComAzim)>AzErr){ // if target is off tolerance AzStop =false; // it's not equal AzimRotate(); // rotate }// this is to rotate in elevation if (TruElev ==ComElev) { // if equal, stop moving ElStop =true; digitalWrite(ElRotPinD, LOW); // deactivate elevator pin digitalWrite(ElRotPinU, LOW); lcd.setCursor(8, 1); lcd.print("="); ElUp =0; // flag for elevation STOP } else if ((abs(TruElev - ComElev)<=ElErr)&&(ElStop ==false)) { // if in tolerance, but it wasn't an equal, rotate ElevRotate();} else if (abs(TruElev - ComElev)>ElErr){ // if target is off tolerance ElStop =false; // it's not equal ElevRotate(); // rotate }// this is to interpret x10 AZ ENC multiplication while (AzEncBut ==10) { // while toggled to x10 digitalWrite(AzRotPinL, LOW); // deactivate rotation pin digitalWrite(AzRotPinR, LOW); digitalWrite(ElRotPinD, LOW); // deactivate elevator pin digitalWrite(ElRotPinU, LOW); lcd.setCursor(8, 0); lcd.print("*"); ReadAzimEncoder(); if (OldComAzim !=ComAzim){ // update display only if numbers change DisplAzim(ComAzim, 12, 0); OldComAzim =ComAzim; } penundaan(100); }}// end main LOOP//____________________________________________________// ___________procedures definitions__________________void DisplAzim(int x, int y, int z) { char displayString[7] =""; sprintf(displayString, "%03d", x); //outputs a fixed lenght number (3 integer) lcd.setCursor(y, z); // for no leading zeros "__7" use "%3d" lcd.print(displayString); // ************** FOR CALIBRATION PURPOSES **************// Serial.print ("Az ");// Serial.println (analogRead(AzPotPin));}void DisplElev(int x, int y, int z){ char displayString[7] =""; sprintf(displayString, "%02d", x); //outputs a fixed lenght number (2 integer) lcd.setCursor(y, z); // for no leading zeros "_7" use "%2d" lcd.print(displayString);// ************** FOR CALIBRATION PURPOSES **************// Serial.print ("El ");// Serial.println (analogRead(ElPotPin));}void ReadElevEncoder() { aState =digitalRead(ElEncoderPinA); // Reads the "current" state of the ElEncoderPinA // If the previous and the current state of the ElEncoderPinA are different, that means a Pulse has occured if (aState !=aLastState){ // If the ElEncoderPinB state is different to the ElEncoderPinA state, that means the encoder is rotating clockwise if (digitalRead(ElEncoderPinB) !=aState) { ComElev ++;} else { ComElev --;} if (ComElev <0) {ComElev =0;} if (ComElev>90) {ComElev =90;} } aLastState =aState; // Updates the previous state of the ElEncoderPinA with the current state}void ReadAzimEncoder() { rotating =true; // reset the debouncer if (lastReportedPos !=ComAzim) { lastReportedPos =ComAzim; } penundaan (10); if (digitalRead(AzClearButton) ==LOW ) { // if encoder switch depressed delay (250); // debounce switch if (AzEncBut ==1){ AzEncBut =10; ComAzim =int(ComAzim/10)*10; // ComAzim in 10deg. steps } else { AzEncBut =1; } }} //end ReadAzimEncoder()// Interrupt on A changing statevoid doEncoderA() { // debounce if ( rotating ) delay (1); // wait a little until the bouncing is done // Test transition, did things really change? if ( digitalRead(AzEncoderPinA) !=A_set ) { // debounce once more A_set =!A_set; // adjust counter + if A leads B if ( A_set &&!B_set ) ComAzim +=AzEncBut; ComAzim =((ComAzim + 360) % 360); // encoderPos between 0 and 359 deg. rotating =false; // no more debouncing until loop() hits again }}// Interrupt on B changing state, same as A abovevoid doEncoderB() { if ( rotating ) delay (1); if ( digitalRead(AzEncoderPinB) !=B_set ) { B_set =!B_set; // adjust counter - 1 if B leads A if ( B_set &&!A_set ) ComAzim -=AzEncBut; ComAzim =((ComAzim + 360) % 360); // encoderPos between 0 and 359 deg. rotating =false; } }void AzimRotate() { if ((ComAzim-TruAzim)> (TruAzim-ComAzim)) { // this to determine direction of rotation// cold switching - stop motor before changing direction - to protect mechanic and electric parts digitalWrite(AzRotPinL, LOW); // deactivate rotation pin Left if (AzDir ==char(127)) {delay(500);} // if previously rotating in the oposite direction, wait 0.5 seconds digitalWrite(AzRotPinR, HIGH); // activate rotation pin Right AzDir =char(126); // "->" } else { digitalWrite(AzRotPinR, LOW); if (AzDir ==char(126)) {delay(500);} digitalWrite(AzRotPinL, HIGH); AzDir =char(127); // "<-" } lcd.setCursor(8, 0); lcd.print(String(AzDir));}void ElevRotate() {// this to determine direction of rotation if ((ComElev-TruElev)> (TruElev-ComElev)) { digitalWrite(ElRotPinD, LOW); if (ElUp ==1) {delay(500);} digitalWrite(ElRotPinU, HIGH); lcd.setCursor(8, 1); lcd.write(2); // arrow up ElUp =2; } else { digitalWrite(ElRotPinU, LOW); if (ElUp ==2) {delay(500);} digitalWrite(ElRotPinD, HIGH); lcd.setCursor(8, 1); lcd.write(1); // arrow down ElUp =1; }}void SerComm() { // initialize readings ComputerRead =""; Azimuth =""; Elevation =""; while(Serial.available()) { ComputerRead=Serial.readString(); // read the incoming data as string Serial.println(ComputerRead); // echo the reception for testing purposes } // looking for command  for (int i =0; i <=ComputerRead.length(); i++) { if ((ComputerRead.charAt(i) =='A')&&(ComputerRead.charAt(i+1) =='Z')){ // if read AZ for (int j =i+2; j <=ComputerRead.length(); j++) { if (isDigit(ComputerRead.charAt(j))) { // if the character is number Azimuth =Azimuth + ComputerRead.charAt(j); } else {break;} } } } // looking for command  for (int i =0; i <=(ComputerRead.length()-2); i++) { if ((ComputerRead.charAt(i) =='E')&&(ComputerRead.charAt(i+1) =='L')){ // if read EL if ((ComputerRead.charAt(i+2)) =='-') { ComElev =0; // if elevation negative break; } for (int j =i+2; j <=ComputerRead.length(); j++) { if (isDigit(ComputerRead.charAt(j))) { // if the character is number Elevation =Elevation + ComputerRead.charAt(j); } else {break;} } } } // if  received if (Azimuth !=""){ ComAzim =Azimuth.toInt(); ComAzim =ComAzim%360; // keeping values between limits }// if  received if (Elevation !=""){ ComElev =Elevation.toInt(); if (ComElev>180) { ComElev =0;} if (ComElev>90) { //if received more than 90deg. (for trackers with 180deg. elevation) ComElev =180-ComElev; //keep below 90deg. ComAzim =(ComAzim+180)%360; //and rotate the antenna on the back } }// looking for  interogation for antenna position for (int i =0; i <=(ComputerRead.length()-4); i++) { if ((ComputerRead.charAt(i) =='A')&&(ComputerRead.charAt(i+1) =='Z')&&(ComputerRead.charAt(i+3) =='E')&&(ComputerRead.charAt(i+4) =='L')){ // send back the antenna position <+xxx.x xx.x> ComputerWrite ="+"+String(TruAzim)+".0 "+String(TruElev)+".0"; Serial.println(ComputerWrite); } }}// end SerComm()
Potentiometer calibration procedureArduino
AZ / EL Potentiometers limit calibration PROCEDURE for displaying the correct antenna angles and rotation limits ( 0-359ᴼ / 0-90ᴼ)
This is plain text, not a code :)
AZ / EL Potentiometers limit calibration PROCEDURE ( 0-359ᴼ / 0-90ᴼ)This might seem complicated, but it only has to be done once.1. Open the code in Arduino and - Look for void DisplAzim(int x, int y, int z) {...// Serial.print ("Az ");// Serial.println (analogRead(AzPotPin)); - Uncoment these lines. Should look like this:Serial.print ("Az "); Serial.println (analogRead(AzPotPin)); - Look for void DisplElev(int x, int y, int z){...// Serial.print ("El ");// Serial.println (analogRead(ElPotPin));Uncoment these lines, too. Should look like this:Serial.print ("El "); Serial.println (analogRead(ElPotPin));2. Upload the code and open the Serial Monitor. There you will see a lot of numbers;3. With the help of the encoders, move the antenna to minimum values, 0ᴼ in azimuth and 0ᴼ in elevation.- Write down the values for Azimuth and Elevation. (in my case it was AzMin=90, ElMin=10)- These are the input values read by Arduino, not the real angles;4. Move the antenna again to maximum values, 359ᴼ in azimuth and 90ᴼ in elevation.- Again, write down the values for Azimuth and Elevation. (in my case it was AzMax=1000, ElMax=992);5. Look in the code, at the beginning, for the section// ANTENNA potentiometers CALIBRATION int AzMin =1; int AzMax =1023; int ElMin =1; int ElMax =1023;- Here input the values you wrote down for each situation;6. Now it is no longer necessary to send this on serial, so you have to comment back these lines, like this:// Serial.print ("Az "); // Serial.println (analogRead(AzPotPin));... // Serial.print ("El "); // Serial.println (analogRead(ElPotPin));7. Upload again the code.That's all.Now, in the serial monitor, there should be no more numbers, and the true antenna position is read correctly.
Motor calibration procedureArduino
This procedure sets the parameters for the Antenna Speed-Up / Slow-Down Zone.
This is plain text, not a code :)
Motor Calibration Procedure For Soft-Start / Soft-Stop feature.This procedure sets the parameters for the Antenna Speed-Up / Slow-Down and the Dead-Zone.You basically set how fast and how slow you want the antenna to start and to stop. You also set much the target can move, before the antenna will adjust again.It’s not strictly necessary, only if you don’t like the default settings.Make sure you first apply the Potentiometer Calibration Procedure !!! That one is strictly necessary.Look at the power diagram for a better understanding.***For Azimuth movement***-As the antenna starts to move towards the target, is picking up speed, reaching full power after  degrees difference. -As the antenna closes in to the target, below  degrees difference, it starts to slow down.  should be higher for heavier antennas.-The power starts to decrease from  to  until the angle difference becomes zero.  (in percents %) should be 100 for full speed. If you ever think your antenna rotates too fast, you can set a smaller .  (in percents %) is the minimum power for which your motor doesn’t stall and can start under load. The power output never falls below this value.-Once the antenna reaches the target position (zero degrees error), it stops and doesn’t move again until the target travels more than  degrees. This is a dead zone, to prevent continuously shaking the antenna for the smallest target movement, or potentiometer position jitter. The smaller the , the more precise tracking, the more frequent shacking of the motors.***For Elevation movement***Exactly as for the Azimuth.Look at the beginning of the code for this section. Here you can input your desired values./**************THIS IS WHERE YOU REALY TWEAK THE ANTENNA MOVEMENT************/...// Allowed error for which antennna won't move. int AzErr =8; int ElErr =4;// Angle difference where soft stop begins int Amax =25; //azimuth int Emax =15; //elevation// min and max power for motors, percents; int PwAzMin =30; //minimum power for which the motor doesn't stall and starts under load int PwAzMax =100; //full power for the fastest speed int PwElMin =30; int PwElMax =100;/****************************************************************************/

Skema

Make sure you use this diagram with the code for DC motors.
Connection of all the modules, encoders, LCD, relays, MosFet etc, Make sure you use this diagram with the code for AC motors.
Offers dry contacts (ON/OFF). It can be easily interfaced with commercial rotators.

Proses manufaktur

  1. Peredupan Lampu dengan PWM menggunakan Tombol Tekan
  2. Game Arduino Gyroscope dengan MPU-6050
  3. Sensor DHT11 dengan LED dan Speaker Piezo
  4. Unopad - Pengontrol MIDI Arduino dengan Ableton
  5. Iron Man
  6. Sensor Kendala Sederhana dengan Arduino
  7. Temukan Saya
  8. Kontrol Humidifier Arduino
  9. 4x4x4 LED cube dengan Arduino Uno dan 1sheeld
  10. Arduino Joystick