Запуск функции при помощи энкодера

Vasya73
Offline
Зарегистрирован: 06.11.2016

Приветстую Вас гуру! Алчу помощи, ибо заблукал в "трёх соснах".  ТЗ таково: есть в наличии энкодер, при вращении которого должна два раза запускаться функция, в начале, строго после первого импульса от энкодера  и в конце, назавём её - "запрос значения частоты" Задача, вроде бы, тривиальная, но...

P.S. ниже привожу весь код скетча.

Заранее спасибо за помощь:)


 
  1. #include <ArduinoJson.h>
  2. #include "Arduino.h"
  3. #include <Encoder.h>
  4.  
  5. // Initialise the encoder and freq.button
  6. Encoder encoder(3, 2);
  7. const int pinButton = 8;
  8. long oldPos  = -999;
  9.  
  10. // Initial frequency
  11. long frequency = 451000000;
  12.  
  13. // Timeouts
  14. unsigned long reqTime       = 0;
  15. const long    reqInterval   = 10;
  16. unsigned long respTime      = 0;
  17. const long    respInterval  = 500;
  18. boolean gotAnswer = true;
  19.  
  20. void setup() {
  21.   Serial.begin(115200);
  22.   pinMode(pinButton, INPUT);
  23. }
  24.  
  25. void loop()
  26. {
  27.         int stateButton = digitalRead(pinButton);
  28.         if(stateButton == 1 && gotAnswer && (abs(millis() - reqTime) > reqInterval)) {
  29.                 reqTime   = millis();
  30.                 respTime  = millis();
  31.                 gotAnswer = false;
  32.                 //send to sdrsharp get comm.
  33.                 Serial.println("{\"Command\": \"Get\", \"Method\": \"Frequency\"}");  
  34.                 //Json get frequency
  35.                 String inData = Serial.readStringUntil('\n');
  36.                 StaticJsonBuffer<200> jsonBuffer;
  37.                 JsonObject& root = jsonBuffer.parseObject(inData);
  38.  
  39.                         if (!root.success()) {
  40.                         Serial.println("cant_get_frequency");
  41.                         delay(1000);
  42.                         return;
  43.                         }
  44.  
  45.                 frequency = root["Value"];
  46.                 inData = "";
  47.                 //Clear encoder counter
  48.                 encoder.write(0);
  49.  
  50.                         if(Serial.available() > 0) {
  51.                         gotAnswer = true;
  52.                         String inData = Serial.readStringUntil('\n');
  53.                         inData = "";
  54.             }
  55.  
  56.                         if ((abs(millis() - respTime) > respInterval) && !gotAnswer) {
  57.                         respTime = millis();
  58.                         gotAnswer = true;
  59.             }
  60.         }
  61. //Get the encoder position
  62. long newPos = encoder.read();
  63.          if (newPos != oldPos && gotAnswer && (abs(millis() - reqTime) > reqInterval) ) {
  64.      reqTime   = millis();
  65.      respTime  = millis();
  66.      gotAnswer = false;
  67.      oldPos    = newPos;
  68.          //Set feq.
  69.      long newFrequency = frequency + (newPos * 3125);
  70.      Serial.println("{\"Command\": \"Set\", \"Method\": \"Frequency\", \"Value\": "+String(newFrequency)+"}");
  71.  
  72.         }
  73.                         if(Serial.available() > 0) {
  74.                         gotAnswer = true;
  75.                         String inData = Serial.readStringUntil('\n');
  76.                         inData = "";
  77.             }
  78.  
  79.                         if ((abs(millis() - respTime) > respInterval) && !gotAnswer) {
  80.                         respTime = millis();
  81.                         gotAnswer = true;
  82.             }
  83. }
Megawollt
Offline
Зарегистрирован: 06.12.2015

Раз уж повесили энкодер на контакты прерываний, используйте их

frequency = root["Value"]; 

А это еще что? Зачем кавычки?

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

Vasya73 пишет:

должна два раза запускаться функция, в начале, строго после первого импульса от энкодера  и в конце, назавём её - "запрос значения частоты" Задача, вроде бы, тривиальная

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

Определитесь сначала с алгоритмом. а потом приступайте к программированию.

Что означает выражение "и в конце"? Когда перестанут вращать энкодер? А откуда Ваша программа узнает. что его перестали вращать? Телепатически? Или по некоторой временной паузе от последнего импульса? Или, может "в конце" означает, "когда на энкодере кнопку нажмут"? Или ещё что-то произойдёт?

