Согласующее устройство (LC) на ARDUINO

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Используя наработки DF7XH / R. Buese решил немного переписать его скетч. Просьба следующий пост не комментировать. Код будет дополняться.

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Просьба не цитировать!!! Код будет дополняться.

Версия от 29.09.2020 - тестируйте
немного причесал, добавлена заготовка под интерфейс ICOM, библиотека пишется,
под YAESU на гитхабе
 

/*****************************************************************************/

#define SERIAL_ON       // Serial ON  if "//" Serial OFF
#define LCD_I2C
//#define DEBUG
#define YAESU
//#define ICOM

/**********************Arduino Pin Definition************************/

// PWM (Enable) output pin for L motor
#define  pwm_L 11
// Direction Up (I1) output pin for L motor
#define up_L 13
// Direction Down (I2) output pin for L motor
#define down_L 12
// PWM (Enable) output pin for C motor
#define pwm_C 10
// Direction Up (I1) output pin for C motor
#define up_C 8
// Direction Down (I2) output pin for C motor
#define down_C 9
// Analog input pin L motor position
#define ana_pin_L 1
// Analog input pin C motor position
#define ana_pin_C 0
// Analog input pin for band selection switch
#define ana_band 2
// Analog input pin for band selection switch
#define ana_band2 6
// Analog input pin for fine tuning C motor PB switch
#define ana_pin_fine_tune_C 3
// Discrete input pin for fine tuning L motor PB switch
#define pin_fine_tune_L_up 7
// Discrete input pin for fine tuning L motor PB switch
#define pin_fine_tune_L_dwn 6

/* LCD circuit
 * LCD RS pin to digital pin 0
 * LCD Enable pin to digital pin 1
 * LCD D4 pin to digital pin 5
 * LCD D5 pin to digital pin 4
 * LCD D6 pin to digital pin 3
 * LCD D7 pin to digital pin 2
 * LCD R/W pin to ground
 * 10K resistor:
 * ends to +5V and ground
 * wiper to LCD VO pin (pin 3)*/

/**********************Arduino Constant Definition*******************/

// Thresholds for C / L motor control
#define LOW_SPEED_THRES 20   // Low speed threshold
//#define LOW_SPEED_THRES 10   // Low speed threshold
#define TARGET_THRES_L 0     // Target positioning threshold
#define TARGET_THRES_C 0     // Target positioning threshold

// Commanded positions for L motor depending on band
#define POSN_CMD_L_160 640 // Commanded position L motor for 160m band
#define POSN_CMD_L_80 640  // Commanded position L motor for 80m band
#define POSN_CMD_L_40 640  // Commanded position L motor for 40m band
#define POSN_CMD_L_30 640  // Commanded position L motor for 30m band
#define POSN_CMD_L_20 184  // Commanded position L motor for 20m band
#define POSN_CMD_L_17 972  // Commanded position L motor for 17m band
#define POSN_CMD_L_15 373  // Commanded position L motor for 15m band
#define POSN_CMD_L_12 180  // Commanded position L motor for 12m band
#define POSN_CMD_L_10 160  // Commanded position L motor for 10m band

// Commanded positions for C motor depending on band
#define POSN_CMD_C_160 180 // Commanded position C motor for 160m band
#define POSN_CMD_C_80 180  // Commanded position C motor for 80m band
#define POSN_CMD_C_40 180  // Commanded position C motor for 40m band
#define POSN_CMD_C_30 180  // Commanded position C motor for 30m band
#define POSN_CMD_C_20 582  // Commanded position C motor for 20m band
#define POSN_CMD_C_17 361  // Commanded position C motor for 17m band
#define POSN_CMD_C_15 247  // Commanded position C motor for 15m band
#define POSN_CMD_C_12 277  // Commanded position C motor for 12m band
#define POSN_CMD_C_10 384  // Commanded position C motor for 10m band

#define RELE_160 0 // Rele (0 - OFF, 1 - ON) for 160m band
#define RELE_80 0  // Rele (0 - OFF, 1 - ON) for 80m band
#define RELE_40 0  // Rele (0 - OFF, 1 - ON) for 40m band
#define RELE_30 0  // Rele (0 - OFF, 1 - ON) for 30m band
#define RELE_20 1  // Rele (0 - OFF, 1 - ON) for 20m band
#define RELE_17 1  // Rele (0 - OFF, 1 - ON) for 17m band
#define RELE_15 1  // Rele (0 - OFF, 1 - ON) for 15m band
#define RELE_12 1  // Rele (0 - OFF, 1 - ON) for 12m band
#define RELE_10 1  // Rele (0 - OFF, 1 - ON) for 10m band

// PWM settings
// PWM 0 == Duty Cycle = 0%  255 == Duty Cycle = 100%
#define PWM_CMD_HIGH_SPEED_L 190 // ~75% duty cycle for high speed operation
#define PWM_CMD_LOW_SPEED_L  90  // ~30% duty cycle for low speed operation
#define PWM_CMD_HIGH_SPEED_C 190 // ~75% duty cycle for high speed operation
#define PWM_CMD_LOW_SPEED_C  90  // ~30% duty cycle for low speed operation

// Defines the number of loops before the LCD display will be updated
#define DISPLAY_LOOP_COUNTER_MAX 6

// EEPROM Pause 
#define PAUSE_EEPROM 100

// первичная инициализация EEPROM без нажатия клавиши по проверяемому флагу
uint8_t a73=88;  // для проверки первичной инициализации смените это значение на любое до 250
int eeprom_flag = 0;
int rom_flag = 0;
int eeprom_band = 20;
int rom_band = 2;
byte flag_band = 0;
uint8_t cycle = 8;
uint8_t  relay = 6;
uint8_t rele = 0;
uint8_t  button_relay = 7;     // кнопка реле
uint8_t  flag_button = 0;
volatile unsigned long r_millis = 0;
uint16_t recycle = 100;

/**********************Arduino Libraries*****************************/
#ifdef YAESU
#include <SoftwareSerial.h>
#include "FT897D.h"   
FT897D radio;  
volatile unsigned long myfreq = 0; 
volatile unsigned long cat_millis = 0; 
unsigned int cat_band = 0;
#define CATPIN 5
#endif

#ifdef ICOM
#include <SoftwareSerial.h>
#include "ICOM.h"   
ICOM radio;  
volatile unsigned long myfreq = 0; 
volatile unsigned long cat_millis = 0; 
unsigned int cat_band = 0;
#define CATPIN 5
#endif


// Include the library code:
#include <EEPROM.h>

#ifdef LCD_I2C
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3F, 20, 4); // A0,A1,A2 -HIGH
/*
 * A0 A1 A2 PCF8574A
 * 0  0  0  - 0x38
 * 1  0  0  - 0x39
 * 0  1  0  - 0x3A
 * 1  1  0  - 0x3B
 * 0  0  1  - 0x3C
 * 1  0  1  - 0x3D
 * 0  1  1  - 0x3E
 * 1  1  1  - 0x3F 
 * 
 */
#else
#include <LiquidCrystal.h>
// Initialize the library with the numbers of the interface pins
LiquidCrystal lcd(0, 1, 5, 4, 3, 2);
#endif

/**********************Variable Declaration***************************/

int posn_cmd_L = 0;
int posn_cmd_C = 0;

boolean in_motion_L = false;
boolean in_motion_C = false;

boolean power_up = true;

int posn_L = 0;          // Input position (0..1000) i.e. (0..5V)  for L motor
int posn_L_0 = 0;        // Past values of input position
int posn_L_1 = 0;
int posn_L_2 = 0;
int posn_L_3 = 0;
int posn_L_4 = 0;
int posn_L_5 = 0;
int posn_L_6 = 0;

int posn_C = 0;          // Input position (0..1000) i.e. (0..5V)  for C motor
int posn_C_0 = 0;        // Past values of input position
int posn_C_1 = 0;
int posn_C_2 = 0;
int posn_C_3 = 0;
int posn_C_4 = 0;
int posn_C_5 = 0;
int posn_C_6 = 0;

int posn_diff_L = 0;
int posn_diff_C = 0;

int band = 0;
int band_0 = 0;        // Past values of band selection switch
int band_1 = 0;
int band_2 = 0;
int band_3 = 0;
int band_4 = 0;

int band2 = 0;
int band2_0 = 0;        // Past values of band selection switch
int band2_1 = 0;
int band2_2 = 0;
int band2_3 = 0;
int band2_4 = 0;

unsigned int band_sel = 0;
unsigned int band_sel_old = 0;

int fine_tune_C = 512;
int fine_tune_C_0 = 512;        // Past values of band selection switch
int fine_tune_C_1 = 512;
int fine_tune_C_2 = 512;
int fine_tune_C_3 = 512;
int fine_tune_C_4 = 512;

int display_loop_counter = DISPLAY_LOOP_COUNTER_MAX;

/***************** FUNCTION ******************/

void setRelay(){
  if (flag_button == 1 && digitalRead(button_relay) == 1){ // кнопка отжата
      delay(20);
      flag_button = 0;
  }
  if (flag_button == 0 && digitalRead(button_relay) == 0){ // кнопка нажата
      delay(20);
      flag_button = 1;
      digitalWrite(relay,!digitalRead(relay));
      //rele = digitalRead(relay);
  }
}

void setaRelay(){
  if (flag_button == 1 && millis()-r_millis >=200 && ((band <855) || (band > 890))){ // кнопка отжата
      delay(20);
      flag_button = 0;
  }
}


/**********************Arduino SETUP*********************************/

