Вопрос по функции sscanf

KADAVR
Offline
Зарегистрирован: 21.10.2016

Всем добрый вечер! просьба помочь в правильном написании значений для функции sscanf.

есть рабочий код для arduino для поворотной антенны. Координаты в ардуино поступают через USB- порт от программы WXtrack формата:  

AZ255.7 EL1.0 UP0 DN0

с этим форматом arduino- код работает, функция так прописана:

sscanf(usb, "AZ%s EL%s\#13",&a, &b); 

Я данную поворотку хочу подключить к программе ORBITRON, формат данных там немного другой:

AZ255.7 EL1.0

Вопрос: как правильно прописать параметры в sscanf, чтобы она понимала этот формат строк.

мsscanf(usb, "AZ%s EL%s\#13",&a, &b);   -  не работает, поворотка вообще не реагирует на координаты :(

Заранее больше спасибо. Если нужно, могу выложить код целиком

 

 

firstengraver
Offline
Зарегистрирован: 17.02.2021

поддерживаю

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вы вводите числа как строки и непонятно, что потом с ними делаете, потому трудно сказать как Вам написать - непонятно как надо. 

Попробуйте после вызовов scanf напечатать a и b и сравните. Величины b будут у Вас разными, а вот насколько это критично - неясно, т.к. непонятно что с ними потом делается.

Код мог бы помочь (из Вашего поста даже непонятно как описаны a и b), если он не очень большой и не слишком запутан. Разбираться в большом и запутанном ... ну, Вы сами понимаете.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

а через какой драйвер цепляете к Орбитрону, может сменить программу управления на PSTROTATOR? Она всего 20$ и подобрать контроллер поворотки соответствующий вашему?

KADAVR
Offline
Зарегистрирован: 21.10.2016

Следующим постом выкладываю свой скетч, он хорошо работает с WXtrack
сам проект повортки взял отсюда https://github.com/OpenATS/OpenATS)
в свой скетч добавил только вывод информации на OLED дисплей.

ua6em
к орбитрону через WispDDE... а от него сразу на com-порт ардуино

ЕвгенийП
Код выложу постом ниже... он не сложный. да я для себя все комментариями расписал.
Сначала шаговые моторы по магнитным датчикам выставляются в начал координат ( в нули)
далее ждем команд на USB. преобразовываем их и поворачиваем моторы по вертикали и горизонтали

KADAVR
Offline
Зарегистрирован: 21.10.2016



#include<AccelStepper.h>

#define ACCELERATION_1 500.0   //400                 //Параметры ускорения шагового двигателя AZ
#define ACCELERATION_2 500.0   // 400                   //Параметры ускорения шагового двигателя EL
#define MAXSPEED_1 700.0                         //Максимальная скорость шагового двигателя AZ
#define MAXSPEED_2 700.0                         //Максимальная скорость шагового двигателя EL

#define STEPPER1_STEP_PIN 5                       // stepper1 AZ
#define STEPPER1_DIR_PIN  6
                       
#define STEPPER2_STEP_PIN 11                       //stepper2 EL 
#define STEPPER2_DIR_PIN 10 
                  

// установки для позиционирования антенны в ноль
#define STEPPER1_LS_PIN 2 // концевик горизонтального мотора AZ
#define STEPPER2_LS_PIN A7 // концевик вертикального мотора EL

// скорость вращения мотора при позиционировании в ноль
#define STEPPER1_INIT_SPEED 400.0 
#define STEPPER2_INIT_SPEED 400.0 

// Тут выставляем коэффициенты в в зависимости какой редуктор у  вас установлен
#define AZFACTOR 6.5                           //Коэффициент угла импульса AZ было 2.666 
#define ELFACTOR 6.5                          //Коэффициент угла импульса EL было 2.666      




//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "SSD1306Ascii.h"  
#include "SSD1306AsciiAvrI2c.h"
#define RST_PIN -1
SSD1306AsciiAvrI2c oled;
#define I2C_ADDRESS 0x3C  //  (0x3C is the Oled I2C Address)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

int power;
int looptime = 1;
int angle_x   = 0;    
int power1Pin = 4;
int power2Pin = 8;
int power_tmp = 0;                                 //0-это нормальное состояние, -1-заблокированное состояние,1-выключенное состояние

float X;
float Y;
float M;
float N;
float gotoangle_x;                                 //переменная для AZ координат
float gotoangle_y;                                 //переменная для EL координат
float angle_x_tmp = 0;                             //Параметр azimuth cache используется для определения разности углов AZ

String usbdata = "";                               //Определяем пустую строку
boolean _angle_1 = false;                          //Логическое значение для определения того, соответствует ли AZ требованиям
boolean _angle_2 = false;                          //Логическое значение для определения того, соответствует ли угол EL требованиям

unsigned long accumulate;                          //Функция накопления времени цикла


AccelStepper stepper1(AccelStepper::DRIVER, STEPPER1_STEP_PIN, STEPPER1_DIR_PIN);
AccelStepper stepper2(AccelStepper::DRIVER, STEPPER2_STEP_PIN, STEPPER2_DIR_PIN);



void setup() {                
  pinMode(STEPPER1_DIR_PIN, OUTPUT);
  pinMode(STEPPER2_DIR_PIN, OUTPUT);
  pinMode(STEPPER1_STEP_PIN, OUTPUT);
  pinMode(STEPPER2_STEP_PIN, OUTPUT);
 
  pinMode(STEPPER1_LS_PIN, INPUT_PULLUP); // Концевик AZ
  pinMode(STEPPER2_LS_PIN, INPUT_PULLUP); // Концевик EL
  stepper1.setMaxSpeed(MAXSPEED_1);
  stepper2.setMaxSpeed(MAXSPEED_2);
  stepper1.setAcceleration(ACCELERATION_1); 
  stepper2.setAcceleration(ACCELERATION_2); 
  stepper1.setSpeed(0);
  stepper2.setSpeed(0);
  stepper1.setSpeed(STEPPER1_INIT_SPEED);

#if RST_PIN >= 0
  oled.begin(&Adafruit128x32, I2C_ADDRESS, RST_PIN);
  #else
  oled.begin(&Adafruit128x32, I2C_ADDRESS);
  #endif 
  oled.setFont(Adafruit5x7);

  oled.setCursor (20,0); 
  oled.set1X();
  oled.println("ANTENNA ROTATOR");
  oled.setCursor (20,2);
  oled.set1X();
  oled.println("initialization");   
  delay(1000);
  //oled.clear();
  
  while (digitalRead(STEPPER1_LS_PIN) != 0) {
    stepper1.runSpeed();
  }
  
  
// Позиционирование анетнны "в нулевые координаты" по магнитным датчикам положения.
  stepper1.setCurrentPosition(0);
  stepper1.setSpeed(-STEPPER1_INIT_SPEED);
  while (abs(stepper1.currentPosition()) < 0) // ставим ноль и останавливается на нуле, либо числ на которое отклонится после срабатывания датчика 
  { 
   
    
    stepper1.runSpeed();
  } 
  stepper1.setCurrentPosition(0);
  stepper1.setSpeed(0);
  oled.clear();
  oled.setCursor (40,1);
  oled.set2X();
  oled.println("READY"); 

  pinMode(power1Pin, OUTPUT);
   pinMode(power2Pin, OUTPUT);
   float angle_x_tmp = 0;     
  Serial.begin(19200);
   
   Serial.println("++++++++++++++++++++++++++++++++++++++++++++++++++++");
   Serial.println("+    The Open Auto Tracking System is online !     +");
   Serial.println("+                   (WXtrack)                      +");
   Serial.println("+        Use 'XX YY' to control the antenna        +");
   Serial.println("+               XX is AZ, YY is EL                 +");
   Serial.println("+           Like this : 35.56 45.23                +");
   Serial.println("+          Send '0' or space to back home          +"); 
   Serial.println("+          Send 'W' to wakeup the antenna          +"); 
   Serial.println("+         Send 'S' to shutdown the antenna         +"); 
   Serial.println("+   Send 'X 52.4' will set 52.4 angle to AZ's 0    +");
   Serial.println("+   Send 'Y 30.6' will set 30.6 angle to EL's 0    +");
   Serial.println("+                 GOOD LUCK !!!                    +");
   Serial.println("+--------------------------------------------------+");
   Serial.println("+                  Version 2.0                     +");
   Serial.println("+--------------------------------------------------+");
   
}

void loop()                                          
{

//starttime = millis();   //Требуется время, чтобы вычислить программный цикл один раз

//Ниже приводится инициализация различных переменных.
char a[10]={0};
char b[10]={0};
char c[10]={0};
char d[10]={0};
char e[10]={0};
char f[10]={0};

String tmp_a = "";
String tmp_b = "";
String tmp_c = "";
String tmp_d = "";
String tmp_e = "";
String tmp_f = "";
String usbdata = "";


//Ниже приведены данные последовательного порта, строковые данные последовательного порта, передаваемые в переменную usbdata

   while (Serial.available() > 0) 
   {
    usbdata += char(Serial.read());
    delay(2);
   }                                                                    

//пример формата данных последовательного порта usb:
//Easycomm I данные режима COM порта таковы: (режим после регистрации)
//AZ84.46 EL19.41\#13
//UP0 DN12635455 UMFM-N DMFM-N AZ253.62 EL56.13 SNNOAA-18\#0\#13\#10
//AZ84.46 EL19.41\#13
//AZ:23.0,EL:56.0
//25.3 36.2


//Начинается автоматическое слежение.
 if ( usbdata.length() > 11 )
   {
      const char *usb=usbdata.c_str();    
      
  
      //Ниже приведен выбор протокола отслеживания в зависимости от использования изменений управляющего программного обеспечения

      sscanf(usb, "AZ%s EL%s\#13",&a, &b);                           //WXtrack Easycomm 
     // sscanf(usb, "AZ%s EL%s",&a, &b);                                 // WXtrack тоже работает
         
     
      
      //sscanf(usb, "AZ:%[^','],EL:%s",&a, &b);                      // split out AZ and EL yes---DDE client 
      //sscanf(usb, "UP0 DN%s UMFM-N DMFM-N AZ%s EL%s SNNOAA-%s\#0\#13\#10",&g,&a,&b,&h);    //no split  ---DDE client  
     
      
      tmp_a = a;                                                
      tmp_b = b;                                                 
                                          
      X = tmp_a.toFloat();                                            //Выполнить преобразование с плавающей запятой
      Y = tmp_b.toFloat();                                      
   
 
     
      
      if( X - angle_x_tmp > 359 && angle_x == 0 )                     //Определите,пересекает ли он от 0 до 359 градусов, чтобы не перевернуть азимутальный круг
         {
             angle_x = -1;
          } 
      else if( angle_x_tmp - X > 2 && angle_x == -1 )                 //Определить WXtrack команду парковки антенны при 0--> 359.x
         {
             angle_x = 0;      
          }
      else if( angle_x_tmp - X > 2 && angle_x == 1 )                  //Определить WXtracк парковки антенны при 359.x--> 0 
         {  
             angle_x = 0;
          }
      else if( X - angle_x_tmp < -359 && angle_x == 0 )               //Определите,пересекает ли он от 359 до 0 градусов, чтобы не перевернуть азимутальный круг
         {
             angle_x = 1;           
          }

      angle_x_tmp = X;                                               
      gotoangle_x = X;
      gotoangle_y = Y;
      _angle_1 = true;   
      _angle_2 = true;   

   //Отображает координаты на дисплее при передач их с WXtrack. В ручном режиме не отображает
  oled.setCursor (0,0); 
  oled.set2X();
  oled.println("AZ= ");
  oled.setCursor (45,0); 
  oled.set2X();
  oled.print(gotoangle_x);
  oled.setCursor (0,2);    
  oled.set2X();
  oled.println("EL= ");
  oled.setCursor (45,2); 
  oled.set2X();
  oled.print(gotoangle_y);  
        
   }
//Программа автоматически отслеживает конец кода
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  else if (usbdata.startsWith("W") && power == 0 && power_tmp == 1 )    //Определите,есть ли у антенны команда пробуждения " W”
  {     
      Serial.println("Antenna's power is ON, Now please wait 2 senconds !!");
      Serial.println("----------------------------------------------------"); 
      digitalWrite(power1Pin, HIGH);
      digitalWrite(power2Pin, HIGH);
      power = 1; 
      power_tmp = 0;
      delay(2000);
      Serial.println("AZ= 0.00");
      Serial.println("EL= 0.00");
      Serial.println("-----------");

  oled.clear();
  oled.setCursor (0,0); // set cursror row 5, line 0
  oled.set1X();
  oled.println("ANTENNA");
  oled.setCursor (0,2); // set cursror row 5, line 0
  oled.set2X();
  oled.println("POWER ON");   
   oled.clear();
 oled.setCursor (0,0); // set cursror row 5, line 0
  oled.set2X();
  oled.println("AZ= 0.00");
  oled.setCursor (0,2); // set cursror row 5, line 0
  oled.set2X();
  oled.println("EL= 0.00");   
   
 
  }
 else if ( usbdata.startsWith("U") && power == 0 && power_tmp == -1 )     //Определите, нужно ли разблокировать антенну командой " W”
  {     
      Serial.println("Antenna is UNLOACKED, Now please wait 2 senconds !!");
      Serial.println("---------------------------------------------------");
  oled.clear();
  oled.setCursor (0,0); // set cursror row 5, line 0
  oled.set1X();
  oled.println("ANTENNA");
  oled.setCursor (0,2); // set cursror row 5, line 0
  oled.set2X();
  oled.println("UNLOCKED");   
  

       
      digitalWrite(power1Pin, HIGH);
      //digitalWrite(power2Pin, HIGH);
      power = 1; 
      power_tmp = 0;
      delay(2000);
      Serial.println("OK !");
      Serial.println("-----------");
  oled.setCursor (80,0); // set cursror row 5, line 0
  oled.set1X();
  oled.println("OK !");
  

  }
 else if ( usbdata.startsWith("S") )   //Определить, является ли команда "остановить" антенна "S” 
  {
      power_tmp = 1; 
      gotoangle_x = 0;
      gotoangle_y = 0;
      _angle_1 = true;
      _angle_2 = true;
      angle_x = 0;  
  } 
 else if ( usbdata.startsWith("L") )   //Определите, есть ли команда блокировки антенны " L” 
  {
      power_tmp = -1;         
  } 
 else if ( usbdata.length() > 0 && power_tmp == 1 )
  {
         Serial.println("#############################################################"); 
         Serial.println("The antenna's power is OFF , Please send 'W' to wake him up !");
         Serial.println("#############################################################");
         
  oled.setCursor (0,0); 
  oled.set1X();
  oled.println("ANTENNA");
  oled.setCursor (0,2); 
  oled.set2X();
  oled.println("POWER OFF");   
  //oled.clear();    
 
          
  }  
 else if ( usbdata.length() > 0 && power_tmp == -1 )   
  {
         Serial.println("######################################################"); 
         Serial.println("The antenna is LOCKED , Please send 'U' to UNLOCK him !");
         Serial.println("######################################################"); 
  oled.clear();
  oled.setCursor (0,0); 
  oled.set1X();
  oled.println("ANTENNA");
  oled.setCursor (0,2); 
  oled.set2X();
  oled.println("LOCKED");       
  }
 
 else if ( usbdata.length() > 0 && power == 1 && power_tmp == 0 )
  {                                                              
    if ( usbdata.startsWith("X") )        //Определите, соответствует ли команда калибровки Азимута
      { 
      const char *usb=usbdata.c_str(); 
      sscanf(usb, "X%s",&e);
      tmp_e = e;
      N = tmp_e.toFloat()*AZFACTOR;
      stepper1.setCurrentPosition(N);
      _angle_1 = true;
      //_angle_2 = true;  
      }
    else if ( usbdata.startsWith("Y") )      //Определите, является ли команда калибровки высоты
      { 
      const char *usb=usbdata.c_str();
      sscanf(usb, "Y%s",&f);
      tmp_f = f;
      M = tmp_f.toFloat()*ELFACTOR;
      stepper2.setCurrentPosition(-M);
      //_angle_1 = true;
      _angle_2 = true;
      }
    //В противном случае осуществляется ручное управление.
    else                             
      {
      const char *usb=usbdata.c_str();        //Извлеките строковые данные из данных высот
      sscanf(usb, "%s %s",&c, &d);
      tmp_c = c;
      tmp_d = d;
      X = tmp_c.toFloat();
      Y = tmp_d.toFloat();
      if (X < 400 && X > -450)      // Тут регулируем диапазон допустимых значений по горизонтали
       {        
          gotoangle_x = X;
          Serial.print("AZ= ");
          Serial.println(X);
  // Отображает на дисплее при ручном вводе координат. Данные, идущие через порт - не отображаются       
  oled.clear();
  oled.setCursor (0,0); 
  oled.set2X();
  oled.println("AZ= ");
  oled.setCursor (45,0); 
  oled.set2X();
  oled.print(X);
  oled.setCursor (0,2);    
  oled.set2X();
  oled.println("EL= ");
  oled.setCursor (45,2); 
  oled.set2X();
  oled.print(Y);  


       }
      else
       {
          Serial.println("Wrong angle of AZ !");
  oled.clear(); 
  oled.setCursor (0,0); 
  oled.set2X();
  oled.println("AZ= Err");   
    
          
       }
      if (Y > -10 && Y < 100)     // Тут регулируем диапазон допустимых значений по высоте
       {
          gotoangle_y = Y;
          Serial.print("EL= ");
          Serial.println(Y);
         
       }
      else
       {
          Serial.println("Wrong angle of EL !");
  //oled.clear(); 
  oled.setCursor (0,2); 
  oled.set2X();
  oled.println("EL= Err"); 
          
       }
      Serial.println("-----------");
      angle_x = 0;      
      _angle_1 = true;
      _angle_2 = true;
     }
  }
                                        
//Преобразование угла поворота по азимуту

   if (_angle_1)     
     {
       if ( angle_x == -1 )         //Определяем, находится антенна  от 0 до 359.х градусов
        {       
        stepper1.moveTo((360+(-gotoangle_x)) * AZFACTOR);   
        }
       else if ( angle_x == 1 )         //Определите Азимут от 359.x Переход на 0 градусов
        {    
         stepper1.moveTo(((-gotoangle_x)-360) * AZFACTOR);          
        }
       else if ( angle_x == 0 )                      
        {       
        stepper1.moveTo((-gotoangle_x) * AZFACTOR);   
        }                                                 
     }
//Преобразование угла поворота высоты
   
   if (_angle_2)   
       stepper2.moveTo(gotoangle_y * ELFACTOR);   
       stepper1.run();
       stepper2.run();

         
  


if ( power_tmp == 1 )      //Выполните процедуру отключения питания антенны
  {
    //looptime = stoptime - starttime;
    accumulate += looptime;
           
    if( accumulate > 60000 )
        {
          digitalWrite(power1Pin, LOW);
          digitalWrite(power2Pin, LOW);
          Serial.println("Antenna's power is OFF!");
          Serial.println("#######################");
oled.clear();
  oled.setCursor (0,0); 
  oled.set1X();
  oled.println("ANTENNA");
  oled.setCursor (0,2); // 
  oled.set2X();
  oled.println("Power OFF!");   
          
          accumulate = 0;               //Сброс счетчика времени
          power = 0; 
        }
  }

if ( power_tmp == -1 && power == 1 )
  {     
      digitalWrite(power1Pin, LOW);
      Serial.println("Antenna is LOCKED!");
      Serial.println("##################");
      oled.clear();
  oled.setCursor (0,0); 
  oled.set1X();
  oled.println("ANTENNA");
  oled.setCursor (0,2); 
  oled.set2X();
  oled.println("is LOCKED!");   
      power = 0;


      
  }

if ( power_tmp == 0 && power == 0)
   {
      digitalWrite(power1Pin, HIGH);
      digitalWrite(power2Pin, HIGH);
      power = 1;  
      delay (2000);      
   }
}


 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Интересный выбор, почему не K3NG к примеру

По программе: для начала надо видимо попытаться оптимизировать использование ОЗУ!
PS не настоящий "сталевар", надеюсь настоящие поправят, если что не так сделал...
 

#include<AccelStepper.h>

#define ACCELERATION_1 500.0   //400                 //Параметры ускорения шагового двигателя AZ
#define ACCELERATION_2 500.0   // 400                   //Параметры ускорения шагового двигателя EL
#define MAXSPEED_1 700.0                         //Максимальная скорость шагового двигателя AZ
#define MAXSPEED_2 700.0                         //Максимальная скорость шагового двигателя EL

#define STEPPER1_STEP_PIN 5                       // stepper1 AZ
#define STEPPER1_DIR_PIN  6

#define STEPPER2_STEP_PIN 11                       //stepper2 EL 
#define STEPPER2_DIR_PIN 10


// установки для позиционирования антенны в ноль
#define STEPPER1_LS_PIN 2 // концевик горизонтального мотора AZ
#define STEPPER2_LS_PIN A7 // концевик вертикального мотора EL

// скорость вращения мотора при позиционировании в ноль
#define STEPPER1_INIT_SPEED 400.0
#define STEPPER2_INIT_SPEED 400.0

// Тут выставляем коэффициенты в в зависимости какой редуктор у  вас установлен
#define AZFACTOR 6.5                           //Коэффициент угла импульса AZ было 2.666 
#define ELFACTOR 6.5                          //Коэффициент угла импульса EL было 2.666      




//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "SSD1306Ascii.h"  // Oled library    <a href="https://github.com/greiman/SSD1306Ascii" title="https://github.com/greiman/SSD1306Ascii" rel="nofollow">https://github.com/greiman/SSD1306Ascii</a> 
#include "SSD1306AsciiAvrI2c.h"
#define RST_PIN -1
SSD1306AsciiAvrI2c oled;
#define I2C_ADDRESS 0x3C  //  (0x3C is the Oled I2C Address)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

int power;
int looptime = 1;
int angle_x   = 0;
int power1Pin = 4;
int power2Pin = 8;
int power_tmp = 0;                                 //0-это нормальное состояние, -1-заблокированное состояние,1-выключенное состояние

float X;
float Y;
float M;
float N;
float gotoangle_x;                                 //Шаговый двигатель для прохождения азимутального импульса
float gotoangle_y;                                 //Шаговый двигатель для перемещения импульса высоты
float angle_x_tmp = 0;                             //Параметр azimuth cache используется для определения разности углов AZ

String usbdata = "";                               //Определите пустую строку
boolean _angle_1 = false;                          //Логическое значение для определения того, соответствует ли Азимут требованиям
boolean _angle_2 = false;                          //Логическое значение для определения того, соответствует ли угол возвышения требованиям

unsigned long accumulate;                          //Функция накопления времени цикла


AccelStepper stepper1(AccelStepper::DRIVER, STEPPER1_STEP_PIN, STEPPER1_DIR_PIN);
AccelStepper stepper2(AccelStepper::DRIVER, STEPPER2_STEP_PIN, STEPPER2_DIR_PIN);



void setup() {
  pinMode(STEPPER1_DIR_PIN, OUTPUT);
  pinMode(STEPPER2_DIR_PIN, OUTPUT);
  pinMode(STEPPER1_STEP_PIN, OUTPUT);
  pinMode(STEPPER2_STEP_PIN, OUTPUT);

  pinMode(STEPPER1_LS_PIN, INPUT_PULLUP); // Концевик AZ
  pinMode(STEPPER2_LS_PIN, INPUT_PULLUP); // Концевик EL
  stepper1.setMaxSpeed(MAXSPEED_1);
  stepper2.setMaxSpeed(MAXSPEED_2);
  stepper1.setAcceleration(ACCELERATION_1);
  stepper2.setAcceleration(ACCELERATION_2);
  stepper1.setSpeed(0);
  stepper2.setSpeed(0);
  stepper1.setSpeed(STEPPER1_INIT_SPEED);

#if RST_PIN >= 0
  oled.begin(&Adafruit128x32, I2C_ADDRESS, RST_PIN);
#else
  oled.begin(&Adafruit128x32, I2C_ADDRESS);
#endif
  oled.setFont(Adafruit5x7);

  oled.setCursor (20, 0);
  oled.set1X();
  oled.println(F("ANTENNA ROTATOR"));
  oled.setCursor (20, 2);
  oled.set1X();
  oled.println(F("initialization"));
  delay(1000);
  //oled.clear();

  while (digitalRead(STEPPER1_LS_PIN) != 0) {
    stepper1.runSpeed();
  }


  // Позиционирование анетнны "в нулевые координаты" по магнитным датчикам положения.
  stepper1.setCurrentPosition(0);
  stepper1.setSpeed(-STEPPER1_INIT_SPEED);
  while (abs(stepper1.currentPosition()) < 0) // ставим ноль и останавливается на нуле, либо числ на которое отклонится после срабатывания датчика было 500
  {


    stepper1.runSpeed();
  }
  stepper1.setCurrentPosition(0);
  stepper1.setSpeed(0);
  oled.clear();
  oled.setCursor (40, 1);
  oled.set2X();
  oled.println("READY");

  pinMode(power1Pin, OUTPUT);
  pinMode(power2Pin, OUTPUT);
  float angle_x_tmp = 0;
  Serial.begin(19200);

  Serial.println(F("++++++++++++++++++++++++++++++++++++++++++++++++++++"));
  Serial.println(F("+    The Open Auto Tracking System is online !     +"));
  Serial.println(F("+                   (WXtrack)                      +"));
  Serial.println(F("+        Use 'XX YY' to control the antenna        +"));
  Serial.println(F("+               XX is AZ, YY is EL                 +"));
  Serial.println(F("+           Like this : 35.56 45.23                +"));
  Serial.println(F("+          Send '0' or space to back home          +"));
  Serial.println(F("+          Send 'W' to wakeup the antenna          +"));
  Serial.println(F("+         Send 'S' to shutdown the antenna         +"));
  Serial.println(F("+   Send 'X 52.4' will set 52.4 angle to AZ's 0    +"));
  Serial.println(F("+   Send 'Y 30.6' will set 30.6 angle to EL's 0    +"));
  Serial.println(F("+                 GOOD LUCK !!!                    +"));
  Serial.println(F("+--------------------------------------------------+"));
  Serial.println(F("+                  Version 2.0                     +"));
  Serial.println(F("+--------------------------------------------------+"));

}

void loop()
{

  //starttime = millis();   //Требуется время, чтобы вычислить программный цикл один раз

  //Ниже приводится инициализация различных переменных, не перемещайте позицию
  char a[10] = {0};
  char b[10] = {0};
  char c[10] = {0};
  char d[10] = {0};
  char e[10] = {0};
  char f[10] = {0};

  String tmp_a = "";
  String tmp_b = "";
  String tmp_c = "";
  String tmp_d = "";
  String tmp_e = "";
  String tmp_f = "";
  String usbdata = "";


  //Ниже приведены данные последовательного порта, строковые данные последовательного порта, передаваемые в переменную usbdata

  while (Serial.available() > 0)
  {
    usbdata += char(Serial.read());
    delay(2);
  }

  //пример формата данных последовательного порта usb:
  //Easycomm I данные режима COM порта таковы: (режим после регистрации)
  //AZ84.46 EL19.41\#13
  //UP0 DN12635455 UMFM-N DMFM-N AZ253.62 EL56.13 SNNOAA-18\#0\#13\#10
  //AZ84.46 EL19.41\#13
  //AZ:23.0,EL:56.0
  //25.3 36.2


  //Начинается автоматическое слежение.
  if ( usbdata.length() > 11 )
  {
    const char *usb = usbdata.c_str();  //Преобразование строковых данных в строковые данные


    //Ниже приведен выбор протокола отслеживания в зависимости от использования изменений управляющего программного обеспечения

    sscanf(usb, "AZ%s EL%s\#13", &a, &b);                          //WXtrack Easycomm
    // sscanf(usb, "AZ%s EL%s",&a, &b);                                 // WXtrack тоже работает



    //sscanf(usb, "AZ:%[^','],EL:%s",&a, &b);                      // split out AZ and EL yes---DDE client
    //sscanf(usb, "UP0 DN%s UMFM-N DMFM-N AZ%s EL%s SNNOAA-%s\#0\#13\#10",&g,&a,&b,&h);    //no split  ---DDE client


    tmp_a = a;
    tmp_b = b;

    X = tmp_a.toFloat();                                            //Выполнить преобразование с плавающей запятой
    Y = tmp_b.toFloat();




    if ( X - angle_x_tmp > 359 && angle_x == 0 )                    //Определите,пересекает ли он от 0 до 359 градусов, чтобы не перевернуть азимутальный круг
    {
      angle_x = -1;
    }
    else if ( angle_x_tmp - X > 2 && angle_x == -1 )                //Определить WXtrack приказ park antenna,0--> 359.x
    {
      angle_x = 0;
    }
    else if ( angle_x_tmp - X > 2 && angle_x == 1 )                 //Определить WXtrack的park antenna ,359.x--> 0
    {
      angle_x = 0;
    }
    else if ( X - angle_x_tmp < -359 && angle_x == 0 )              //Определите,пересекает ли он от 359 до 0 градусов, чтобы не перевернуть азимутальный круг
    {
      angle_x = 1;
    }

    angle_x_tmp = X;                                                //Переназначьте новое значение угла сравнения
    gotoangle_x = X;
    gotoangle_y = Y;
    _angle_1 = true;
    _angle_2 = true;

    //Отображает координаты на дисплее при передач их с WXtrack. В ручном режиме не отображает
    oled.setCursor (0, 0);
    oled.set2X();
    oled.println(F("AZ= "));
    oled.setCursor (45, 0);
    oled.set2X();
    oled.print(gotoangle_x);
    oled.setCursor (0, 2);
    oled.set2X();
    oled.println(F("EL= "));
    oled.setCursor (45, 2);
    oled.set2X();
    oled.print(gotoangle_y);

  }
  //Программа автоматически отслеживает конец кода
  ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  else if (usbdata.startsWith("W") && power == 0 && power_tmp == 1 )                                 //Определите,есть ли у антенны команда пробуждения " W”
  {
    Serial.println(F("Antenna's power is ON, Now please wait 2 senconds !!"));
    Serial.println(F("----------------------------------------------------"));
    digitalWrite(power1Pin, HIGH);
    digitalWrite(power2Pin, HIGH);
    power = 1;
    power_tmp = 0;
    delay(2000);
    Serial.println(F("AZ= 0.00"));
    Serial.println(F("EL= 0.00"));
    Serial.println(F("-----------"));

    oled.clear();
    oled.setCursor (0, 0); // set cursror row 5, line 0
    oled.set1X();
    oled.println(F("ANTENNA"));
    oled.setCursor (0, 2); // set cursror row 5, line 0
    oled.set2X();
    oled.println(F("POWER ON"));
    oled.clear();
    oled.setCursor (0, 0); // set cursror row 5, line 0
    oled.set2X();
    oled.println(F("AZ= 0.00"));
    oled.setCursor (0, 2); // set cursror row 5, line 0
    oled.set2X();
    oled.println(F("EL= 0.00"));


  }
  else if ( usbdata.startsWith("U") && power == 0 && power_tmp == -1 )     //Определите, нужно ли разблокировать антенну командой " W”
  {
    Serial.println(F("Antenna is UNLOACKED, Now please wait 2 senconds !!"));
    Serial.println(F("---------------------------------------------------"));
    oled.clear();
    oled.setCursor (0, 0); // set cursror row 5, line 0
    oled.set1X();
    oled.println(F("ANTENNA"));
    oled.setCursor (0, 2); // set cursror row 5, line 0
    oled.set2X();
    oled.println(F("UNLOCKED"));



    digitalWrite(power1Pin, HIGH);
    //digitalWrite(power2Pin, HIGH);
    power = 1;
    power_tmp = 0;
    delay(2000);
    Serial.println(F("OK !"));
    Serial.println(F("-----------"));
    oled.setCursor (80, 0); // set cursror row 5, line 0
    oled.set1X();
    oled.println(F("OK !"));


  }
  else if ( usbdata.startsWith("S") )        //Определить, является ли команда "остановить" антенна "S”
  {
    power_tmp = 1;
    gotoangle_x = 0;
    gotoangle_y = 0;
    _angle_1 = true;
    _angle_2 = true;
    angle_x = 0;
  }
  else if ( usbdata.startsWith("L") )      //Определите, есть ли команда блокировки антенны " L”
  {
    power_tmp = -1;
  }
  else if ( usbdata.length() > 0 && power_tmp == 1 )
  {
    Serial.println(F("#############################################################"));
    Serial.println(F("The antenna's power is OFF , Please send 'W' to wake him up !"));
    Serial.println(F("#############################################################"));

    oled.setCursor (0, 0);
    oled.set1X();
    oled.println(F("ANTENNA"));
    oled.setCursor (0, 2);
    oled.set2X();
    oled.println(F("POWER OFF"));
    //oled.clear();


  }
  else if ( usbdata.length() > 0 && power_tmp == -1 )
  {
    Serial.println(F("######################################################"));
    Serial.println(F("The antenna is LOCKED , Please send 'U' to UNLOCK him !"));
    Serial.println(F("######################################################"));
    oled.clear();
    oled.setCursor (0, 0);
    oled.set1X();
    oled.println(F("ANTENNA"));
    oled.setCursor (0, 2);
    oled.set2X();
    oled.println(F("LOCKED"));
  }

  else if ( usbdata.length() > 0 && power == 1 && power_tmp == 0 )
  {
    if ( usbdata.startsWith("X") )        //Определите, соответствует ли команда калибровки Азимута
    {
      const char *usb = usbdata.c_str();
      sscanf(usb, "X%s", &e);
      tmp_e = e;
      N = tmp_e.toFloat() * AZFACTOR;
      stepper1.setCurrentPosition(N);
      _angle_1 = true;
      //_angle_2 = true;
    }
    else if ( usbdata.startsWith("Y") )      //Определите, является ли команда калибровки высоты
    {
      const char *usb = usbdata.c_str();
      sscanf(usb, "Y%s", &f);
      tmp_f = f;
      M = tmp_f.toFloat() * ELFACTOR;
      stepper2.setCurrentPosition(-M);
      //_angle_1 = true;
      _angle_2 = true;
    }
    //В противном случае осуществляется ручное управление.
    else
    {
      const char *usb = usbdata.c_str();      //Извлеките строковые данные из данных высот
      sscanf(usb, "%s %s", &c, &d);
      tmp_c = c;
      tmp_d = d;
      X = tmp_c.toFloat();
      Y = tmp_d.toFloat();
      if (X < 400 && X > -450)      // Тут регулируем диапазон допустимых значений по горизонтали
      {
        gotoangle_x = X;
        Serial.print("AZ= ");
        Serial.println(X);
        // Отображает на дисплее при ручном вводе координат. Данные, идущие через порт - не отображаются20
        oled.clear();
        oled.setCursor (0, 0);
        oled.set2X();
        oled.println(F("AZ= "));
        oled.setCursor (45, 0);
        oled.set2X();
        oled.print(X);
        oled.setCursor (0, 2);
        oled.set2X();
        oled.println(F("EL= "));
        oled.setCursor (45, 2);
        oled.set2X();
        oled.print(Y);


      }
      else
      {
        Serial.println(F("Wrong angle of AZ !"));
        oled.clear();
        oled.setCursor (0, 0);
        oled.set2X();
        oled.println(F("AZ= Err"));


      }
      if (Y > -10 && Y < 100)     // Тут регулируем диапазон допустимых значений по высоте
      {
        gotoangle_y = Y;
        Serial.print(F("EL= "));
        Serial.println(Y);

      }
      else
      {
        Serial.println(F("Wrong angle of EL !"));
        //oled.clear();
        oled.setCursor (0, 2);
        oled.set2X();
        oled.println(F("EL= Err"));

      }
      Serial.println(F("-----------"));
      angle_x = 0;
      _angle_1 = true;
      _angle_2 = true;
    }
  }

  //Преобразование угла поворота по азимуту

  if (_angle_1)
  {
    if ( angle_x == -1 )                              //Определите, находится ли он от 0 до 359.х градусов
    {
      stepper1.moveTo((360 + (-gotoangle_x)) * AZFACTOR);
    }
    else if ( angle_x == 1 )                          //Определите Азимут от 359.x Переход на 0 градусов
    {
      stepper1.moveTo(((-gotoangle_x) - 360) * AZFACTOR);
    }
    else if ( angle_x == 0 )
    {
      stepper1.moveTo((-gotoangle_x) * AZFACTOR);
    }
  }
  //Преобразование угла поворота высоты

  if (_angle_2)
    stepper2.moveTo(gotoangle_y * ELFACTOR);
  stepper1.run();
  stepper2.run();





  if ( power_tmp == 1 )                //Выполните процедуру отключения питания антенны
  {
    //looptime = stoptime - starttime;
    accumulate += looptime;

    if ( accumulate > 60000 )
    {
      digitalWrite(power1Pin, LOW);
      digitalWrite(power2Pin, LOW);
      Serial.println(F("Antenna's power is OFF!"));
      Serial.println(F("#######################"));
      oled.clear();
      oled.setCursor (0, 0);
      oled.set1X();
      oled.println(F("ANTENNA"));
      oled.setCursor (0, 2); //
      oled.set2X();
      oled.println(F("Power OFF!"));

      accumulate = 0;               //Сброс счетчика времени
      power = 0;
    }
  }

  if ( power_tmp == -1 && power == 1 )
  {
    digitalWrite(power1Pin, LOW);
    Serial.println(F("Antenna is LOCKED!"));
    Serial.println(F("##################"));
    oled.clear();
    oled.setCursor (0, 0);
    oled.set1X();
    oled.println(F("ANTENNA"));
    oled.setCursor (0, 2);
    oled.set2X();
    oled.println(F("is LOCKED!"));
    power = 0;



  }

  if ( power_tmp == 0 && power == 0)
  {
    digitalWrite(power1Pin, HIGH);
    digitalWrite(power2Pin, HIGH);
    power = 1;
    delay (2000);
  }
}

 

Скетч использует 19718 байт (61%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 495 байт (24%) динамической памяти, оставляя 1553 байт для локальных 

 

KADAVR
Offline
Зарегистрирован: 21.10.2016

ua6em

Что-то не смог сразу разобраться с этим проектомм K3NG. а тут наткнулся на этот проект Китайца... а он как раз сделан на шаговых дигателях и с управлением под WXtrack  - попробовал, и сразу все заработало.

на счет памяти - львиную долю жрет  функционал OLED дисплея

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

KADAVR, а давайте вот так выложим - с номерами строк, а то ведь невозможно!

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

del

KADAVR
Offline
Зарегистрирован: 21.10.2016

Исправил

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

KADAVR пишет:

Исправил

больше 100 строк здесь принято сворачивать и, повтор внизу подчистить

проверь правленный мной код, работает?

KADAVR
Offline
Зарегистрирован: 21.10.2016

ua6em

больше 100 строк здесь принято сворачивать и, повтор внизу подчистить

свернул. Ваш правленный код работает на WXtrack. ORBITRON по прежнему не воспринимает формат.

странно, в пакетах  ORBITRON отсутсвут последние группы символы из  AZ255.7 EL1.0 UP0 DN0 

во всем остальном одинаковый формат же.

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

А в настройках wispdde Easycomm I выбираешь? Если да, обязано работать

KADAVR
Offline
Зарегистрирован: 21.10.2016

да, везеде это протокол ставлю.

только с orbocom идут данные вида: AZ255.7 EL1.0 

а с WXtrack  AZ255.7 EL1.0 UP0 DN0 

и почему-то для кода ардуино важны эти последние группы UP0 DN0. 

KADAVR
Offline
Зарегистрирован: 21.10.2016

у меня sniffer com-порта есть... я вижу все данные которые программы шлют... различие только в этих двух групп символов UP0 DN0. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вы пытаетесь ввесть величину, выделенную жирным 

KADAVR пишет:

AZ255.7 EL1.0 UP0 DN0

в переменную b, описанную в строке №148, а она туда не лезет! Замените в строке №148 число 10 на 20, скажем и проблема должна уйти.

KADAVR
Offline
Зарегистрирован: 21.10.2016

ЕвгенийП

Попробовал - не помогает..

да и у меня наоборот, с данными AZ255.7 EL1.0 UP0 DN0  - работает

AZ255.7 EL1.0 UP0 DN0 - нет

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

KADAVR пишет:

ЕвгенийП

Попробовал - не помогает..

да и у меня наоборот, с данными AZ255.7 EL1.0 UP0 DN0  - работает

AZ255.7 EL1.0 UP0 DN0 - нет

То, что наоборот - не удивляет - распашка памяти приводит к непредсказуемым эффектам - могут быть любые чудеса.

По любому этим символы в 10 байтов не лезут, просто посчитайте их пальцем. Это однозначная ошибка. Она не обсуждается, её надо исправлять. 

Тревожит другое. Если автор позволял себе такое, то что там ещё может быть :-(

KADAVR
Offline
Зарегистрирован: 21.10.2016

поправил на 20.

Я обратил внимание сейчас (через sniffer) что WXtrack "выплевывает свою строку с координатами сразу все символы

а ORBITRON  выдает "посимвольно"

у меня в строке 168 стоит задержка 2 мс - может из за этого.. не успевают данные пройти?

KADAVR
Offline
Зарегистрирован: 21.10.2016

да, точно, причина в этом. я сейчас в терминал передал  AZ255.7 EL1.0 - и ардуино их прочитала.   Видмо проблема в том, что арудино не успевает "подождать" все данные с orbitrona. 

Подскажите, где в коде можно увеличить сбор данных с порта ? в строке 168  так?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

а если дописать в usbdata при выходе из цикла (170 строка) код пробела?

А точнее - возврат каретки, перевод строки (x0D, x0A)

 usbdata += char(0x0D); usbdata += char(0x0A);

 

KADAVR
Offline
Зарегистрирован: 21.10.2016

ua6em

попробую сейчас

KADAVR
Offline
Зарегистрирован: 21.10.2016

Итого испытаний: 

со строкой usbdata += char(0x0D); usbdata += char(0x0A); - данные вощбще перестают приниматься обеими программами.

при установке в строке 168 значения в 10 мс - orbitron координаты принимает. Но ардуино работает не стабильно, при переключении на другой спутник - виснет. После "ресет" опять принимает координаты верно.  В чем может быть причина?

еще вопрос -  в строке 188. sscanf(usb, "AZ%s EL%s\#13", &a, &b);     что обозначает параметр #13 

 

KADAVR
Offline
Зарегистрирован: 21.10.2016

 

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

подозреваю, что это код возврата каретки, десятичное 13, шестнадцатеричное 0x0D... убери перевод строки дописываемый в строку

ты свой код пытаешь или что я привёл, если свой он не будет работать нормально, памяти мало

KADAVR
Offline
Зарегистрирован: 21.10.2016

Нет, ваш код.. но у меня Arduino mega 2560.  памяти хватает

 

Скетч использует 20688 байт (8%) памяти устройства. Всего доступно 253952 байт.
Глобальные переменные используют 495 байт (6%) динамической памяти, оставляя 7697 байт для локальных переменных. Максимум: 8192 байт.
 
ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Попробуй оставить только это:
 

while (Serial.available() > 0)
  {
    usbdata += char(Serial.read());
    delay(2);
  }
usbdata += char(0x0D);

В этой конструкции, как мне кажется, во вторую переменную вычитывается строка до символа возврата каретки
sscanf(usb, "AZ%s EL%s\#13",&a, &b);

Знающие поправят...

Можно проверить - отправлять с терминала на контроллер с различным завершающим управляющим символом и смотреть, на что срабатывает, есть подозрение, что WISPDDE шлёт строку с завершающим нулём, тогда его надо заменить на возврат каретки...

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Слушайте, а чего Вы мучаетесь, да выбросьте эту sscanf(usb, "AZ%s EL%s\#13",&a, &b); к чёртовой матери и поставьте нормальное чтение плавающих значений. И работать будет везде и память программы сэкономите.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ЕвгенийП пишет:

Слушайте, а чего Вы мучаетесь, да выбросьте эту sscanf(usb, "AZ%s EL%s\#13",&a, &b); к чёртовой матери и поставьте нормальное чтение плавающих значений. И работать будет везде и память программы сэкономите.

я не мучаюсь, я наслаждаюсь )))
ЗЫ чесслово с разбором строк не сталкивался пока что