Определитесь сначала с задачей чётко и однозначно, а потом уже приступайте к программе.

Vasya73
Offline
Зарегистрирован: 06.11.2016

Скетч сотворён по образу и подобию примеров к библиотеке ArduinoJson. Пример кода с "кавычками" приведён ниже. Скетч из первого  моего сообщения прекрасно работает... но хотелось бы избавиться от кнопки переключающей режимы SET/GET. Т.е. мне нужно что бы при первом же импульсе с энкодера однократно выполнялась функция GET, запрашивающая значения частоты, ну, и после крайнего импульса с энкодера (хотя, сие и необязательно, можно обойтись запросом в начеле вращения энкодера). В процессе вращения энкодера запросов частоты быть не должно. Вот такая задачка:) 

P.S. Пример кода с "кавычками". 

/ Copyright Benoit Blanchon 2014-2016
// MIT License
//
// Arduino JSON library
// https://github.com/bblanchon/ArduinoJson
// If you like this project, please add a star!

#include <ArduinoJson.h>

void setup() {
  Serial.begin(9600);
  while (!Serial) {
    // wait serial port initialization
  }

  // Memory pool for JSON object tree.
  //
  // Inside the brackets, 200 is the size of the pool in bytes,
  // If the JSON object is more complex, you need to increase that value.
  StaticJsonBuffer<200> jsonBuffer;

  // StaticJsonBuffer allocates memory on the stack, it can be
  // replaced by DynamicJsonBuffer which allocates in the heap.
  // It's simpler but less efficient.
  //
  // DynamicJsonBuffer  jsonBuffer;

  // JSON input string.
  //
  // It's better to use a char[] as shown here.
  // If you use a const char* or a String, ArduinoJson will
  // have to make a copy of the input in the JsonBuffer.
  char json[] =
      "{\"sensor\":\"gps\",\"time\":1351824120,\"data\":[48.756080,2.302038]}";

  // Root of the object tree.
  //
  // It's a reference to the JsonObject, the actual bytes are inside the
  // JsonBuffer with all the other nodes of the object tree.
  // Memory is freed when jsonBuffer goes out of scope.
  JsonObject& root = jsonBuffer.parseObject(json);

  // Test if parsing succeeds.
  if (!root.success()) {
    Serial.println("parseObject() failed");
    return;
  }

  // Fetch values.
  //
  // Most of the time, you can rely on the implicit casts.
  // In other case, you can do root["time"].as<long>();
  const char* sensor = root["sensor"];
  long time = root["time"];
  double latitude = root["data"][0];
  double longitude = root["data"][1];

  // Print values.
  Serial.println(sensor);
  Serial.println(time);
  Serial.println(latitude, 6);
  Serial.println(longitude, 6);
}

void loop() {
  // not used in this example
}

 

Vasya73
Offline
Зарегистрирован: 06.11.2016

Я уже давно опредилился, даже слепил некого "франкенштейна" из кусков чужого и своего кода, который даже работает:) Осталась одна задача,  решить которую мне тяму не хватает. Как заставить энкодер однократно вызывать функцию GET т.е. крутишь энкодер (перестраиваешь частоту) - функция GET одноразово вызвалась, следующий раз функция GET вызывается при новом врещении энкодера, т.е. при следующей перестройке частоты. 

P.S. Сейчас немного "причешу" "франкенштейна" и выложу "код" в тему. Прошу не кидаться помидорами, Arduino IDE изучаю только вторую неделю:)

Vasya73
Offline
Зарегистрирован: 06.11.2016

Ву-аля! Вот и мой эпичесий "говнокод":) Которы даже работает, вот бы ещё однократно вызываемую энкодером функцию GET прикрутить, радости моей не было бы предела!

P.S. Пока решил вызывать функцию GET с помощью millis(); что дико меня не устраивает, нужнен вызов функции именно энкодером. Почему именно энкодером, обьясню позже.