void setup()
{
  pinMode(pwm_L, OUTPUT);
  pinMode(up_L, OUTPUT);
  pinMode(down_L, OUTPUT);

  pinMode(pwm_C, OUTPUT);
  pinMode(up_C, OUTPUT);
  pinMode(down_C, OUTPUT);

  //pinMode(pin_fine_tune_L_up, INPUT_PULLUP); // Discrete input pin for fine tuning L motor PB switch
  pinMode(pin_fine_tune_L_dwn, OUTPUT); // Discrete input pin for fine tuning L motor PB switch

  #ifdef SERIAL_ON
  // Output on serial monitor
  // Open the serial port at 9600 bps:
  Serial.begin(9600);
  #endif  
  
  // Set up the LCD's number of columns and rows:
#ifdef LCD_I2C
 lcd.begin();
 #else
 lcd.begin(16, 2);
#endif

  // Initialization EEPROM
  for (uint8_t i = 0; i < 50; i ++) {
    fine_tune_C_0 = analogRead(ana_pin_fine_tune_C);

    fine_tune_C   = (fine_tune_C_0 + fine_tune_C_1 + fine_tune_C_2 + fine_tune_C_3 + fine_tune_C_4)/5;
    fine_tune_C_4 = fine_tune_C_3;
    fine_tune_C_3 = fine_tune_C_2;
    fine_tune_C_2 = fine_tune_C_1;
    fine_tune_C_1 = fine_tune_C_0;
  }

  if ((fine_tune_C >= 740 && fine_tune_C < 810 && fine_tune_C_1 >= 740 && fine_tune_C_1 < 810) || EEPROM.get(rom_flag,eeprom_flag)!=a73) {
    eeprom_flag = a73 ;
    delay(PAUSE_EEPROM);
    EEPROM.put(rom_flag,eeprom_flag);
    delay(PAUSE_EEPROM);
    EEPROM.put(rom_band,eeprom_band);   // Первично выбранный диапазон (20м)
 
    lcd.setCursor(0, 0);
    lcd.print("Init EEPROM");
    delay(PAUSE_EEPROM);
    EEPROM.put(10, POSN_CMD_L_10);
    EEPROM.put(110, POSN_CMD_C_10);
    EEPROM.put(210, RELE_10);
    lcd.print('.');
    delay(PAUSE_EEPROM);
    EEPROM.put(12, POSN_CMD_L_12);
    EEPROM.put(112, POSN_CMD_C_12);
    EEPROM.put(212, RELE_12);
    lcd.print('.');
    delay(PAUSE_EEPROM);
    EEPROM.put(15, POSN_CMD_L_15);
    EEPROM.put(115, POSN_CMD_C_15);
    EEPROM.put(215, RELE_15);
    lcd.print('.');
    delay(PAUSE_EEPROM);
    EEPROM.put(17, POSN_CMD_L_17);
    EEPROM.put(117, POSN_CMD_C_17);
    EEPROM.put(217, RELE_17);
    lcd.print('.');
    delay(PAUSE_EEPROM);
    EEPROM.put(20, POSN_CMD_L_20);
    EEPROM.put(120, POSN_CMD_C_20);
    EEPROM.put(220, RELE_20);
    lcd.print('.');
    delay(PAUSE_EEPROM);
    EEPROM.put(30, POSN_CMD_L_30);
    EEPROM.put(130, POSN_CMD_C_30);
    EEPROM.put(230, RELE_30);
    lcd.setCursor(0, 1);
    lcd.print('.');
    delay(PAUSE_EEPROM);
    EEPROM.put(40, POSN_CMD_L_40);
    EEPROM.put(140, POSN_CMD_C_40);
    EEPROM.put(240, RELE_40);
    lcd.print('.');
    delay(PAUSE_EEPROM);
    EEPROM.put(80, POSN_CMD_L_80);
    EEPROM.put(180, POSN_CMD_C_80);
    EEPROM.put(280, RELE_80);
    lcd.print('.');
    delay(PAUSE_EEPROM);
    EEPROM.put(160, POSN_CMD_L_160);
    EEPROM.put(260, POSN_CMD_C_160);
    EEPROM.put(360, RELE_160);
    lcd.print('.');
    delay(PAUSE_EEPROM);
    lcd.print(" OK");
    delay(2000);
    lcd.clear();
  }

  // Display intro
  lcd.setCursor(0, 0);
  lcd.print(" Tuner  Control ");
  lcd.setCursor(0, 1);
  lcd.print("v.26 2020  UA6EM");

  delay(3000);

  lcd.clear();
  
#ifdef YAESU
radio.begin(4800);
cat_millis = millis();
pinMode(CATPIN,INPUT_PULLUP);  // пин потом перенести в дефайны
#endif

#ifdef ICOM
radio.begin(9600);
cat_millis = millis();
pinMode(CATPIN,INPUT_PULLUP);  // пин потом перенести в дефайны
#endif

} //END SETUP

/**********************Arduino LOOP**********************************/