MaksVV
Offline
Зарегистрирован: 06.08.2015
#define BUF_SIZE 40       // размер буфера парсилки
char currStr[BUF_SIZE+3]; // буфер парсилки  

const char AZ[] = "AZ";
const char EL[] = "EL";

float  azimut    = 0;
float  elevation = 0;

//------------------------функция чтения информации из UART
void UART_read()
{
  if (!Serial.available()) return; // если данных нет игнорируем эту функцию
  char currSymb[2] = {0};          // символьный кэш
  currSymb[0] = Serial.read();     // читаем очередной символ
  static bool stringEnd = 0;       // флаг переполнения буфера

 if (currSymb[0] == '\r' || stringEnd == 1)   // если полностью получили строку - парсим:
 {
  char *sTr; 
if ((sTr =strstr(currStr, AZ))>0) {azimut    = atof(sTr+strlen(AZ));}
if ((sTr =strstr(currStr, EL))>0) {elevation = atof(sTr+strlen(EL));}

 Serial.println(azimut);
 Serial.println(elevation);
 
 currStr[0] = 0; stringEnd = 0; // в конце парсинга нулим буфер
 } 

// если не конец строки, то прибавляем очередной байт к буферу : 
else if ( currSymb[0] != '\n')  strcat (currStr,currSymb); 
// если буфер закончился , то режем строку на этом месте: 
     if (strlen(currStr)>=BUF_SIZE) {stringEnd = 1;}

}
//--------------------------------