#include <ArduinoJson.h>
#include "Arduino.h"
#include <Encoder.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#define pinModul 11  /* кнопка выбора модуляции */
#define pinFreq 10   /* кнопка GET/SET */
#define pinBaypas 9  /* байпас */
#define pinStep 8    /* кнопка "шаг настройки" */
LiquidCrystal_I2C lcd(0x3F, 20, 4);   //устанавливаем адрес 0x3F, и дисплей 20 символов в 4 строки (20х4)
//--------------------------------Инициализация энкодеоа-----------------------------------------------
Encoder encoder(3, 2);            //номера входов, подключенные к энкодеру
//------------------------------------------------------------------------------------------------
boolean state = true;             //переменная запроса GET
//-----------------------------------Кнопка LSB/USB/AM---------------------------------------------
int regimA = 1;
int flagA = 0;
//---------------------------------- Кнопка Step size ---------------------------------------------
int stepFreq;                     //шаг настройки
int regim = 1;                     //переменная кнопки
int flag = 0;                      //флаг работы кнопки
//--------------------------------- Initial frequency----------------------------------------------
long oldPos  = -999;
long newPos;
long frequency;                   //значения начальной частоты Гц
long newFrequency;                //значение установки частоты SET
//------------ Timeouts----------------------------------------------------------------------------
unsigned long reqTime       = 0;
const long    reqInterval   = 10;
unsigned long respTime      = 0;
const long    respInterval  = 500;
boolean gotAnswer = true;         //флаг "получил ответ"
//--------------------------------------------------------------------------------------------------
boolean getState = false;         //состояние вызова
unsigned long previousMillis = 0; //последний момент времени, когда состояние запроса GET изменялось
long OnGet = 15;                 //длительность запроса GET (в миллисекундах)
long OffGet = 2500;              //пауза между запросами GET (в миллисекундах)
boolean stopGet = false;
//--------------------------------------------------------------------------------------------------

void baypassOn() //функция включения байпаса
{ 
  stopGet = true; 
  lcd.setCursor(12, 0);
  lcd.print("BAYPASS");
  lcd.setCursor(5, 2);                     //устанавливаем курсор на 3 строку 5 знак
  lcd.print((float)300000000 / frequency); //расчёт длинны волны "m" с плавающей запятой
  lcd.print("m  ");                        //вывод знака "метр"
  PORTB = B00000010;                       //порт 'В' 9-pin HIGH

  //--------------------------------------------------------------------------------------------------
}
void pausTemp() //функция задержки
{
  if ((abs(millis() - respTime) > respInterval) && !gotAnswer) {
    respTime = millis();
    gotAnswer = true;
  }
}
void portClean() //  функция очистки буфера
{
  if (Serial.available() > 0) {
    gotAnswer = true;
    String inData = Serial.readStringUntil('\n');
    inData = "";
  }
}
//-----------------------блок "антипрыжок"--------------------------------
void blockJamp() {
  if (flag == 1)
  {
    int i = 0;
    while (i < 1) {
      getFreq();        // вызов функции GET - запрос частоты SDR#
      i++;
    }
  }
}
//-------------------- mode USB ---------------------------------------
void modeUsb() {
  if (flagA == 1)
  {
    int b = 0;
    while (b < 1) {
      Serial.println("{\"Command\": \"Set\", \"Method\": \"DetectorType\", \"Value\": \"USB\"}");
      b++;
    }
  }
}
//---------------------------mode LSB-----------------------------------
void modeLsb() {
  if (flagA == 1)
  {
    int b = 0;
    while (b < 1) {
      Serial.println("{\"Command\": \"Set\", \"Method\": \"DetectorType\", \"Value\": \"LSB\"}");
      b++;
    }
  }
}

//--------------------------mode AM--------------------------------------
void modeAm() {
  if (flagA == 1)
  {
    int b = 0;
    while (b < 1) {
      Serial.println("{\"Command\": \"Set\", \"Method\": \"DetectorType\", \"Value\": \"AM\"}");
      b++;
    }
  }
}
//---------------------------mode CW--------------------------------------------------
void modeCw() {
  if (flagA == 1)
  {
    int b = 0;
    while (b < 1) {
      Serial.println("{\"Command\": \"Set\", \"Method\": \"DetectorType\", \"Value\": \"CW\"}");
      b++;
    }
  }
}
//------------------------------------------------------------------------------------------
void setup() {
  Serial.begin(115200);
  pinMode(pinModul, INPUT);
  pinMode(pinStep, INPUT);
  pinMode(pinFreq, INPUT);
  DDRD = DDRD | B11110000; //выводы с 1 по 3 OUTPUT
  DDRB = DDRB | B00000010; //9-pinBaypas, OUTPUT
  lcd.init();              //инициализация дисплея
  lcd.backlight();         //включаем подсветку дисплея
  getFreq();               //запрос актуальной частоты

  //---------------------- включение вида модуляции (первый запуск программы)---------------------------
  delay(50);
  if (frequency < 14000000) {
    Serial.println("{\"Command\": \"Set\", \"Method\": \"DetectorType\", \"Value\": \"LSB\"}");
    regimA = 1;
  }
  delay(50);
  if (frequency > 14000000) {
    Serial.println("{\"Command\": \"Set\", \"Method\": \"DetectorType\", \"Value\": \"USB\"}");
    regimA = 2;
  }
}