void loop()
{
#ifdef YAESU
//if(millis() - cat_millis >= recycle){
//Serial.print("FREQ = ");
//Serial.println(radio.getFreqMode());
/* *
    Radio CAT port GND -> Arduino GND
    Radio CAT port TX  -> Arduino pin 3
    Radio CAT port RX  -> Arduino pin 2
/* */
cat_millis = millis();
//}
#endif

#ifdef ICOM
//if(millis() - cat_millis >= recycle){
//Serial.print("FREQ = ");
//Serial.println(radio.getFreqMode());
/* *
    Radio CAT port GND -> Arduino GND
    Radio CAT port TX  -> Arduino pin 3
    Radio CAT port RX  -> Arduino pin 2
/* */
cat_millis = millis();
//}
#endif
  
  uint8_t y=0;
  do{
  band_0 = analogRead(ana_band); // Read position band selection switch
  band2_0 = analogRead(ana_band2); // Read position band selection switch

  if (power_up == true)
  {
   band_4 = band_0;
   band_3 = band_0;
   band_2 = band_0;
   band_1 = band_0;
   band2_4 = band_0;
   band2_3 = band_0;
   band2_2 = band_0;
   band2_1 = band_0;
  }

  // Band sensor filter
  band = (band_0 + band_1 + band_2 + band_3+ band_4)/5;
  band_4 = band_3;
  band_3 = band_2;
  band_2 = band_1;
  band_1 = band_0;
  band2 = (band2_0 + band2_1 + band2_2 + band2_3+ band2_4)/5;
  band2_4 = band2_3;
  band2_3 = band2_2;
  band2_2 = band2_1;
  band2_1 = band2_0;
  y++;
  } while(y < cycle);
  y = 0;

  if (((band >= 35) && (band < 70)) && ((band_1 >= 35) && (band_1 < 70)))   // 10m band selected
  {
   band_sel = 10;
   EEPROM.update(rom_band,band_sel); 
   flag_band = 1;
  } else
  if (((band >= 75) && (band < 110)) && ((band_1 >= 75) && (band_1 < 110)))   // 12m band selected    
   {
     band_sel = 12;
      EEPROM.put(rom_band,band_sel); 
       flag_band = 1;
    } else
       if (((band >= 115) && (band < 150)) && ((band_1 >= 115) && (band_1 < 150)))  // 15m band selected      
        {
       band_sel = 15;
        EEPROM.put(rom_band,band_sel); 
         flag_band = 1;
      } else
       if (((band >= 180) && (band < 220)) && ((band_1 >= 180) && (band_1 < 220)))   // 17m band selected
        {
         band_sel = 17;
          EEPROM.put(rom_band,band_sel); 
           flag_band = 1;
        } else
        if (((band >= 290) && (band < 330)) && ((band_1 >= 290) && (band_1 < 330)))    // 20m band selected
           {
           band_sel = 20;
            EEPROM.put(rom_band,band_sel); 
             flag_band = 1;
          } else
          if (((band >= 390) && (band < 450)) && ((band_1 >= 390) && (band_1 < 450)))    // 30m band selected
             {
             band_sel = 30;
              EEPROM.put(rom_band,band_sel); 
               flag_band = 1;
            } else
            if (((band >= 530) && (band < 580)) && ((band_1 >= 530) && (band_1 < 580)))    // 40m band selected
               {
               band_sel = 40;
               EEPROM.put(rom_band,band_sel); 
               flag_band = 1;
              } else
              if (((band >= 675) && (band < 720)) && ((band_1 >= 675) && (band_1 < 720)))    // 80m band selected
                 {
                 band_sel = 80;
                 EEPROM.put(rom_band,band_sel); 
                 flag_band = 1;
                } else
                if (((band >= 770) && (band < 810)) && ((band_1 >= 770) && (band_1 < 810)))    // 160m band selected
                   {
                   band_sel = 160;
                   EEPROM.put(rom_band,band_sel); 
                   flag_band = 1;
                 } else
                   if (((band >= 855) && (band < 900)) && (flag_button == 0) &&((band_1 >= 855) && (band_1 < 900)))    //  RELE is ON 
                    {
                    digitalWrite(relay,!digitalRead(relay));
                    r_millis = millis();
                    flag_button = 1;                    
                    } else
                      if (((band >= 900) && (band < 946)) && ((band_1 >= 900) && (band_1 < 946)))   // Save Memory EEPROM
                      {
                        /* */
                 lcd.setCursor(10, 1);
                 lcd.print("M+");
                 EEPROM.put(band_sel, posn_L);
                 delay(PAUSE_EEPROM);
                 EEPROM.put((band_sel + 100), posn_C); 
                 delay(PAUSE_EEPROM);
                 EEPROM.update(rom_band,band_sel);
                 delay(PAUSE_EEPROM);
                 EEPROM.get(band_sel, posn_cmd_L);
                 EEPROM.get((band_sel + 100), posn_cmd_C);
                 rele = digitalRead(relay);
                 EEPROM.put((band_sel + 200), rele);     
                 delay(2000);
                 lcd.setCursor(10, 1);
                 lcd.print("  ");
                 /* */
                 }else
                  if (((band >= 946) && (band < 1023)) && ((band_1 >= 946) && (band_1 < 1023)))   // STOP
                      {
                        // для функции стоп
                      }

  setaRelay();   // обработать кнопку реле
  rele = digitalRead(relay);

  if (band_sel == 0)
  {
     EEPROM.get(rom_band,band_sel); 
     EEPROM.get(band_sel, posn_cmd_L);
     EEPROM.get((band_sel + 100), posn_cmd_C);
     EEPROM.get((band_sel + 200), rele);
     digitalWrite(pin_fine_tune_L_dwn, rele);
     power_up = false;
  }
   if (band_sel != 0 && flag_band) {
   flag_band = 0; 
   EEPROM.get(band_sel, posn_cmd_L);
   EEPROM.get((band_sel + 100), posn_cmd_C);
   EEPROM.get((band_sel + 200), rele);
   digitalWrite(pin_fine_tune_L_dwn, rele);
   }
   
  if ((band_sel != band_sel_old) && (power_up == false))
  {
    in_motion_L = true;
    in_motion_C = true;
  }
  

  band_sel_old = band_sel;
  power_up = false;

  uint8_t x = 0;
  do{ 
  posn_L_0 = analogRead(ana_pin_L); // Read position L motor

  // Map position sensor value to 0...1000
  posn_L_0 = map(posn_L_0, 0, 1023, 0, 1000);

  // Position sensor filter
  posn_L = (posn_L_0 + posn_L_1 + posn_L_2 + posn_L_3 + posn_L_4 + posn_L_5 + posn_L_6)/7;
  posn_L_6 = posn_L_5;
  posn_L_5 = posn_L_4;
  posn_L_4 = posn_L_3;
  posn_L_3 = posn_L_2;
  posn_L_2 = posn_L_1;
  posn_L_1 = posn_L_0;
  x++;
  } while(x<cycle);
  x=0;

  // Caution C Poti rotates only 1/2 turn, i.e. max. voltage is 4.5V. This related to 5V results in a factor 1.112
  // Removed the value for recalculating the rotation of the capacitor. For R2ARR modification.
  do {
  posn_C_0 = /* 1.11 * */analogRead(ana_pin_C); // Read position C motor

  // Map position sensor value to 0...1000
  posn_C_0 = map(posn_C_0, 0, 1023, 0, 1000);

  // Position sensor filter
  posn_C = (posn_C_0 + posn_C_1 + posn_C_2 + posn_C_3 + posn_C_4 + posn_C_5 + posn_C_6)/7;
  posn_C_6 = posn_C_5;
  posn_C_5 = posn_C_4;
  posn_C_4 = posn_C_3;
  posn_C_3 = posn_C_2;
  posn_C_2 = posn_C_1;
  posn_C_1 = posn_C_0;
  x++;
  } while(x<cycle);
  x=0;

  // Compute position difference between current position and command
  posn_diff_L = posn_cmd_L - posn_L;
  posn_diff_C = posn_cmd_C - posn_C;

  // Motion for C motor and L motor requested (motion of C motor has priority over motion of L motor) or
  // Motion only for C motor requested
  if (((in_motion_C == true) && (in_motion_L == true)) || ((in_motion_C == true) && (in_motion_L == false)))
  {
   // Reset direction and PWM output of L motor (for safety)
   digitalWrite(up_L, LOW);
   digitalWrite(down_L, LOW);
   analogWrite(pwm_L, 0);

   // Control motion of C motor depending on C motor position
   if (posn_diff_C > LOW_SPEED_THRES)
   {
      digitalWrite(up_C, HIGH); // Set direction of C motor to Up
      digitalWrite(down_C, LOW);
      analogWrite(pwm_C, PWM_CMD_HIGH_SPEED_C);  // Set PWM output to High speed
      lcd.setCursor(10, 1);
      lcd.print(">>");
   }
   if (posn_diff_C < -LOW_SPEED_THRES)
   {
      digitalWrite(up_C, LOW); // Set direction of C motor to Down
      digitalWrite(down_C, HIGH);
      analogWrite(pwm_C, PWM_CMD_HIGH_SPEED_C);  // Set PWM output to High speed
      lcd.setCursor(10, 1);
      lcd.print("<<");
   }
   if ((posn_diff_C <= LOW_SPEED_THRES) && (posn_diff_C > TARGET_THRES_C))
   {
      digitalWrite(up_C, HIGH); // Set direction of C motor to Up
      digitalWrite(down_C, LOW);
      analogWrite(pwm_C, PWM_CMD_LOW_SPEED_C);  // Set PWM output to Low speed
      lcd.setCursor(10, 1);
      lcd.print("> ");
   }
   if ((posn_diff_C >= -LOW_SPEED_THRES) && (posn_diff_C < -TARGET_THRES_C))
   {
      digitalWrite(up_C, LOW); // Set direction of C motor to Down
      digitalWrite(down_C, HIGH);
      analogWrite(pwm_C, PWM_CMD_LOW_SPEED_C);  // Set PWM output to Low speed
      lcd.setCursor(10, 1);
      lcd.print("< ");
   }
   if ((posn_diff_C <= TARGET_THRES_C) && (posn_diff_C >= -TARGET_THRES_C))
   {
      digitalWrite(up_C, LOW); // Reset direction of C motor
      digitalWrite(down_C, LOW);
      analogWrite(pwm_C, 0);  // Reset PWM output
      lcd.setCursor(10, 1);
      lcd.print("  ");
      in_motion_C = false;
   }
  }
  else
    // Motion only for L motor requested
    if ((in_motion_C == false) && (in_motion_L == true))
    {
     // Reset direction and PWM output of C motor (for safety)
     digitalWrite(up_C, LOW);
     digitalWrite(down_C, LOW);
     analogWrite(pwm_C, 0);

     // Control motion of L motor depending on L motor position
     if (posn_diff_L > LOW_SPEED_THRES)
     {
        digitalWrite(up_L, HIGH); // Set direction of L motor to Up
        digitalWrite(down_L, LOW);
        analogWrite(pwm_L, PWM_CMD_HIGH_SPEED_L);  // Set PWM output to High speed
        lcd.setCursor(4, 1);
        lcd.print(">>");
     }
     if (posn_diff_L < -LOW_SPEED_THRES)
     {
        digitalWrite(up_L, LOW); // Set direction of L motor to Down
        digitalWrite(down_L, HIGH);
        analogWrite(pwm_L, PWM_CMD_HIGH_SPEED_L);  // Set PWM output to High speed
        lcd.setCursor(4, 1);
        lcd.print("<<");
     }
     if ((posn_diff_L <= LOW_SPEED_THRES) && (posn_diff_L > TARGET_THRES_L))
     {
        digitalWrite(up_L, HIGH); // Set direction of L motor to Up
        digitalWrite(down_L, LOW);
        analogWrite(pwm_L, PWM_CMD_LOW_SPEED_L);  // Set PWM output to Low speed
        lcd.setCursor(4, 1);
        lcd.print(" >");
     }
     if ((posn_diff_L >= -LOW_SPEED_THRES) && (posn_diff_L < -TARGET_THRES_L))
     {
        digitalWrite(up_L, LOW); // Set direction of L motor to Down
        digitalWrite(down_L, HIGH);
        analogWrite(pwm_L, PWM_CMD_LOW_SPEED_L);  // Set PWM output to Low speed
        lcd.setCursor(4, 1);
        lcd.print(" <");
     }
     if ((posn_diff_L <= TARGET_THRES_L) && (posn_diff_L >= -TARGET_THRES_L))
     {
        digitalWrite(up_L, LOW); // Reset direction of L motor
        digitalWrite(down_L, LOW);
        analogWrite(pwm_L, 0);  // Reset PWM output
        lcd.setCursor(4, 1);
        lcd.print("  ");
        in_motion_L = false;
     }
    }
    else
      // No motion requested
      {
       // Reset direction and PWM output of L motor (for safety)
       digitalWrite(up_L, LOW);
       digitalWrite(down_L, LOW);
       analogWrite(pwm_L, 0);

       // Reset direction and PWM output of C motor (for safety)
       digitalWrite(up_C, LOW);
       digitalWrite(down_C, LOW);
       analogWrite(pwm_C, 0);

      // Fine tune is allowed only, neither C motor nor L motor motion is requested
       do{
       fine_tune_C_0 = analogRead(ana_pin_fine_tune_C); // Read position of fine tuning C motor PB switch
        
       // Fine tuning C motor PB switch filter
       fine_tune_C = (fine_tune_C_0 + fine_tune_C_1 + fine_tune_C_2 + fine_tune_C_3+ fine_tune_C_4)/5;
       fine_tune_C_4 = fine_tune_C_3;
       fine_tune_C_3 = fine_tune_C_2;
       fine_tune_C_2 = fine_tune_C_1;
       fine_tune_C_1 = fine_tune_C_0;
       x++;
       } while (x < cycle);
       x = 0;

       if (((fine_tune_C >= 0) && (fine_tune_C < 250)) && ((fine_tune_C_1 >= 0) && (fine_tune_C_1 < 250)))   // Fine tuning C motor PB switch commands the C motor to Up
       {
        digitalWrite(up_C, HIGH); // Set direction of C motor to Up
        digitalWrite(down_C, LOW);
        analogWrite(pwm_C, PWM_CMD_HIGH_SPEED_C);  // Set PWM output to High speed
        lcd.setCursor(11, 1);
        lcd.print(">");

        delay(100);  // Allow C motor to move (fine tune)

        digitalWrite(up_C, LOW); // Reset direction of C motor
        digitalWrite(down_C, LOW);
        analogWrite(pwm_C, 0);  // Reset PWM output
        lcd.setCursor(11, 1);
        lcd.print(" ");

       } else
         if (((fine_tune_C >= 251) && (fine_tune_C < 416)) && ((fine_tune_C_1 >= 251) && (fine_tune_C_1 < 416)))    // Fine tuning C motor PB switch commands the C motor to Down
         {
          digitalWrite(up_C, LOW); // Set direction of C motor to Down
          digitalWrite(down_C, HIGH);
          analogWrite(pwm_C, PWM_CMD_HIGH_SPEED_C);  // Set PWM output to High speed
          lcd.setCursor(11, 1);
          lcd.print("<");

          delay(100);  // Allow C motor to move (fine tune)

          digitalWrite(up_C, LOW); // Reset direction of C motor
          digitalWrite(down_C, LOW);
          analogWrite(pwm_C, 0);  // Reset PWM output
          lcd.setCursor(11, 1);
          lcd.print(" ");

         } else
           if (((fine_tune_C >= 416) && (fine_tune_C < 603)) && ((fine_tune_C_1 >= 416) && (fine_tune_C_1 < 603)))    // Fine tuning L motor PB switch commands the L motor to Up
           {
            digitalWrite(up_L, HIGH); // Set direction of L motor to Up
            digitalWrite(down_L, LOW);
            analogWrite(pwm_L, PWM_CMD_HIGH_SPEED_L);  // Set PWM output to High speed
            lcd.setCursor(4, 1);
            lcd.print(">");

            delay(200);  // Allow L motor to move (fine tune)

            digitalWrite(up_L, LOW); // Reset direction of L motor
            digitalWrite(down_L, LOW);
            analogWrite(pwm_L, 0);  // Reset PWM output
            lcd.setCursor(4, 1);
            lcd.print(" ");          
           } else
             if (((fine_tune_C >= 603) && (fine_tune_C < 740)) && ((fine_tune_C_1 >= 603) && (fine_tune_C_1 < 740)))    // Fine tuning L motor PB switch commands the L motor to Dwn
             {
              digitalWrite(up_L, LOW); // Set direction of L motor to Down
              digitalWrite(down_L, HIGH);
              analogWrite(pwm_L, PWM_CMD_HIGH_SPEED_L);  // Set PWM output to High speed
              lcd.setCursor(4, 1);
              lcd.print("<");

              delay(200);  // Allow L motor to move (fine tune)

              digitalWrite(up_L, LOW); // Reset direction of L motor
              digitalWrite(down_L, LOW);
              analogWrite(pwm_L, 0);  // Reset PWM output
              lcd.setCursor(4, 1);
              lcd.print(" ");
              
             } else
               if (((fine_tune_C >= 740) && (fine_tune_C < 810)) && ((fine_tune_C_1 >= 740) && (fine_tune_C_1 < 810)))    // Save EEPROM
               {
                lcd.setCursor(10, 1);
                lcd.print("M+");
                EEPROM.put(band_sel, posn_L);
                EEPROM.put((band_sel + 100), posn_C);
                EEPROM.put((band_sel + 200), rele);
                delay(2000);
                lcd.setCursor(10, 1);
                lcd.print("  ");
                 }
      }

  delay(30);

  #ifdef SERIAL_ON
  // Output on serial monitor

  Serial.print(band_sel);
  Serial.print("m");
  Serial.print(" aL=");
  Serial.print(posn_L);
  Serial.print(" cmdL=");
  Serial.print(posn_cmd_L);
  Serial.print(" aC=");
  Serial.print(posn_C);
  Serial.print(" cmdC=");
  Serial.println(posn_cmd_C);
  #endif

  if (display_loop_counter >= DISPLAY_LOOP_COUNTER_MAX)
  {

  // Print a fixed message to the LCD.
  // lcd.setCursor(8, 0);
  // lcd.print("m");

  // set the cursor to column 6, line 0
  lcd.setCursor(6, 0);
  lcd.print("    ");
  lcd.setCursor(6, 0);
  // print band_sel
  lcd.print(band_sel);
  lcd.print("m");
  
  // Clear specific column, line on LCD.
  lcd.setCursor(3, 0);
  lcd.print(" ");

  // set the cursor to column 0, line 0
  lcd.setCursor(0, 0);
  // clear
  lcd.print("    ");
  // re-position cursor
  lcd.setCursor(0, 0);
  // print posn_cmd_L
  lcd.print(posn_cmd_L);

  // set the cursor to column 0, line 1
  lcd.setCursor(0, 1);
  // clear
  lcd.print("    ");
  // re-position cursor
  lcd.setCursor(0, 1);
  // print posn_L
  lcd.print(posn_L);

  // set the cursor to column 12, line 0
  lcd.setCursor(12, 0);
  // clear
  lcd.print("    ");
  // re-position cursor
  lcd.setCursor(12, 0);
  // print posn_cmd_C
  lcd.print(posn_cmd_C);

  // set the cursor to column 12, line 1
  lcd.setCursor(12, 1);
  // clear
  lcd.print("    ");
  // re-position cursor
  lcd.setCursor(12, 1);
  // print posn_C
  lcd.print(posn_C);

 // set the cursor to column 7, line 1
  lcd.setCursor(7, 1);
  if (rele)
    // print Rele ON
    lcd.print('R');
  else
    // clear
    lcd.print(' ');

  display_loop_counter = 0;
  } else
  {
    display_loop_counter ++;
  }
  
// ******* Обработчик САТ интерфейса YAESU *******
#ifdef YAESU
if(!digitalRead(CATPIN)){
    myfreq = radio.getFreqMode();
     myfreq = myfreq/100000;
     if(myfreq==1){
     cat_band = 160;
     } else
       if(myfreq==3){
       cat_band = 80;  
       } else
         if(myfreq==7){
         cat_band = 40;  
         } else
           if(myfreq==10){
           cat_band = 30;  
           } else
             if(myfreq==14){
             cat_band = 20;  
             } else
               if(myfreq==18){
               cat_band = 17;  
               } else
                 if(myfreq==21){
                 cat_band = 15;  
                 } else
                   if(myfreq==24){
                   cat_band = 12;  
                   } else
                     if(myfreq >= 28){
                     cat_band = 10;  
                     } 

if(cat_band != band_sel){
//   Здесь принятие решения кому отдать первенство, САТ или кнопкам
  }
 }
#endif 

// ******* Обработчик САТ интерфейса ICOM *******
#ifdef ICOM
if(!digitalRead(CATPIN)){
    myfreq = radio.getFreqMode();
     myfreq = myfreq/100000;
     if(myfreq==1){
     cat_band = 160;
     } else
       if(myfreq==3){
       cat_band = 80;  
       } else
         if(myfreq==7){
         cat_band = 40;  
         } else
           if(myfreq==10){
           cat_band = 30;  
           } else
             if(myfreq==14){
             cat_band = 20;  
             } else
               if(myfreq==18){
               cat_band = 17;  
               } else
                 if(myfreq==21){
                 cat_band = 15;  
                 } else
                   if(myfreq==24){
                   cat_band = 12;  
                   } else
                     if(myfreq >= 28){
                     cat_band = 10;  
                     } 

if(cat_band != band_sel){
//   Здесь принятие решения кому отдать первенство, САТ или кнопкам
  }
 }
#endif 
}