void setup() 
{
 Serial.begin(19200);
}

void loop() 
{
UART_read(); // функция чтения из UART
// тут остальной код
}

 

KADAVR
Offline
Зарегистрирован: 21.10.2016

попробовал все варианты. проблему нашел, она действительно была в строке №148 - установил значение 20

и в строке №168 - там установил 10 мс (вместо2)  

целый день тестировал на обеих программах - все работает и не глючит.

Всем спасибо за подсказки, они мне помогли.

выкладываю рабочий код, может кому понадобится для поворотки.  использовать лучше MEGA2560

// 18.02.2021 Работает и с WXtrack и с ORBITRON
// для стабильности ардуино ставил конденсатор на 2 мкф межуд GND и RESET (после заливки кода)
#include<AccelStepper.h>

#define ACCELERATION_1 500.0   //400                 //Параметры ускорения шагового двигателя AZ
#define ACCELERATION_2 500.0   // 400                   //Параметры ускорения шагового двигателя EL
#define MAXSPEED_1 700.0                         //Максимальная скорость шагового двигателя AZ
#define MAXSPEED_2 700.0                         //Максимальная скорость шагового двигателя EL

#define STEPPER1_STEP_PIN 5                       // stepper1 AZ
#define STEPPER1_DIR_PIN  6
                       