void loop()
{
  //------------------------- запроса GET----------------------------------------
  
  unsigned long currentMillis = millis(); //текущее время в миллисекундах
  
  if ((getState == true) && (currentMillis - previousMillis >= OnGet)) // вызов GET 
  {
    getState = false;                                       //запрашиваем частоту
    previousMillis = currentMillis;                         //запоминаем момент времени
    state = false;                                          //флаг запроса
    getFreq();
  }

  else if ((getState == false) && (currentMillis - previousMillis >= OffGet)) //пауза между запросами
  {
    getState = true;                                        
    previousMillis = currentMillis;                        //запоминаем момент времени
    state = true;
    }                                               
    pausTemp();
    setFreq();  //вызов функции SET - установка частоты SDR#
}
//---------------------------- GET------------------------------------------------
void getFreq()
{
  reqTime   = millis();
  respTime  = millis();
  gotAnswer = false;
  Serial.println("{\"Command\": \"Get\", \"Method\": \"Frequency\"}");
  //-------------------------JSON GET запрос частоты---------------------------------
  String inData = Serial.readStringUntil('\n');
  StaticJsonBuffer<200> jsonBuffer;
  JsonObject& root = jsonBuffer.parseObject(inData);

  if (!root.success()) {
    //lcd.clear();
    lcd.setCursor(3, 3);
    lcd.print("No  connection");
    lcd.setCursor(5, 2);
    lcd.print("   NO       ");
    delay(100);                  
    return;
  }

  frequency = root["Value"];
  inData = "";
  encoder.write(0);                    //сброс счётчика энкодера

  portClean();                         //очистка буфера
  pausTemp();                          //задержка

  //-----------блок управления ПДФ 160 м---------------------------------
  lcd.setCursor(3, 3);
  lcd.print( "              ");         //сброс сообщения "No  connection"
  if (frequency > 1810000)
  {
    PORTB = B00000000;                  //все LOW
    PORTD = B00000000;                  //все LOW
    lcd.setCursor(5, 2);                //устанавливаем курсор на третью строку пятый символ
    lcd.print("160m    ");              //выводим знак диапазона
    lcd.setCursor(12, 0);
    lcd.print("        ");              //сброс сообщения "BAYPASS"
  }
  if (frequency < 1810000) {
    baypassOn();
  }
  if (frequency > 2000000) {
    baypassOn();
  }
  //-----------блок управления ПДФ 80 м------------------------------------
  if (frequency > 3500000)
  {
    PORTB = B00000000;
    PORTD = B00010000;           //HIGH 4-pin
    lcd.setCursor(5, 2);
    lcd.print("80m     ");
    lcd.setCursor(12, 0);
    lcd.print("        ");
  }
  if (frequency > 3800000) {
    baypassOn();
  }

  //-----------блок управления ПДФ 40 м--------------------------------------
  if (frequency > 7000000)
  {
    PORTB = B00000000;
    PORTD = B00100000;            //HIGH 5-pin
    lcd.setCursor(5, 2);
    lcd.print("40m      ");
    lcd.setCursor(12, 0);
    lcd.print("        ");
  }
  if (frequency > 7300000) {
    baypassOn();
  }

  //-----------блок управления ПДФ 20 м----------------------------------------
  if (frequency > 14000000)
  {
    PORTB = B00000000;
    PORTD = B01000000;              //HIGH 6-pin
    lcd.setCursor(5, 2);
    lcd.print("20m      ");
    lcd.setCursor(12, 0);
    lcd.print("        ");
  }
  if (frequency > 14400000) {
    baypassOn();
  }

  //--------------блок управления ПДФ 17,15,12,10 м---------------------------
  if (frequency > 18068000)
  {
    PORTB = B00000000;
    PORTD = B01010000;                //HIGH 4, 6-pin
    lcd.setCursor(5, 2);
    lcd.print("17m-10m   ");
    lcd.setCursor(12, 0);
    lcd.print("        ");
  }
  if (frequency > 29800000)
  {
    baypassOn();
  }
  state = false;
}