/**********************Arduino Functions*****************************/



/************************End****************************************/  

 

 

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

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

А можно букв побольше? Это вообще про что? Что с кем согласовывается? Если можно, например, согласовать смету нтп в минфине, там я, пожалуй, повторю конструкцию - пригодится.

нет, по смете это не ко мне. Вчера открыл тему, смотрю минут через 10 снесли, сегодня чудным образом появилась, жизнь здесь всё чудесатее и чудесатее )))
Любое радиопередающее устройство с нагрузкой, то бишь антенной при перестройки по частоте требует согласования - компенсации реактивной составляющей сия чудная программа, надеюсь она будет реализована, для этого и предназначена. Девайс управляет двумя двигателями, один управляет индуктивностью колебательного контура, другой ёмкостью, в оригнинале выход передающего устройства симметричный, нагрузка - антенна типа диполь - тоже, здесь же скетч будет управлять устройствами с несиметричными выходом и входом, хотя по сути своей автоматике ведь без разницы.

Оригинальная схема устройства:

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Так как некоторые логические перлы в оригинале кода у меня вызывают некоторые замешательства, публикую, авось знающие люди подскажут, что автор сказать хотел?
 

if (((in_motion_C == true) && (in_motion_L == true)) || ((in_motion_C == true) && (in_motion_L == false)))
  {
   // Reset direction and PWM output of L motor (for safety)
   digitalWrite(up_L, LOW);
   digitalWrite(down_L, LOW);
   analogWrite(pwm_L, 0);

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Только то, что он выразил в условиях

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Правильно ли составлены условия - решать не нам, а аффтару. :-)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

По Фортрану угадывая - int. Неизвесно какой размерности. :-)

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

DetSimen пишет:

По Фортрану угадывая - int. Неизвесно какой размерности. :-)

я их не менял, оригинал кода буду использовать по максимуму, в посте #1 приведены, но можно и повторить

boolean in_motion_L = false;
boolean in_motion_C = false;

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Ну, не угадал. Бывает. 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Мда ТС забыл указать источник из которого это все накопал.

-NMi-
Offline
Зарегистрирован: 20.08.2018

ua6em пишет:

Так как некоторые логические перлы в оригинале кода у меня вызывают некоторые замешательства, публикую, авось знающие люди подскажут, что автор сказать хотел?
 

if (((in_motion_C == true) && (in_motion_L == true)) || ((in_motion_C == true) && (in_motion_L == false)))
  {
   // Reset direction and PWM output of L motor (for safety)
   digitalWrite(up_L, LOW);
   digitalWrite(down_L, LOW);
   analogWrite(pwm_L, 0);

 

Странный ты малый, вроде позывной есть, да вот толку от него маловасто.

Здеся аффтор кота правиряит ЕСЛИ маторчик-С и маторчик-L крутяццо или только маторчик-С крутиццо ->> тагды выключам к херам маторчик-L вместе с PWM, (написано-же for safety в пириводе - шоп нинаипнулсо) ачо уж он там PWM-ит - этт ты униво спраси.

И вообще, советую посмотреть как работает любой антенный тюнер у аппаратов класса аля 300+т.р. (да, да, не удивляйтесь ценам, есть и по миллиону "игрушки") и понять, какой логикой он руководствуется. Скажу сразу - будет "сложновасто" с первого раза.

Araris
Offline
Зарегистрирован: 09.11.2012

ua6em пишет:

Вчера открыл тему, смотрю минут через 10 снесли, сегодня чудным образом появилась, жизнь здесь всё чудесатее и чудесатее )))

Не снесли, а перенесли из "Проектов".

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Araris пишет:

ua6em пишет:

Вчера открыл тему, смотрю минут через 10 снесли, сегодня чудным образом появилась, жизнь здесь всё чудесатее и чудесатее )))

Не снесли, а перенесли из "Проектов".

Не догадался однако, ссыль закричала - страница не найдена, глянул - в проектах нет...

Jeka_M
Jeka_M аватар
Offline
Зарегистрирован: 06.07.2014

Проверяйте наличие темы через свой профиль.

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

-NMi- пишет:

ua6em пишет:

Так как некоторые логические перлы в оригинале кода у меня вызывают некоторые замешательства, публикую, авось знающие люди подскажут, что автор сказать хотел?
 

if (((in_motion_C == true) && (in_motion_L == true)) || ((in_motion_C == true) && (in_motion_L == false)))
  {
   // Reset direction and PWM output of L motor (for safety)
   digitalWrite(up_L, LOW);
   digitalWrite(down_L, LOW);
   analogWrite(pwm_L, 0);

 

Странный ты малый, вроде позывной есть, да вот толку от него маловасто.

Здеся аффтор кота правиряит ЕСЛИ маторчик-С и маторчик-L крутяццо или только маторчик-С крутиццо ->> тагды выключам к херам маторчик-L вместе с PWM, (написано-же for safety в пириводе - шоп нинаипнулсо) ачо уж он там PWM-ит - этт ты униво спраси.

И вообще, советую посмотреть как работает любой антенный тюнер у аппаратов класса аля 300+т.р. (да, да, не удивляйтесь ценам, есть и по миллиону "игрушки") и понять, какой логикой он руководствуется. Скажу сразу - будет "сложновасто" с первого раза.

не не странный, толку ровно столько чтобы шейхи разных мастей в очередь выстраивались - поговорить )))

А говорит он ровно то, что если крутится моторчик С вырубить мотор L и, не больше и не меньше, в рамках действий по решению простейшего уравнения булевой алгебры правая часть в лог. И безсмысленна, не находите?
Тюнер в Р-140 поболее наверно стоит, так как позволяет настраивать вообще без подачи ВЧ напряжения на передачу )))

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Jeka_M пишет:

Проверяйте наличие темы через свой профиль.

век живи век учись ))) благодарствую!

-NMi-
Offline
Зарегистрирован: 20.08.2018

ua6em пишет:

Тюнер в Р-140 поболее наверно стоит, так как позволяет настраивать вообще без подачи ВЧ напряжения на передачу )))

На данный момент времени я уже "отболел" этой "болезнью" под названием радиогубительство. Скока денег эта дурная привычка угробила... пипец просто. И чо там в Р-140 настраиваиццо без атвёртки - мне то-же пабарабану. Единственное, что я могу сказать - дурдуина и антенный тюнер - детсад на горшке!

negavoid
Offline
Зарегистрирован: 09.07.2016

Лукавите-с, насколько я помню, по регламенту "поговорить с шейхами" ни о чём ином, кроме уровня сигнала да обсуждения использованной для связи антенны запрещено. Да и король Иордании давно уж SK. И смысл? Узнать, какая у богатенького буратины суперантенна и как десять паков или индусов ему её поднимали в пустыне? О$#енно важная и интересная информация, как же жить-то без неё!!! Видимо, non-maskable interrupt, как и я, выбрал интернет - тут хоть можно с Шарон Стоун потрещать, попросить её прислать сиськи, всё интереснее :)

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

negavoid пишет:

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

Можно, о чём хочешь, в рамках этики...

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

ua6em пишет:

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

А можно букв побольше? Это вообще про что? Что с кем согласовывается? Если можно, например, согласовать смету нтп в минфине, там я, пожалуй, повторю конструкцию - пригодится.

Любое радиопередающее устройство с нагрузкой, то бишь антенной при перестройки по частоте требует согласования - компенсации реактивной составляющей сия чудная программа, надеюсь она будет реализована, для этого и предназначена.

Т.е. одно аппаратное устройство (радиопередающее) согласуется с другим аппаратным устройством (антенной) посредством программы?

Интересно было бы посмотреть на блок-схему: как именно соединены между собой радиопередатчик, программа и антенна.

negavoid
Offline
Зарегистрирован: 09.07.2016

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

В радиолюбительстве цель в самом процессе, а финальной цели-результата нет, это и разочаровывает. Ну не считать же достойной целью журнал связей с удалёнными абонентами, разве что для самолюбования, ах какой я крутой и какие крутые у меня девайсы. Гм. Да, раньше практический смысл был, в случае войны получаем сразу много подготовленных радистов. Но время-то идёт, нонче даже рации уже через интернет связываются.

PS просить сиськи Шарон гораздо веселее, чем сиськи шейха :)))

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

