Не то слово - зло (( Однако сейчас через него вышел, как через роутер. Мне так и не подключили интет гады Ростелеком...
Зубьев не помню, не смогу уже посмотреть... уматываю в столицы на выходные
Примерно 40-60 оборотов, не меньше (если на максимуме). Ну не 5 точно.
Попробовал скетч. Реакция на кнопки чуть хуже стала. Не по 10 а по 20-40 теперь. Причем чем выше частота изначально, тем больше интервал изменения кнопками.
п.с. ну и чуть подправил код, чтобы отображалось корректно на дисплее (а то долго думал, что за слово сверху после нуля "trol" )) Тренируюсь. Кстати напомню, на ардуино мини про нет ноги А7.
Код:
/*
Управление шаговиком (драйвер степ-дир) переменным резистором
теперь с кнопками! :)
А на этот раз - с экраном и резистивными кнопками.
v 0.4 */
/*
Вывод Назначение
0 UART
1 UART
2
3
4
5 Dir_pin
6 Step_pin
7 LCD RS
8 LCD RW
9 LCD E
10 LCD DB4
11 LCD DB5
12 LCD DB6
13 LCD DB7
A0 Резистор
A1 Кнопки
A2
A3
A4
A5
A6
A7
*/
#include <LiquidCrystal.h> // Подключаем стандартную библиотеку LiquidCrystal
// Инициализируем объект-экран, передаём использованные
// для подключения контакты на Arduino в порядке:
#define lcd_RS_pin 7
#define lcd_RW_pin 8
#define lcd_E_pin 9
#define lcd_DB4_pin 10
#define lcd_DB5_pin 11
#define lcd_DB6_pin 12
#define lcd_DB7_pin 13
// RS, RW, E, DB4, DB5, DB6, DB7
LiquidCrystal lcd(lcd_RS_pin, lcd_RW_pin, lcd_E_pin, lcd_DB4_pin, lcd_DB5_pin, lcd_DB6_pin, lcd_DB7_pin);
#define Step_pin 6 //вывод Arduino для ноги STEP контроллера
#define Dir_pin 5 //вывод Arduino для ноги DIR контроллера
#define Resistor_pin A0 //вывод Arduino резистора 0-5вольт
//********** Кнопки:
#define btnRIGHT 1 //Определяем кнопки
#define btnUP 2
#define btnDOWN 3
#define btnLEFT 4
#define btnSELECT 5
#define btnNONE 0
#define btnDEFtime 30 //Значение для антидребезга - клавиша удерживаемая столько времени в миллисекундах считается нажатой.
#define btnPAUSEtime 400 //Значение в миллисекундах паузы между повторами
int lcd_key = btnNONE; //Для хранения полученного значеник кнопки
byte keyTemp = btnNONE; //Переменная для хранения временного состояния кнопок
byte keyCONTpress; //Переменная взводится после первого срабатывания клавиши и определяет автоповтор
unsigned long BtnTime; //Хранит время начала нажатия кнопок
byte btnCONTpress; //Переменная взводится после первого срабатывания клавиши и определяет автоповтор
byte btnTemp=btnNONE; //Для хранения номера ранее нажатой кнопки
#define ButtonPin A1 //Сюда подключены кнопки
//************
byte ControlMode = 0; //Переменная определяет режим управления. 0 - резистор. 1 - кнопки.
//Переменная для значения таймера
volatile unsigned char FullTimer0;
//Переменная для количества холостых 256циклов таймера
volatile unsigned int FullTimer256;//Переменная для количества холостых 256циклов таймера
volatile unsigned int FullTimer256Count; //внутренный счетчик таймера
//значение минимальной частоты
#define LowFreq 1
//значение МАКСИмальной частоты
#define HighFreq 10000
//Переменная для шага ча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);
lcd.begin(16,2); //Инициализируем экран
//Установим на выходах 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);
//Запускает таймер и получает загружаемое значение таймера.
//Параметр - желаемая частота в герцах.
FullTimer0=SetupTimer2(50);
//Установки Таймер2: Делитель частоты /8, режим 0
//Частота = 16MHz/64 = 125000 герц или
//Делитель /64 дает нам хороший рабочий диапазон
//так что сейчас мы просто жестко запрограммируем это.
TCCR2A = 0;
TCCR2B = 1<<CS22 | 0<<CS21 | 0<<CS20; //это на 64
//Подключение прерывания по переполнению Timer2
TIMSK2 = 1<<TOIE2;
//Выводит загружаемое значение таймера
Serial.print("Timer2 Load:");
Serial.println(FullTimer0,HEX);
lcd.setCursor(0, 0); //устанавливаем курсор
lcd.print("Stepper control"); //выводим на него строку
lcd.setCursor(0, 1); //устанавливаем курсор
lcd.print("R B "); //выводим на него строку
lcd.setCursor(0, 1); //устанавливаем курсор
lcd.cursor(); //Включим курсор
lcd.blink(); //Пусть мигает
delay(100);
}
void loop() {
lcd_key=read_LCD_buttons(); //прочитаем нажатую кнопку
if (lcd_key) //Нажата какая-то кнопка
{
Serial.print("Button=");
Serial.println(lcd_key,DEC);
if (btnRIGHT==lcd_key) //нажата кнопка ВПРАВО
{
lcd.setCursor(6, 1);
ControlMode = 1;
}
if (btnLEFT==lcd_key) //нажата кнопка ВЛЕВО
{
lcd.setCursor(0, 1);
ControlMode = 0;
}
}
if (ControlMode) //Если режим "кнопки"
{
if (btnUP==lcd_key) //Если нажата кнопка "Больше"
{OutFreq+=1;}
if (btnDOWN==lcd_key) //Если нажата кнопка "Меньше"
{OutFreq-=1;}
if (lcd_key) //Если вообще что-то нажато
{
SetupTimer2(OutFreq);
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print(FullTimer0);
lcd.setCursor(6, 0);
lcd.print(FullTimer256);
lcd.setCursor(7, 1);
lcd.print(" "); //чистим вывод
lcd.setCursor(7, 1);
lcd.print(OutFreq); //выводим Частоту
lcd.setCursor(6, 1);
}
}
else //Если режим резистор (светодиод выключен)
{
//Тут будем читать занчение
sensorValue=analogRead(Resistor_pin);
//Сравним значение со старым, если отличается - пересчитаем установку таймера
if (sensorValue!= OLDsensorValue)
{ //Serial.println("ReCall"); //debug
OLDsensorValue=sensorValue;
OutFreq = LowFreq+FreqStep*sensorValue; //Вычислим новое значение частоты
lcd.setCursor(1, 1);
lcd.print(" "); //Чистим вывод
lcd.setCursor(1, 1);
lcd.print(OutFreq); //выводим Частоту
lcd.setCursor(0, 1);
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(FullTimer0,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 (FullTimer256Count>1)
{FullTimer256Count--;}
else
{if (FullTimer256Count==1) //предпоследний цикл
{
TCNT2+=FullTimer0;
FullTimer256Count=0;
}
{if (FullTimer256Count==0) // Срабатывание
{
FullTimer256Count=FullTimer256;
//Переключение IO-вывода в другое состояние.
digitalWrite(Step_pin,!digitalRead(Step_pin));
//Перезагрузка таймера и коррекция по задержке
if (FullTimer256)
{TCNT2=1;} //Если холостые циклы есть - максимальное значение
else
{TCNT2+=FullTimer0;}
}
}
}
}
#define TIMER_CLOCK_FREQ 250000.0
//15625 for /1024
//2MHz for /8 prescale from 16MHz
//Установка Таймера2.
//Конфигурирует 8-битный Таймер2 ATMega168 для выработки прерывания
//с заданной частотой.
//Возвращает начальное значение таймера, которое должно быть загружено в TCNT2
//внутри вашей процедуры ISR.
//Смотри пример использования ниже.
unsigned char SetupTimer2(float timeoutFrequency){
//Подсчет начального значения таймера
//Слегка усложним, добавив холостые просчеты
long ticks = TIMER_CLOCK_FREQ/timeoutFrequency; // тиков счетчика для получения заданной частоты
FullTimer256=ticks/256; //Вычисляем количество ПОЛНЫХ 256 циклов таймера
ticks-=FullTimer256*256;
FullTimer0=(byte)(257.0-(ticks+0.5)); //Вычисляем количество доплнительных тиков таймера
//257 на самом деле должно быть 256, но я получил лучшие результаты с 257.
//загружает таймер для первого цикла
if (FullTimer256)
{TCNT2=1;} //Если холостые циклы есть - максимальное значение
else
{TCNT2=FullTimer0;}
}
// *****************************
//Чтение кнопок с антидребезгом
// read the buttons
int read_LCD_buttons()
{
int adc_key_in = analogRead(ButtonPin); // Получаем напряжение с АЦП
byte btnTempTemp = btnNONE; //Переменная для хранения свежесчитанного внутри функции
//digitalWrite (LED_pin,0); //debug
//lcd.setCursor(5, 0); //debug
//lcd.print(adc_key_in); //debug
//delay (400); //debug
//Тут используем millis() для отслеживания нажатия кнопки
// Запоминиаем в переменной BtnTime ВРЕМЯ НАЧАЛА нажатия
// Запоминаем в переменной btnTemp нажатия
// Дефиним время антидребезга #define
if (adc_key_in > 950) //Ничего не нажато
{
//BtnTime=0; //Скидываем время нажатия
btnCONTpress=0;
return btnNONE; // We make ths the 1st option for speed reasons since it will be the most likely result
}
else //что-то нажато
{
if (adc_key_in < 790) { btnTempTemp=btnSELECT; } //Определяем в переменную ТЕКУЩУЮ нажатую кнопку.
if (adc_key_in < 555) { btnTempTemp=btnLEFT; }
if (adc_key_in < 380) { btnTempTemp=btnDOWN; }
if (adc_key_in < 195) { btnTempTemp=btnUP; }
if (adc_key_in < 50) { btnTempTemp=btnRIGHT; }
//А тут проверим, совпадает ли с btnTemp (была ли нажата ранее)
/* lcd.setCursor(0, 0); //debug
lcd.print(btnTempTemp); //debug
lcd.setCursor(2, 0); //debug
lcd.print(btnTemp); //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 (btnTempTemp==btnTemp) //Кнопка уже БЫЛА нажата
{
if (btnCONTpress) //Повторные установки клавиши
{
if ((millis()-BtnTime) > btnPAUSEtime)
{
BtnTime=millis(); // Ставим стартово время для автоповтора
return btnTemp;
}
}
else //Первая установка клавиши
{
if ((millis()-BtnTime) > btnDEFtime)
{
btnCONTpress=1;
BtnTime=millis(); // Ставим стартово время для автоповтора
return btnTemp;
}
}
}
else //Раньше было другое состояние
{
// digitalWrite (LED_pin,1); //debug
// delay (100);
btnCONTpress=0;
BtnTime=millis(); //Устанавливаем ТЕКУЩЕЕ время в переменную BtnTime
btnTemp=btnTempTemp; //устанавливаем кнопку во временную переменную.
}
}
return btnNONE; // Если ничего не сработало, то ничего не возвращаем
}
//***********************************