#define STEPPER2_STEP_PIN 11                       //stepper2 EL 
#define STEPPER2_DIR_PIN 10 
                  

// установки для позиционирования антенны в ноль
#define STEPPER1_LS_PIN 2 // концевик горизонтального мотора AZ
#define STEPPER2_LS_PIN A7 // концевик вертикального мотора EL

// скорость вращения мотора при позиционировании в ноль
#define STEPPER1_INIT_SPEED 400.0 
#define STEPPER2_INIT_SPEED 400.0 

// Тут выставляем коэффициенты в в зависимости какой редуктор у  вас установлен
#define AZFACTOR 6.5                           //Коэффициент угла импульса AZ было 2.666 
#define ELFACTOR 6.5                          //Коэффициент угла импульса EL было 2.666      




//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "SSD1306Ascii.h"  
#include "SSD1306AsciiAvrI2c.h"
#define RST_PIN -1
SSD1306AsciiAvrI2c oled;
#define I2C_ADDRESS 0x3C  //  (0x3C is the Oled I2C Address)
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

int power;
int looptime = 1;
int angle_x   = 0;    
int power1Pin = 4;
int power2Pin = 8;
int power_tmp = 0;                                 //0-это нормальное состояние, -1-заблокированное состояние,1-выключенное состояние