negavoid пишет:

Да там программа переключает многопозиционную релюшку

там проще, реле бистабильные и набор конденсаторов и индуктивностей в формате 1-2-4-8, ими и оперирует микропроцессор при подборе коэффициента согласования по минимуму отраженной и максимуму падающей волны, только мощности в автоматических тюнерах как правило ограниченны 100 ваттами, а если разрешено 1 киловаттом, вот тут как раз раздолье для творчества...
Это устройство настраивается при переключении на среднюю частоту диапазона, а далее ручная подстройка, это как раз и недостаток, требуется сохранять окончательные настройки в EEPROM и при включении их оттуда восстанавливать, ну и расширить добавив недостающие диапазоны, такое было пожелание, у меня то самого автоматические тюнера имеются )))

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

negavoid пишет:

Ну Виктор Николаич, ну а :) ну пишите же, если что, подмогнём. Но мисс Стоун мне однозначно нравится больше, чем шейхи. :)

мне в этом смысле тоже )))

Пока анализирую его код на предмет точности к примеру значения с аналоговых пинов усредняет (фильтрует) так:
 

 posn_L_0 = analogRead(ana_pin_L); // Read position L motor

  // Map position sensor value to 0...1000
  posn_L_0 = map(posn_L_0, 0, 1023, 0, 1000);

  // Position sensor filter
  posn_L = (posn_L_0 + posn_L_1 + posn_L_2 + posn_L_3 + posn_L_4 + posn_L_5 + posn_L_6)/7;
  posn_L_6 = posn_L_5;
  posn_L_5 = posn_L_4;
  posn_L_4 = posn_L_3;
  posn_L_3 = posn_L_2;
  posn_L_2 = posn_L_1;
  posn_L_1 = posn_L_0;

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

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

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

ua6em пишет:
этим пузырьком
А где тут метод пузырька? Код неполный? Или Вы словом "пузырёк" что-то другое обозвали? Если так, то напрасно - в программировании это давно устоявшийся термин (слава Богу, в "Библии" от Кнута рассматривается) и использовать его не по назначению - Вас не будут понимать.

не, ну у него же данные первую часть пузырька выполняют, всплывают жеж )))
PS а как это действо назвать, стек, так он оттуда не забирает, он же данные только в одну сторону буфера засовывает выталкивая предыдущие вверх (вниз)

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

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

ua6em пишет:

не, ну у него же данные первую часть пузырька выполняют, всплывают жеж )))
PS а как это действо назвать, стек, так он оттуда не забирает, он же данные только в одну сторону буфера засовывает выталкивая предыдущие вверх (вниз)

Да, нет, это просто "скользящее окно". Он считает скользящее среднее.

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ua6em пишет:
значит оставляю, ... так и не понял из обсуждения какой из методов для съема значения с потенциометра подключенного к аналоговому пину лучше, дискуссии то были жаркие...
Самые жаркие дискуссии, это дискуссии не о чем. Если Вы сможете написать код отделяющий уровень полезного сигнала от уровня шумов. А то можно написать настроечное устройство настраивающее приемную антенну на максимальный шум. 

-NMi-
Offline
Зарегистрирован: 20.08.2018

andriano пишет:

Интересно было бы посмотреть на блок-схему: как именно соединены между собой радиопередатчик, программа и антенна.

Ну шож, можешь посмотреть, например, Icom IC-746. У него в комплекте можно приобрести так называемый антенный тюнер. Это устройство с микропроцессором, программой управления оным и несколькими группами реле и даже, в некоторых, есть шаговые моторы. Устройство подсоединяется межда трансивером и антенной и автоматически подстраивает КСВ для согласования с антенной. Это не ново,старо как радио Попова.

PS: в топовых трансиверах энта "штука" встроена в сам трансивер. Тока цены на них не смотри, голова закружится.   )))

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

qwone пишет:

ua6em пишет:
значит оставляю, ... так и не понял из обсуждения какой из методов для съема значения с потенциометра подключенного к аналоговому пину лучше, дискуссии то были жаркие...
Самые жаркие дискуссии, это дискуссии не о чем. Если Вы сможете написать код отделяющий уровень полезного сигнала от уровня шумов. А то можно написать настроечное устройство настраивающее приемную антенну на максимальный шум. 

здесь вопросы аппаратные видимо внесут ограничения, к примеру есть у меня шикарные энкодеры, выдают напряжение от 0 до 5 вольт с точностью 0, 08 градуса угла, а 10 битный ацп в максимале 0,3 градуса, значит уже не годится...здесь применены резисторы, вроде неплохие, но не посмотрев насколько там сигнал моросит сказать трудно...

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

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Вот об этом я и говорю. Не нужны всякие методы пузырьков. А просто свести к апаратному решению как в АРУ(автоматической ругулировки усиление). Чем больше сигнал(с шумом разумеется), тем лучше.

Green
Offline
Зарегистрирован: 01.10.2015

negavoid пишет:

В радиолюбительстве цель в самом процессе, а финальной цели-результата нет, это и разочаровывает. Ну не считать же достойной целью журнал связей с удалёнными абонентами, разве что для самолюбования, ах какой я крутой и какие крутые у меня девайсы. Гм.

Цели, как известно, у каждого свои. Чем бы дитя не тешилось...) Но, неужто и тесты не интересны? Или там тоже результата нет?

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Обновил код программы, переделал на дисплей LCD1602 I2C и матричную клавиатуру на аналоговом пине, реализована тактовая кнопка для включения реле (на аналоговом пине).
Работа идёт над интерфейсом CAT.

26/02/2020 Добавлен интерфейс для трансиверов YAESU (817,857,897) остальные по даташиту не смотрел
 

-NMi-
Offline
Зарегистрирован: 20.08.2018

Ну таки и шо? Кады SDRшлешмоб? Ну типа ты там чонить буишь глаголить а мы через SDR-Online буим слушать?

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

-NMi- пишет:

Ну таки и шо? Кады SDRшлешмоб? Ну типа ты там чонить буишь глаголить а мы через SDR-Online буим слушать?

А надо? Антенны куда направлять?

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Green пишет:

negavoid пишет:

В радиолюбительстве цель в самом процессе, а финальной цели-результата нет, это и разочаровывает. Ну не считать же достойной целью журнал связей с удалёнными абонентами, разве что для самолюбования, ах какой я крутой и какие крутые у меня девайсы. Гм.

Цели, как известно, у каждого свои. Чем бы дитя не тешилось...) Но, неужто и тесты не интересны? Или там тоже результата нет?

в тестах результаты есть, в них на УКВ перешел, остановился на чемпионе Кавказа, приятель несколько раз команду выводил в чемпионы России, но это уже битва техники )))
сейчас меня можно встретить в цифровых модах, в основном FT8
 

Green
Offline
Зарегистрирован: 01.10.2015

Да, сейчас много всего разнообразного и интересного, не то что раньше. Но битва техники была и есть всегда. Это во всех технических видах.
В нашей местности КВ было в почёте. УКВ так, баловство. Но от полевых дней осталась масса впечатлений, до сих пор.) 

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Green пишет:

В нашей местности КВ было в почёте. УКВ так, баловство.

Это да, чтобы стать чемпионом Ставропольского края на УКВ мне нужно было просто поучаствовать )))

Green
Offline
Зарегистрирован: 01.10.2015

Джигиты видать не по этому делу.))

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Green пишет:

Джигиты видать не по этому делу.))

просто КВ это скоростная радиосвязь, а УКВ...

-NMi-
Offline
Зарегистрирован: 20.08.2018

ua6em пишет:

просто КВ это скоростная радиосвязь, а УКВ...

И чо с УКВ??? 

Чо, "резинкой" по лбу получил???     )))))))))))))))))))))))))))))))))))))))))))))))))))

Green
Offline
Зарегистрирован: 01.10.2015

ua6em пишет:

Это да, чтобы стать чемпионом Ставропольского края на УКВ мне нужно было просто поучаствовать )))


А у меня всё "детство" на это КВ ушло(. С 9-го класса начал заниматься.

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Есть кто готов помочь в написании библиотеки для аппаратуры ICOM, в библиотеке по сути всего две функции
нужны, инициализация и получение частоты...

Morroc
Offline
Зарегистрирован: 24.10.2016

Не совсем понимаю что имеется в виду. Обмен по cat для забора текущей частоты трансивера ? А сам интерфейс с ним как реализован ? на штатных rx/tx ардуины ?

Тема че то... для cqham. Тут радиолюбителей-связистов походу аж целыз два ) Народ вон прикалывается, а эта штука на киловатт и правда весьма актуальна, особенно если антенна абы какая - на релюшках и кондерах можно и спалить если конечно это не к15у и в2в какие нибудь.

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Morroc пишет:
Не совсем понимаю что имеется в виду. Обмен по cat для забора текущей частоты трансивера ? А сам интерфейс с ним как реализован ? на штатных rx/tx ардуины ? Тема че то... для cqham. Тут радиолюбителей-связистов походу аж целыз два ) Народ вон прикалывается, а эта штука на киловатт и правда весьма актуальна, особенно если антенна абы какая - на релюшках и кондерах можно и спалить если конечно это не к15у и в2в какие нибудь.

Обмен по SoftwareSerial на пинах 2 и 3, по USB в обратку (на PC) можно организовать сплиттер.
Устройство рабочее используется с ICOM с забором на девайс по BCD, но используется для переключения антенн, сопряжение на жёсткой логике.
Для YAESU нашёл библиотеку от канадца, но она еще под версию IDE 1.0.5, поправил под новые версии в меру своего разумения (библиотек не писал), работает, но при компилиции выкидывает предупреждения:
 

Compiling library "FT897D-master"
"C:\\Users\\User\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328pb -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\cores\\MCUdude_corefiles" "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\variants\\pb-variant" "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\libraries\\SoftwareSerial\\src" "-IC:\\ARDUINO\\arduino-1.8.9\\libraries\\FT897D-master\\src" "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\libraries\\EEPROM\\src" "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\libraries\\Wire\\src" "-IC:\\ARDUINO\\arduino-1.8.9\\libraries\\Arduino-LiquidCrystal-I2C-library-master" "C:\\ARDUINO\\arduino-1.8.9\\libraries\\FT897D-master\\src\\FT897D.cpp" -o "C:\\temp\\arduino_build_674190\\libraries\\FT897D-master\\FT897D.cpp.o"
C:\ARDUINO\arduino-1.8.9\libraries\FT897D-master\src\FT897D.cpp:25:29: warning: 'rigCat' initialized and declared 'extern'

 extern SoftwareSerial rigCat(2,3); // rx,tx

                             ^

C:\ARDUINO\arduino-1.8.9\libraries\FT897D-master\src\FT897D.cpp: In member function 'byte FT897D::getMode()':

C:\ARDUINO\arduino-1.8.9\libraries\FT897D-master\src\FT897D.cpp:192:16: warning: unused variable 'l' [-Wunused-variable]

  unsigned long l = getFreqMode();

                ^

C:\ARDUINO\arduino-1.8.9\libraries\FT897D-master\src\FT897D.cpp: In member function 'long unsigned int FT897D::from_bcd_be(const byte*, unsigned int)':

