как срастить два кода в один
- Войдите на сайт для отправки комментариев
Сб, 24/03/2018 - 22:27
Прошу помощи. Я еще новичок в программировании.
Задача: при помощи квадратурного энкодера изменять частоту таймера, создающего последовательность импульсов с различными длительностью и паузами. Например, азбука Морзе и т.п.
Нашел два работающих кода: отдельно Enсoder с защитой от дребезга, и отдельно Таймер последовательности имп.
Вопрос тривиальный: как срастить эти два кода в один?
Код Enсoder
// Объявляем переменные
int pinA = 2; // Пины прерываний
int pinB = 3; // Пины прерываний
volatile long pause = 50; // Пауза для борьбы с дребезгом
volatile long lastTurn = 0; // Переменная для хранения времени последнего изменения
volatile int count = 0; // Счетчик оборотов
int actualcount = 0; // Временная переменная определяющая изменение основного счетчика
volatile int state = 0; // Статус одного шага - от 0 до 4 в одну сторону, от 0 до -4 - в другую
volatile int pinAValue = 0; // Переменные хранящие состояние пина, для экономии времени
volatile int pinBValue = 0; // Переменные хранящие состояние пина, для экономии времени
void setup()
{
pinMode(pinA, INPUT); // Пины в режим приема INPUT
pinMode(pinB, INPUT); // Пины в режим приема INPUT
digitalWrite(pinA, HIGH); // Задействуем встроенные подтягивающие резисторы
digitalWrite(pinB, HIGH); // Задействуем встроенные подтягивающие резисторы
attachInterrupt(0, A, CHANGE); // Настраиваем обработчик прерываний по изменению сигнала
attachInterrupt(1, B, CHANGE); // Настраиваем обработчик прерываний по изменению сигнала
Serial.begin(9600); // Включаем Serial
}
void loop()
{
if (actualcount != count) { // Чтобы не загружать ненужным выводом в Serial, выводим состояние
actualcount = count; // счетчика только в момент изменения
Serial.println(actualcount);
}
}
void A()
{
if (micros() - lastTurn < pause) return; // Если с момента последнего изменения состояния не прошло
// достаточно времени - выходим из прерывания
pinAValue = digitalRead(pinA); // Получаем состояние пинов A и B
pinBValue = digitalRead(pinB);
cli(); // Запрещаем обработку прерываний, чтобы не отвлекаться
if (state == 0 && !pinAValue && pinBValue || state == 2 && pinAValue && !pinBValue) {
state += 1; // Если выполняется условие, наращиваем переменную state
lastTurn = micros();
}
if (state == -1 && !pinAValue && !pinBValue || state == -3 && pinAValue && pinBValue) {
state -= 1; // Если выполняется условие, наращиваем в минус переменную state
lastTurn = micros();
}
setCount(state); // Проверяем не было ли полного шага из 4 изменений сигналов (2 импульсов)
sei(); // Разрешаем обработку прерываний
if (pinAValue && pinBValue && state != 0) state = 0; // Если что-то пошло не так, возвращаем статус в исходное состояние
}
void B()
{
if (micros() - lastTurn < pause) return;
pinAValue = digitalRead(pinA);
pinBValue = digitalRead(pinB);
cli();
if (state == 1 && !pinAValue && !pinBValue || state == 3 && pinAValue && pinBValue) {
state += 1; // Если выполняется условие, наращиваем переменную state
lastTurn = micros();
}
if (state == 0 && pinAValue && !pinBValue || state == -2 && !pinAValue && pinBValue) {
state -= 1; // Если выполняется условие, наращиваем в минус переменную state
lastTurn = micros();
}
setCount(state); // Проверяем не было ли полного шага из 4 изменений сигналов (2 импульсов)
sei();
if (pinAValue && pinBValue && state != 0) state = 0; // Если что-то пошло не так, возвращаем статус в исходное состояние
}
void setCount(int state) { // Устанавливаем значение счетчика
if (state == 4 || state == -4) { // Если переменная state приняла заданное значение приращения
count += (int)(state / 4); // Увеличиваем/уменьшаем счетчик
lastTurn = micros(); // Запоминаем последнее изменение
}
}
Код Таймера
/* Пример 1.3
мигание светодиода с определеной последовательностью
*/
//---------------классы---------
//класс Cl_LED просто светодиод мигает с полупериодом time
const int time[] = {200, 200, 500, 500, 1000, 1000, 300, 300};
const byte num_time = 8; //количество чисел в time[]
class Cl_LED {
uint32_t past; // время послед переключения
byte i_time;//номер в последовательности мигания
bool led; // состояние на светодиоде
byte pin;//нога светодиода
public:
// конструктор класса
Cl_LED(int _pin): pin(_pin) {}
// метод setup()
void setup() {
pinMode(pin, OUTPUT);
i_time = 0; //устанавливаем послед мигания в начало
digitalWrite(pin, led = 1);
past = millis();
}
// метод loop()
void loop() {
if (millis() - past >= time[i_time]) {
++i_time; // переход на след шаг последовательности
if (i_time >= num_time)i_time = 0;//если послед закончилась,начать с начала
digitalWrite(pin, led = !led);//<--- переключаем светодиод
past = millis(); //<--- сохраняем время переключения
}
}
};
//--------------компоновка------------
Cl_LED LED(/*нога светодиода*/ 13);
//------------main()--------------
void setup() {
LED.setup();
}
void loop() {
LED.loop();
}
Знаешь как приготовить коктейль «Зима в России»?
1. Берёшь 50% водки
2. Добавляешь ещё 50% водки
3. Тщательно перемешиваешь
4. Перед употреблением добавляешь водку по вкусу.
Вот и со скетчами надо примерно также.
С водкой-то я еще справляюсь, а вот с кодом ...
Призывайте в пост Квона. Судя по стилю - это его классы в кашу заварены. Вот теперь пусть ея и расхлебывает.
Так вопрос только в тщательности перемешивания.
Призывайте в пост Квона.
Хреново, что лички нет. Вот как его пригласить? разве что в заголовке темы его упомянуть.
Срастить то можно. Но 1 - зачем? 2 - и что должно вообще получится.
Задача: при помощи энкодера изменять множитель частоты таймера
А разьве энкодер это может. 1 - нужен код обслуживающий энкодер 2 - нужен код в котором можно менять частоту мигания 3- нужен код который позвляет пользователю понимать что нужно делать и что получилось . Программирование это не механическое сливания жидкостей и смотреть что получилось .
Ну код обслуживающий энкодер я привел в начале темы, и код мигания (кажется твоего производства?) тоже привел. Но не хватило заний, чтобы объединить их.
Однако, нашел подходящий код (ну не умею пока самостоятельно составить код с нуля), http://cyber-place.ru/showthread.php?t=2703. Чуть-чуть подредактировал под свои задачи, все работает как необходимо, только джиттер довольно сильный на высоких частотах. Как я понял, джиттер простыми средствами не устранить. Код стробоскопа (регулировка энкодером частоты и скважности), может кому и сгодится.
//Скетч от Cyber-Place.ru // Выводы ЭНКОДЕРА #define CLK 3 // Clock Подключаем к INT1, нельзя переназначать #define DT 4 // второй вывод энкодера #define SW 5 // switch кнопка энкодера #define Min 66 // минимальное значение #define Max 1134 //максимальное значение #define led_pin 13 // подключен светодиод #define step_freq 66.667 // шаг изменения частоты volatile uint32_t freq = 1133.3; // нач. частота в Гц volatile uint32_t paus, time_light; // время свечения светодиода в мкс uint32_t oldcount; boolean DT_last; // последнее состояние энкодера void setup() { pinMode(CLK, INPUT_PULLUP); // Clock Подключаем к INT1, нельзя переназначать pinMode(DT, INPUT_PULLUP); // второй вывод энкодера pinMode(SW, INPUT_PULLUP); // кнопка энкодера pinMode(led_pin, OUTPUT); // управление симистором attachInterrupt(1, encoderTick, CHANGE); // прерывания от Энкодера DT_last = digitalRead(CLK); // считываем положение CLK } void loop() { time_light = (54398 / freq); paus = 17.375 * time_light; digitalWrite(led_pin, 1); oldcount = micros(); while ( (micros() - oldcount) < time_light) {} // длительность импульса светодиода digitalWrite(led_pin, 0); while ( (micros() - oldcount) < paus) {} // положительный полупериод oldcount = micros(); digitalWrite(led_pin, 1); oldcount = micros(); while ( (micros() - oldcount) < time_light) {} // длительность импульса светодиода digitalWrite(led_pin, 0); while ( (micros() - oldcount) < paus) {} // положительный полупериод oldcount = micros(); digitalWrite(led_pin, 1); oldcount = micros(); while ( (micros() - oldcount) < time_light) {} // длительность импульса светодиода digitalWrite(led_pin, 0); while ( (micros() - oldcount) < paus * 0.6) {} // положительный полупериод oldcount = micros(); digitalWrite(led_pin, 1); oldcount = micros(); while ( (micros() - oldcount) < time_light * 6.) {} // длительность импульса светодиода digitalWrite(led_pin, 0); while ( (micros() - oldcount) < paus*1.25) {} // положительный полупериод oldcount = micros(); } //********************обработчики прерываний Энкодера******************************* void encoderTick() // Обратка прерываний от Энкодера { uint8_t DT_now = digitalRead(CLK); // считываем текущее положение CLK if (DT_now != DT_last && digitalRead(SW)) // если предыдущее и текущее положение не равны, значит был поворот { if (digitalRead(DT) != DT_now) // если DT не равен CLK, значит вращение по часовой стрелке { if ( freq < Max ) freq += step_freq; // прибавить } else { // если DT равен CLK, значит вращение против часовой if ( freq > Min ) freq -= step_freq; // убавить } } }