float X;
float Y;
float M;
float N;
float gotoangle_x;                                 //переменная для AZ координат
float gotoangle_y;                                 //переменная для EL координат
float angle_x_tmp = 0;                             //Параметр azimuth cache используется для определения разности углов AZ

String usbdata = "";                               //Определяем пустую строку
boolean _angle_1 = false;                          //Логическое значение для определения того, соответствует ли AZ требованиям
boolean _angle_2 = false;                          //Логическое значение для определения того, соответствует ли угол EL требованиям

unsigned long accumulate;                          //Функция накопления времени цикла


AccelStepper stepper1(AccelStepper::DRIVER, STEPPER1_STEP_PIN, STEPPER1_DIR_PIN);
AccelStepper stepper2(AccelStepper::DRIVER, STEPPER2_STEP_PIN, STEPPER2_DIR_PIN);



void setup() {                
  pinMode(STEPPER1_DIR_PIN, OUTPUT);
  pinMode(STEPPER2_DIR_PIN, OUTPUT);
  pinMode(STEPPER1_STEP_PIN, OUTPUT);
  pinMode(STEPPER2_STEP_PIN, OUTPUT);
 
  pinMode(STEPPER1_LS_PIN, INPUT_PULLUP); // Концевик AZ
  pinMode(STEPPER2_LS_PIN, INPUT_PULLUP); // Концевик EL
  stepper1.setMaxSpeed(MAXSPEED_1);
  stepper2.setMaxSpeed(MAXSPEED_2);
  stepper1.setAcceleration(ACCELERATION_1); 
  stepper2.setAcceleration(ACCELERATION_2); 
  stepper1.setSpeed(0);
  stepper2.setSpeed(0);
  stepper1.setSpeed(STEPPER1_INIT_SPEED);

#if RST_PIN >= 0
  oled.begin(&Adafruit128x32, I2C_ADDRESS, RST_PIN);
  #else
  oled.begin(&Adafruit128x32, I2C_ADDRESS);
  #endif 
  oled.setFont(Adafruit5x7);

  oled.setCursor (20,0); 
  oled.set2X();
  oled.println("WAITING");
  oled.setCursor (29,2);
  oled.set1X();
  oled.println("COORDINATES");   
 // delay(1000);

 //++++++++++++++++++ КОД ПОЗИЦИОНИРОВАНИЯ в НОЛЬ КООРДИНАТ ++++++++++++++
   // расскомментировать, если нужно позиционирование моторов в нулевые координаты.
           
//while (digitalRead(STEPPER1_LS_PIN) != 0) 
  //{
    //stepper1.runSpeed();
  //}
  //stepper1.setCurrentPosition(0);
  //stepper1.setSpeed(-STEPPER1_INIT_SPEED);
  //while (abs(stepper1.currentPosition()) < 0) // ставим ноль и останавливается на нуле, либо числ на которое отклонится после срабатывания датчика было 500
  //{ 
    // stepper1.runSpeed();
  //} 
  //stepper1.setCurrentPosition(0);
  //stepper1.setSpeed(0);
  //oled.clear();
  //oled.setCursor (40,1);
  //oled.set2X();
  //oled.println("READY"); 

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
  pinMode(power1Pin, OUTPUT);
   pinMode(power2Pin, OUTPUT);
   float angle_x_tmp = 0;     
  Serial.begin(9600);
   
  Serial.println(F("++++++++++++++++++++++++++++++++++++++++++++++++++++"));
  Serial.println(F("+    The Open Auto Tracking System is online !     +"));
  Serial.println(F("+                   (WXtrack)                      +"));
  Serial.println(F("+        Use 'XX YY' to control the antenna        +"));
  Serial.println(F("+               XX is AZ, YY is EL                 +"));
  Serial.println(F("+           Like this : 35.56 45.23                +"));
  Serial.println(F("+          Send '0' or space to back home          +"));
  Serial.println(F("+          Send 'W' to wakeup the antenna          +"));
  Serial.println(F("+         Send 'S' to shutdown the antenna         +"));
  Serial.println(F("+   Send 'X 52.4' will set 52.4 angle to AZ's 0    +"));
  Serial.println(F("+   Send 'Y 30.6' will set 30.6 angle to EL's 0    +"));
  Serial.println(F("+                 GOOD LUCK !!!                    +"));
  Serial.println(F("+--------------------------------------------------+"));
  Serial.println(F("+                  Version 2.0                     +"));
  Serial.println(F("+--------------------------------------------------+"));
   
}