C:\ARDUINO\arduino-1.8.9\libraries\FT897D-master\src\FT897D.cpp:293:14: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]

  for (i=0; i < bcd_len/2; i++) {

            ~~^~~~~~~~~~~

C:\ARDUINO\arduino-1.8.9\libraries\FT897D-master\src\FT897D.cpp: In member function 'void FT897D::squelchFreq(unsigned int, char*)':

C:\ARDUINO\arduino-1.8.9\libraries\FT897D-master\src\FT897D.cpp:185:29: warning: iteration 2 invokes undefined behavior [-Waggressive-loop-optimizations]

   rigSqlFreq[i] = freq_bcd[i];

                   ~~~~~~~~~~^

C:\ARDUINO\arduino-1.8.9\libraries\FT897D-master\src\FT897D.cpp:184:18: note: within this loop

  for (byte i=0; i<4; i++){

                 ~^~

C:\ARDUINO\arduino-1.8.9\libraries\FT897D-master\src\FT897D.cpp:185:29: warning: array subscript is above array bounds [-Warray-bounds]

   rigSqlFreq[i] = freq_bcd[i];

                   ~~~~~~~~~~^

C:\ARDUINO\arduino-1.8.9\libraries\FT897D-master\src\FT897D.cpp:185:29: warning: array subscript is above array bounds [-Warray-bounds]

Compiling library "EEPROM"
Compiling library "Wire"
"C:\\Users\\User\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328pb -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\cores\\MCUdude_corefiles" "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\variants\\pb-variant" "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\libraries\\SoftwareSerial\\src" "-IC:\\ARDUINO\\arduino-1.8.9\\libraries\\FT897D-master\\src" "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\libraries\\EEPROM\\src" "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\libraries\\Wire\\src" "-IC:\\ARDUINO\\arduino-1.8.9\\libraries\\Arduino-LiquidCrystal-I2C-library-master" "C:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\libraries\\Wire\\src\\Wire.cpp" -o "C:\\temp\\arduino_build_674190\\libraries\\Wire\\Wire.cpp.o"

 

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Смотрю по предупреждениям, в этой функции точно косяк,
заполняем значения первого массива из второго, при этом второй выходит,
за рамки массива, то-есть в массиве далее второго байта будет мусор
И как исправить?
 

void FT897D::squelchFreq(unsigned int freq, char * sqlType) {
	byte rigSqlFreq[5] = {0x00,0x00,0x00,0x00,0x00};
if (strcasecmp(sqlType,"C")==0) rigSqlFreq[4] = CAT_SQL_CTCSS_SET;
if (strcasecmp(sqlType,"D")==0) rigSqlFreq[4] = CAT_SQL_DCS_SET;
	
	byte freq_bcd[2];
	to_bcd_be(freq_bcd, (long)  freq, 4);

	for (byte i=0; i<4; i++){
		rigSqlFreq[i] = freq_bcd[i];
	}
	sendCmd(rigSqlFreq,5);
	getByte();
}

И еще один косяк:
 

byte FT897D::getMode() {
	unsigned long l = getFreqMode();
	return mode;

Всё что смог поправил, подскажите это как поправить?
 

Compiling library "FT897D-master"
"C:\\Users\\User\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++11 -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -mmcu=atmega328pb -DF_CPU=16000000L -DARDUINO=10809 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\cores\\MCUdude_corefiles" "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\variants\\pb-variant" "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\libraries\\SoftwareSerial\\src" "-IC:\\ARDUINO\\arduino-1.8.9\\libraries\\FT897D-master\\src" "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\libraries\\EEPROM\\src" "-IC:\\Users\\User\\Documents\\Arduino\\hardware\\HAMDUINO\\avr\\libraries\\Wire\\src" "-IC:\\ARDUINO\\arduino-1.8.9\\libraries\\Arduino-LiquidCrystal-I2C-library-master" "C:\\ARDUINO\\arduino-1.8.9\\libraries\\FT897D-master\\src\\FT897D.cpp" -o "C:\\temp\\arduino_build_742192\\libraries\\FT897D-master\\FT897D.cpp.o"
C:\ARDUINO\arduino-1.8.9\libraries\FT897D-master\src\FT897D.cpp:25:29: warning: 'rigCat' initialized and declared 'extern'

 extern SoftwareSerial rigCat(2,3); // rx,tx

                             ^

Compiling library "EEPROM"

 

Morroc
Offline
Зарегистрирован: 24.10.2016

ua6em пишет:
Обмен по SoftwareSerial на пинах 2 и 3, по USB в обратку (на PC) можно организовать сплиттер.

Можно попробовать. В свой синтез я делал cat "под icom". Правда точно не скажу когда, не на этих выходных точно, возможно на следующих руки дойдут. Непонятная фигня с популярным логом правда была у того варианта (это в плане сплита) - смотрел анализатором, ничего не понял, кроме небольшой задержки ответа по сравнению с прямым подключением компа к icom разницы никакой не было, но связь с самоделкой тупила, с icom нет, в других программах такого не наблюдал. Самому девайсу кроме частоты ничего не нужно же ? Остальное только компу отдавать ? Можно еще TX взять в принципе, в моем icom по cat его нет и испытать не на чем, но в синтезе делал - с компа работало.

Я себе вот такое заготовил для экспериментов - 1/2 согласовывать. Чем крутить кпе есть, уже пробовал и муфты печатал, правда точно не знаю еще как позиционирование делать в 0, громоздко получается. Чем катуху крутить пока не знаю - тугая. В плане обычного тюнера у меня была мысль на входе поставить рэв-14 и на китайскую nanoVNA, управляемую ардуиной, там вроде есть контакты для uart - вариант на любителя, но я в той математике и измерениях плаваю, а хотелось бы знать полный расклад сопротивления с реактивностью и знаком, а то было дело - настраивал диполь по КСВ-метру, а потом оказалось, что там активное 22 ома из за особенностей подвеса, а остальное реактивность, КСВ тем не менее показывало ~1.

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

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

А я не понял, что исправлять? Предупреждение в 7-ой строке. Так переменная extern объявлена, значит она реально живёт в другом файле и её нельзя инициализировать, можно только пользоваться. А что ещё?

Это получается через КАРО-ПАГО )))
По нормальному есть объект FT897D (так называется библиотека), для работы ему нужен SOFTWARE SERIAL, при инициализации объекта и надо бы сказать, на каких пинах совтового сериала работать, это если логически поразмыслить:

FT897D.h
 

