Новый код. версия 0.2
Изменения:
1. Добавлен светодиод "тип управления". На ногу ардуины 7, анодом к ноге, катодом - на землю, обязательно токоограничивающий резистор ом 200
2. Добавлена кнопка "Больше" - нога 4, замыкание на землю
3. Добавлена кнопка "Меньше" - нога 2, замыкание на землю
4. Добавлена кнопка "Режим" - нога 3, замыкание на землю
Логика работы: После включения светодиод "тип управления" - выключен. Частота задается резистором.
После однократного нажатия на кнопку "режим" - светодиод включается, устройство продолжает генерировать частоту установленную резистором, но ее можно менять кнопками "Больше" и "Меньше". При этом положение и изменения резистора - неважны.
Если снова нажать кнопку режим - то светодиод выключится, частота снова задается резистором напрямую.
Сейчас в скетче установлена минимальная частота 2, максимальная 100. Меняйте как надо.
Жду результатов теста.
- Код: Выделить всё • Развернуть
/*
Управление шаговиком (драйвер степ-дир) переменным резистором
теперь с кнопками! :)
v 0.2 */
#define Step_pin 6 //вывод Arduino для ноги STEP контроллера
#define Dir_pin 5 //вывод Arduino для ноги DIR контроллера
#define Resistor_pin A0 //вывод Arduino резистора 0-5вольт
#define Mode_led_pin 7 //вывод Arduino Светодиода "режим"
//********** Кнопки:
#define keyDEFtime 30 //Значение для антидребезга - клавиша удерживаемая столько времени в миллисекундах считается нажатой.
#define keyPAUSEtime 400 //Значение в миллисекундах паузы между повторами
#define Butt_Mode 3 //Кнопка "режим"
//номер кнопки - 3
#define KeyMode 3
#define Butt_Down 2 //Кнопка "Меньше"
//номер кнопки - 1
#define KeyDown 1
#define Butt_Up 4 //Кнопка "Больше"
//номер кнопки - 2
#define KeyUp 2
#define KeyNONE 0 //Ничего не нажато
byte keyTemp = KeyNONE; //Переменная для хранения временного состояния кнопок
byte keyCONTpress; //Переменная взводится после первого срабатывания клавиши и определяет автоповтор
unsigned long BtnTime; //Хранит время начала нажатия кнопок
//************
byte ControlMode = 0; //Переменная определяет режим управления. 0 - резистор. 1 - кнопки.
//Переменная для значения таймера
volatile unsigned char timerLoadValue;
//Переменная для количества холостых циклов таймера
volatile unsigned char FullTimer;
volatile unsigned char FullTimerCount; //внутренный счетчик таймера
//значение минимальной частоты
#define LowFreq 2
//значение МАКСИмальной частоты
#define HighFreq 100
//Переменная для шага чаcтоты на едниницу изменения АЦП
float FreqStep;
int OutFreq = LowFreq; //Переменная для хранения установленной частоты
//Переменная для текущего значения резистора
int sensorValue = 0;
//Переменная для Старого значения резистора
int OLDsensorValue = 0;
void setup() {
// Конфигурим вывод Step_pin как выход
pinMode(Step_pin,OUTPUT);
// Конфигурим вывод Dir_pin как выход
pinMode(Dir_pin,OUTPUT);
// Конфигурим вывод Dir_pin как вход
pinMode(Resistor_pin,INPUT);
// Конфигурим выводы кнопок как входы с подтяжкой
pinMode(Butt_Down, INPUT_PULLUP);
pinMode(Butt_Mode,INPUT_PULLUP);
pinMode(Butt_Up,INPUT_PULLUP);
pinMode(Mode_led_pin,OUTPUT); // Конфигурим вывод Mode_led_pin как выход
//Установим на выходах 0
digitalWrite(Step_pin, LOW);
digitalWrite(Dir_pin, LOW);
// Посчитаем "шаг" изменения частоты на единицу изменения резистора
FreqStep=(float)(HighFreq-LowFreq)/1024;
//Запускает последовательный порт
Serial.begin(9600);
//Сообщение о запуске программы
Serial.println("Program started");
Serial.print("FreqStep=");
Serial.println(FreqStep);
//Запускает таймер и получает загружаемое значение таймера.
//Параметр - желаемая частота в герцах.
timerLoadValue=SetupTimer2(50);
//Установки Таймер2: Делитель частоты /8, режим 0
//Частота = 16MHz/256 = 62500 герц или
//Делитель /256 дает нам хороший рабочий диапазон
//так что сейчас мы просто жестко запрограммируем это.
TCCR2A = 0;
//TCCR2B = 1<<CS22 | 0<<CS21 | 0<<CS20; //это на 256
TCCR2B = 4;
//Подключение прерывания по переполнению Timer2
TIMSK2 = 1<<TOIE2;
//Выводит загружаемое значение таймера
Serial.print("Timer2 Load:");
Serial.println(timerLoadValue,HEX);
}
void loop() {
byte ButtPressed=read_buttons(); //прочитаем нажатую кнопку
if (KeyMode==ButtPressed) //Если нажата кнопка - меняем режим управления и управляем светодиодом
{ControlMode=!ControlMode; digitalWrite(Mode_led_pin,ControlMode);}
if (ControlMode) //Если режим кнопки (светодиод включен)
{
if (KeyUp==ButtPressed) //Если нажата кнопка "Больше"
{OutFreq+=1;}
if (KeyDown==ButtPressed) //Если нажата кнопка "Меньше"
{OutFreq-=1;}
if (ButtPressed) {SetupTimer2(OutFreq);} //Если вообще что-то нажато
}
else //Если режим резистор (светодиод выключен)
{
//Тут будем читать занчение
sensorValue=analogRead(Resistor_pin);
//Сравним значение со старым, если отличается - пересчитаем установку таймера
if (sensorValue!= OLDsensorValue)
{ //Serial.println("ReCall"); //debug
OLDsensorValue=sensorValue;
OutFreq = LowFreq+FreqStep*sensorValue; //Вычислим новое значение частоты
SetupTimer2(OutFreq);
}
}
/*
Serial.print("sensor=");
Serial.println(sensorValue,DEC);
Serial.print("FullTimerCount");
Serial.println(FullTimerCount);
Serial.print("FullTimer");
Serial.println(FullTimer,DEC);
Serial.print("timer=");
Serial.println(timerLoadValue,DEC);
Serial.print("ButtPressed=");
Serial.println(ButtPressed,DEC);
Serial.print("OutFreq=");
Serial.println(OutFreq,DEC);
Serial.println("***");
Serial.println("");
*/
delay (1);
}
//Timer2 указатель вектора прерывания по переполнению
//Собственно говоря частота будет в два раза ниже.
ISR(TIMER2_OVF_vect)
{
if (FullTimerCount>1)
{FullTimerCount--;}
else
{if (FullTimerCount==1) //предпоследний цикл
{
TCNT2+=timerLoadValue;
FullTimerCount=0;
}
{if (FullTimerCount==0) // Срабатывание
{
FullTimerCount=FullTimer;
//Переключение IO-вывода в другое состояние.
digitalWrite(Step_pin,!digitalRead(Step_pin));
//Перезагрузка таймера и коррекция по задержке
if (FullTimer)
{TCNT2=1;} //Если холостые циклы есть - максимальное значение
else
{TCNT2+=timerLoadValue;}
}
}
}
}
#define TIMER_CLOCK_FREQ 62500.0
//15625 for /1024
//2MHz for /8 prescale from 16MHz
//Установка Таймера2.
//Конфигурирует 8-битный Таймер2 ATMega168 для выработки прерывания
//с заданной частотой.
//Возвращает начальное значение таймера, которое должно быть загружено в TCNT2
//внутри вашей процедуры ISR.
//Смотри пример использования ниже.
unsigned char SetupTimer2(float timeoutFrequency){
//Подсчет начального значения таймера
//Слегка усложним, добавив холостые просчеты
int ticks = TIMER_CLOCK_FREQ/timeoutFrequency;
FullTimer=ticks/256; //Вычисляем количество ПОЛНЫХ циклов таймера
timerLoadValue=(int)(257.0-(ticks-(256*FullTimer)+0.5)); //Вычисляем количество доплнительных тиков таймера
//257 на самом деле должно быть 256, но я получил лучшие результаты с 257.
//загружает таймер для первого цикла
if (FullTimer)
{TCNT2=1;} //Если холостые циклы есть - максимальное значение
else
{TCNT2=timerLoadValue;}
}
// *****************************
//Чтение кнопок с антидребезгом
int read_buttons() {
byte KeyTempTemp = KeyNONE; //Переменная для хранения свежесчитанного внутри функции
//digitalWrite (LED_pin,0); //debug
//delay (400); //debug
//Тут используем millis() для отслеживания нажатия кнопки
// Запоминиаем в переменной BtnTime ВРЕМЯ НАЧАЛА нажатия
// Запоминаем в переменной keyTemp нажатия
// Дефиним время антидребезга #define
if (!digitalRead(Butt_Mode)) { KeyTempTemp=KeyMode; } //Определяем в переменную ТЕКУЩУЮ нажатую кнопку.
if (!digitalRead(Butt_Down)) { KeyTempTemp=KeyDown; }
if (!digitalRead(Butt_Up)) { KeyTempTemp=KeyUp; }
//А тут проверим, совпадает ли с keyTemp (была ли нажата ранее)
/* lcd.setCursor(0, 0); //debug
lcd.print(KeyTempTemp); //debug
lcd.setCursor(2, 0); //debug
lcd.print(keyTemp); //debug
lcd.setCursor(1, 1); //debug
lcd.print(millis()); //debug
lcd.setCursor(12, 1); //debug
digitalWrite (LED_pin,1); //debug
delay (100);
lcd.print(" "); //debug
lcd.setCursor(12, 1); //debug
lcd.print(adc_key_in); //debug
*/
if (KeyTempTemp==keyTemp) //Кнопка уже БЫЛА нажата
{
if (keyCONTpress) //Повторные установки клавиши
{
if ((millis()-BtnTime) > keyPAUSEtime)
{
BtnTime=millis(); // Ставим стартовое время для автоповтора
return keyTemp;
}
}
else //Первая установка клавиши
{
if ((millis()-BtnTime) > keyDEFtime)
{
keyCONTpress=1;
BtnTime=millis(); // Ставим стартовое время для автоповтора
return keyTemp;
}
}
}
else //Раньше было другое состояние
{
keyCONTpress=0;
BtnTime=millis(); //Устанавливаем ТЕКУЩЕЕ время в переменную BtnTime
keyTemp=KeyTempTemp; //устанавливаем кнопку во временную переменную.
}
return KeyNONE; } // Если ничего не сработало, то ничего не возвращаем
//***********************************
Ну и пожеланий жду, могу например установленную частоту запоминать. Но с экраном все ж проще, имхо.