//--------------Позиция энкодера + шаг настройки + вид модуляции -------------------------
void setFreq() {
  lcd.setCursor(0, 2);               //курсор на 3 строку
  lcd.print("Band:");                //строка "диапазон"
  //--------------------------Шаг настройки ------------------------------------------------
  if (digitalRead(pinStep) == HIGH && flag == 0) //если кнопка нажата и перемення flag равна 0
  {
    regim++;  // только одно действие плюс защита от "дребезга"  100%
    flag = 1;
    if (regim > 4) // количество режимов 4
    {
      regim = 1; // мы используем только одну кнопку, то переключать режимы будем циклично
    }
  }
  if (digitalRead(pinStep) == LOW && flag == 1) //если кнопка НЕ нажата и переменная flag равна - 1.
  {
    flag = 0; //обнуляем переменную "кнопка"
  }
  if (regim == 1) //первый режим
  {
    stepFreq = 110; // шаг настройки 110 Гц
    blockJamp();   // вызов блока "антипрыжок"
    lcd.setCursor(0, 0);
    lcd.print("Step:110Hz  ");
  }
  if (regim == 2) //второй режим
  {
    stepFreq = 150; // шаг настройки 150 Гц
    blockJamp();
    lcd.setCursor(0, 0);
    lcd.print("Step:150Hz");
  }
  if (regim == 3) //третий режим
  {
    stepFreq = 250;  // шаг настройки 250 Гц
    blockJamp();
    lcd.setCursor(0, 0);
    lcd.print("Step:250Hz");
  }
  if (regim == 4) //четвертый режим
  {
    stepFreq = 550; // шаг настройки 550 Гц
    blockJamp();
    lcd.setCursor(0, 0);
    lcd.print("Step:550Hz");
  }

  //-------------------------------тип модуляции--------------------------------------------

  if (digitalRead(pinModul) == HIGH && flagA == 0) //если кнопка нажата и перемення flagA равна 0
  {
    regimA++;  // только одно действие плюс защита от "дребезга"  100%
    flagA = 1;
    if (regimA > 4) // количество режимов 4
    {
      regimA = 1; // мы используем только одну кнопку, то переключать режимы будем циклично
    }
  }
  if (digitalRead(pinModul) == LOW && flagA == 1) //если кнопка НЕ нажата и переменная flagA равна 1.
  {
    flagA = 0; //обнуляем переменную "кнопка"
  }

  if (regimA == 1) //первый режим
  {
    modeLsb();            //вид модуляции LSB
    lcd.setCursor(17, 2);
    lcd.print("LSB");
  }
  if (regimA == 2) //второй режим
  {
    modeUsb();            //вид модуляции USB
    lcd.setCursor(17, 2);
    lcd.print("USB");
  }
  if (regimA == 3) //третий режим
  {
    modeAm();               //вид модуляции AM
    lcd.setCursor(17, 2);
    lcd.print("AM ");
  }
  if (regimA == 4)            //вид модуляции CW
  { modeCw();
    lcd.setCursor(17, 2);
    lcd.print("CW ");
  }
  //----------отслеживание состояния энкодера + вызов GET---------------------------
  long newPos = encoder.read();
  if (newPos != oldPos && gotAnswer && (abs(millis() - reqTime) > reqInterval) ) {
    getState = false;                        //флаг - запрет GET во время вращения энкодера
    state = false;
    reqTime   = millis();
    respTime  = millis();
    oldPos    = newPos;

    //----------------------------------SET частоты ----------------------------------
    newFrequency = frequency + ((newPos / 2) * stepFreq); // частота + шаг перестройки
    Serial.println("{\"Command\": \"Set\", \"Method\": \"Frequency\", \"Value\": " + String(newFrequency) + "}");
    gotAnswer = true;
  }
  lcd.setCursor(0, 1);                          //устанавливаем курсор на вторую строку и первый символ.
  lcd.print("Freq>");                           //строка "частота" 
  if (newFrequency < 1000) lcd.print("   ");    //убираем мерцание "частота"
  lcd.print(newFrequency);                      //выводим значение частоты
  lcd.print(" Hz       ");                      //выводим знак Hz
   
  portClean();
}



 

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