/*
  FT897D.h		Arduino library for controlling a Yaesu FT857D/FT857D
			radio via CAT commands.

Version:  0.1
 Created:  2012.08.16
Released:  2012.08.17
  Author:  James Buck, VE3BUX
     Web:  http://www.ve3bux.com
	 
	 Version:  0.2 (MODYFI in FT897D) add clarFreq() RX3QFM and wkd in IDE > 1.8.0
 Created:  2020.02.26
Released:  2020.02.26
  Author:  Victor UA6EM (LN14AE)
     Web:  http://www.ua6em.ru

CAT commands for FT-857D radio taken from the FT-857D Manual (page 66):
	
http://www.yaesu.co.uk/files/FT-857D_Operating%20Manual.pdf

Или страницы 63-64 полной русской инструкции
http://www.radioscanner.ru/files/yaesu/file4567/
http://www.radioscanner.ru/files/download/file4567/ft-897.rar

All CAT commands to the radio should be sent as 5-byte blocks. The commands are generally in the form of: 

	{P1,P2,P3,P4,CMD}
		where P1-P4 are parameters
		and   CMD is the command code (ie. set mode)

----Lock On / Off------------------------------------------------
	{0x00,0x00,0x00,0x00,CAT_LOCK_ON}
	{0x00,0x00,0x00,0x00,CAT_LOCK_OFF}

	Toggle the lock as: {0x00,0x00,0x00,0x00,CMD}
	CMD byte:
		0x00 = lock on				= CAT_LOCK_ON
		0x80 = lock off				= CAT_LOCK_OFF

	Eg: {0x00,0x00,0x00,0x00,0x00} enables the lock

----PTT On / Off-------------------------------------------------
	{0x00,0x00,0x00,0x00,CAT_PTT_ON}
	{0x00,0x00,0x00,0x00,CAT_PTT_OFF}

	Toggle PTT as: {0x00,0x00,0x00,0x00,CMD}
	CMD byte:
		0x08 = PTT on				= CAT_PTT_ON
		0x88 = PTT off				= CAT_PTT_OFF

	Eg: {0x00,0x00,0x00,0x00,0x08} causes radio to TX

----Set Frequency------------------------------------------------
	{0x00,0x00,0x00,0x00,CAT_FREQ_SET}

	Tune the radio to a frequency as: {P1,P2,P3,P4,0x01}
	Parameters:
		P1-P4 = frequency as: aa,bb,cc,dd
		
	Eg: {0x01,0x40,0x07,0x00,0x01} tunes to 14.070MHz
	Eg2:{0x14,0x43,0x90,0x00,0x01} tunes to 144.390MHz

----Operating Mode-----------------------------------------------
	{0x00,0x00,0x00,0x00,CAT_MODE_SET}

	Set radio mode as: {P1,0x00,0x00,0x00,0x07}
	P1 Byte:
	0x00 = LSB						 = CAT_MODE_LSB
	0x01 = USB						 = CAT_MODE_USB
  	0x02 = CW						 = CAT_MODE_CW
  	0x03 = CW-R					 = CAT_MODE_CWR
  	0x04 = AM						 = CAT_MODE_AM
  	0x08 = FM						 = CAT_MODE_FM
  	0x0A = DIG						 = CAT_MODE_DIG
  	0x0C = PKT						 = CAT_MODE_PKT
  	0x88 = FM-N					 = CAT_MODE_FMN

	Eg: {0x00,0x00,0x00,0x00,0x07} sets the radio to LSB

----Clar On / Off------------------------------------------------
	{0x00,0x00,0x00,0x00,CAT_CLAR_ON}
	{0x00,0x00,0x00,0x00,CAT_CLAR_OFF}

	Toggle clarifier as: {0x00,0x00,0x00,0x00,CMD}
	CMD byte:
		0x05 = CLAR on				= CAT_CLAR_ON
		0x85 = CLAR off				= CAT_CLAR_OFF

	Eg: {0x00,0x00,0x00,0x00,0x05} turns on the clarifier

----Clar Frequency-----------------------------------------------
	{0x00,0x00,0x00,0x00,CAT_CLAR_SET}

	Set clarifier frequency as: {P1,0x00,P3,P4,0xF5}
	P1 byte:
		0x00 = toggle between + and - offset
	P3,P4 bytes:
			= frequency as: aa,bb

	Eg: {0x00,0x12,0x34,0xF5} sets the clarifier to 12.34kHz
	Eg2:{0x00,0x06,0x50,0xF5} sets the clarifier to -6.5kHz

----VFO A/B------------------------------------------------------
	{0x00,0x00,0x00,0x00,CAT_VFO_AB}

	Toggle between VFO A and B as: {0x00,0x00,0x00,0x00,CMD}
	CMD byte:
		0x81 = chg  between A & B		= CAT_VFO_AB

	Eg: {0x00,0x00,0x00,0x00,0x81} change from VFO A to VFO B

----Split On / Off-----------------------------------------------
	{0x00,0x00,0x00,0x00,CAT_SPLIT_ON}
	{0x00,0x00,0x00,0x00,CAT_SPLIT_OFF}

	Toggle Split operation as: {0x00,0x00,0x00,0x00,CMD}
	CMD byte:
		0x02 = split on				= CAT_SPLIT_ON
		0x82 = split off				= CAT_SPLIT_OFF

	Eg: {0x00,0x00,0x00,0x00,0x02} enables split mode operation

----Repeater Offset---------------------------------------------
	{P1,0x00,0x00,0x00,CAT_RPTR_OFFSET_CMD}

	Set repeater offset as: {P1,0x00,0x00,0x00,0x09}
	P1 byte:
		0x09 = negative shift			= CAT_RPTR_OFFSET_N
		0x49 = positive shift			= CAT_RPTR_OFFSET_P
		0x89 = simplex				= CAT_RPTR_OFFSET_S

	Eg: {0x49,0x00,0x00,0x00,0x09} sets positive repeater shift

----Repeater Offset Frequency-----------------------------------
	{0x00,0x00,0x00,0x00,CAT_RPTR_FREQ_SET}

	Set repeater offset frequency as: {P1,P2,P3,P4,0xF9}
	Parameters:
		P1-P4 = frequency as: aa,bb,cc,dd
		
	Eg: {0x05,0x43,0x21,0x00,0xF9} sets offset to 5.4321MHz
	Eg2:{0x00,0x60,0x00,0x00,0xF9} sets offset to 0.600MHz
	
----CTCSS / DCS Mode--------------------------------------------
	{P1,0x00,0x00,0x00,CAT_SQL_CMD}

	Select CTCSS / DCS mode as: {P1,0x00,0x00,0x00,0x0A}
	P1 Byte:
	0x0A = DCS on					= CAT_SQL_DCS
	0x0B = DCS decoder on 			= CAT_SQL_DCS_DECD
  	0x0C = DCS encoder on 			= CAT_SQL_DCS_ENCD
  	0x2A = CTCSS on					= CAT_SQL_CTCSS
  	0x3A = CTCSS decoder on			= CAT_SQL_CTCSS_DECD
  	0x4A = CTCSS encoder on			= CAT_SQL_CTCSS_ENCD
  	0x8A = off						= CAT_SQL_OFF

	Eg: {0x2A,0x00,0x00,0x00,0x0A} enables CTCSS tones on TX&RX

----CTCSS Tone--------------------------------------------------
	{0x00,0x00,0x00,0x00,CAT_SQL_CTCSS_SET}

	Set CTCSS tones as: {P1,P2,P3,P4,0x0B}
	Parameters:
		P1-P2 = CTCSS tone on TX as: aa,bb
		P3-P4 = CTCSS tone on RX as: cc,dd
		
	Eg: {0x08,0x85,0x10,0x00,0x0B} CTCSS TX = 88.5Hz, RX = 100Hz
	Eg2:{0x10,0x00,0x10,0x00,0x0B} CTCSS TX&RX = 100Hz
	
----DCS Code----------------------------------------------------
	{0x00,0x00,0x00,0x00,CAT_SQL_DCS_SET}

	Set DCS codes as: {P1,P2,P3,P4,0x0C}
	Parameters:
		P1-P2 = DCS code on TX as: aa,bb
		P3-P4 = DCS code on RX as: cc,dd

	Eg: {0x00,0x23,0x03,0x71,0x0C} DCS TX = 023, RX = 371
	
----Read RX Status (Squelch, CTCSS/DCS, Disc. Ctr, S-Meter)------
	{0x00,0x00,0x00,0x00,CAT_RX_DATA_CMD}

	Read the RX status as: {0x00,0x00,0x00,0x00,E7}

	The radio will then output 4 bytes of data to report the 	various parameters:

	{D1,D2,D3,D4}

	Data:
		D1 = {0xij}	i = 0 = squelch off
					i = 1 = squelch on
					j = 0 = CTCSS/DCS matched
					j = 1 = CTCSS/DCS unmatched
		D2 = {0xkl}	k = 0 = discriminator centered
					k = 1 = discriminator offcentered
					l = dummy data
		D3-D4 = S-meter data

	Eg: {0x00,0x00,0x00,0x00,0xE7} gets the radio status

----Read TX Status (PTT, SWR Hi/Lo, Split, PO Meter)------------
	{0x00,0x00,0x00,0x00,CAT_TX_DATA_CMD}

	Read the TX status as: {0x00,0x00,0x00,0x00,F7}

	The radio will then output 4 bytes of data to report the 	various parameters:

	{D1,D2,D3,D4}

	Data:
		D1 = {0xmn}	m = 0 = PTT off
					m = 2 = PTT on
					n = 0 = HI SWR off
					n = 1 = HI SWR on
		D2 = {0xpq}	p = 0 = split on
					p = 1 = split off
					q = dummy data
		D3-D4 = PO meter data

----Read Frequency / Mode Status---------------------------------
	{0x00,0x00,0x00,0x00,CAT_RX_FREQ_CMD}

	Read the frequency and mode as: {0x00,0x00,0x00,0x00,03}

	The radio will then output 5 bytes of data to report the 	current frequency and mode:

	{D1,D2,D3,D4,D5}

	Data:
		D1-D4 = frequency
		D5 = mode (same as set mode)

	Eg: {0x00,0x00,0x00,0x00,0x03} gets the current freq & mode
	
	Result from radio is:
		{0x43,0x97,0x00,0x00,0x08}
	which means:
		439.700MHz in mode 08 (FM)

----------------------------------------------------------------
*/

#ifndef CAT_h
#define CAT_h

#include <Arduino.h>
#include <SoftwareSerial.h>

#define CAT_LOCK_ON			0x00
#define CAT_LOCK_OFF			0x80
#define CAT_PTT_ON			0x08
#define CAT_PTT_OFF			0x88
#define CAT_FREQ_SET			0x01
#define CAT_MODE_SET			0x07
#define CAT_MODE_LSB			0x00
#define CAT_MODE_USB			0x01
#define CAT_MODE_CW			0x02
#define CAT_MODE_CWR			0x03
#define CAT_MODE_AM			0x04
#define CAT_MODE_FM			0x08
#define CAT_MODE_DIG			0x0A
#define CAT_MODE_PKT			0x0C
#define CAT_MODE_FMN			0x88
#define CAT_CLAR_ON			0x05
#define CAT_CLAR_OFF			0x85
#define CAT_CLAR_SET			0xF5
#define CAT_VFO_AB			0x81
#define CAT_SPLIT_ON			0x02
#define CAT_SPLIT_OFF			0x82
#define CAT_RPTR_OFFSET_CMD		0x09
#define CAT_RPTR_OFFSET_N		0x09 // -
#define CAT_RPTR_OFFSET_P		0x49 // +
#define CAT_RPTR_OFFSET_S		0x89 // simlex
#define CAT_RPTR_FREQ_SET		0xF9
#define CAT_SQL_CMD			0x0A //{P1 ,0x00,0x00,0x00,0x0A}
#define CAT_SQL_DCS			0x0A // all values below are P1
#define CAT_SQL_DCS_DECD		0x0B // only useful in "split"
#define CAT_SQL_DCS_ENCD		0x0C
#define CAT_SQL_CTCSS			0x2A
#define CAT_SQL_CTCSS_DECD		0x3A
#define CAT_SQL_CTCSS_ENCD		0x4A
#define CAT_SQL_OFF			0x8A
#define CAT_SQL_CTCSS_SET		0x0B
#define CAT_SQL_DCS_SET		0x0C
#define CAT_RX_DATA_CMD		0xE7
#define CAT_TX_DATA_CMD		0xF7
#define CAT_RX_FREQ_CMD		0x03
#define CAT_NULL_DATA			0x00

class FT897D
{
  public:
	FT897D();
	void setSerial(SoftwareSerial portInfo);
	void begin(int baud);

	void lock(boolean toggle);
	void PTT(boolean toggle);
	void setFreq(long freq);
	void setMode(char * mode);
	void clar(boolean toggle);
	void clarFreq(long freq);
	void switchVFO();
	void split(boolean toggle);
	void rptrOffset(char * ofst);
	void rptrOffsetFreq(long freq);
	void squelch(char * mode);
	void squelchFreq(unsigned int, char * sqlType);
	byte getMode();
	unsigned long getFreqMode();
	boolean chkTX();
	void flushRX();

  private:
	unsigned char * converted;		// holds the converted freq
	unsigned long freq;			// frequency data as a long
	unsigned char tempWord[4];		// temp value during conv.
	byte mode;

	void sendCmd(byte cmd[], byte len);
	byte singleCmd(int cmd);		// simplifies small cmds
	byte getByte();

	void sendByte(byte cmd);
	unsigned long from_bcd_be(const byte bcd_data[], unsigned bcd_len);
	unsigned char * to_bcd_be( byte bcd_data[], unsigned long freq, unsigned bcd_len);
	void comError(char * string);
};

#endif

FT897D.cpp

/*
  FT897D.cpp	Arduino library for controlling a Yaesu FT857D/FT897D
			radio via CAT commands.
 
 Version:  0.1
 Created:  2012.08.16
Released:  2012.08.17
  Author:  James Buck, VE3BUX
     Web:  http://www.ve3bux.com
	 
	 Version:  0.2 (MODYFI in FT897D)
 Created:  2020.02.26
Released:  2020.02.26
  Author:  Victor UA6EM (LN14AE)
     Web:  http://www.ua6em.ru
	 

*/

#include <Arduino.h>
#include <SoftwareSerial.h>
#include "FT897D.h"

// define software serial IO pins here:
extern SoftwareSerial rigCat(2,3); // rx,tx

#define dlyTime 5	// delay (in ms) after serial writes

FT897D::FT897D(){ }	// nothing to do when first instanced

// Setup software serial with user defined input
// from the Arduino sketch (function, though very slow)
void FT897D::setSerial(SoftwareSerial portInfo) {
  rigCat = portInfo;
}

// similar to Serial.begin(baud); command
void FT897D::begin(int baud) {
  rigCat.begin(baud);
}

// lock or unlock the radio
void FT897D::lock(boolean toggle) {
	if (toggle == true) singleCmd(CAT_LOCK_ON);
	if (toggle == false) singleCmd(CAT_LOCK_OFF);
}

// set or release the virtual PTT button
void FT897D::PTT(boolean toggle) {
	if (toggle == true) singleCmd(CAT_PTT_ON);
	if (toggle == false) singleCmd(CAT_PTT_OFF);
}

// set radio frequency directly (as a long integer)
void FT897D::setFreq(long freq) {
	byte rigFreq[5] = {0x00,0x00,0x00,0x00,0x00};
rigFreq[4] = CAT_FREQ_SET; // command byte

	unsigned char tempWord[4];
	converted = to_bcd_be(tempWord, freq, 8);

	for (byte i=0; i<4; i++){
		rigFreq[i] = converted[i];
	}

sendCmd(rigFreq,5);
	getByte();
}