void loop()                                          
{

//starttime = millis();   //Требуется время, чтобы вычислить программный цикл один раз

//Ниже приводится инициализация различных переменных.
char a[20]={0}; 
char b[20]={0};  
char c[10]={0};
char d[10]={0};
char e[10]={0};
char f[10]={0};

String tmp_a = "";
String tmp_b = "";
String tmp_c = "";
String tmp_d = "";
String tmp_e = "";
String tmp_f = "";
String usbdata = "";


//Ниже приведены данные последовательного порта, строковые данные последовательного порта, передаваемые в переменную usbdata

   while (Serial.available() > 0) 
   {
    usbdata += char(Serial.read());
    
    delay(10); // было 2, но ORBITRON не успевает передать вой пакет с координатами.
   }                                                                    

//пример формата данных последовательного порта usb:
//Easycomm I данные режима COM порта таковы:
//AZ84.46 EL19.41\#13
//UP0 DN12635455 UMFM-N DMFM-N AZ253.62 EL56.13 SNNOAA-18\#0\#13\#10
//AZ84.46 EL19.41\#13
//AZ:23.0,EL:56.0
//25.3 36.2

 
//Начинается автоматическое слежение.
 if ( usbdata.length() > 11 )
   {
     
      const char *usb=usbdata.c_str();    
      
  
      //Ниже приведен выбор протокола отслеживания в зависимости от использования изменений управляющего программного обеспечения

      sscanf(usb, "AZ%s EL%s\#13",&a, &b);                           //WXtrack Easycomm 
     //sscanf(usb, "AZ%s EL%s",&a, &b);                                 // WXtrack тоже работает
         
     
      
      //sscanf(usb, "AZ:%[^','],EL:%s",&a, &b);                      // split out AZ and EL yes---DDE client 
      //sscanf(usb, "UP0 DN%s UMFM-N DMFM-N AZ%s EL%s SNNOAA-%s\#0\#13\#10",&g,&a,&b,&h);    //no split  ---DDE client  
     
      
      tmp_a = a;                                                
      tmp_b = b;                                                 
                                          
      X = tmp_a.toFloat();                                            //Выполнить преобразование с плавающей запятой
      Y = tmp_b.toFloat();                                      
   
 
     
      
      if( X - angle_x_tmp > 359 && angle_x == 0 )                     //Определите,пересекает ли он от 0 до 359 градусов, чтобы не перевернуть азимутальный круг
         {
             angle_x = -1;
          } 
      else if( angle_x_tmp - X > 2 && angle_x == -1 )                 //Определить WXtrack команду парковки антенны при 0--> 359.x
         {
             angle_x = 0;      
          }
      else if( angle_x_tmp - X > 2 && angle_x == 1 )                  //Определить WXtracк парковки антенны при 359.x--> 0 
         {  
             angle_x = 0;
          }
      else if( X - angle_x_tmp < -359 && angle_x == 0 )               //Определите,пересекает ли он от 359 до 0 градусов, чтобы не перевернуть азимутальный круг
         {
             angle_x = 1;           
          }

      angle_x_tmp = X;                                               
      gotoangle_x = X;
      gotoangle_y = Y;
      _angle_1 = true;   
      _angle_2 = true;   

   //Отображает координаты на дисплее при передач их с WXtrack или ORBITRON. При ручном вводе координат в COM - не отображает.
  oled.setCursor (0,0); 
  oled.set2X();
  oled.println("AZ= ");
  oled.setCursor (45,0); 
  oled.set2X();
  oled.print(gotoangle_x);
  oled.setCursor (0,2);    
  oled.set2X();
  oled.println("EL= ");
  oled.setCursor (45,2); 
  oled.set2X();
  oled.print(gotoangle_y);  
        
   }
//Программа автоматически отслеживает конец кода
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
  else if (usbdata.startsWith("W") && power == 0 && power_tmp == 1 )    //Определите,есть ли у антенны команда пробуждения " W”
  {     
      Serial.println(F("Antenna's power is ON, Now please wait 2 senconds !!"));
      Serial.println(F("----------------------------------------------------")); 
      digitalWrite(power1Pin, HIGH);
      digitalWrite(power2Pin, HIGH);
      power = 1; 
      power_tmp = 0;
      delay(2000);
      Serial.println(F("AZ= 0.00"));
      Serial.println(F("EL= 0.00"));
      Serial.println(F("-----------"));

  oled.clear();
  oled.setCursor (0,0); // set cursror row 5, line 0
  oled.set1X();
  oled.println("ANTENNA");
  oled.setCursor (0,2); // set cursror row 5, line 0
  oled.set2X();
  oled.println("POWER ON");   
   oled.clear();
 oled.setCursor (0,0); // set cursror row 5, line 0
  oled.set2X();
  oled.println("AZ= 0.00");
  oled.setCursor (0,2); // set cursror row 5, line 0
  oled.set2X();
  oled.println("EL= 0.00");   
   
 
  }
 else if ( usbdata.startsWith("U") && power == 0 && power_tmp == -1 )     //Определите, нужно ли разблокировать антенну командой " W”
  {     
      Serial.println(F("Antenna is UNLOACKED, Now please wait 2 senconds !!"));
      Serial.println(F("---------------------------------------------------"));
  oled.clear();
  oled.setCursor (0,0); // set cursror row 5, line 0
  oled.set1X();
  oled.println("ANTENNA");
  oled.setCursor (0,2); // set cursror row 5, line 0
  oled.set2X();
  oled.println("UNLOCKED");   
  

       
      digitalWrite(power1Pin, HIGH);
      power = 1; 
      power_tmp = 0;
      delay(2000);
      Serial.println(F("OK !"));
      Serial.println(F("-----------"));
  oled.setCursor (80,0); // set cursror row 5, line 0
  oled.set1X();
  oled.println("OK !");
  

  }
 else if ( usbdata.startsWith("S") )   //Определить, является ли команда "остановить" антенна "S” 
  {
      power_tmp = 1; 
      gotoangle_x = 0;
      gotoangle_y = 0;
      _angle_1 = true;
      _angle_2 = true;
      angle_x = 0;  
  } 
 else if ( usbdata.startsWith("L") )   //Определите, есть ли команда блокировки антенны " L” 
  {
      power_tmp = -1;         
  } 
 else if ( usbdata.length() > 0 && power_tmp == 1 )
  {
    Serial.println(F("#############################################################"));
    Serial.println(F("The antenna's power is OFF , Please send 'W' to wake him up !"));
    Serial.println(F("#############################################################"));
         
  oled.setCursor (0,0); 
  oled.set1X();
  oled.println("ANTENNA");
  oled.setCursor (0,2); 
  oled.set2X();
  oled.println("POWER OFF");   
      
 
          
  }  
 else if ( usbdata.length() > 0 && power_tmp == -1 )   
  {
    Serial.println(F("######################################################"));
    Serial.println(F("The antenna is LOCKED , Please send 'U' to UNLOCK him !"));
    Serial.println(F("######################################################")); 
  oled.clear();
  oled.setCursor (0,0); 
  oled.set1X();
  oled.println("ANTENNA");
  oled.setCursor (0,2); 
  oled.set2X();
  oled.println("LOCKED");       
  }
 
 else if ( usbdata.length() > 0 && power == 1 && power_tmp == 0 )
  {                                                              
    if ( usbdata.startsWith("X") )        //Определите, соответствует ли команда калибровки Азимута
      { 
      const char *usb=usbdata.c_str(); 
      sscanf(usb, "X%s",&e);
      tmp_e = e;
      N = tmp_e.toFloat()*AZFACTOR;
      stepper1.setCurrentPosition(N);
      _angle_1 = true;
      //_angle_2 = true;  
      }
    else if ( usbdata.startsWith("Y") )      //Определите, является ли команда калибровки высоты
      { 
      const char *usb=usbdata.c_str();
      sscanf(usb, "Y%s",&f);
      tmp_f = f;
      M = tmp_f.toFloat()*ELFACTOR;
      stepper2.setCurrentPosition(-M);
      //_angle_1 = true;
      _angle_2 = true;
      }
    //В противном случае осуществляется ручное управление.
    else                             
      {
      const char *usb=usbdata.c_str();        //Извлеките строковые данные из данных высот
      sscanf(usb, "%s %s",&c, &d);
      tmp_c = c;
      tmp_d = d;
      X = tmp_c.toFloat();
      Y = tmp_d.toFloat();
      if (X < 400 && X > -450)      // Тут регулируем диапазон допустимых значений по горизонтали
       {        
          gotoangle_x = X;
          Serial.print("AZ= ");
          Serial.println(X);
  // Отображает на дисплее при ручном вводе координат. Данные, идущие через порт - не отображаются       
  oled.clear();
  oled.setCursor (0,0); 
  oled.set2X();
  oled.println("AZ= ");
  oled.setCursor (45,0); 
  oled.set2X();
  oled.print(X);
  oled.setCursor (0,2);    
  oled.set2X();
  oled.println("EL= ");
  oled.setCursor (45,2); 
  oled.set2X();
  oled.print(Y);  


       }
      else
       {
          Serial.println(F("Wrong angle of AZ !"));
  oled.clear(); 
  oled.setCursor (0,0); 
  oled.set2X();
  oled.println("AZ= Err");   
    
          
       }
      if (Y > -10 && Y < 100)     // Тут регулируем диапазон допустимых значений по высоте
       {
          gotoangle_y = Y;
          Serial.print("EL= ");
          Serial.println(Y);
         
       }
      else
       {
          Serial.println(F("Wrong angle of EL !"));
  
  oled.setCursor (0,2); 
  oled.set2X();
  oled.println("EL= Err"); 
          
       }
      Serial.println(F("-----------"));
      angle_x = 0;      
      _angle_1 = true;
      _angle_2 = true;
     }
  }
                                        
//Преобразование угла поворота по азимуту

   if (_angle_1)     
     {
       if ( angle_x == -1 )         //Определяем, находится антенна  от 0 до 359.х градусов
        {       
        stepper1.moveTo((360+(-gotoangle_x)) * AZFACTOR);   
        }
       else if ( angle_x == 1 )         //Определите Азимут от 359.x Переход на 0 градусов
        {    
         stepper1.moveTo(((-gotoangle_x)-360) * AZFACTOR);          
        }
       else if ( angle_x == 0 )                      
        {       
        stepper1.moveTo((-gotoangle_x) * AZFACTOR);   
        }                                                 
     }
//Преобразование угла поворота высоты
   
   if (_angle_2)   
       stepper2.moveTo(gotoangle_y * ELFACTOR);   
       stepper1.run();
       stepper2.run();

         
  


if ( power_tmp == 1 )      //Выполните процедуру отключения питания антенны
  {
    //looptime = stoptime - starttime;
    accumulate += looptime;
           
    if( accumulate > 60000 )
        {
          digitalWrite(power1Pin, LOW);
          digitalWrite(power2Pin, LOW);
          Serial.println(F("Antenna's power is OFF!"));
          Serial.println(F("#######################"));
oled.clear();
  oled.setCursor (0,0); 
  oled.set1X();
  oled.println("ANTENNA");
  oled.setCursor (0,2); // 
  oled.set2X();
  oled.println("Power OFF!");   
          
          accumulate = 0;               //Сброс счетчика времени
          power = 0; 
        }
  }

if ( power_tmp == -1 && power == 1 )
  {     
      digitalWrite(power1Pin, LOW);
      Serial.println(F("Antenna is LOCKED!"));
      Serial.println(F("##################"));
      oled.clear();
  oled.setCursor (0,0); 
  oled.set1X();
  oled.println("ANTENNA");
  oled.setCursor (0,2); 
  oled.set2X();
  oled.println("is LOCKED!");   
      power = 0;


      
  }

if ( power_tmp == 0 && power == 0)
   {
      digitalWrite(power1Pin, HIGH);
      digitalWrite(power2Pin, HIGH);
      power = 1;  
      delay (2000);      
   }
}

 

 

KADAVR
Offline
Зарегистрирован: 21.10.2016

MaksVV

Спасибо Вам за код, попробую сегодня с вашим вариантом. Спасибо

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Видимо проблема всё же в WISPDDE, уж больно стара )))

KADAVR
Offline
Зарегистрирован: 21.10.2016

Вот как выглядит моя повортка, сделана на основе "световой головы" которые испльзуются в клубах для светомузыки.

там механика очень добротно сделана. Потроха пришлось все выкинуть, оставил только шаговые моторы

на фото только основание, без пластмассовых лицевых панелек.

общий вид

тут нижняя часть привода по горизонтали

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Зачёт!