Vasya73 пишет:

Я уже давно опредилился,

Да, ни фига Вы не определились. У Вас в каждом посте хотелки разные.

А на вопрос

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

Что означает выражение "и в конце"? 

ответа так и нет. И не будет? Ну, ладно, как хотите.

Vasya73
Offline
Зарегистрирован: 06.11.2016

"Вконце" - это "одноразовый" вызов функции сразу после остановки вращения энкодера, подумав, считаю что сия функция будет излишней, вполне хватит запроса в начале вращения энкодера.

P.S. В чём заключается моя "неопределённость"? В том, что я хочу реализовать в коде свою "хотелку" в плане одноразового вызова функции GET при помощи энкодера? Куда уж определённее:)

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

Vasya73, Вы, похоже даже вопроса понять не можете. Вот Вы пишете

Vasya73 пишет:

"Вконце" - это "одноразовый" вызов функции сразу после остановки вращения энкодера

Так я же Вас и спрашивал как именно Вы собираетесь определять момент "сразу после остановки вращения энкодера"? Ждать некий таймаут и если в течение этого таймаута новых импульсов нет, то значит вращать закончили? Но это не сразу. Как Вы сразу определать собирались?

Vasya73 пишет:

P.S. В чём заключается моя "неопределённость"? 

В том, что в первом посте Вы пишете

Vasya73 пишет:

должна два раза запускаться функция

А в четвёртом посте Вы же пишете

Vasya73 пишет:

заставить энкодер однократно вызывать функцию GET 

Вы не видите здесь противоречия?

Vasya73 пишет:

Куда уж определённее:)

Вот и я про то же.

 

Vasya73
Offline
Зарегистрирован: 06.11.2016

Хорошо, вношу так сказать, ясность:)  Как реализовать в коде одноразовый вызов функции GET. Т.е. крутим ручку энкодера, при первом же импульсе от энкодера вызывается функция GET (запрос актуальной частоты), далее, при дальнейшем вращении энкодера функция GET вызываться не должна. Остановились, перестали крутить энкодер функция GET не вызывается. Посидели покурили, решили перестроиться по частоте, снова крутим энкодер вызывая при этом одноразово функцию GET. На данный момент, вроде бы всё доходчиво объяснил. Черновик скетча выкладывал выше. 

P.S. Данный скетч разрабатываю для работы с программой SDR#, "посредником" между ПК и Arduino является плагин SDRSharp-Net-Remote. SDR# - это программа управления SDR приёмником. В принципе, управление полосовыми фильтрами я ужо реализовал, переключаются идеально:) А вот работу с энкодером никак не поборю:) Вот и попросил помощи у гуру, мож кто и подскажит как решить сию "проблему" с запросом GET посредством вращения энкодера. В общем, как то так.  

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

Мдаа ... гуманитарий???

Vasya73 пишет:

На данный момент, вроде бы всё доходчиво объяснил ...

Для гуманитария, может быть, но программировать по такому объяснению невозможно.

Я целый день спрашиваю у Вас одно и то же, но Вы даже вопроса не понимаете.

Vasya73 пишет:

1) при дальнейшем вращении энкодера функция GET вызываться не должна

2) Посидели покурили, этом одноразово функцию GET

Ну нет в языках программирования понятия "покурили" - НЕТУ!

Вы скажете наконец долбанную длительность перекура? Просто, на случай, если Вы плохо понимаете по-русски: "Would you tell me the fucking smoke break duration!"

Если энкодер не выдаёт щелчков 50мс это уже "покурили" или ещё нет? А если сто мс? Секунда? Минута?

СКОЛЬКО времени нужно курить, чтобы таки вызвать функцию (а при более коротких перекурах не вызывать)?

Вы вопрос понимаете? Вот я медленно вращаю энкодер - 2 щелчка в секунду - вызываем -  нет? А если два щелчка в минуту? А если два щелчка в час?

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

Vasya73
Offline
Зарегистрирован: 06.11.2016