// set radio mode using human friendly terms (ie. USB)
void FT897D::setMode(char * mode) {
	byte rigMode[5] = {0x00,0x00,0x00,0x00,0x00};
rigMode[0] = CAT_MODE_USB; // default to USB mode
rigMode[4] = CAT_MODE_SET; // command byte

if (strcasecmp(mode, "LSB") == 0) rigMode[0] = CAT_MODE_LSB;
if (strcasecmp(mode, "USB") == 0) rigMode[0] = CAT_MODE_USB;
if (strcasecmp(mode, "CW") == 0) rigMode[0] = CAT_MODE_CW;
if (strcasecmp(mode, "CWR") == 0) rigMode[0] = CAT_MODE_CWR;
if (strcasecmp(mode, "AM") == 0) rigMode[0] = CAT_MODE_AM;
if (strcasecmp(mode, "FM") == 0) rigMode[0] = CAT_MODE_FM;
if (strcasecmp(mode, "DIG") == 0) rigMode[0] = CAT_MODE_DIG;
if (strcasecmp(mode, "PKT") == 0) rigMode[0] = CAT_MODE_PKT;
if (strcasecmp(mode, "FMN") == 0) rigMode[0] = CAT_MODE_FMN;

sendCmd(rigMode,5);
	getByte();
}

// turn the clarifier on or off
void FT897D::clar(boolean toggle) {
	if (toggle == true) singleCmd(CAT_CLAR_ON);
	if (toggle == false) singleCmd(CAT_CLAR_OFF);
}

// set the clarifier frequency
void FT897D::clarFreq(long freq) {
	// will come back to this later
	byte clarOfst[5] = {0x00,0x00,0x00,0x00,0x00};
    if (freq >= 0 ) clarOfst[0] = 0x00;//offset > 0
	if (freq < 0 ) clarOfst[0] = 0x01; // offset < 0
	clarOfst[1] = 0x00;//default
	clarOfst[4] = CAT_CLAR_SET;//command byte

unsigned char tempWord[2];
converted = to_bcd_be(tempWord, abs(freq), 4);

for (byte i=0; i<2; i++){
clarOfst[i+2] = converted[i];
}

sendCmd(clarOfst,5);
getByte();
}

// switch between VFO A and VFO B
void FT897D::switchVFO() {
	singleCmd(CAT_VFO_AB);
}

// turn split operation on or off
void FT897D::split(boolean toggle) {
	if (toggle == true) singleCmd(CAT_SPLIT_ON);
	if (toggle == false) singleCmd(CAT_SPLIT_OFF);
}

// control repeater offset direction
void FT897D::rptrOffset(char * ofst) {
	byte rigOfst[5] = {0x00,0x00,0x00,0x00,0x00};
	rigOfst[0] = CAT_RPTR_OFFSET_S; // default to simplex
	rigOfst[4] = CAT_RPTR_OFFSET_CMD; // command byte

if (strcmp(ofst, "-") == 0) rigOfst[0] = CAT_RPTR_OFFSET_N;
if (strcmp(ofst, "+") == 0) rigOfst[0] = CAT_RPTR_OFFSET_P;
if (strcmp(ofst, "s") == 0) rigOfst[0] = CAT_RPTR_OFFSET_S;

sendCmd(rigOfst,5);
	getByte();
}

void FT897D::rptrOffsetFreq(long freq) {
	byte offsetFreq[5] = {0x00,0x00,0x00,0x00,0x00};
	offsetFreq[4] = CAT_RPTR_FREQ_SET; // command byte

freq = (freq * 100); // convert the incoming value to kHz

	unsigned char tempWord[4];
	converted = to_bcd_be(tempWord, freq, 8);

	for (byte i=0; i<4; i++){
		offsetFreq[i] = converted[i];
	}

	sendCmd(offsetFreq,5);
	getByte();
}

// enable or disable various CTCSS and DCS squelch options
void FT897D::squelch(char * mode) {
	byte rigSql[5] = {0x00,0x00,0x00,0x00,0x00};
	rigSql[0] = CAT_MODE_USB; // default to USB mode
	rigSql[4] = CAT_SQL_CMD; // command byte

if (strcasecmp(mode,"DCS")==0) rigSql[0]= CAT_SQL_DCS;
if (strcasecmp(mode,"DDC")==0) rigSql[0]= CAT_SQL_DCS_DECD;
if (strcasecmp(mode,"DEN")==0) rigSql[0]= CAT_SQL_DCS_ENCD;
if (strcasecmp(mode,"TSQ")==0) rigSql[0]= CAT_SQL_CTCSS;
if (strcasecmp(mode,"TDC")==0) rigSql[0]=CAT_SQL_CTCSS_DECD;
if (strcasecmp(mode,"TEN")==0) rigSql[0]=CAT_SQL_CTCSS_ENCD;
if (strcasecmp(mode,"OFF")==0) rigSql[0]= CAT_SQL_OFF;

	sendCmd(rigSql,5);
	getByte();
}

void FT897D::squelchFreq(unsigned int freq, char * sqlType) {
	byte rigSqlFreq[5] = {0x00,0x00,0x00,0x00,0x00};
if (strcasecmp(sqlType,"C")==0) rigSqlFreq[4] = CAT_SQL_CTCSS_SET;
if (strcasecmp(sqlType,"D")==0) rigSqlFreq[4] = CAT_SQL_DCS_SET;
	
	byte freq_bcd[5];
	to_bcd_be(freq_bcd, (long)  freq, 4);

	for (byte i=0; i<4; i++){
		byte j = freq_bcd[i];
		rigSqlFreq[i] = j; /*freq_bcd[i];*/
	}
	sendCmd(rigSqlFreq,5);
	getByte();
}

byte FT897D::getMode() {
	unsigned long mode /*l*/ = getFreqMode();
	return mode;
}

// get the frequency and the current mode
// if called as getFreqMode() return only the frequency
unsigned long FT897D::getFreqMode() {
	byte rigGetFreq[5] = {0x00,0x00,0x00,0x00,0x00};
	rigGetFreq[4] = CAT_RX_FREQ_CMD; // command byte
	byte chars[4];
	long timeout = millis();
	long elapsed = 0;

	rigCat.flush();	// clear the RX buffer which helps prevent
				// any crap data from making it through

	sendCmd(rigGetFreq, 5);
	
	while (rigCat.available() < 5 && elapsed < 2000) {
		elapsed = millis() - timeout;
     	;}
	
	for (int j = 0; j < 4; j++) {
		chars[j] = rigCat.read();  
   	}
	mode = rigCat.read(); 
	freq = from_bcd_be(chars, 8);
	return freq;
}


// determine if the radio is in TX state
// unless the radio is actively TX, the result is always
// 0x255 so any value other than 0x255 means TX !
boolean FT897D::chkTX() {
	byte rigTXState[5] = {0x00,0x00,0x00,0x00,0x00};
	rigTXState[4] = CAT_TX_DATA_CMD;
	
	sendCmd(rigTXState, 5);

	byte reply = getByte();
	
	if (reply == 0) {
		return false;
	}
	else {
		return true;
	}
}

// spit out any DEBUG data via this function
void FT897D::comError(char * string) {
 Serial.println("Communication Error!");
 Serial.println(string);
}

// gets a byte of input data from the radio
byte FT897D::getByte() {
	unsigned long startTime = millis();
	while (rigCat.available() < 1 && millis() < startTime + 2000) {
		;
	}
	byte radioReply = rigCat.read();
	return radioReply ;
}

// this is the function which actually does the 
// serial transaction to the radio
void FT897D::sendCmd(byte cmd[], byte len) {
	for (byte i=0; i<len; i++) {
		rigCat.write(cmd[i]);
	}
//	return getByte();	// should make this work more quickly
					// in a future update
}

// this function reduces total code-space by allowing for
// single byte commands to be issued (ie. all the toggles)
byte FT897D::singleCmd(int cmd) {
	byte outByte[5] = {0x00,0x00,0x00,0x00,0x00};
	outByte[4] = cmd;
	sendCmd(outByte, 5);
	return getByte();
}

// send a single byte of data (will be removed later)
void FT897D::sendByte(byte cmd) {
	rigCat.write(cmd);
}

void FT897D::flushRX() {
	rigCat.flush();
}

// GPL
// taken from hamlib work
unsigned long FT897D::from_bcd_be(const  byte bcd_data[], unsigned bcd_len)
{
	int i;
	int j = bcd_len/2;;
	long f = 0;

	for (i=0; i < j /* = bcd_len/2 */; i++) {
		f *= 10;
		f += bcd_data[i]>>4;
		f *= 10;
		f += bcd_data[i] & 0x0f;
	}
	if (bcd_len&1) {
		f *= 10;
		f += bcd_data[bcd_len/2]>>4;
	}
	return f;
}

// GPL
// taken from hamlib work
unsigned char * FT897D::to_bcd_be( unsigned char bcd_data[], unsigned long  freq, unsigned bcd_len)
{
	int i;
	unsigned char a;

	if (bcd_len&1) {
		bcd_data[bcd_len/2] &= 0x0f;
		bcd_data[bcd_len/2] |= (freq%10)<<4;
/* NB: low nibble is left uncleared */
		freq /= 10;
	}
	for (i=(bcd_len/2)-1; i >= 0; i--) {
		a = freq%10;
		freq /= 10;
		a |= (freq%10)<<4;
		freq /= 10;
		bcd_data[i] = a;
	}
	return bcd_data;
}

 

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Вдогонку:

В хидере смущает это
#ifndef CAT_h

244 #define CAT_h

 

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Со всем уважением, поддерживаю - тема вопроса больше на cqham или qrz. Как минимум нужно понимать физ. процессы в устройстве, чтобы оперировать кодом. 

Morroc
Offline
Зарегистрирован: 24.10.2016

ua6em пишет:

В хидере смущает это
#ifndef CAT_h

244 #define CAT_h

Если не определено - определяем. Зачем... ну а вдруг определено ) Вообще кто то нехило заморочился с поддержкой такой кучи команд, обычно встречал гораздо более куцые версии, где было только необходимое.

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

BOOM пишет:

Со всем уважением, поддерживаю - тема вопроса больше на cqham или qrz. Как минимум нужно понимать физ. процессы в устройстве, чтобы оперировать кодом. 

физика нам побоку, она работает, библиотека принимает команды по UART, работает по софтовому порту, это и надо поправить, а вся логика команд расписана в хидере, одну команду я сам дописал и она работает.
Надо уйти от жёсткой привязке ко второму и 3 портам ардуины, те, кто понимает в объектном программировании  это влёт, сам то не "настоящий сталевар" )))

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Morroc пишет:

ua6em пишет:

В хидере смущает это
#ifndef CAT_h

244 #define CAT_h

Если не определено - определяем. Зачем... ну а вдруг определено ) Вообще кто то нехило заморочился с поддержкой такой кучи команд, обычно встречал гораздо более куцые версии, где было только необходимое.

 Author:  James Buck, VE3BUX

было бы понятно если это был FT897_h ))) чтобы не плодить сущностей