Отвечаю. Первый импульс с энкодера - вызов функции GET. Все последующие импульсы игнорируются. Остановились, хоть на минуту, хоть на час, крутанули энкодер - однократно вызвали функцию GET, все последующие импульсы игнорируются. Т.е. сигналы с энкодера будут иметь следующий вид - GET, SET, SET... n-SET и так до остановки вращения энкодера. Через некоторое время, снова крутим энкодер, опять тот же алгоритм - GET, SET, SET, SET... n-SET.  SET - это команда установки частоты отправляемая в порт ПК. GET - запрос частоты. Почему нужен именно такой алгоритм? Потому что, перестраивать частоту можно и из окна программы SDR#, для того чтобы "синхронизировать" Arduino с "шарпом" нужно запросить актуальное на данный момент времени значение частоты, что бы Arduino начало перестраивать частоту отталкиваясь от частоты установленной в "шарпе". Например: в SDR# установленна частота 3690000 Гц для того чтобы Arduino начало перестраивать частоту начиная с 3690000 Гц ей нужно запросить значение частоты от которой и будет "плясать":) Такой алгоритм первоначально уже риализован, т.е. переключение с помощью кнопки, т.е. нажал на кнопку SET/GET перед настройкой частоты с помощью энкодера, считал частоту из "шарпа", переключился в режим SET и начинаешь перестраивать частоту от той что считало Arduino. Но такой метод настройки частоты крайне неудобен, поэтому, временно, реализовал сие используя millis(); Теперь о нюансах. Дело в том, что когда происходит запрос частоты из SDR#, то последний "заикаеться":) И используя запрос по таймеру очень уж некомфортно слушать "заикания". Вот я и решил сделать одноразовый запрос частоты в начале вращения энкодера, одно "заикание" SDR# не столь напрягает, как постоянное:) 

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

Тяжело...

Vasya73, что значит "остановились"?

Сама ручка энкодера-то может вращаться непрерывно, но импульсы то от него поступают время от времени. Поэому:

1. "Сразу" в данном случае принципиально невозможно. Возможно только подождать некоторое время и, если мы решим, что ждали уже достаточно долго, а очередного импульса нет, сделать вывод, что экнодер остановился.

2. Необходимо количественно определить это время (называется оно таймаут).

Vasya73
Offline
Зарегистрирован: 06.11.2016

Тэээксс..:) Оставим пока в покое "мой" скетч. Берём гипотетический энкодер и начинаем его крутить. При появлении первого импульса с энкодера, вызываем функцию GET, которая запрашивает значение частоты установленное в SDR#-е. Основываясь на значении считанной из SDR# частоты, Arduino  начинает перестройку, т.е. в SDR# установлена частота 7100000 Гц считав сие значение Arduino "синхронизируется" с SDR# и начинает перестройку именно с 7100000 Гц. Я уже не знаю, как ещё объяснять:) Еще один пример: гипотетический энкодер управляет включением лампочки, так вот, при вращении энкодера, получив первый импульс, лампочка включается, получив второй и последующие импульсы лампочка гаснет и так до конца вращения энкодера. Останавливаем вращение энкодера, лампочка находиться в выключенном состоянии. Снова начинаем вращать энкодер, получив первый импульс энкодера, лампочка снова загорается и гаснет получив второй и последущие импульсы. Теперь возвращаемся к работе скетча. Вращаем энкодер, однократно вызвали функцию GET, которая запросила  значение частоты от которой и будет перестраиваться Arduino. Т.е. "запросила -> получила" ответ и больше не вызывается, в силу вступает функция SET которая будет работать до конца вращения энкодера. Как то так:) Я уже и алгоритм расписал и скетч черновой выложил, как ещё то объяснить?:)

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

Vasya73 пишет:

станавливаем вращение энкодера, 

Блин, Вы можете наконец сказать что такое "останавливаем".

Vasya73 пишет:

Я уже и алгоритм расписал 

Ничерта Вы не расписадли, Вы не хнаете что такое алгоритм

Vasya73 пишет:

как ещё то объяснить?:)

Очено просто. Скажите так: "останавливаем, это когда от энкродера не поступает импульсов в тчение N секунд". Просто скажите, чему равно N.

Без этого, всё Ваши "останавливаем" и "покурили" - это болтовня не имеющая к понятию алгоритма никакого отношения.

Vasya73
Offline
Зарегистрирован: 06.11.2016

Всем участвующим в сим весьма познавательном диалоге большой респект:) Путь к решению вышеуказанной задачи нашел самомтаятельно. Так что, тему можно смело закрывать. Как говориться, если хочешь что-то сделать качественно и что бы понравилось, в первую очередь, самому себе, сделай сам!:) Всем удачи! 73!

P.S. А вот нервничать не рекомендую, берегите себя:)